@nxtedition/rocksdb 8.1.17 → 8.2.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding.cc +32 -2
- package/binding.gyp +8 -0
- package/deps/liburing/liburing.gyp +20 -0
- package/deps/rocksdb/rocksdb/CMakeLists.txt +4 -0
- package/deps/rocksdb/rocksdb/TARGETS +7 -0
- package/deps/rocksdb/rocksdb/cache/cache.cc +43 -0
- package/deps/rocksdb/rocksdb/cache/cache_bench_tool.cc +8 -5
- package/deps/rocksdb/rocksdb/cache/cache_entry_stats.h +1 -1
- package/deps/rocksdb/rocksdb/cache/cache_reservation_manager.cc +1 -1
- package/deps/rocksdb/rocksdb/cache/cache_test.cc +12 -48
- package/deps/rocksdb/rocksdb/cache/charged_cache.cc +26 -18
- package/deps/rocksdb/rocksdb/cache/charged_cache.h +5 -62
- package/deps/rocksdb/rocksdb/cache/clock_cache.cc +119 -44
- package/deps/rocksdb/rocksdb/cache/clock_cache.h +34 -29
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.cc +3 -3
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.h +2 -2
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache_test.cc +148 -209
- package/deps/rocksdb/rocksdb/cache/lru_cache.cc +118 -284
- package/deps/rocksdb/rocksdb/cache/lru_cache.h +23 -71
- package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +351 -392
- package/deps/rocksdb/rocksdb/cache/secondary_cache.cc +5 -2
- package/deps/rocksdb/rocksdb/cache/secondary_cache_adapter.cc +296 -0
- package/deps/rocksdb/rocksdb/cache/secondary_cache_adapter.h +52 -0
- package/deps/rocksdb/rocksdb/cache/sharded_cache.h +22 -19
- package/deps/rocksdb/rocksdb/cache/typed_cache.h +56 -20
- package/deps/rocksdb/rocksdb/db/arena_wrapped_db_iter.cc +3 -0
- package/deps/rocksdb/rocksdb/db/blob/blob_counting_iterator.h +4 -0
- package/deps/rocksdb/rocksdb/db/blob/blob_source.cc +3 -3
- package/deps/rocksdb/rocksdb/db/blob/blob_source_test.cc +19 -25
- package/deps/rocksdb/rocksdb/db/blob/db_blob_basic_test.cc +216 -0
- package/deps/rocksdb/rocksdb/db/c.cc +90 -1
- package/deps/rocksdb/rocksdb/db/column_family.cc +8 -7
- package/deps/rocksdb/rocksdb/db/column_family.h +0 -6
- package/deps/rocksdb/rocksdb/db/compaction/clipping_iterator.h +5 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +24 -7
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +17 -1
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +18 -12
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +3 -1
- package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +245 -302
- package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +13 -2
- package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.h +5 -0
- package/deps/rocksdb/rocksdb/db/db_basic_test.cc +75 -15
- package/deps/rocksdb/rocksdb/db/db_block_cache_test.cc +2 -3
- package/deps/rocksdb/rocksdb/db/db_filesnapshot.cc +1 -5
- package/deps/rocksdb/rocksdb/db/db_flush_test.cc +91 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +5 -12
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +16 -4
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +47 -24
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_debug.cc +4 -2
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +1 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_write.cc +32 -3
- package/deps/rocksdb/rocksdb/db/db_iter.cc +28 -29
- package/deps/rocksdb/rocksdb/db/db_iter.h +0 -3
- package/deps/rocksdb/rocksdb/db/db_properties_test.cc +176 -0
- package/deps/rocksdb/rocksdb/db/db_range_del_test.cc +391 -2
- package/deps/rocksdb/rocksdb/db/db_with_timestamp_basic_test.cc +26 -0
- package/deps/rocksdb/rocksdb/db/db_write_test.cc +13 -5
- package/deps/rocksdb/rocksdb/db/dbformat.h +3 -1
- package/deps/rocksdb/rocksdb/db/error_handler_fs_test.cc +0 -1
- package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +0 -6
- package/deps/rocksdb/rocksdb/db/forward_iterator.cc +3 -0
- package/deps/rocksdb/rocksdb/db/forward_iterator.h +1 -1
- package/deps/rocksdb/rocksdb/db/history_trimming_iterator.h +4 -0
- package/deps/rocksdb/rocksdb/db/import_column_family_job.cc +68 -40
- package/deps/rocksdb/rocksdb/db/import_column_family_job.h +3 -3
- package/deps/rocksdb/rocksdb/db/import_column_family_test.cc +115 -0
- package/deps/rocksdb/rocksdb/db/internal_stats.cc +169 -72
- package/deps/rocksdb/rocksdb/db/internal_stats.h +36 -7
- package/deps/rocksdb/rocksdb/db/memtable.cc +6 -4
- package/deps/rocksdb/rocksdb/db/merge_helper.cc +4 -0
- package/deps/rocksdb/rocksdb/db/perf_context_test.cc +151 -0
- package/deps/rocksdb/rocksdb/db/range_del_aggregator.cc +47 -16
- package/deps/rocksdb/rocksdb/db/range_del_aggregator.h +10 -8
- package/deps/rocksdb/rocksdb/db/range_del_aggregator_test.cc +91 -93
- package/deps/rocksdb/rocksdb/db/range_tombstone_fragmenter.h +1 -2
- package/deps/rocksdb/rocksdb/db/version_edit_handler.cc +1 -1
- package/deps/rocksdb/rocksdb/db/version_set.cc +30 -14
- package/deps/rocksdb/rocksdb/db/version_set.h +1 -0
- package/deps/rocksdb/rocksdb/db/write_stall_stats.cc +179 -0
- package/deps/rocksdb/rocksdb/db/write_stall_stats.h +47 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/batched_ops_stress.cc +109 -7
- package/deps/rocksdb/rocksdb/db_stress_tool/cf_consistency_stress.cc +147 -12
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.cc +31 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +22 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +4 -1
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +42 -59
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.h +7 -4
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_tool.cc +7 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/expected_state.cc +6 -10
- package/deps/rocksdb/rocksdb/db_stress_tool/multi_ops_txns_stress.cc +6 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/multi_ops_txns_stress.h +4 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/no_batched_ops_stress.cc +127 -36
- package/deps/rocksdb/rocksdb/env/fs_posix.cc +8 -0
- package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.cc +35 -0
- package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.h +29 -8
- package/deps/rocksdb/rocksdb/file/file_util.cc +14 -10
- package/deps/rocksdb/rocksdb/file/prefetch_test.cc +183 -63
- package/deps/rocksdb/rocksdb/include/rocksdb/advanced_cache.h +159 -66
- package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +3 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/c.h +52 -5
- package/deps/rocksdb/rocksdb/include/rocksdb/cache.h +3 -3
- package/deps/rocksdb/rocksdb/include/rocksdb/compaction_filter.h +134 -73
- package/deps/rocksdb/rocksdb/include/rocksdb/db.h +46 -3
- package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +6 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/listener.h +0 -6
- package/deps/rocksdb/rocksdb/include/rocksdb/metadata.h +7 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/options.h +2 -2
- package/deps/rocksdb/rocksdb/include/rocksdb/perf_context.h +6 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/secondary_cache.h +3 -3
- package/deps/rocksdb/rocksdb/include/rocksdb/statistics.h +18 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/types.h +28 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/version.h +2 -2
- package/deps/rocksdb/rocksdb/include/rocksdb/wide_columns.h +39 -0
- package/deps/rocksdb/rocksdb/monitoring/perf_context.cc +5 -0
- package/deps/rocksdb/rocksdb/monitoring/statistics.cc +9 -1
- package/deps/rocksdb/rocksdb/options/customizable_test.cc +2 -2
- package/deps/rocksdb/rocksdb/port/stack_trace.cc +17 -7
- package/deps/rocksdb/rocksdb/port/win/env_win.h +1 -0
- package/deps/rocksdb/rocksdb/src.mk +4 -0
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +38 -34
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +11 -12
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_impl.h +5 -5
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +126 -132
- package/deps/rocksdb/rocksdb/table/block_based/block_cache.cc +16 -16
- package/deps/rocksdb/rocksdb/table/block_based/cachable_entry.h +0 -16
- package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.cc +1 -1
- package/deps/rocksdb/rocksdb/table/block_based/index_reader_common.cc +1 -1
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +3 -4
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_index_reader.cc +1 -1
- package/deps/rocksdb/rocksdb/table/block_based/uncompression_dict_reader.cc +1 -1
- package/deps/rocksdb/rocksdb/table/compaction_merging_iterator.cc +370 -0
- package/deps/rocksdb/rocksdb/table/compaction_merging_iterator.h +44 -0
- package/deps/rocksdb/rocksdb/table/get_context.cc +4 -2
- package/deps/rocksdb/rocksdb/table/merging_iterator.cc +555 -267
- package/deps/rocksdb/rocksdb/table/merging_iterator.h +10 -5
- package/deps/rocksdb/rocksdb/table/table_test.cc +113 -70
- package/deps/rocksdb/rocksdb/test_util/secondary_cache_test_util.cc +96 -0
- package/deps/rocksdb/rocksdb/test_util/secondary_cache_test_util.h +117 -0
- package/deps/rocksdb/rocksdb/utilities/checkpoint/checkpoint_impl.cc +5 -3
- package/deps/rocksdb/rocksdb/utilities/fault_injection_secondary_cache.cc +3 -3
- package/deps/rocksdb/rocksdb/utilities/fault_injection_secondary_cache.h +1 -1
- package/deps/rocksdb/rocksdb/utilities/simulator_cache/sim_cache.cc +9 -2
- package/deps/rocksdb/rocksdb/utilities/ttl/db_ttl_impl.cc +5 -1
- package/deps/rocksdb/rocksdb/utilities/ttl/ttl_test.cc +11 -0
- package/deps/rocksdb/rocksdb.gyp +7 -1
- package/package.json +1 -1
- package/prebuilds/linux-x64/node.napi.node +0 -0
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
#include <cstdio>
|
|
15
15
|
#include <cstdlib>
|
|
16
16
|
|
|
17
|
+
#include "cache/secondary_cache_adapter.h"
|
|
17
18
|
#include "monitoring/perf_context_imp.h"
|
|
18
19
|
#include "monitoring/statistics.h"
|
|
19
20
|
#include "port/lang.h"
|
|
@@ -22,14 +23,6 @@
|
|
|
22
23
|
namespace ROCKSDB_NAMESPACE {
|
|
23
24
|
namespace lru_cache {
|
|
24
25
|
|
|
25
|
-
namespace {
|
|
26
|
-
// A distinct pointer value for marking "dummy" cache entries
|
|
27
|
-
struct DummyValue {
|
|
28
|
-
char val[12] = "kDummyValue";
|
|
29
|
-
};
|
|
30
|
-
DummyValue kDummyValue{};
|
|
31
|
-
} // namespace
|
|
32
|
-
|
|
33
26
|
LRUHandleTable::LRUHandleTable(int max_upper_hash_bits,
|
|
34
27
|
MemoryAllocator* allocator)
|
|
35
28
|
: length_bits_(/* historical starting size*/ 4),
|
|
@@ -103,7 +96,7 @@ void LRUHandleTable::Resize() {
|
|
|
103
96
|
std::unique_ptr<LRUHandle* []> new_list {
|
|
104
97
|
new LRUHandle* [size_t{1} << new_length_bits] {}
|
|
105
98
|
};
|
|
106
|
-
uint32_t count = 0;
|
|
99
|
+
[[maybe_unused]] uint32_t count = 0;
|
|
107
100
|
for (uint32_t i = 0; i < old_length; i++) {
|
|
108
101
|
LRUHandle* h = list_[i];
|
|
109
102
|
while (h != nullptr) {
|
|
@@ -127,7 +120,7 @@ LRUCacheShard::LRUCacheShard(size_t capacity, bool strict_capacity_limit,
|
|
|
127
120
|
CacheMetadataChargePolicy metadata_charge_policy,
|
|
128
121
|
int max_upper_hash_bits,
|
|
129
122
|
MemoryAllocator* allocator,
|
|
130
|
-
|
|
123
|
+
const Cache::EvictionCallback* eviction_callback)
|
|
131
124
|
: CacheShardBase(metadata_charge_policy),
|
|
132
125
|
capacity_(0),
|
|
133
126
|
high_pri_pool_usage_(0),
|
|
@@ -141,7 +134,7 @@ LRUCacheShard::LRUCacheShard(size_t capacity, bool strict_capacity_limit,
|
|
|
141
134
|
usage_(0),
|
|
142
135
|
lru_usage_(0),
|
|
143
136
|
mutex_(use_adaptive_mutex),
|
|
144
|
-
|
|
137
|
+
eviction_callback_(*eviction_callback) {
|
|
145
138
|
// Make empty circular linked list.
|
|
146
139
|
lru_.next = &lru_;
|
|
147
140
|
lru_.prev = &lru_;
|
|
@@ -341,16 +334,19 @@ void LRUCacheShard::EvictFromLRU(size_t charge,
|
|
|
341
334
|
}
|
|
342
335
|
}
|
|
343
336
|
|
|
344
|
-
void LRUCacheShard::
|
|
345
|
-
autovector<LRUHandle
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
337
|
+
void LRUCacheShard::NotifyEvicted(
|
|
338
|
+
const autovector<LRUHandle*>& evicted_handles) {
|
|
339
|
+
MemoryAllocator* alloc = table_.GetAllocator();
|
|
340
|
+
for (LRUHandle* entry : evicted_handles) {
|
|
341
|
+
if (eviction_callback_ &&
|
|
342
|
+
eviction_callback_(entry->key(),
|
|
343
|
+
reinterpret_cast<Cache::Handle*>(entry))) {
|
|
344
|
+
// Callback took ownership of obj; just free handle
|
|
345
|
+
free(entry);
|
|
346
|
+
} else {
|
|
347
|
+
// Free the entries here outside of mutex for performance reasons.
|
|
348
|
+
entry->Free(alloc);
|
|
351
349
|
}
|
|
352
|
-
// Free the entries here outside of mutex for performance reasons.
|
|
353
|
-
entry->Free(table_.GetAllocator());
|
|
354
350
|
}
|
|
355
351
|
}
|
|
356
352
|
|
|
@@ -364,7 +360,7 @@ void LRUCacheShard::SetCapacity(size_t capacity) {
|
|
|
364
360
|
EvictFromLRU(0, &last_reference_list);
|
|
365
361
|
}
|
|
366
362
|
|
|
367
|
-
|
|
363
|
+
NotifyEvicted(last_reference_list);
|
|
368
364
|
}
|
|
369
365
|
|
|
370
366
|
void LRUCacheShard::SetStrictCapacityLimit(bool strict_capacity_limit) {
|
|
@@ -372,8 +368,7 @@ void LRUCacheShard::SetStrictCapacityLimit(bool strict_capacity_limit) {
|
|
|
372
368
|
strict_capacity_limit_ = strict_capacity_limit;
|
|
373
369
|
}
|
|
374
370
|
|
|
375
|
-
Status LRUCacheShard::InsertItem(LRUHandle* e, LRUHandle** handle
|
|
376
|
-
bool free_handle_on_fail) {
|
|
371
|
+
Status LRUCacheShard::InsertItem(LRUHandle* e, LRUHandle** handle) {
|
|
377
372
|
Status s = Status::OK();
|
|
378
373
|
autovector<LRUHandle*> last_reference_list;
|
|
379
374
|
|
|
@@ -392,10 +387,9 @@ Status LRUCacheShard::InsertItem(LRUHandle* e, LRUHandle** handle,
|
|
|
392
387
|
// into cache and get evicted immediately.
|
|
393
388
|
last_reference_list.push_back(e);
|
|
394
389
|
} else {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
}
|
|
390
|
+
free(e);
|
|
391
|
+
e = nullptr;
|
|
392
|
+
*handle = nullptr;
|
|
399
393
|
s = Status::MemoryLimit("Insert failed due to LRU cache being full.");
|
|
400
394
|
}
|
|
401
395
|
} else {
|
|
@@ -427,185 +421,27 @@ Status LRUCacheShard::InsertItem(LRUHandle* e, LRUHandle** handle,
|
|
|
427
421
|
}
|
|
428
422
|
}
|
|
429
423
|
|
|
430
|
-
|
|
424
|
+
NotifyEvicted(last_reference_list);
|
|
431
425
|
|
|
432
426
|
return s;
|
|
433
427
|
}
|
|
434
428
|
|
|
435
|
-
void LRUCacheShard::Promote(LRUHandle* e) {
|
|
436
|
-
SecondaryCacheResultHandle* secondary_handle = e->sec_handle;
|
|
437
|
-
|
|
438
|
-
assert(secondary_handle->IsReady());
|
|
439
|
-
// e is not thread-shared here; OK to modify "immutable" fields as well as
|
|
440
|
-
// "mutable" (normally requiring mutex)
|
|
441
|
-
e->SetIsPending(false);
|
|
442
|
-
e->value = secondary_handle->Value();
|
|
443
|
-
assert(e->total_charge == 0);
|
|
444
|
-
size_t value_size = secondary_handle->Size();
|
|
445
|
-
delete secondary_handle;
|
|
446
|
-
|
|
447
|
-
if (e->value) {
|
|
448
|
-
e->CalcTotalCharge(value_size, metadata_charge_policy_);
|
|
449
|
-
Status s;
|
|
450
|
-
if (e->IsStandalone()) {
|
|
451
|
-
assert(secondary_cache_ && secondary_cache_->SupportForceErase());
|
|
452
|
-
|
|
453
|
-
// Insert a dummy handle and return a standalone handle to caller.
|
|
454
|
-
// Charge the standalone handle.
|
|
455
|
-
autovector<LRUHandle*> last_reference_list;
|
|
456
|
-
bool free_standalone_handle{false};
|
|
457
|
-
{
|
|
458
|
-
DMutexLock l(mutex_);
|
|
459
|
-
|
|
460
|
-
// Free the space following strict LRU policy until enough space
|
|
461
|
-
// is freed or the lru list is empty.
|
|
462
|
-
EvictFromLRU(e->total_charge, &last_reference_list);
|
|
463
|
-
|
|
464
|
-
if ((usage_ + e->total_charge) > capacity_ && strict_capacity_limit_) {
|
|
465
|
-
free_standalone_handle = true;
|
|
466
|
-
} else {
|
|
467
|
-
usage_ += e->total_charge;
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
TryInsertIntoSecondaryCache(last_reference_list);
|
|
472
|
-
if (free_standalone_handle) {
|
|
473
|
-
e->Unref();
|
|
474
|
-
e->Free(table_.GetAllocator());
|
|
475
|
-
e = nullptr;
|
|
476
|
-
} else {
|
|
477
|
-
PERF_COUNTER_ADD(block_cache_standalone_handle_count, 1);
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
// Insert a dummy handle into the primary cache. This dummy handle is
|
|
481
|
-
// not IsSecondaryCacheCompatible().
|
|
482
|
-
// FIXME? This should not overwrite an existing non-dummy entry in the
|
|
483
|
-
// rare case that one exists
|
|
484
|
-
Cache::Priority priority =
|
|
485
|
-
e->IsHighPri() ? Cache::Priority::HIGH : Cache::Priority::LOW;
|
|
486
|
-
s = Insert(e->key(), e->hash, &kDummyValue, &kNoopCacheItemHelper,
|
|
487
|
-
/*charge=*/0,
|
|
488
|
-
/*handle=*/nullptr, priority);
|
|
489
|
-
} else {
|
|
490
|
-
e->SetInCache(true);
|
|
491
|
-
LRUHandle* handle = e;
|
|
492
|
-
// This InsertItem() could fail if the cache is over capacity and
|
|
493
|
-
// strict_capacity_limit_ is true. In such a case, we don't want
|
|
494
|
-
// InsertItem() to free the handle, since the item is already in memory
|
|
495
|
-
// and the caller will most likely just read it from disk if we erase it
|
|
496
|
-
// here.
|
|
497
|
-
s = InsertItem(e, &handle, /*free_handle_on_fail=*/false);
|
|
498
|
-
if (s.ok()) {
|
|
499
|
-
PERF_COUNTER_ADD(block_cache_real_handle_count, 1);
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
if (!s.ok()) {
|
|
504
|
-
// Item is in memory, but not accounted against the cache capacity.
|
|
505
|
-
// When the handle is released, the item should get deleted.
|
|
506
|
-
assert(!e->InCache());
|
|
507
|
-
}
|
|
508
|
-
} else {
|
|
509
|
-
// Secondary cache lookup failed. The caller will take care of detecting
|
|
510
|
-
// this and eventually releasing e.
|
|
511
|
-
assert(!e->value);
|
|
512
|
-
assert(!e->InCache());
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
|
|
516
429
|
LRUHandle* LRUCacheShard::Lookup(const Slice& key, uint32_t hash,
|
|
517
|
-
const Cache::CacheItemHelper* helper
|
|
518
|
-
Cache::CreateContext* create_context
|
|
519
|
-
Cache::Priority priority
|
|
520
|
-
Statistics* stats) {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
{
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
// For a dummy handle, if it was retrieved from secondary cache,
|
|
530
|
-
// it may still exist in secondary cache.
|
|
531
|
-
// If the handle exists in secondary cache, the value should be
|
|
532
|
-
// erased from sec cache and be inserted into primary cache.
|
|
533
|
-
found_dummy_entry = true;
|
|
534
|
-
// Let the dummy entry be overwritten
|
|
535
|
-
e = nullptr;
|
|
536
|
-
} else {
|
|
537
|
-
if (!e->HasRefs()) {
|
|
538
|
-
// The entry is in LRU since it's in hash and has no external
|
|
539
|
-
// references.
|
|
540
|
-
LRU_Remove(e);
|
|
541
|
-
}
|
|
542
|
-
e->Ref();
|
|
543
|
-
e->SetHit();
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
// If handle table lookup failed or the handle is a dummy one, allocate
|
|
549
|
-
// a handle outside the mutex if we re going to lookup in the secondary cache.
|
|
550
|
-
//
|
|
551
|
-
// When a block is firstly Lookup from CompressedSecondaryCache, we just
|
|
552
|
-
// insert a dummy block into the primary cache (charging the actual size of
|
|
553
|
-
// the block) and don't erase the block from CompressedSecondaryCache. A
|
|
554
|
-
// standalone handle is returned to the caller. Only if the block is hit
|
|
555
|
-
// again, we erase it from CompressedSecondaryCache and add it into the
|
|
556
|
-
// primary cache.
|
|
557
|
-
if (!e && secondary_cache_ && helper && helper->create_cb) {
|
|
558
|
-
bool is_in_sec_cache{false};
|
|
559
|
-
std::unique_ptr<SecondaryCacheResultHandle> secondary_handle =
|
|
560
|
-
secondary_cache_->Lookup(key, helper, create_context, wait,
|
|
561
|
-
found_dummy_entry, is_in_sec_cache);
|
|
562
|
-
if (secondary_handle != nullptr) {
|
|
563
|
-
e = static_cast<LRUHandle*>(malloc(sizeof(LRUHandle) - 1 + key.size()));
|
|
564
|
-
|
|
565
|
-
e->m_flags = 0;
|
|
566
|
-
e->im_flags = 0;
|
|
567
|
-
e->helper = helper;
|
|
568
|
-
e->key_length = key.size();
|
|
569
|
-
e->hash = hash;
|
|
570
|
-
e->refs = 0;
|
|
571
|
-
e->next = e->prev = nullptr;
|
|
572
|
-
e->SetPriority(priority);
|
|
573
|
-
memcpy(e->key_data, key.data(), key.size());
|
|
574
|
-
e->value = nullptr;
|
|
575
|
-
e->sec_handle = secondary_handle.release();
|
|
576
|
-
e->total_charge = 0;
|
|
577
|
-
e->Ref();
|
|
578
|
-
e->SetIsInSecondaryCache(is_in_sec_cache);
|
|
579
|
-
e->SetIsStandalone(secondary_cache_->SupportForceErase() &&
|
|
580
|
-
!found_dummy_entry);
|
|
581
|
-
|
|
582
|
-
if (wait) {
|
|
583
|
-
Promote(e);
|
|
584
|
-
if (e) {
|
|
585
|
-
if (!e->value) {
|
|
586
|
-
// The secondary cache returned a handle, but the lookup failed.
|
|
587
|
-
e->Unref();
|
|
588
|
-
e->Free(table_.GetAllocator());
|
|
589
|
-
e = nullptr;
|
|
590
|
-
} else {
|
|
591
|
-
PERF_COUNTER_ADD(secondary_cache_hit_count, 1);
|
|
592
|
-
RecordTick(stats, SECONDARY_CACHE_HITS);
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
} else {
|
|
596
|
-
// If wait is false, we always return a handle and let the caller
|
|
597
|
-
// release the handle after checking for success or failure.
|
|
598
|
-
e->SetIsPending(true);
|
|
599
|
-
// This may be slightly inaccurate, if the lookup eventually fails.
|
|
600
|
-
// But the probability is very low.
|
|
601
|
-
PERF_COUNTER_ADD(secondary_cache_hit_count, 1);
|
|
602
|
-
RecordTick(stats, SECONDARY_CACHE_HITS);
|
|
603
|
-
}
|
|
604
|
-
} else {
|
|
605
|
-
// Caller will most likely overwrite the dummy entry with an Insert
|
|
606
|
-
// after this Lookup fails
|
|
607
|
-
assert(e == nullptr);
|
|
430
|
+
const Cache::CacheItemHelper* /*helper*/,
|
|
431
|
+
Cache::CreateContext* /*create_context*/,
|
|
432
|
+
Cache::Priority /*priority*/,
|
|
433
|
+
Statistics* /*stats*/) {
|
|
434
|
+
DMutexLock l(mutex_);
|
|
435
|
+
LRUHandle* e = table_.Lookup(key, hash);
|
|
436
|
+
if (e != nullptr) {
|
|
437
|
+
assert(e->InCache());
|
|
438
|
+
if (!e->HasRefs()) {
|
|
439
|
+
// The entry is in LRU since it's in hash and has no external
|
|
440
|
+
// references.
|
|
441
|
+
LRU_Remove(e);
|
|
608
442
|
}
|
|
443
|
+
e->Ref();
|
|
444
|
+
e->SetHit();
|
|
609
445
|
}
|
|
610
446
|
return e;
|
|
611
447
|
}
|
|
@@ -614,8 +450,6 @@ bool LRUCacheShard::Ref(LRUHandle* e) {
|
|
|
614
450
|
DMutexLock l(mutex_);
|
|
615
451
|
// To create another reference - entry must be already externally referenced.
|
|
616
452
|
assert(e->HasRefs());
|
|
617
|
-
// Pending handles are not for sharing
|
|
618
|
-
assert(!e->IsPending());
|
|
619
453
|
e->Ref();
|
|
620
454
|
return true;
|
|
621
455
|
}
|
|
@@ -639,14 +473,13 @@ bool LRUCacheShard::Release(LRUHandle* e, bool /*useful*/,
|
|
|
639
473
|
if (e == nullptr) {
|
|
640
474
|
return false;
|
|
641
475
|
}
|
|
642
|
-
bool
|
|
643
|
-
|
|
644
|
-
// a secondary cache handle.
|
|
645
|
-
assert(!e->IsPending());
|
|
476
|
+
bool must_free;
|
|
477
|
+
bool was_in_cache;
|
|
646
478
|
{
|
|
647
479
|
DMutexLock l(mutex_);
|
|
648
|
-
|
|
649
|
-
|
|
480
|
+
must_free = e->Unref();
|
|
481
|
+
was_in_cache = e->InCache();
|
|
482
|
+
if (must_free && was_in_cache) {
|
|
650
483
|
// The item is still in cache, and nobody else holds a reference to it.
|
|
651
484
|
if (usage_ > capacity_ || erase_if_last_ref) {
|
|
652
485
|
// The LRU list must be empty since the cache is full.
|
|
@@ -657,29 +490,38 @@ bool LRUCacheShard::Release(LRUHandle* e, bool /*useful*/,
|
|
|
657
490
|
} else {
|
|
658
491
|
// Put the item back on the LRU list, and don't free it.
|
|
659
492
|
LRU_Insert(e);
|
|
660
|
-
|
|
493
|
+
must_free = false;
|
|
661
494
|
}
|
|
662
495
|
}
|
|
663
|
-
// If
|
|
664
|
-
if (
|
|
496
|
+
// If about to be freed, then decrement the cache usage.
|
|
497
|
+
if (must_free) {
|
|
665
498
|
assert(usage_ >= e->total_charge);
|
|
666
499
|
usage_ -= e->total_charge;
|
|
667
500
|
}
|
|
668
501
|
}
|
|
669
502
|
|
|
670
503
|
// Free the entry here outside of mutex for performance reasons.
|
|
671
|
-
if (
|
|
672
|
-
|
|
504
|
+
if (must_free) {
|
|
505
|
+
// Only call eviction callback if we're sure no one requested erasure
|
|
506
|
+
// FIXME: disabled because of test churn
|
|
507
|
+
if (false && was_in_cache && !erase_if_last_ref && eviction_callback_ &&
|
|
508
|
+
eviction_callback_(e->key(), reinterpret_cast<Cache::Handle*>(e))) {
|
|
509
|
+
// Callback took ownership of obj; just free handle
|
|
510
|
+
free(e);
|
|
511
|
+
} else {
|
|
512
|
+
e->Free(table_.GetAllocator());
|
|
513
|
+
}
|
|
673
514
|
}
|
|
674
|
-
return
|
|
515
|
+
return must_free;
|
|
675
516
|
}
|
|
676
517
|
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
Cache::Priority priority) {
|
|
518
|
+
LRUHandle* LRUCacheShard::CreateHandle(const Slice& key, uint32_t hash,
|
|
519
|
+
Cache::ObjectPtr value,
|
|
520
|
+
const Cache::CacheItemHelper* helper,
|
|
521
|
+
size_t charge) {
|
|
682
522
|
assert(helper);
|
|
523
|
+
// value == nullptr is reserved for indicating failure in SecondaryCache
|
|
524
|
+
assert(!(helper->IsSecondaryCacheCompatible() && value == nullptr));
|
|
683
525
|
|
|
684
526
|
// Allocate the memory here outside of the mutex.
|
|
685
527
|
// If the cache is full, we'll have to release it.
|
|
@@ -695,16 +537,53 @@ Status LRUCacheShard::Insert(const Slice& key, uint32_t hash,
|
|
|
695
537
|
e->hash = hash;
|
|
696
538
|
e->refs = 0;
|
|
697
539
|
e->next = e->prev = nullptr;
|
|
698
|
-
e->SetInCache(true);
|
|
699
|
-
e->SetPriority(priority);
|
|
700
540
|
memcpy(e->key_data, key.data(), key.size());
|
|
701
541
|
e->CalcTotalCharge(charge, metadata_charge_policy_);
|
|
702
542
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
assert(!(e->IsSecondaryCacheCompatible() && value == nullptr));
|
|
543
|
+
return e;
|
|
544
|
+
}
|
|
706
545
|
|
|
707
|
-
|
|
546
|
+
Status LRUCacheShard::Insert(const Slice& key, uint32_t hash,
|
|
547
|
+
Cache::ObjectPtr value,
|
|
548
|
+
const Cache::CacheItemHelper* helper,
|
|
549
|
+
size_t charge, LRUHandle** handle,
|
|
550
|
+
Cache::Priority priority) {
|
|
551
|
+
LRUHandle* e = CreateHandle(key, hash, value, helper, charge);
|
|
552
|
+
e->SetPriority(priority);
|
|
553
|
+
e->SetInCache(true);
|
|
554
|
+
return InsertItem(e, handle);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
LRUHandle* LRUCacheShard::CreateStandalone(const Slice& key, uint32_t hash,
|
|
558
|
+
Cache::ObjectPtr value,
|
|
559
|
+
const Cache::CacheItemHelper* helper,
|
|
560
|
+
size_t charge,
|
|
561
|
+
bool allow_uncharged) {
|
|
562
|
+
LRUHandle* e = CreateHandle(key, hash, value, helper, charge);
|
|
563
|
+
e->SetIsStandalone(true);
|
|
564
|
+
e->Ref();
|
|
565
|
+
|
|
566
|
+
autovector<LRUHandle*> last_reference_list;
|
|
567
|
+
|
|
568
|
+
{
|
|
569
|
+
DMutexLock l(mutex_);
|
|
570
|
+
|
|
571
|
+
EvictFromLRU(e->total_charge, &last_reference_list);
|
|
572
|
+
|
|
573
|
+
if (strict_capacity_limit_ && (usage_ + e->total_charge) > capacity_) {
|
|
574
|
+
if (allow_uncharged) {
|
|
575
|
+
e->total_charge = 0;
|
|
576
|
+
} else {
|
|
577
|
+
free(e);
|
|
578
|
+
e = nullptr;
|
|
579
|
+
}
|
|
580
|
+
} else {
|
|
581
|
+
usage_ += e->total_charge;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
NotifyEvicted(last_reference_list);
|
|
586
|
+
return e;
|
|
708
587
|
}
|
|
709
588
|
|
|
710
589
|
void LRUCacheShard::Erase(const Slice& key, uint32_t hash) {
|
|
@@ -733,16 +612,6 @@ void LRUCacheShard::Erase(const Slice& key, uint32_t hash) {
|
|
|
733
612
|
}
|
|
734
613
|
}
|
|
735
614
|
|
|
736
|
-
bool LRUCacheShard::IsReady(LRUHandle* e) {
|
|
737
|
-
bool ready = true;
|
|
738
|
-
if (e->IsPending()) {
|
|
739
|
-
assert(secondary_cache_);
|
|
740
|
-
assert(e->sec_handle);
|
|
741
|
-
ready = e->sec_handle->IsReady();
|
|
742
|
-
}
|
|
743
|
-
return ready;
|
|
744
|
-
}
|
|
745
|
-
|
|
746
615
|
size_t LRUCacheShard::GetUsage() const {
|
|
747
616
|
DMutexLock l(mutex_);
|
|
748
617
|
return usage_;
|
|
@@ -782,26 +651,23 @@ LRUCache::LRUCache(size_t capacity, int num_shard_bits,
|
|
|
782
651
|
double low_pri_pool_ratio,
|
|
783
652
|
std::shared_ptr<MemoryAllocator> allocator,
|
|
784
653
|
bool use_adaptive_mutex,
|
|
785
|
-
CacheMetadataChargePolicy metadata_charge_policy
|
|
786
|
-
std::shared_ptr<SecondaryCache> _secondary_cache)
|
|
654
|
+
CacheMetadataChargePolicy metadata_charge_policy)
|
|
787
655
|
: ShardedCache(capacity, num_shard_bits, strict_capacity_limit,
|
|
788
|
-
std::move(allocator))
|
|
789
|
-
secondary_cache_(std::move(_secondary_cache)) {
|
|
656
|
+
std::move(allocator)) {
|
|
790
657
|
size_t per_shard = GetPerShardCapacity();
|
|
791
|
-
SecondaryCache* secondary_cache = secondary_cache_.get();
|
|
792
658
|
MemoryAllocator* alloc = memory_allocator();
|
|
659
|
+
const EvictionCallback* eviction_callback = &eviction_callback_;
|
|
793
660
|
InitShards([=](LRUCacheShard* cs) {
|
|
794
|
-
new (cs) LRUCacheShard(
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
661
|
+
new (cs) LRUCacheShard(per_shard, strict_capacity_limit,
|
|
662
|
+
high_pri_pool_ratio, low_pri_pool_ratio,
|
|
663
|
+
use_adaptive_mutex, metadata_charge_policy,
|
|
664
|
+
/* max_upper_hash_bits */ 32 - num_shard_bits, alloc,
|
|
665
|
+
eviction_callback);
|
|
798
666
|
});
|
|
799
667
|
}
|
|
800
668
|
|
|
801
669
|
Cache::ObjectPtr LRUCache::Value(Handle* handle) {
|
|
802
670
|
auto h = reinterpret_cast<const LRUHandle*>(handle);
|
|
803
|
-
assert(!h->IsPending() || h->value == nullptr);
|
|
804
|
-
assert(h->value != &kDummyValue);
|
|
805
671
|
return h->value;
|
|
806
672
|
}
|
|
807
673
|
|
|
@@ -824,42 +690,6 @@ double LRUCache::GetHighPriPoolRatio() {
|
|
|
824
690
|
return GetShard(0).GetHighPriPoolRatio();
|
|
825
691
|
}
|
|
826
692
|
|
|
827
|
-
void LRUCache::WaitAll(std::vector<Handle*>& handles) {
|
|
828
|
-
if (secondary_cache_) {
|
|
829
|
-
std::vector<SecondaryCacheResultHandle*> sec_handles;
|
|
830
|
-
sec_handles.reserve(handles.size());
|
|
831
|
-
for (Handle* handle : handles) {
|
|
832
|
-
if (!handle) {
|
|
833
|
-
continue;
|
|
834
|
-
}
|
|
835
|
-
LRUHandle* lru_handle = reinterpret_cast<LRUHandle*>(handle);
|
|
836
|
-
if (!lru_handle->IsPending()) {
|
|
837
|
-
continue;
|
|
838
|
-
}
|
|
839
|
-
sec_handles.emplace_back(lru_handle->sec_handle);
|
|
840
|
-
}
|
|
841
|
-
secondary_cache_->WaitAll(sec_handles);
|
|
842
|
-
for (Handle* handle : handles) {
|
|
843
|
-
if (!handle) {
|
|
844
|
-
continue;
|
|
845
|
-
}
|
|
846
|
-
LRUHandle* lru_handle = reinterpret_cast<LRUHandle*>(handle);
|
|
847
|
-
if (!lru_handle->IsPending()) {
|
|
848
|
-
continue;
|
|
849
|
-
}
|
|
850
|
-
GetShard(lru_handle->hash).Promote(lru_handle);
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
void LRUCache::AppendPrintableOptions(std::string& str) const {
|
|
856
|
-
ShardedCache::AppendPrintableOptions(str); // options from shard
|
|
857
|
-
if (secondary_cache_) {
|
|
858
|
-
str.append(" secondary_cache:\n");
|
|
859
|
-
str.append(secondary_cache_->GetPrintableOptions());
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
|
|
863
693
|
} // namespace lru_cache
|
|
864
694
|
|
|
865
695
|
std::shared_ptr<Cache> NewLRUCache(
|
|
@@ -887,10 +717,14 @@ std::shared_ptr<Cache> NewLRUCache(
|
|
|
887
717
|
if (num_shard_bits < 0) {
|
|
888
718
|
num_shard_bits = GetDefaultCacheShardBits(capacity);
|
|
889
719
|
}
|
|
890
|
-
|
|
720
|
+
std::shared_ptr<Cache> cache = std::make_shared<LRUCache>(
|
|
891
721
|
capacity, num_shard_bits, strict_capacity_limit, high_pri_pool_ratio,
|
|
892
722
|
low_pri_pool_ratio, std::move(memory_allocator), use_adaptive_mutex,
|
|
893
|
-
metadata_charge_policy
|
|
723
|
+
metadata_charge_policy);
|
|
724
|
+
if (secondary_cache) {
|
|
725
|
+
cache = std::make_shared<CacheWithSecondaryAdapter>(cache, secondary_cache);
|
|
726
|
+
}
|
|
727
|
+
return cache;
|
|
894
728
|
}
|
|
895
729
|
|
|
896
730
|
std::shared_ptr<Cache> NewLRUCache(const LRUCacheOptions& cache_opts) {
|