@nxtedition/rocksdb 7.1.4 → 7.1.5

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.
Files changed (151) hide show
  1. package/deps/rocksdb/iostats.patch +19 -0
  2. package/deps/rocksdb/rocksdb/CMakeLists.txt +15 -1
  3. package/deps/rocksdb/rocksdb/cache/cache_test.cc +93 -58
  4. package/deps/rocksdb/rocksdb/cache/clock_cache.cc +88 -40
  5. package/deps/rocksdb/rocksdb/cache/clock_cache.h +57 -32
  6. package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.cc +103 -28
  7. package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.h +33 -1
  8. package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache_test.cc +177 -38
  9. package/deps/rocksdb/rocksdb/cache/fast_lru_cache.cc +3 -1
  10. package/deps/rocksdb/rocksdb/cache/lru_cache.cc +2 -2
  11. package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +125 -71
  12. package/deps/rocksdb/rocksdb/crash_test.mk +15 -1
  13. package/deps/rocksdb/rocksdb/db/arena_wrapped_db_iter.cc +2 -2
  14. package/deps/rocksdb/rocksdb/db/blob/blob_index.h +1 -1
  15. package/deps/rocksdb/rocksdb/db/blob/blob_log_format.cc +3 -5
  16. package/deps/rocksdb/rocksdb/db/blob/blob_log_writer.cc +25 -19
  17. package/deps/rocksdb/rocksdb/db/blob/db_blob_basic_test.cc +149 -0
  18. package/deps/rocksdb/rocksdb/db/blob/db_blob_compaction_test.cc +36 -0
  19. package/deps/rocksdb/rocksdb/db/column_family.cc +2 -15
  20. package/deps/rocksdb/rocksdb/db/column_family_test.cc +17 -4
  21. package/deps/rocksdb/rocksdb/db/compact_files_test.cc +8 -8
  22. package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +0 -7
  23. package/deps/rocksdb/rocksdb/db/compaction/compaction.h +5 -0
  24. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +50 -52
  25. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +33 -11
  26. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +41 -10
  27. package/deps/rocksdb/rocksdb/db/compaction/compaction_job_test.cc +1 -2
  28. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +143 -2
  29. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +43 -18
  30. package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +48 -65
  31. package/deps/rocksdb/rocksdb/db/corruption_test.cc +1 -0
  32. package/deps/rocksdb/rocksdb/db/db_basic_test.cc +73 -4
  33. package/deps/rocksdb/rocksdb/db/db_block_cache_test.cc +17 -8
  34. package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +71 -2
  35. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +144 -33
  36. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +18 -35
  37. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +11 -5
  38. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_experimental.cc +7 -7
  39. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +15 -8
  40. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_readonly.cc +2 -1
  41. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.cc +3 -1
  42. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_write.cc +11 -0
  43. package/deps/rocksdb/rocksdb/db/db_iter.cc +69 -11
  44. package/deps/rocksdb/rocksdb/db/db_iter.h +16 -0
  45. package/deps/rocksdb/rocksdb/db/db_memtable_test.cc +2 -1
  46. package/deps/rocksdb/rocksdb/db/db_merge_operand_test.cc +42 -0
  47. package/deps/rocksdb/rocksdb/db/db_test.cc +61 -28
  48. package/deps/rocksdb/rocksdb/db/db_test2.cc +18 -7
  49. package/deps/rocksdb/rocksdb/db/db_wal_test.cc +17 -0
  50. package/deps/rocksdb/rocksdb/db/db_with_timestamp_compaction_test.cc +61 -0
  51. package/deps/rocksdb/rocksdb/db/db_write_test.cc +130 -0
  52. package/deps/rocksdb/rocksdb/db/experimental.cc +7 -8
  53. package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +1 -2
  54. package/deps/rocksdb/rocksdb/db/flush_job.cc +11 -7
  55. package/deps/rocksdb/rocksdb/db/flush_job_test.cc +7 -1
  56. package/deps/rocksdb/rocksdb/db/forward_iterator.cc +4 -2
  57. package/deps/rocksdb/rocksdb/db/import_column_family_job.cc +1 -1
  58. package/deps/rocksdb/rocksdb/db/log_reader.cc +48 -11
  59. package/deps/rocksdb/rocksdb/db/log_reader.h +8 -2
  60. package/deps/rocksdb/rocksdb/db/log_test.cc +10 -1
  61. package/deps/rocksdb/rocksdb/db/log_writer.cc +7 -1
  62. package/deps/rocksdb/rocksdb/db/manual_compaction_test.cc +4 -4
  63. package/deps/rocksdb/rocksdb/db/memtable.cc +49 -14
  64. package/deps/rocksdb/rocksdb/db/memtable.h +60 -14
  65. package/deps/rocksdb/rocksdb/db/memtable_list.cc +14 -8
  66. package/deps/rocksdb/rocksdb/db/memtable_list_test.cc +30 -10
  67. package/deps/rocksdb/rocksdb/db/perf_context_test.cc +5 -5
  68. package/deps/rocksdb/rocksdb/db/pinned_iterators_manager.h +5 -0
  69. package/deps/rocksdb/rocksdb/db/repair.cc +2 -3
  70. package/deps/rocksdb/rocksdb/db/seqno_time_test.cc +3 -7
  71. package/deps/rocksdb/rocksdb/db/table_cache.cc +72 -0
  72. package/deps/rocksdb/rocksdb/db/table_cache.h +19 -1
  73. package/deps/rocksdb/rocksdb/db/table_cache_sync_and_async.h +8 -14
  74. package/deps/rocksdb/rocksdb/db/table_properties_collector_test.cc +2 -2
  75. package/deps/rocksdb/rocksdb/db/version_builder_test.cc +35 -64
  76. package/deps/rocksdb/rocksdb/db/version_edit.cc +3 -32
  77. package/deps/rocksdb/rocksdb/db/version_edit.h +2 -12
  78. package/deps/rocksdb/rocksdb/db/version_edit_test.cc +10 -23
  79. package/deps/rocksdb/rocksdb/db/version_set.cc +34 -10
  80. package/deps/rocksdb/rocksdb/db/version_set.h +3 -3
  81. package/deps/rocksdb/rocksdb/db/version_set_sync_and_async.h +5 -6
  82. package/deps/rocksdb/rocksdb/db/version_set_test.cc +17 -15
  83. package/deps/rocksdb/rocksdb/db/wal_manager.cc +0 -4
  84. package/deps/rocksdb/rocksdb/db/wal_manager_test.cc +2 -1
  85. package/deps/rocksdb/rocksdb/db/wide/db_wide_basic_test.cc +137 -42
  86. package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization.cc +21 -0
  87. package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization.h +1 -0
  88. package/deps/rocksdb/rocksdb/db/write_batch_test.cc +2 -1
  89. package/deps/rocksdb/rocksdb/db/write_callback_test.cc +4 -4
  90. package/deps/rocksdb/rocksdb/db/write_thread.cc +51 -46
  91. package/deps/rocksdb/rocksdb/db/write_thread.h +0 -4
  92. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +4 -0
  93. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +6 -0
  94. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +6 -0
  95. package/deps/rocksdb/rocksdb/env/env_posix.cc +1 -1
  96. package/deps/rocksdb/rocksdb/env/env_test.cc +38 -8
  97. package/deps/rocksdb/rocksdb/env/file_system.cc +20 -0
  98. package/deps/rocksdb/rocksdb/env/fs_posix.cc +2 -46
  99. package/deps/rocksdb/rocksdb/env/io_posix.cc +1 -0
  100. package/deps/rocksdb/rocksdb/file/writable_file_writer.cc +110 -5
  101. package/deps/rocksdb/rocksdb/file/writable_file_writer.h +7 -0
  102. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +14 -1
  103. package/deps/rocksdb/rocksdb/include/rocksdb/db.h +4 -0
  104. package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +1 -1
  105. package/deps/rocksdb/rocksdb/include/rocksdb/iostats_context.h +7 -0
  106. package/deps/rocksdb/rocksdb/include/rocksdb/options.h +10 -3
  107. package/deps/rocksdb/rocksdb/include/rocksdb/slice.h +3 -1
  108. package/deps/rocksdb/rocksdb/include/rocksdb/status.h +1 -1
  109. package/deps/rocksdb/rocksdb/include/rocksdb/wide_columns.h +2 -0
  110. package/deps/rocksdb/rocksdb/logging/auto_roll_logger.cc +12 -0
  111. package/deps/rocksdb/rocksdb/logging/auto_roll_logger_test.cc +9 -13
  112. package/deps/rocksdb/rocksdb/logging/env_logger.h +39 -13
  113. package/deps/rocksdb/rocksdb/memtable/inlineskiplist.h +1 -1
  114. package/deps/rocksdb/rocksdb/memtable/write_buffer_manager_test.cc +1 -1
  115. package/deps/rocksdb/rocksdb/microbench/db_basic_bench.cc +6 -0
  116. package/deps/rocksdb/rocksdb/monitoring/iostats_context_imp.h +4 -1
  117. package/deps/rocksdb/rocksdb/options/cf_options.cc +6 -3
  118. package/deps/rocksdb/rocksdb/options/cf_options.h +6 -5
  119. package/deps/rocksdb/rocksdb/options/options_helper.cc +2 -1
  120. package/deps/rocksdb/rocksdb/options/options_settable_test.cc +1 -0
  121. package/deps/rocksdb/rocksdb/options/options_test.cc +4 -2
  122. package/deps/rocksdb/rocksdb/port/util_logger.h +1 -3
  123. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +50 -8
  124. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +4 -0
  125. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +7 -0
  126. package/deps/rocksdb/rocksdb/table/block_based/block_like_traits.h +28 -10
  127. package/deps/rocksdb/rocksdb/table/block_based/data_block_hash_index_test.cc +1 -1
  128. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +5 -2
  129. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.h +1 -0
  130. package/deps/rocksdb/rocksdb/table/get_context.cc +16 -6
  131. package/deps/rocksdb/rocksdb/table/table_reader.h +9 -0
  132. package/deps/rocksdb/rocksdb/table/table_test.cc +2 -1
  133. package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +14 -1
  134. package/deps/rocksdb/rocksdb/tools/db_sanity_test.cc +5 -2
  135. package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +7 -8
  136. package/deps/rocksdb/rocksdb/tools/ldb_cmd_test.cc +6 -6
  137. package/deps/rocksdb/rocksdb/tools/reduce_levels_test.cc +1 -1
  138. package/deps/rocksdb/rocksdb/util/file_reader_writer_test.cc +2 -0
  139. package/deps/rocksdb/rocksdb/util/stderr_logger.h +13 -0
  140. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +55 -46
  141. package/deps/rocksdb/rocksdb/utilities/cassandra/cassandra_functional_test.cc +2 -1
  142. package/deps/rocksdb/rocksdb/utilities/counted_fs.cc +10 -0
  143. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_locking_test.cc +2 -2
  144. package/deps/rocksdb/rocksdb/utilities/transactions/optimistic_transaction_test.cc +2 -2
  145. package/deps/rocksdb/rocksdb/utilities/ttl/ttl_test.cc +2 -2
  146. package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index_test.cc +2 -2
  147. package/index.js +2 -2
  148. package/package.json +1 -1
  149. package/prebuilds/darwin-arm64/node.napi.node +0 -0
  150. package/prebuilds/linux-x64/node.napi.node +0 -0
  151. package/deps/rocksdb/rocksdb/logging/posix_logger.h +0 -179
