GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 82.0% 273 / 0 / 333
Functions: 87.8% 65 / 0 / 74
Branches: 49.5% 108 / 0 / 218

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/4
void 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/4
recstore::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/8
recstore::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/4
recstore::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/4
recstore::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/4
recstore::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/4
recstore::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/8
recstore::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/4
recstore::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/4
recstore::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/4
recstore::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/4
recstore::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/4
recstore::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/4
recstore::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/4
recstore::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/4
recstore::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/4
recstore::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/4
recstore::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/4
recstore::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