storage/external/fasterkv/fasterkv_backend.cc
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "storage/external/fasterkv/fasterkv_backend.h" | ||
| 2 | |||
| 3 | #include <algorithm> | ||
| 4 | #include <atomic> | ||
| 5 | #include <cstring> | ||
| 6 | #include <filesystem> | ||
| 7 | #include <limits> | ||
| 8 | #include <stdexcept> | ||
| 9 | #include <string> | ||
| 10 | #include <thread> | ||
| 11 | #include <vector> | ||
| 12 | |||
| 13 | #include "core/faster.h" | ||
| 14 | #include "core/config.h" | ||
| 15 | #include "core/key_hash.h" | ||
| 16 | #include "core/status.h" | ||
| 17 | #include "device/file_system_disk.h" | ||
| 18 | #include "device/null_disk.h" | ||
| 19 | #include "environment/file_linux.h" | ||
| 20 | |||
| 21 | namespace recstore::storage::fasterkv { | ||
| 22 | namespace { | ||
| 23 | |||
| 24 | using FASTER::core::CallbackContext; | ||
| 25 | using FASTER::core::FasterHashHelper; | ||
| 26 | using FASTER::core::FasterKv; | ||
| 27 | using FASTER::core::IAsyncContext; | ||
| 28 | using FASTER::core::KeyHash; | ||
| 29 | using FASTER::core::Status; | ||
| 30 | using FASTER::core::StatusStr; | ||
| 31 | |||
| 32 | class GenLock { | ||
| 33 | public: | ||
| 34 | 904 | GenLock() : control_(0) {} | |
| 35 | 1270 | explicit GenLock(uint64_t control) : control_(control) {} | |
| 36 | |||
| 37 | 904 | GenLock& operator=(const GenLock& other) { | |
| 38 | 904 | control_ = other.control_; | |
| 39 | 904 | return *this; | |
| 40 | } | ||
| 41 | |||
| 42 | union { | ||
| 43 | struct { | ||
| 44 | uint64_t gen_number : 62; | ||
| 45 | uint64_t locked : 1; | ||
| 46 | uint64_t replaced : 1; | ||
| 47 | }; | ||
| 48 | uint64_t control_; | ||
| 49 | }; | ||
| 50 | }; | ||
| 51 | |||
| 52 | static_assert(sizeof(GenLock) == 8, "GenLock must be 8 bytes"); | ||
| 53 | |||
| 54 | class AtomicGenLock { | ||
| 55 | public: | ||
| 56 | AtomicGenLock() : control_(0) {} | ||
| 57 | explicit AtomicGenLock(uint64_t control) : control_(control) {} | ||
| 58 | |||
| 59 | 1808 | GenLock load() const { return GenLock{control_.load()}; } | |
| 60 | |||
| 61 | 358 | void store(GenLock desired) { control_.store(desired.control_); } | |
| 62 | |||
| 63 | 4 | bool try_lock(bool& replaced) { | |
| 64 | 4 | replaced = false; | |
| 65 | 8 | GenLock expected{control_.load()}; | |
| 66 | 4 | expected.locked = 0; | |
| 67 | 4 | expected.replaced = 0; | |
| 68 | 4 | GenLock desired{expected.control_}; | |
| 69 | 4 | desired.locked = 1; | |
| 70 | |||
| 71 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
8 | if (control_.compare_exchange_strong(expected.control_, desired.control_)) { |
| 72 | 4 | return true; | |
| 73 | } | ||
| 74 | ✗ | if (expected.replaced) { | |
| 75 | ✗ | replaced = true; | |
| 76 | } | ||
| 77 | ✗ | return false; | |
| 78 | } | ||
| 79 | |||
| 80 | 4 | void unlock(bool replaced) { | |
| 81 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (!replaced) { |
| 82 | 4 | const uint64_t sub_delta = (uint64_t{1} << 62) - 1; | |
| 83 | 4 | control_.fetch_sub(sub_delta); | |
| 84 | } else { | ||
| 85 | ✗ | const uint64_t add_delta = (uint64_t{1} << 63) - (uint64_t{1} << 62) + 1; | |
| 86 | ✗ | control_.fetch_add(add_delta); | |
| 87 | } | ||
| 88 | 4 | } | |
| 89 | |||
| 90 | private: | ||
| 91 | std::atomic<uint64_t> control_; | ||
| 92 | }; | ||
| 93 | |||
| 94 | static_assert(sizeof(AtomicGenLock) == 8, "AtomicGenLock must be 8 bytes"); | ||
| 95 | |||
| 96 | class UInt64Key { | ||
| 97 | public: | ||
| 98 | 826 | explicit UInt64Key(uint64_t key) : key(key) {} | |
| 99 | |||
| 100 | UInt64Key(const UInt64Key&) = default; | ||
| 101 | |||
| 102 | 1172 | inline static constexpr uint32_t size() { | |
| 103 | 1172 | return static_cast<uint32_t>(sizeof(UInt64Key)); | |
| 104 | } | ||
| 105 | |||
| 106 | 1546 | inline KeyHash GetHash() const { | |
| 107 | 1546 | return KeyHash{FasterHashHelper<uint64_t>::compute(key)}; | |
| 108 | } | ||
| 109 | |||
| 110 | 456 | inline bool operator==(const UInt64Key& other) const { | |
| 111 | 456 | return key == other.key; | |
| 112 | } | ||
| 113 | |||
| 114 | inline bool operator!=(const UInt64Key& other) const { | ||
| 115 | return key != other.key; | ||
| 116 | } | ||
| 117 | |||
| 118 | uint64_t key; | ||
| 119 | }; | ||
| 120 | |||
| 121 | class VariableValue { | ||
| 122 | public: | ||
| 123 | VariableValue() : gen_lock_{0}, size_{0}, length_{0} {} | ||
| 124 | |||
| 125 | ✗ | inline uint32_t size() const { return size_; } | |
| 126 | |||
| 127 | private: | ||
| 128 | friend class UpsertContext; | ||
| 129 | friend class ReadContext; | ||
| 130 | |||
| 131 | AtomicGenLock gen_lock_; | ||
| 132 | uint32_t size_; | ||
| 133 | uint32_t length_; | ||
| 134 | |||
| 135 | 452 | inline const uint8_t* buffer() const { | |
| 136 | 452 | return reinterpret_cast<const uint8_t*>(this + 1); | |
| 137 | } | ||
| 138 | |||
| 139 | 362 | inline uint8_t* buffer() { return reinterpret_cast<uint8_t*>(this + 1); } | |
| 140 | }; | ||
| 141 | |||
| 142 | class UpsertContext : public IAsyncContext { | ||
| 143 | public: | ||
| 144 | using key_t = UInt64Key; | ||
| 145 | using value_t = VariableValue; | ||
| 146 | |||
| 147 | 362 | UpsertContext(uint64_t key, const char* value, uint32_t value_size) | |
| 148 | 724 | : key_(key), | |
| 149 | 362 | value_(reinterpret_cast<const uint8_t*>(value)), | |
| 150 | 362 | value_size_(value_size) {} | |
| 151 | |||
| 152 | ✗ | UpsertContext(const UpsertContext& other) | |
| 153 | ✗ | : key_(other.key_), | |
| 154 | ✗ | owned_value_(other.value_, other.value_ + other.value_size_), | |
| 155 | ✗ | value_(owned_value_.data()), | |
| 156 | ✗ | value_size_(other.value_size_) {} | |
| 157 | |||
| 158 | 1802 | inline const key_t& key() const { return key_; } | |
| 159 | |||
| 160 | 720 | inline uint32_t value_size() const { | |
| 161 | 720 | return static_cast<uint32_t>(sizeof(value_t) + value_size_); | |
| 162 | } | ||
| 163 | |||
| 164 | 358 | inline void Put(value_t& value) { | |
| 165 | 358 | value.gen_lock_.store(GenLock{0}); | |
| 166 | 358 | value.size_ = value_size(); | |
| 167 | 358 | value.length_ = value_size_; | |
| 168 | 358 | std::memcpy(value.buffer(), value_, value_size_); | |
| 169 | 358 | } | |
| 170 | |||
| 171 | 4 | inline bool PutAtomic(value_t& value) { | |
| 172 | 4 | bool replaced = false; | |
| 173 |
2/6✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
|
4 | while (!value.gen_lock_.try_lock(replaced) && !replaced) { |
| 174 | ✗ | std::this_thread::yield(); | |
| 175 | } | ||
| 176 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (replaced) { |
| 177 | ✗ | return false; | |
| 178 | } | ||
| 179 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (value.size_ < value_size()) { |
| 180 | ✗ | value.gen_lock_.unlock(true); | |
| 181 | ✗ | return false; | |
| 182 | } | ||
| 183 | 4 | value.length_ = value_size_; | |
| 184 | 4 | std::memcpy(value.buffer(), value_, value_size_); | |
| 185 | 4 | value.gen_lock_.unlock(false); | |
| 186 | 4 | return true; | |
| 187 | } | ||
| 188 | |||
| 189 | protected: | ||
| 190 | ✗ | Status DeepCopy_Internal(IAsyncContext*& context_copy) override { | |
| 191 | ✗ | return IAsyncContext::DeepCopy_Internal(*this, context_copy); | |
| 192 | } | ||
| 193 | |||
| 194 | private: | ||
| 195 | key_t key_; | ||
| 196 | std::vector<uint8_t> owned_value_; | ||
| 197 | const uint8_t* value_; | ||
| 198 | uint32_t value_size_; | ||
| 199 | }; | ||
| 200 | |||
| 201 | class ReadContext : public IAsyncContext { | ||
| 202 | public: | ||
| 203 | using key_t = UInt64Key; | ||
| 204 | using value_t = VariableValue; | ||
| 205 | |||
| 206 | 464 | ReadContext(uint64_t key, | |
| 207 | char* output, | ||
| 208 | uint32_t expected_size, | ||
| 209 | size_t index, | ||
| 210 | const FasterKVBackend::MissCallback* on_miss) | ||
| 211 | 928 | : key_(key), | |
| 212 | 464 | output_(reinterpret_cast<uint8_t*>(output)), | |
| 213 | 464 | expected_size_(expected_size), | |
| 214 | 464 | index_(index), | |
| 215 | 464 | on_miss_(on_miss), | |
| 216 | 464 | found_(false) {} | |
| 217 | |||
| 218 | ✗ | ReadContext(const ReadContext& other) | |
| 219 | ✗ | : key_(other.key_), | |
| 220 | ✗ | output_(other.output_), | |
| 221 | ✗ | expected_size_(other.expected_size_), | |
| 222 | ✗ | index_(other.index_), | |
| 223 | ✗ | on_miss_(other.on_miss_), | |
| 224 | ✗ | found_(other.found_) {} | |
| 225 | |||
| 226 | 916 | inline const key_t& key() const { return key_; } | |
| 227 | |||
| 228 | ✗ | inline void Get(const value_t& value) { CopyValue(value); } | |
| 229 | |||
| 230 | 452 | inline void GetAtomic(const value_t& value) { | |
| 231 | 452 | GenLock before; | |
| 232 | 452 | GenLock after; | |
| 233 | do { | ||
| 234 | 452 | before = value.gen_lock_.load(); | |
| 235 |
1/2✓ Branch 1 taken 452 times.
✗ Branch 2 not taken.
|
452 | CopyValue(value); |
| 236 | 452 | after = value.gen_lock_.load(); | |
| 237 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
|
452 | } while (before.gen_number != after.gen_number); |
| 238 | 452 | } | |
| 239 | |||
| 240 | 452 | bool found() const { return found_; } | |
| 241 | |||
| 242 | 12 | void NotifyMiss() const { | |
| 243 |
3/6✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
|
12 | if (on_miss_ != nullptr && *on_miss_) { |
| 244 | 12 | (*on_miss_)(index_); | |
| 245 | } | ||
| 246 | 12 | } | |
| 247 | |||
| 248 | protected: | ||
| 249 | ✗ | Status DeepCopy_Internal(IAsyncContext*& context_copy) override { | |
| 250 | ✗ | return IAsyncContext::DeepCopy_Internal(*this, context_copy); | |
| 251 | } | ||
| 252 | |||
| 253 | private: | ||
| 254 | 452 | void CopyValue(const value_t& value) { | |
| 255 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
|
452 | if (value.length_ != expected_size_) { |
| 256 | ✗ | throw std::runtime_error("FasterKV value size mismatch"); | |
| 257 | } | ||
| 258 | 452 | std::memcpy(output_, value.buffer(), expected_size_); | |
| 259 | 452 | found_ = true; | |
| 260 | 452 | } | |
| 261 | |||
| 262 | key_t key_; | ||
| 263 | uint8_t* output_; | ||
| 264 | uint32_t expected_size_; | ||
| 265 | size_t index_; | ||
| 266 | const FasterKVBackend::MissCallback* on_miss_; | ||
| 267 | bool found_; | ||
| 268 | }; | ||
| 269 | |||
| 270 | using MemoryStore = | ||
| 271 | FasterKv<UInt64Key, VariableValue, FASTER::device::NullDisk>; | ||
| 272 | using SsdDisk = | ||
| 273 | FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, | ||
| 274 | uint64_t{1} << 30>; | ||
| 275 | using SsdStore = FasterKv<UInt64Key, VariableValue, SsdDisk>; | ||
| 276 | |||
| 277 | 106 | uint64_t NextPowerOfTwo(uint64_t value) { | |
| 278 | 106 | uint64_t out = 1; | |
| 279 |
5/6✓ Branch 0 taken 2654 times.
✓ Branch 1 taken 106 times.
✓ Branch 2 taken 2654 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2654 times.
✓ Branch 5 taken 106 times.
|
2760 | while (out < value && out <= (uint64_t{1} << 63)) { |
| 280 | 2654 | out <<= 1; | |
| 281 | } | ||
| 282 | 106 | return out; | |
| 283 | } | ||
| 284 | |||
| 285 | 26 | uint64_t ComputeHashTableSize(uint64_t capacity) { | |
| 286 | 26 | const uint64_t min_size = 1024; | |
| 287 | 26 | const uint64_t wanted = std::max(min_size, capacity * 2); | |
| 288 | 26 | return NextPowerOfTwo(wanted); | |
| 289 | } | ||
| 290 | |||
| 291 | 24 | uint64_t ComputeLogSize(uint64_t capacity, size_t value_size) { | |
| 292 | 24 | const uint64_t min_size = uint64_t{256} << 20; | |
| 293 | 24 | const uint64_t record_overhead = 128; | |
| 294 | 24 | const uint64_t per_record = | |
| 295 | record_overhead + static_cast<uint64_t>(value_size); | ||
| 296 | 24 | return std::max(min_size, NextPowerOfTwo(capacity * per_record * 2)); | |
| 297 | } | ||
| 298 | |||
| 299 | 814 | void CheckStatus(Status status, const char* operation) { | |
| 300 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 814 times.
|
814 | if (status != Status::Ok) { |
| 301 | ✗ | throw std::runtime_error( | |
| 302 | ✗ | std::string(operation) + " failed: " + StatusStr(status)); | |
| 303 | } | ||
| 304 | 814 | } | |
| 305 | |||
| 306 | 26 | uint64_t ResolveLogSize(uint64_t capacity, | |
| 307 | size_t value_size, | ||
| 308 | const FasterKVBackendOptions& options) { | ||
| 309 | uint64_t log_size = | ||
| 310 | 26 | ResolveHlogMemoryBytesForOptions(capacity, value_size, options); | |
| 311 | 26 | return NextPowerOfTwo(log_size); | |
| 312 | } | ||
| 313 | |||
| 314 | } // namespace | ||
| 315 | |||
| 316 | 30 | uint64_t ResolveHlogMemoryBytesForOptions( | |
| 317 | uint64_t capacity, | ||
| 318 | size_t value_size, | ||
| 319 | const FasterKVBackendOptions& options) { | ||
| 320 | 30 | constexpr uint64_t kPageSize = 32ULL << 20; | |
| 321 | 30 | const uint64_t min_log_size = kPageSize * 6; | |
| 322 | 30 | uint64_t log_size = options.hlog_memory_bytes; | |
| 323 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 4 times.
|
30 | if (log_size == 0) { |
| 324 | 26 | log_size = options.storage == FasterKVStorage::kSsd | |
| 325 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
|
26 | ? min_log_size |
| 326 | 24 | : ComputeLogSize(capacity, value_size); | |
| 327 | } | ||
| 328 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
|
30 | if (log_size < kPageSize * 6) { |
| 329 | ✗ | log_size = min_log_size; | |
| 330 | } | ||
| 331 | 30 | return NextPowerOfTwo(log_size); | |
| 332 | } | ||
| 333 | |||
| 334 | namespace { | ||
| 335 | |||
| 336 | ✗ | uint64_t ResolveReadCacheSize(uint64_t read_cache_bytes) { | |
| 337 | ✗ | constexpr uint64_t kPageSize = 32ULL << 20; | |
| 338 | ✗ | return NextPowerOfTwo(std::max(read_cache_bytes, kPageSize * 6)); | |
| 339 | } | ||
| 340 | |||
| 341 | 30 | double ResolveMutableFraction(const FasterKVBackendOptions& options) { | |
| 342 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 26 times.
|
30 | if (options.mutable_fraction < 0.0 || options.mutable_fraction > 1.0) { |
| 343 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | throw std::invalid_argument("FasterKV mutable_fraction must be in [0, 1]"); |
| 344 | } | ||
| 345 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 24 times.
|
26 | if (options.mutable_fraction > 0.0) { |
| 346 | 2 | return options.mutable_fraction; | |
| 347 | } | ||
| 348 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
|
24 | return options.storage == FasterKVStorage::kSsd ? 0.5 : 1.0; |
| 349 | } | ||
| 350 | |||
| 351 | template <typename Store> | ||
| 352 | 250 | void CompletePendingOrThrow(Store& store, const char* operation) { | |
| 353 |
2/4void recstore::storage::fasterkv::(anonymous namespace)::CompletePendingOrThrow<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >(FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> >&, char const*):
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
void recstore::storage::fasterkv::(anonymous namespace)::CompletePendingOrThrow<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >(FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> >&, char const*):
✗ Branch 1 not taken.
✓ Branch 2 taken 244 times.
|
250 | if (!store.CompletePending(true)) { |
| 354 | ✗ | throw std::runtime_error(std::string(operation) + | |
| 355 | " failed: pending operations did not complete"); | ||
| 356 | } | ||
| 357 | 250 | } | |
| 358 | |||
| 359 | template <typename Store> | ||
| 360 | class FasterStoreAdapter { | ||
| 361 | public: | ||
| 362 | 26 | FasterStoreAdapter(std::unique_ptr<Store> store, size_t value_size) | |
| 363 | 26 | : value_size_(value_size), store_(std::move(store)) {} | |
| 364 | |||
| 365 | 26 | ~FasterStoreAdapter() { StopThreadSessionIfNeeded(); } | |
| 366 | |||
| 367 | 250 | void Insert(size_t num_keys, const long long* keys, const char* values) { | |
| 368 |
2/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::Insert(unsigned long, long long const*, char const*):
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::Insert(unsigned long, long long const*, char const*):
✓ Branch 1 taken 244 times.
✗ Branch 2 not taken.
|
250 | EnsureThreadSession(); |
| 369 | auto callback = [](IAsyncContext*, Status status) { | ||
| 370 | CheckStatus(status, "FasterKV::Upsert async"); | ||
| 371 | }; | ||
| 372 | |||
| 373 |
6/8recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::Insert(unsigned long, long long const*, char const*):
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 6 times.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::Insert(unsigned long, long long const*, char const*):
✓ Branch 1 taken 350 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 350 times.
✓ Branch 4 taken 244 times.
|
974 | for (size_t i = 0; i < num_keys; ++i) { |
| 374 | 362 | UpsertContext context{static_cast<uint64_t>(keys[i]), | |
| 375 | 362 | values + i * value_size_, | |
| 376 | 362 | static_cast<uint32_t>(value_size_)}; | |
| 377 | const Status status = | ||
| 378 |
2/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::Insert(unsigned long, long long const*, char const*):
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::Insert(unsigned long, long long const*, char const*):
✓ Branch 4 taken 350 times.
✗ Branch 5 not taken.
|
362 | store_->Upsert(context, callback, NextSerialNumber()); |
| 379 |
2/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::Insert(unsigned long, long long const*, char const*):
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::Insert(unsigned long, long long const*, char const*):
✗ Branch 0 not taken.
✓ Branch 1 taken 350 times.
|
362 | if (status == Status::Pending) { |
| 380 | ✗ | continue; | |
| 381 | } | ||
| 382 |
2/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::Insert(unsigned long, long long const*, char const*):
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::Insert(unsigned long, long long const*, char const*):
✓ Branch 1 taken 350 times.
✗ Branch 2 not taken.
|
362 | CheckStatus(status, "FasterKV::Upsert"); |
| 383 | } | ||
| 384 |
2/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::Insert(unsigned long, long long const*, char const*):
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::Insert(unsigned long, long long const*, char const*):
✓ Branch 2 taken 244 times.
✗ Branch 3 not taken.
|
250 | CompletePendingOrThrow(*store_, "FasterKV::Upsert"); |
| 385 | 250 | } | |
| 386 | |||
| 387 | 332 | void Fetch(size_t num_keys, | |
| 388 | const long long* keys, | ||
| 389 | char* values, | ||
| 390 | const FasterKVBackend::MissCallback& on_miss) { | ||
| 391 | 332 | EnsureThreadSession(); | |
| 392 |
8/8recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::Fetch(unsigned long, long long const*, char*, std::function<void (unsigned long)> const&):
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 8 times.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::Fetch(unsigned long, long long const*, char*, std::function<void (unsigned long)> const&):
✓ Branch 1 taken 440 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 448 times.
✓ Branch 4 taken 324 times.
|
1260 | for (size_t i = 0; i < num_keys; ++i) { |
| 393 | auto callback = [](IAsyncContext* context, Status status) { | ||
| 394 | CallbackContext<ReadContext> read_context{context}; | ||
| 395 | if (status == Status::NotFound) { | ||
| 396 | read_context->NotifyMiss(); | ||
| 397 | return; | ||
| 398 | } | ||
| 399 | CheckStatus(status, "FasterKV::Read async"); | ||
| 400 | if (!read_context->found()) { | ||
| 401 | throw std::runtime_error("FasterKV::Read async returned no value"); | ||
| 402 | } | ||
| 403 | }; | ||
| 404 | |||
| 405 | 464 | ReadContext context{ | |
| 406 | 464 | static_cast<uint64_t>(keys[i]), | |
| 407 | 464 | values + i * value_size_, | |
| 408 | 464 | static_cast<uint32_t>(value_size_), | |
| 409 | i, | ||
| 410 | &on_miss}; | ||
| 411 |
2/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::Fetch(unsigned long, long long const*, char*, std::function<void (unsigned long)> const&):
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::Fetch(unsigned long, long long const*, char*, std::function<void (unsigned long)> const&):
✓ Branch 4 taken 448 times.
✗ Branch 5 not taken.
|
464 | const Status status = store_->Read(context, callback, NextSerialNumber()); |
| 412 |
4/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::Fetch(unsigned long, long long const*, char*, std::function<void (unsigned long)> const&):
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12 times.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::Fetch(unsigned long, long long const*, char*, std::function<void (unsigned long)> const&):
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 440 times.
|
464 | if (status == Status::NotFound) { |
| 413 |
2/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::Fetch(unsigned long, long long const*, char*, std::function<void (unsigned long)> const&):
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::Fetch(unsigned long, long long const*, char*, std::function<void (unsigned long)> const&):
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
12 | context.NotifyMiss(); |
| 414 | 12 | continue; | |
| 415 | } | ||
| 416 |
2/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::Fetch(unsigned long, long long const*, char*, std::function<void (unsigned long)> const&):
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::Fetch(unsigned long, long long const*, char*, std::function<void (unsigned long)> const&):
✗ Branch 0 not taken.
✓ Branch 1 taken 440 times.
|
452 | if (status == Status::Pending) { |
| 417 | ✗ | CompletePendingOrThrow(*store_, "FasterKV::Read"); | |
| 418 | ✗ | continue; | |
| 419 | } | ||
| 420 |
2/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::Fetch(unsigned long, long long const*, char*, std::function<void (unsigned long)> const&):
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::Fetch(unsigned long, long long const*, char*, std::function<void (unsigned long)> const&):
✓ Branch 1 taken 440 times.
✗ Branch 2 not taken.
|
452 | CheckStatus(status, "FasterKV::Read"); |
| 421 |
2/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::Fetch(unsigned long, long long const*, char*, std::function<void (unsigned long)> const&):
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::Fetch(unsigned long, long long const*, char*, std::function<void (unsigned long)> const&):
✗ Branch 1 not taken.
✓ Branch 2 taken 440 times.
|
452 | if (!context.found()) { |
| 422 | ✗ | throw std::runtime_error("FasterKV::Read returned Ok without value"); | |
| 423 | } | ||
| 424 | } | ||
| 425 | 332 | } | |
| 426 | |||
| 427 | private: | ||
| 428 | 582 | void EnsureThreadSession() { | |
| 429 |
4/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::EnsureThreadSession():
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 4 times.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::EnsureThreadSession():
✓ Branch 1 taken 546 times.
✓ Branch 2 taken 22 times.
|
582 | if (session_.owner == this) { |
| 430 | 556 | return; | |
| 431 | } | ||
| 432 |
2/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::EnsureThreadSession():
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::EnsureThreadSession():
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
|
26 | if (session_.owner != nullptr) { |
| 433 | ✗ | throw std::runtime_error("Thread already owns a FasterKVBackend session"); | |
| 434 | } | ||
| 435 |
2/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::EnsureThreadSession():
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::EnsureThreadSession():
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
|
26 | store_->StartSession(); |
| 436 | 26 | session_.owner = this; | |
| 437 | } | ||
| 438 | |||
| 439 | 26 | void StopThreadSessionIfNeeded() { | |
| 440 |
2/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::StopThreadSessionIfNeeded():
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::StopThreadSessionIfNeeded():
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
26 | if (session_.owner == this) { |
| 441 | 26 | store_->StopSession(); | |
| 442 | 26 | session_.owner = nullptr; | |
| 443 | } | ||
| 444 | 26 | } | |
| 445 | |||
| 446 | ✗ | void StopSessionFromThreadExit() { | |
| 447 | ✗ | store_->StopSession(); | |
| 448 | ✗ | session_.owner = nullptr; | |
| 449 | ✗ | } | |
| 450 | |||
| 451 | 1652 | uint64_t NextSerialNumber() { return serial_number_.fetch_add(1) + 1; } | |
| 452 | |||
| 453 | struct ThreadSession { | ||
| 454 | FasterStoreAdapter* owner = nullptr; | ||
| 455 | |||
| 456 | 12 | ~ThreadSession() { | |
| 457 |
2/4recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::FileSystemDisk<FASTER::environment::QueueIoHandler, 1073741824ul>, FASTER::index::HotLogHashIndexDefinition> > >::ThreadSession::~ThreadSession():
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
recstore::storage::fasterkv::(anonymous namespace)::FasterStoreAdapter<FASTER::core::FasterKv<recstore::storage::fasterkv::(anonymous namespace)::UInt64Key, recstore::storage::fasterkv::(anonymous namespace)::VariableValue, FASTER::device::NullDisk, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition>, FASTER::index::MemHashIndex<FASTER::device::NullDisk, FASTER::index::HotLogHashIndexDefinition> > >::ThreadSession::~ThreadSession():
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
12 | if (owner != nullptr) { |
| 458 | ✗ | owner->StopSessionFromThreadExit(); | |
| 459 | } | ||
| 460 | 12 | } | |
| 461 | }; | ||
| 462 | |||
| 463 | size_t value_size_; | ||
| 464 | std::unique_ptr<Store> store_; | ||
| 465 | std::atomic<uint64_t> serial_number_{0}; | ||
| 466 | |||
| 467 | static thread_local ThreadSession session_; | ||
| 468 | }; | ||
| 469 | |||
| 470 | template <typename Store> | ||
| 471 | thread_local typename FasterStoreAdapter<Store>::ThreadSession | ||
| 472 | FasterStoreAdapter<Store>::session_; | ||
| 473 | |||
| 474 | class IFasterStore { | ||
| 475 | public: | ||
| 476 | 26 | virtual ~IFasterStore() = default; | |
| 477 | virtual void | ||
| 478 | Insert(size_t num_keys, const long long* keys, const char* values) = 0; | ||
| 479 | virtual void Fetch(size_t num_keys, | ||
| 480 | const long long* keys, | ||
| 481 | char* values, | ||
| 482 | const FasterKVBackend::MissCallback& on_miss) = 0; | ||
| 483 | }; | ||
| 484 | |||
| 485 | template <typename Store> | ||
| 486 | class FasterStoreHolder final : public IFasterStore { | ||
| 487 | public: | ||
| 488 | 26 | FasterStoreHolder(std::unique_ptr<Store> store, size_t value_size) | |
| 489 | 26 | : adapter_(std::move(store), value_size) {} | |
| 490 | |||
| 491 | void | ||
| 492 | 250 | Insert(size_t num_keys, const long long* keys, const char* values) override { | |
| 493 | 250 | adapter_.Insert(num_keys, keys, values); | |
| 494 | 250 | } | |
| 495 | |||
| 496 | 332 | void Fetch(size_t num_keys, | |
| 497 | const long long* keys, | ||
| 498 | char* values, | ||
| 499 | const FasterKVBackend::MissCallback& on_miss) override { | ||
| 500 | 332 | adapter_.Fetch(num_keys, keys, values, on_miss); | |
| 501 | 332 | } | |
| 502 | |||
| 503 | private: | ||
| 504 | FasterStoreAdapter<Store> adapter_; | ||
| 505 | }; | ||
| 506 | |||
| 507 | FASTER::core::ReadCacheConfig | ||
| 508 | 30 | BuildReadCacheConfig(const FasterKVBackendOptions& options) { | |
| 509 |
1/2✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
|
30 | if (options.read_cache_bytes == 0) { |
| 510 | 30 | return FASTER::core::DEFAULT_READ_CACHE_CONFIG; | |
| 511 | } | ||
| 512 | return FASTER::core::ReadCacheConfig{ | ||
| 513 | ✗ | .mem_size = ResolveReadCacheSize(options.read_cache_bytes), | |
| 514 | .mutable_fraction = 0.5, | ||
| 515 | .pre_allocate = false, | ||
| 516 | ✗ | .enabled = true}; | |
| 517 | } | ||
| 518 | |||
| 519 | } // namespace | ||
| 520 | |||
| 521 | class FasterKVBackend::Impl { | ||
| 522 | public: | ||
| 523 | 32 | Impl(uint64_t capacity, | |
| 524 | size_t value_size, | ||
| 525 | 32 | const FasterKVBackendOptions& options) { | |
| 526 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | if (capacity == 0) { |
| 527 | ✗ | throw std::invalid_argument("FasterKVBackend capacity must be > 0"); | |
| 528 | } | ||
| 529 |
2/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
|
64 | if (value_size == 0 || |
| 530 | 32 | value_size > | |
| 531 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
|
32 | static_cast<size_t>(std::numeric_limits<uint32_t>::max())) { |
| 532 | ✗ | throw std::invalid_argument("FasterKVBackend value_size is invalid"); | |
| 533 | } | ||
| 534 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 6 times.
|
32 | if (options.storage == FasterKVStorage::kMemory) { |
| 535 | auto store = std::make_unique<MemoryStore>( | ||
| 536 | 22 | MemoryStore::IndexConfig{ComputeHashTableSize(capacity)}, | |
| 537 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | ResolveLogSize(capacity, value_size, options), |
| 538 | "", | ||
| 539 |
3/4✓ Branch 1 taken 22 times.
✓ Branch 2 taken 4 times.
✓ Branch 4 taken 22 times.
✗ Branch 5 not taken.
|
26 | ResolveMutableFraction(options), |
| 540 |
1/2✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
|
52 | BuildReadCacheConfig(options)); |
| 541 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
44 | store_ = std::make_unique<FasterStoreHolder<MemoryStore>>( |
| 542 | 44 | std::move(store), value_size); | |
| 543 | 22 | return; | |
| 544 | 22 | } | |
| 545 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
|
6 | if (options.log_path.empty()) { |
| 546 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | throw std::invalid_argument("FasterKV SSD storage requires log_path"); |
| 547 | } | ||
| 548 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | std::filesystem::create_directories(options.log_path); |
| 549 | auto store = std::make_unique<SsdStore>( | ||
| 550 | 4 | SsdStore::IndexConfig{ComputeHashTableSize(capacity)}, | |
| 551 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | ResolveLogSize(capacity, value_size, options), |
| 552 | 4 | options.log_path, | |
| 553 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | ResolveMutableFraction(options), |
| 554 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
8 | BuildReadCacheConfig(options)); |
| 555 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
8 | store_ = std::make_unique<FasterStoreHolder<SsdStore>>( |
| 556 | 8 | std::move(store), value_size); | |
| 557 | 10 | } | |
| 558 | |||
| 559 | 250 | void Insert(size_t num_keys, const long long* keys, const char* values) { | |
| 560 | 250 | store_->Insert(num_keys, keys, values); | |
| 561 | 250 | } | |
| 562 | |||
| 563 | 332 | void Fetch(size_t num_keys, | |
| 564 | const long long* keys, | ||
| 565 | char* values, | ||
| 566 | const MissCallback& on_miss) { | ||
| 567 | 332 | store_->Fetch(num_keys, keys, values, on_miss); | |
| 568 | 332 | } | |
| 569 | |||
| 570 | private: | ||
| 571 | std::unique_ptr<IFasterStore> store_; | ||
| 572 | }; | ||
| 573 | |||
| 574 | 4 | FasterKVBackend::FasterKVBackend(uint64_t capacity, size_t value_size) | |
| 575 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | : FasterKVBackend(capacity, value_size, FasterKVBackendOptions{}) {} |
| 576 | |||
| 577 | 32 | FasterKVBackend::FasterKVBackend( | |
| 578 | 32 | uint64_t capacity, size_t value_size, const FasterKVBackendOptions& options) | |
| 579 | 32 | : impl_(std::make_unique<Impl>(capacity, value_size, options)) {} | |
| 580 | |||
| 581 | 26 | FasterKVBackend::~FasterKVBackend() = default; | |
| 582 | |||
| 583 | 250 | void FasterKVBackend::Insert( | |
| 584 | size_t num_keys, const long long* keys, const char* values) { | ||
| 585 | 250 | impl_->Insert(num_keys, keys, values); | |
| 586 | 250 | } | |
| 587 | |||
| 588 | 332 | void FasterKVBackend::Fetch(size_t num_keys, | |
| 589 | const long long* keys, | ||
| 590 | char* values, | ||
| 591 | const MissCallback& on_miss) { | ||
| 592 | 332 | impl_->Fetch(num_keys, keys, values, on_miss); | |
| 593 | 332 | } | |
| 594 | |||
| 595 | } // namespace recstore::storage::fasterkv | ||
| 596 |