@@ -0,0 +1,19 @@
1
+ diff --git a/logging/env_logger.h b/logging/env_logger.h
2
+ index b9099a834..0aa2b768a 100644
3
+ --- a/logging/env_logger.h
4
+ +++ b/logging/env_logger.h
5
+ @@ -57,12 +57,12 @@ class EnvLogger : public Logger {
6
+ // Preserve iostats not to pollute writes from user writes. We might
7
+ // need a better solution than this.
8
+ SetPerfLevel(PerfLevel::kDisable);
9
+ - iostats_context.disable_iostats = true;
10
+ + // iostats_context.disable_iostats = true;
11
+ logger.mutex_.Lock();
12
+ }
13
+ ~FileOpGuard() {
14
+ logger_.mutex_.Unlock();
15
+ - iostats_context.disable_iostats = false;
16
+ + // iostats_context.disable_iostats = false;
17
+ SetPerfLevel(prev_perf_level_);
18
+ }
19
+
@@ -1009,7 +1009,7 @@ set(ROCKSDB_PLUGIN_BUILTINS "")
1009
1009
  message(STATUS "ROCKSDB PLUGINS TO BUILD ${ROCKSDB_PLUGINS}")
1010
1010
  list(APPEND PLUGINS ${ROCKSDB_PLUGINS})
1011
1011
  foreach(PLUGIN IN LISTS PLUGINS)
1012
- set(PLUGIN_ROOT "${CMAKE_SOURCE_DIR}/plugin/${PLUGIN}/")
1012
+ set(PLUGIN_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/plugin/${PLUGIN}/")
1013
1013
  message("including rocksb plugin ${PLUGIN_ROOT}")
1014
1014
  set(PLUGINMKFILE "${PLUGIN_ROOT}${PLUGIN}.mk")
1015
1015
  if (NOT EXISTS ${PLUGINMKFILE})
@@ -1509,6 +1509,20 @@ if(WITH_BENCHMARK_TOOLS)
1509
1509
  ${ROCKSDB_LIB} ${GFLAGS_LIB})
1510
1510
  endif()
1511
1511
 
1512
+ option(WITH_TRACE_TOOLS "build with trace tools" ON)
1513
+ if(WITH_TRACE_TOOLS)
1514
+ add_executable(block_cache_trace_analyzer_tool${ARTIFACT_SUFFIX}
1515
+ tools/block_cache_analyzer/block_cache_trace_analyzer_tool.cc)
1516
+ target_link_libraries(block_cache_trace_analyzer_tool${ARTIFACT_SUFFIX}
1517
+ ${ROCKSDB_LIB} ${GFLAGS_LIB})
1518
+
1519
+ add_executable(trace_analyzer${ARTIFACT_SUFFIX}
1520
+ tools/trace_analyzer.cc)
1521
+ target_link_libraries(trace_analyzer${ARTIFACT_SUFFIX}
1522
+ ${ROCKSDB_LIB} ${GFLAGS_LIB})
1523
+
1524
+ endif()
1525
+
1512
1526
  if(WITH_CORE_TOOLS OR WITH_TOOLS)
1513
1527
  add_subdirectory(tools)
1514
1528
  add_custom_target(core_tools
@@ -23,6 +23,11 @@
23
23
  #include "util/coding.h"
24
24
  #include "util/string_util.h"
25
25
 
26
+ // FastLRUCache and ClockCache only support 16-byte keys, so some of
27
+ // the tests originally wrote for LRUCache do not work on the other caches.
28
+ // Those tests were adapted to use 16-byte keys. We kept the original ones.
29
+ // TODO: Remove the original tests if they ever become unused.
30
+
26
31
  namespace ROCKSDB_NAMESPACE {
27
32
 
28
33
  namespace {
@@ -58,17 +63,22 @@ int DecodeValue(void* v) {
58
63
  return static_cast<int>(reinterpret_cast<uintptr_t>(v));
59
64
  }
60
65
 
61
- const std::string kLRU = "lru";
62
- const std::string kClock = "clock";
63
- const std::string kFast = "fast";
64
-
65
- void dumbDeleter(const Slice& /*key*/, void* /*value*/) {}
66
+ void DumbDeleter(const Slice& /*key*/, void* /*value*/) {}
66
67
 
67
- void eraseDeleter(const Slice& /*key*/, void* value) {
68
+ void EraseDeleter1(const Slice& /*key*/, void* value) {
68
69
  Cache* cache = reinterpret_cast<Cache*>(value);
69
70
  cache->Erase("foo");
70
71
  }
71
72
 
73
+ void EraseDeleter2(const Slice& /*key*/, void* value) {
74
+ Cache* cache = reinterpret_cast<Cache*>(value);
75
+ cache->Erase(EncodeKey16Bytes(1234));
76
+ }
77
+
78
+ const std::string kLRU = "lru";
79
+ const std::string kClock = "clock";
80
+ const std::string kFast = "fast";
81
+
72
82
  } // anonymous namespace
73
83
 
74
84
  class CacheTest : public testing::TestWithParam<std::string> {
@@ -223,13 +233,9 @@ class LRUCacheTest : public CacheTest {};
223
233
 
224
234
  TEST_P(CacheTest, UsageTest) {
225
235
  auto type = GetParam();
226
- if (type == kFast || type == kClock) {
227
- ROCKSDB_GTEST_BYPASS("FastLRUCache and ClockCache require 16-byte keys.");
228
- return;
229
- }
230
236
 
231
237
  // cache is std::shared_ptr and will be automatically cleaned up.
232
- const uint64_t kCapacity = 100000;
238
+ const size_t kCapacity = 100000;
233
239
  auto cache = NewCache(kCapacity, 8, false, kDontChargeCacheMetadata);
234
240
  auto precise_cache = NewCache(kCapacity, 0, false, kFullChargeCacheMetadata);
235
241
  ASSERT_EQ(0, cache->GetUsage());
@@ -239,12 +245,17 @@ TEST_P(CacheTest, UsageTest) {
239
245
  char value[10] = "abcdef";
240
246
  // make sure everything will be cached
241
247
  for (int i = 1; i < 100; ++i) {
242
- std::string key(i, 'a');
248
+ std::string key;
249
+ if (type == kLRU) {
250
+ key = std::string(i, 'a');
251
+ } else {
252
+ key = EncodeKey(i);
253
+ }
243
254
  auto kv_size = key.size() + 5;
244
255
  ASSERT_OK(cache->Insert(key, reinterpret_cast<void*>(value), kv_size,
245
- dumbDeleter));
256
+ DumbDeleter));
246
257
  ASSERT_OK(precise_cache->Insert(key, reinterpret_cast<void*>(value),
247
- kv_size, dumbDeleter));
258
+ kv_size, DumbDeleter));
248
259
  usage += kv_size;
249
260
  ASSERT_EQ(usage, cache->GetUsage());
250
261
  ASSERT_LT(usage, precise_cache->GetUsage());
@@ -256,12 +267,17 @@ TEST_P(CacheTest, UsageTest) {
256
267
  ASSERT_EQ(0, precise_cache->GetUsage());
257
268
 
258
269
  // make sure the cache will be overloaded
259
- for (uint64_t i = 1; i < kCapacity; ++i) {
260
- auto key = std::to_string(i);
270
+ for (size_t i = 1; i < kCapacity; ++i) {
271
+ std::string key;
272
+ if (type == kLRU) {
273
+ key = std::to_string(i);
274
+ } else {
275
+ key = EncodeKey(static_cast<int>(1000 + i));
276
+ }
261
277
  ASSERT_OK(cache->Insert(key, reinterpret_cast<void*>(value), key.size() + 5,
262
- dumbDeleter));
278
+ DumbDeleter));
263
279
  ASSERT_OK(precise_cache->Insert(key, reinterpret_cast<void*>(value),
264
- key.size() + 5, dumbDeleter));
280
+ key.size() + 5, DumbDeleter));
265
281
  }
266
282
 
267
283
  // the usage should be close to the capacity
@@ -271,15 +287,18 @@ TEST_P(CacheTest, UsageTest) {
271
287
  ASSERT_LT(kCapacity * 0.95, precise_cache->GetUsage());
272
288
  }
273
289
 
290
+ // TODO: This test takes longer than expected on ClockCache. This is
291
+ // because the values size estimate at construction is too sloppy.
292
+ // Fix this.
293
+ // Why is it so slow? The cache is constructed with an estimate of 1, but
294
+ // then the charge is claimed to be 21. This will cause the hash table
295
+ // to be extremely sparse, which in turn means clock needs to scan too
296
+ // many slots to find victims.
274
297
  TEST_P(CacheTest, PinnedUsageTest) {
275
298
  auto type = GetParam();
276
- if (type == kFast || type == kClock) {
277
- ROCKSDB_GTEST_BYPASS("FastLRUCache and ClockCache require 16-byte keys.");
278
- return;
279
- }
280
299
 
281
300
  // cache is std::shared_ptr and will be automatically cleaned up.
282
- const uint64_t kCapacity = 200000;
301
+ const size_t kCapacity = 200000;
283
302
  auto cache = NewCache(kCapacity, 8, false, kDontChargeCacheMetadata);
284
303
  auto precise_cache = NewCache(kCapacity, 8, false, kFullChargeCacheMetadata);
285
304
 
@@ -292,15 +311,20 @@ TEST_P(CacheTest, PinnedUsageTest) {
292
311
  // Add entries. Unpin some of them after insertion. Then, pin some of them
293
312
  // again. Check GetPinnedUsage().
294
313
  for (int i = 1; i < 100; ++i) {
295
- std::string key(i, 'a');
314
+ std::string key;
315
+ if (type == kLRU) {
316
+ key = std::string(i, 'a');
317
+ } else {
318
+ key = EncodeKey(i);
319
+ }
296
320
  auto kv_size = key.size() + 5;
297
321
  Cache::Handle* handle;
298
322
  Cache::Handle* handle_in_precise_cache;
299
323
  ASSERT_OK(cache->Insert(key, reinterpret_cast<void*>(value), kv_size,
300
- dumbDeleter, &handle));
324
+ DumbDeleter, &handle));
301
325
  assert(handle);
302
326
  ASSERT_OK(precise_cache->Insert(key, reinterpret_cast<void*>(value),
303
- kv_size, dumbDeleter,
327
+ kv_size, DumbDeleter,
304
328
  &handle_in_precise_cache));
305
329
  assert(handle_in_precise_cache);
306
330
  pinned_usage += kv_size;
@@ -334,12 +358,17 @@ TEST_P(CacheTest, PinnedUsageTest) {
334
358
  ASSERT_LT(pinned_usage, precise_cache_pinned_usage);
335
359
 
336
360
  // check that overloading the cache does not change the pinned usage
337
- for (uint64_t i = 1; i < 2 * kCapacity; ++i) {
338
- auto key = std::to_string(i);
361
+ for (size_t i = 1; i < 2 * kCapacity; ++i) {
362
+ std::string key;
363
+ if (type == kLRU) {
364
+ key = std::to_string(i);
365
+ } else {
366
+ key = EncodeKey(static_cast<int>(1000 + i));
367
+ }
339
368
  ASSERT_OK(cache->Insert(key, reinterpret_cast<void*>(value), key.size() + 5,
340
- dumbDeleter));
369
+ DumbDeleter));
341
370
  ASSERT_OK(precise_cache->Insert(key, reinterpret_cast<void*>(value),
342
- key.size() + 5, dumbDeleter));
371
+ key.size() + 5, DumbDeleter));
343
372
  }
344
373
  ASSERT_EQ(pinned_usage, cache->GetPinnedUsage());
345
374
  ASSERT_EQ(precise_cache_pinned_usage, precise_cache->GetPinnedUsage());
@@ -447,7 +476,7 @@ TEST_P(CacheTest, EvictionPolicy) {
447
476
  Insert(200, 201);
448
477
 
449
478
  // Frequently used entry must be kept around
450
- for (int i = 0; i < kCacheSize * 2; i++) {
479
+ for (int i = 0; i < 2 * kCacheSize; i++) {
451
480
  Insert(1000+i, 2000+i);
452
481
  ASSERT_EQ(101, Lookup(100));
453
482
  }
@@ -500,9 +529,7 @@ TEST_P(CacheTest, EvictionPolicyRef) {
500
529
  Insert(303, 104);
501
530
 
502
531
  // Insert entries much more than cache capacity.
503
- double load_factor =
504
- std::min(fast_lru_cache::kLoadFactor, clock_cache::kLoadFactor);
505
- for (int i = 0; i < 2 * static_cast<int>(kCacheSize / load_factor); i++) {
532
+ for (int i = 0; i < 100 * kCacheSize; i++) {
506
533
  Insert(1000 + i, 2000 + i);
507
534
  }
508
535
 
@@ -533,31 +560,40 @@ TEST_P(CacheTest, EvictionPolicyRef) {
533
560
 
534
561
  TEST_P(CacheTest, EvictEmptyCache) {
535
562
  auto type = GetParam();
536
- if (type == kFast || type == kClock) {
537
- ROCKSDB_GTEST_BYPASS("FastLRUCache and ClockCache require 16-byte keys.");
538
- return;
539
- }
540
563
 
541
564
  // Insert item large than capacity to trigger eviction on empty cache.
542
565
  auto cache = NewCache(1, 0, false);
543
- ASSERT_OK(cache->Insert("foo", nullptr, 10, dumbDeleter));
566
+ if (type == kLRU) {
567
+ ASSERT_OK(cache->Insert("foo", nullptr, 10, DumbDeleter));
568
+ } else {
569
+ ASSERT_OK(cache->Insert(EncodeKey(1000), nullptr, 10, DumbDeleter));
570
+ }
544
571
  }
545
572
 
546
573
  TEST_P(CacheTest, EraseFromDeleter) {
547
574
  auto type = GetParam();
548
- if (type == kFast || type == kClock) {
549
- ROCKSDB_GTEST_BYPASS("FastLRUCache and ClockCache require 16-byte keys.");
550
- return;
551
- }
552
575
 
553
576
  // Have deleter which will erase item from cache, which will re-enter
554
577
  // the cache at that point.
555
578
  std::shared_ptr<Cache> cache = NewCache(10, 0, false);
556
- ASSERT_OK(cache->Insert("foo", nullptr, 1, dumbDeleter));
557
- ASSERT_OK(cache->Insert("bar", cache.get(), 1, eraseDeleter));
558
- cache->Erase("bar");
559
- ASSERT_EQ(nullptr, cache->Lookup("foo"));
560
- ASSERT_EQ(nullptr, cache->Lookup("bar"));
579
+ std::string foo, bar;
580
+ Cache::DeleterFn erase_deleter;
581
+ if (type == kLRU) {
582
+ foo = "foo";
583
+ bar = "bar";
584
+ erase_deleter = EraseDeleter1;
585
+ } else {
586
+ foo = EncodeKey(1234);
587
+ bar = EncodeKey(5678);
588
+ erase_deleter = EraseDeleter2;
589
+ }
590
+
591
+ ASSERT_OK(cache->Insert(foo, nullptr, 1, DumbDeleter));
592
+ ASSERT_OK(cache->Insert(bar, cache.get(), 1, erase_deleter));
593
+
594
+ cache->Erase(bar);
595
+ ASSERT_EQ(nullptr, cache->Lookup(foo));
596
+ ASSERT_EQ(nullptr, cache->Lookup(bar));
561
597
  }
562
598
 
563
599
  TEST_P(CacheTest, ErasedHandleState) {
@@ -590,9 +626,9 @@ TEST_P(CacheTest, HeavyEntries) {
590
626
  const int kHeavy = 10;
591
627
  int added = 0;
592
628
  int index = 0;
593
- while (added < 2*kCacheSize) {
629
+ while (added < 2 * kCacheSize) {
594
630
  const int weight = (index & 1) ? kLight : kHeavy;
595
- Insert(index, 1000+index, weight);
631
+ Insert(index, 1000 + index, weight);
596
632
  added += weight;
597
633
  index++;
598
634
  }
@@ -603,7 +639,7 @@ TEST_P(CacheTest, HeavyEntries) {
603
639
  int r = Lookup(i);
604
640
  if (r >= 0) {
605
641
  cached_weight += weight;
606
- ASSERT_EQ(1000+i, r);
642
+ ASSERT_EQ(1000 + i, r);
607
643
  }
608
644
  }
609
645
  ASSERT_LE(cached_weight, kCacheSize + kCacheSize/10);
@@ -615,7 +651,6 @@ TEST_P(CacheTest, NewId) {
615
651
  ASSERT_NE(a, b);
616
652
  }
617
653
 
618
-
619
654
  class Value {
620
655
  public:
621
656
  explicit Value(int v) : v_(v) {}
@@ -664,7 +699,8 @@ TEST_P(CacheTest, SetCapacity) {
664
699
  auto type = GetParam();
665
700
  if (type == kFast || type == kClock) {
666
701
  ROCKSDB_GTEST_BYPASS(
667
- "FastLRUCache and ClockCache don't support capacity adjustments.");
702
+ "FastLRUCache and ClockCache don't support arbitrary capacity "
703
+ "adjustments.");
668
704
  return;
669
705
  }
670
706
  // test1: increase capacity
@@ -716,9 +752,9 @@ TEST_P(CacheTest, SetCapacity) {
716
752
 
717
753
  TEST_P(LRUCacheTest, SetStrictCapacityLimit) {
718
754
  auto type = GetParam();
719
- if (type == kFast || type == kClock) {
755
+ if (type == kFast) {
720
756
  ROCKSDB_GTEST_BYPASS(
721
- "FastLRUCache and ClockCache don't support an unbounded number of "
757
+ "FastLRUCache only supports a limited number of "
722
758
  "inserts beyond "
723
759
  "capacity.");
724
760
  return;
@@ -775,9 +811,8 @@ TEST_P(LRUCacheTest, SetStrictCapacityLimit) {
775
811
 
776
812
  TEST_P(CacheTest, OverCapacity) {
777
813
  auto type = GetParam();
778
- if (type == kFast || type == kClock) {
779
- ROCKSDB_GTEST_BYPASS(
780
- "FastLRUCache and ClockCache don't support capacity adjustments.");
814
+ if (type == kClock) {
815
+ ROCKSDB_GTEST_BYPASS("Requires LRU eviction policy.");
781
816
  return;
782
817
  }
783
818
  size_t n = 10;
@@ -69,10 +69,10 @@ ClockHandle* ClockHandleTable::Lookup(const Slice& key, uint32_t hash) {
69
69
  // updates where it would be possible to combine into one CAS (more metadata
70
70
  // under one atomic field) or maybe two atomic updates (one arithmetic, one
71
71
  // bitwise). Something to think about optimizing.
72
- e->InternalToExternalRef();
73
72
  e->SetHit();
74
73
  // The handle is now referenced, so we take it out of clock.
75
74
  ClockOff(e);
75
+ e->InternalToExternalRef();
76
76
  }
77
77
 
78
78
  return e;
@@ -312,17 +312,20 @@ void ClockHandleTable::ClockRun(size_t charge) {
312
312
  // hot element, it will be hard to get an exclusive ref.
313
313
  // Do we need a mechanism to prevent an element from sitting
314
314
  // for a long time in cache waiting to be evicted?
315
- assert(charge <= capacity_);
316
315
  autovector<ClockHandle> deleted;
317
316
  uint32_t max_iterations =
318
- 1 + static_cast<uint32_t>(GetTableSize() * kLoadFactor);
317
+ ClockHandle::ClockPriority::HIGH *
318
+ (1 +
319
+ static_cast<uint32_t>(
320
+ GetTableSize() *
321
+ kLoadFactor)); // It may take up to HIGH passes to evict an element.
319
322
  size_t usage_local = usage_;
320
- while (usage_local + charge > capacity_ && max_iterations--) {
323
+ size_t capacity_local = capacity_;
324
+ while (usage_local + charge > capacity_local && max_iterations--) {
321
325
  uint32_t steps = 1 + static_cast<uint32_t>(1 / kLoadFactor);
322
326
  uint32_t clock_pointer_local = (clock_pointer_ += steps) - steps;
323
327
  for (uint32_t i = 0; i < steps; i++) {
324
328
  ClockHandle* h = &array_[ModTableSize(clock_pointer_local + i)];
325
-
326
329
  if (h->TryExclusiveRef()) {
327
330
  if (h->WillBeDeleted()) {
328
331
  Remove(h, &deleted);
@@ -335,7 +338,6 @@ void ClockHandleTable::ClockRun(size_t charge) {
335
338
  // exclusive ref, we know we are in the latter case. This can only
336
339
  // happen when the last external reference to an element was
337
340
  // released, and the element was not immediately removed.
338
-
339
341
  ClockOn(h);
340
342
  }
341
343
  ClockHandle::ClockPriority priority = h->GetClockPriority();
@@ -358,6 +360,7 @@ ClockCacheShard::ClockCacheShard(
358
360
  size_t capacity, size_t estimated_value_size, bool strict_capacity_limit,
359
361
  CacheMetadataChargePolicy metadata_charge_policy)
360
362
  : strict_capacity_limit_(strict_capacity_limit),
363
+ detached_usage_(0),
361
364
  table_(capacity, CalcHashBits(capacity, estimated_value_size,
362
365
  metadata_charge_policy)) {
363
366
  set_metadata_charge_policy(metadata_charge_policy);
@@ -401,15 +404,24 @@ void ClockCacheShard::ApplyToSomeEntries(
401
404
  *state = index_end << (32 - length_bits);
402
405
  }
403
406
 
404
- table_.ApplyToEntriesRange(
407
+ table_.ConstApplyToEntriesRange(
405
408
  [callback,
406
- metadata_charge_policy = metadata_charge_policy_](ClockHandle* h) {
409
+ metadata_charge_policy = metadata_charge_policy_](const ClockHandle* h) {
407
410
  callback(h->key(), h->value, h->GetCharge(metadata_charge_policy),
408
411
  h->deleter);
409
412
  },
410
413
  index_begin, index_end, false);
411
414
  }
412
415
 
416
+ ClockHandle* ClockCacheShard::DetachedInsert(ClockHandle* h) {
417
+ ClockHandle* e = new ClockHandle();
418
+ *e = *h;
419
+ e->SetDetached();
420
+ e->TryExternalRef();
421
+ detached_usage_ += h->total_charge;
422
+ return e;
423
+ }
424
+
413
425
  size_t ClockCacheShard::CalcEstimatedHandleCharge(
414
426
  size_t estimated_value_size,
415
427
  CacheMetadataChargePolicy metadata_charge_policy) {
@@ -430,12 +442,16 @@ int ClockCacheShard::CalcHashBits(
430
442
  return FloorLog2((num_entries << 1) - 1);
431
443
  }
432
444
 
433
- void ClockCacheShard::SetCapacity(size_t /*capacity*/) {
434
- assert(false); // Not supported.
445
+ void ClockCacheShard::SetCapacity(size_t capacity) {
446
+ if (capacity > table_.GetCapacity()) {
447
+ assert(false); // Not supported.
448
+ }
449
+ table_.SetCapacity(capacity);
450
+ table_.ClockRun(detached_usage_);
435
451
  }
436
452
 
437
- void ClockCacheShard::SetStrictCapacityLimit(bool /*strict_capacity_limit*/) {
438
- assert(false); // Not supported.
453
+ void ClockCacheShard::SetStrictCapacityLimit(bool strict_capacity_limit) {
454
+ strict_capacity_limit_ = strict_capacity_limit;
439
455
  }
440
456
 
441
457
  Status ClockCacheShard::Insert(const Slice& key, uint32_t hash, void* value,
@@ -459,27 +475,32 @@ Status ClockCacheShard::Insert(const Slice& key, uint32_t hash, void* value,
459
475
 
460
476
  Status s = Status::OK();
461
477
 
478
+ // Use a local copy to minimize cache synchronization.
479
+ size_t detached_usage = detached_usage_;
480
+
462
481
  // Free space with the clock policy until enough space is freed or there are
463
482
  // no evictable elements.
464
- table_.ClockRun(tmp.total_charge);
483
+ table_.ClockRun(tmp.total_charge + detached_usage);
465
484
 
466
- // occupancy_ and usage_ are contended members across concurrent updates
467
- // on the same shard, so we use a single copy to reduce cache synchronization.
485
+ // Use local copies to minimize cache synchronization
486
+ // (occupancy_ and usage_ are read and written by all insertions).
468
487
  uint32_t occupancy_local = table_.GetOccupancy();
469
- size_t usage_local = table_.GetUsage();
470
- assert(occupancy_local <= table_.GetOccupancyLimit());
471
-
472
- autovector<ClockHandle> deleted;
473
-
474
- if ((usage_local + tmp.total_charge > table_.GetCapacity() &&
475
- (strict_capacity_limit_ || handle == nullptr)) ||
476
- occupancy_local > table_.GetOccupancyLimit()) {
488
+ size_t total_usage = table_.GetUsage() + detached_usage;
489
+
490
+ // TODO: Currently we support strict_capacity_limit == false as long as the
491
+ // number of pinned elements is below table_.GetOccupancyLimit(). We can
492
+ // always support it as follows: whenever we exceed this limit, we dynamically
493
+ // allocate a handle and return it (when the user provides a handle pointer,
494
+ // of course). Then, Release checks whether the handle was dynamically
495
+ // allocated, or is stored in the table.
496
+ if (total_usage + tmp.total_charge > table_.GetCapacity() &&
497
+ (strict_capacity_limit_ || handle == nullptr)) {
477
498
  if (handle == nullptr) {
478
499
  // Don't insert the entry but still return ok, as if the entry inserted
479
500
  // into cache and get evicted immediately.
480
- deleted.push_back(tmp);
501
+ tmp.FreeData();
481
502
  } else {
482
- if (occupancy_local > table_.GetOccupancyLimit()) {
503
+ if (occupancy_local + 1 > table_.GetOccupancyLimit()) {
483
504
  // TODO: Consider using a distinct status for this case, but usually
484
505
  // it will be handled the same way as reaching charge capacity limit
485
506
  s = Status::MemoryLimit(
@@ -491,22 +512,34 @@ Status ClockCacheShard::Insert(const Slice& key, uint32_t hash, void* value,
491
512
  }
492
513
  }
493
514
  } else {
494
- // Insert into the cache. Note that the cache might get larger than its
495
- // capacity if not enough space was freed up.
496
- ClockHandle* h = table_.Insert(&tmp, &deleted, handle != nullptr);
497
- assert(h != nullptr); // The occupancy is way below the table size, so this
498
- // insertion should never fail.
515
+ ClockHandle* h = nullptr;
516
+ if (handle != nullptr && occupancy_local + 1 > table_.GetOccupancyLimit()) {
517
+ // Even if the user wishes to overload the cache, we can't insert into
518
+ // the hash table. Instead, we dynamically allocate a new handle.
519
+ h = DetachedInsert(&tmp);
520
+ // TODO: Return special status?
521
+ } else {
522
+ // Insert into the cache. Note that the cache might get larger than its
523
+ // capacity if not enough space was freed up.
524
+ autovector<ClockHandle> deleted;
525
+ h = table_.Insert(&tmp, &deleted, handle != nullptr);
526
+ if (h == nullptr && handle != nullptr) {
527
+ // The table is full. This can happen when many threads simultaneously
528
+ // attempt an insert, and the table is operating close to full capacity.
529
+ h = DetachedInsert(&tmp);
530
+ }
531
+ // Notice that if handle == nullptr, we don't insert the entry but still
532
+ // return ok.
533
+ if (deleted.size() > 0) {
534
+ s = Status::OkOverwritten();
535
+ }
536
+ table_.Free(&deleted);
537
+ }
499
538
  if (handle != nullptr) {
500
539
  *handle = reinterpret_cast<Cache::Handle*>(h);
501
540
  }
502
-
503
- if (deleted.size() > 0) {
504
- s = Status::OkOverwritten();
505
- }
506
541
  }
507
542
 
508
- table_.Free(&deleted);
509
-
510
543
  return s;
511
544
  }
512
545
 
@@ -516,7 +549,7 @@ Cache::Handle* ClockCacheShard::Lookup(const Slice& key, uint32_t hash) {
516
549
 
517
550
  bool ClockCacheShard::Ref(Cache::Handle* h) {
518
551
  ClockHandle* e = reinterpret_cast<ClockHandle*>(h);
519
- assert(e->HasExternalRefs());
552
+ assert(e->ExternalRefs() > 0);
520
553
  return e->TryExternalRef();
521
554
  }
522
555
 
@@ -530,6 +563,20 @@ bool ClockCacheShard::Release(Cache::Handle* handle, bool erase_if_last_ref) {
530
563
  }
531
564
 
532
565
  ClockHandle* h = reinterpret_cast<ClockHandle*>(handle);
566
+
567
+ if (UNLIKELY(h->IsDetached())) {
568
+ h->ReleaseExternalRef();
569
+ if (h->TryExclusiveRef()) {
570
+ // Only the last reference will succeed.
571
+ // Don't bother releasing the exclusive ref.
572
+ h->FreeData();
573
+ detached_usage_ -= h->total_charge;
574
+ delete h;
575
+ return true;
576
+ }
577
+ return false;
578
+ }
579
+
533
580
  uint32_t refs = h->refs;
534
581
  bool last_reference = ((refs & ClockHandle::EXTERNAL_REFS) == 1);
535
582
  bool will_be_deleted = refs & ClockHandle::WILL_BE_DELETED;
@@ -569,14 +616,15 @@ size_t ClockCacheShard::GetPinnedUsage() const {
569
616
  size_t clock_usage = 0;
570
617
 
571
618
  table_.ConstApplyToEntriesRange(
572
- [&clock_usage](ClockHandle* h) {
573
- if (h->HasExternalRefs()) {
619
+ [&clock_usage](const ClockHandle* h) {
620
+ if (h->ExternalRefs() > 1) {
621
+ // We check > 1 because we are holding an external ref.
574
622
  clock_usage += h->total_charge;
575
623
  }
576
624
  },
577
625
  0, table_.GetTableSize(), true);
578
626
 
579
- return clock_usage;
627
+ return clock_usage + detached_usage_;
580
628
  }
581
629
 
582
630
  ClockCache::ClockCache(size_t capacity, size_t estimated_value_size,