@nxtedition/rocksdb 7.1.25 → 7.1.26

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 (27) hide show
  1. package/deps/rocksdb/rocksdb/cache/clock_cache.cc +7 -4
  2. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +18 -2
  3. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +5 -1
  4. package/deps/rocksdb/rocksdb/db/db_iter.cc +2 -1
  5. package/deps/rocksdb/rocksdb/db/db_test_util.cc +4 -2
  6. package/deps/rocksdb/rocksdb/db/db_test_util.h +1 -1
  7. package/deps/rocksdb/rocksdb/db/version_set.cc +1 -1
  8. package/deps/rocksdb/rocksdb/include/rocksdb/block_cache_trace_writer.h +149 -0
  9. package/deps/rocksdb/rocksdb/include/rocksdb/db.h +8 -1
  10. package/deps/rocksdb/rocksdb/include/rocksdb/table.h +1 -1
  11. package/deps/rocksdb/rocksdb/{table → include/rocksdb}/table_reader_caller.h +0 -0
  12. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +7 -1
  13. package/deps/rocksdb/rocksdb/table/table_reader.h +1 -1
  14. package/deps/rocksdb/rocksdb/table/table_test.cc +29 -22
  15. package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_trace_analyzer.cc +1 -1
  16. package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_trace_analyzer.h +1 -1
  17. package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_trace_analyzer_test.cc +25 -16
  18. package/deps/rocksdb/rocksdb/trace_replay/block_cache_tracer.cc +28 -21
  19. package/deps/rocksdb/rocksdb/trace_replay/block_cache_tracer.h +16 -72
  20. package/deps/rocksdb/rocksdb/trace_replay/block_cache_tracer_test.cc +74 -38
  21. package/deps/rocksdb/rocksdb/util/user_comparator_wrapper.h +11 -31
  22. package/deps/rocksdb/rocksdb/utilities/simulator_cache/cache_simulator.cc +2 -2
  23. package/deps/rocksdb/rocksdb/utilities/simulator_cache/cache_simulator_test.cc +13 -13
  24. package/deps/rocksdb/rocksdb.gyp +1 -0
  25. package/package.json +1 -1
  26. package/prebuilds/darwin-arm64/node.napi.node +0 -0
  27. package/prebuilds/linux-x64/node.napi.node +0 -0
@@ -919,11 +919,13 @@ void ClockHandleTable::Evict(size_t requested_charge, size_t* freed_charge,
919
919
  uint64_t{ClockHandle::kStateConstruction}
920
920
  << ClockHandle::kStateShift,
921
921
  std::memory_order_acquire)) {
922
- // Took ownership
923
- const UniqueId64x2& hashed_key = h.hashed_key;
922
+ // Took ownership.
923
+ // Save info about h to minimize dependences between atomic updates
924
+ // (e.g. fully relaxed Rollback after h released by marking empty)
925
+ const UniqueId64x2 h_hashed_key = h.hashed_key;
926
+ size_t h_total_charge = h.total_charge;
924
927
  // TODO? Delay freeing?
925
928
  h.FreeData();
926
- *freed_charge += h.total_charge;
927
929
  #ifndef NDEBUG
928
930
  // Mark slot as empty, with assertion
929
931
  meta = h.meta.exchange(0, std::memory_order_release);
@@ -934,7 +936,8 @@ void ClockHandleTable::Evict(size_t requested_charge, size_t* freed_charge,
934
936
  h.meta.store(0, std::memory_order_release);
935
937
  #endif
936
938
  *freed_count += 1;
937
- Rollback(hashed_key, &h);
939
+ *freed_charge += h_total_charge;
940
+ Rollback(h_hashed_key, &h);
938
941
  }
939
942
  }
940
943
 
@@ -5782,8 +5782,24 @@ Status DBImpl::NewDefaultReplayer(
5782
5782
  Status DBImpl::StartBlockCacheTrace(
5783
5783
  const TraceOptions& trace_options,
5784
5784
  std::unique_ptr<TraceWriter>&& trace_writer) {
5785
- return block_cache_tracer_.StartTrace(immutable_db_options_.clock,
5786
- trace_options, std::move(trace_writer));
5785
+ BlockCacheTraceOptions block_trace_opts;
5786
+ block_trace_opts.sampling_frequency = trace_options.sampling_frequency;
5787
+
5788
+ BlockCacheTraceWriterOptions trace_writer_opt;
5789
+ trace_writer_opt.max_trace_file_size = trace_options.max_trace_file_size;
5790
+
5791
+ std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
5792
+ NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
5793
+ std::move(trace_writer));
5794
+
5795
+ return block_cache_tracer_.StartTrace(block_trace_opts,
5796
+ std::move(block_cache_trace_writer));
5797
+ }
5798
+
5799
+ Status DBImpl::StartBlockCacheTrace(
5800
+ const BlockCacheTraceOptions& trace_options,
5801
+ std::unique_ptr<BlockCacheTraceWriter>&& trace_writer) {
5802
+ return block_cache_tracer_.StartTrace(trace_options, std::move(trace_writer));
5787
5803
  }
5788
5804
 
5789
5805
  Status DBImpl::EndBlockCacheTrace() {
@@ -568,9 +568,13 @@ class DBImpl : public DB {
568
568
 
569
569
  using DB::StartBlockCacheTrace;
570
570
  Status StartBlockCacheTrace(
571
- const TraceOptions& options,
571
+ const TraceOptions& trace_options,
572
572
  std::unique_ptr<TraceWriter>&& trace_writer) override;
573
573
 
574
+ Status StartBlockCacheTrace(
575
+ const BlockCacheTraceOptions& options,
576
+ std::unique_ptr<BlockCacheTraceWriter>&& trace_writer) override;
577
+
574
578
  using DB::EndBlockCacheTrace;
575
579
  Status EndBlockCacheTrace() override;
576
580
 
@@ -90,7 +90,8 @@ DBIter::DBIter(Env* _env, const ReadOptions& read_options,
90
90
  iter_.iter()->SetPinnedItersMgr(&pinned_iters_mgr_);
91
91
  }
92
92
  status_.PermitUncheckedError();
93
- assert(timestamp_size_ == user_comparator_.timestamp_size());
93
+ assert(timestamp_size_ ==
94
+ user_comparator_.user_comparator()->timestamp_size());
94
95
  }
95
96
 
96
97
  Status DBIter::GetProperty(std::string prop_name, std::string* prop) {
@@ -487,8 +487,10 @@ Options DBTestBase::GetOptions(
487
487
  case kInfiniteMaxOpenFiles:
488
488
  options.max_open_files = -1;
489
489
  break;
490
- case kXXH3Checksum: {
491
- table_options.checksum = kXXH3;
490
+ case kCRC32cChecksum: {
491
+ // Old default was CRC32c, but XXH3 (new default) is faster on common
492
+ // hardware
493
+ table_options.checksum = kCRC32c;
492
494
  // Thrown in here for basic coverage:
493
495
  options.DisableExtraChecks();
494
496
  break;
@@ -1048,7 +1048,7 @@ class DBTestBase : public testing::Test {
1048
1048
  kUniversalCompactionMultiLevel = 20,
1049
1049
  kCompressedBlockCache = 21,
1050
1050
  kInfiniteMaxOpenFiles = 22,
1051
- kXXH3Checksum = 23,
1051
+ kCRC32cChecksum = 23,
1052
1052
  kFIFOCompaction = 24,
1053
1053
  kOptimizeFiltersForHits = 25,
1054
1054
  kRowCache = 26,
@@ -1239,7 +1239,7 @@ void LevelIterator::Seek(const Slice& target) {
1239
1239
  prefix_extractor_ != nullptr && !read_options_.total_order_seek &&
1240
1240
  !read_options_.auto_prefix_mode &&
1241
1241
  file_index_ < flevel_->num_files - 1) {
1242
- size_t ts_sz = user_comparator_.timestamp_size();
1242
+ size_t ts_sz = user_comparator_.user_comparator()->timestamp_size();
1243
1243
  Slice target_user_key_without_ts =
1244
1244
  ExtractUserKeyAndStripTimestamp(target, ts_sz);
1245
1245
  Slice next_file_first_user_key_without_ts =
@@ -0,0 +1,149 @@
1
+ // Copyright (c) 2022, Meta, Inc. All rights reserved.
2
+ // This source code is licensed under both the GPLv2 (found in the
3
+ // COPYING file in the root directory) and Apache 2.0 License
4
+ // (found in the LICENSE.Apache file in the root directory).
5
+
6
+ #pragma once
7
+
8
+ #include "rocksdb/options.h"
9
+ #include "rocksdb/system_clock.h"
10
+ #include "rocksdb/table_reader_caller.h"
11
+ #include "rocksdb/trace_reader_writer.h"
12
+ #include "rocksdb/trace_record.h"
13
+
14
+ namespace ROCKSDB_NAMESPACE {
15
+ // A record for block cache lookups/inserts. This is passed by the table
16
+ // reader to the BlockCacheTraceWriter for every block cache op.
17
+ struct BlockCacheTraceRecord {
18
+ // Required fields for all accesses.
19
+ uint64_t access_timestamp = 0;
20
+
21
+ // Info related to the block being looked up or inserted
22
+ //
23
+ // 1. The cache key for the block
24
+ std::string block_key;
25
+
26
+ // 2. The type of block
27
+ TraceType block_type = TraceType::kTraceMax;
28
+
29
+ // 3. Size of the block
30
+ uint64_t block_size = 0;
31
+
32
+ // Info about the SST file the block is in
33
+ //
34
+ // 1. Column family ID
35
+ uint64_t cf_id = 0;
36
+
37
+ // 2. Column family name
38
+ std::string cf_name;
39
+
40
+ // 3. LSM level of the file
41
+ uint32_t level = 0;
42
+
43
+ // 4. SST file number
44
+ uint64_t sst_fd_number = 0;
45
+
46
+ // Info about the calling context
47
+ //
48
+ // 1. The higher level request triggering the block cache request
49
+ TableReaderCaller caller = TableReaderCaller::kMaxBlockCacheLookupCaller;
50
+
51
+ // 2. Cache lookup hit/miss. Not relevant for inserts
52
+ bool is_cache_hit = false;
53
+
54
+ // 3. Whether this request is a lookup
55
+ bool no_insert = false;
56
+
57
+ // Get/MultiGet specific info
58
+ //
59
+ // 1. A unique ID for Get/MultiGet
60
+ uint64_t get_id = kReservedGetId;
61
+
62
+ // 2. Whether the Get/MultiGet is from a user-specified snapshot
63
+ bool get_from_user_specified_snapshot = false;
64
+
65
+ // 3. The target user key in the block
66
+ std::string referenced_key;
67
+
68
+ // Required fields for data block and user Get/Multi-Get only.
69
+ //
70
+ // 1. Size of te useful data in the block
71
+ uint64_t referenced_data_size = 0;
72
+
73
+ // 2. Only for MultiGet, number of keys from the batch found in the block
74
+ uint64_t num_keys_in_block = 0;
75
+
76
+ // 3. Whether the key was found in the block or not (false positive)
77
+ bool referenced_key_exist_in_block = false;
78
+
79
+ static const uint64_t kReservedGetId;
80
+
81
+ BlockCacheTraceRecord() {}
82
+
83
+ BlockCacheTraceRecord(uint64_t _access_timestamp, std::string _block_key,
84
+ TraceType _block_type, uint64_t _block_size,
85
+ uint64_t _cf_id, std::string _cf_name, uint32_t _level,
86
+ uint64_t _sst_fd_number, TableReaderCaller _caller,
87
+ bool _is_cache_hit, bool _no_insert, uint64_t _get_id,
88
+ bool _get_from_user_specified_snapshot = false,
89
+ std::string _referenced_key = "",
90
+ uint64_t _referenced_data_size = 0,
91
+ uint64_t _num_keys_in_block = 0,
92
+ bool _referenced_key_exist_in_block = false)
93
+ : access_timestamp(_access_timestamp),
94
+ block_key(_block_key),
95
+ block_type(_block_type),
96
+ block_size(_block_size),
97
+ cf_id(_cf_id),
98
+ cf_name(_cf_name),
99
+ level(_level),
100
+ sst_fd_number(_sst_fd_number),
101
+ caller(_caller),
102
+ is_cache_hit(_is_cache_hit),
103
+ no_insert(_no_insert),
104
+ get_id(_get_id),
105
+ get_from_user_specified_snapshot(_get_from_user_specified_snapshot),
106
+ referenced_key(_referenced_key),
107
+ referenced_data_size(_referenced_data_size),
108
+ num_keys_in_block(_num_keys_in_block),
109
+ referenced_key_exist_in_block(_referenced_key_exist_in_block) {}
110
+ };
111
+
112
+ // Options for tracing block cache accesses
113
+ struct BlockCacheTraceOptions {
114
+ // Specify trace sampling option, i.e. capture one per how many requests.
115
+ // Default to 1 (capture every request).
116
+ uint64_t sampling_frequency = 1;
117
+ };
118
+
119
+ // Options for the built-in implementation of BlockCacheTraceWriter
120
+ struct BlockCacheTraceWriterOptions {
121
+ uint64_t max_trace_file_size = uint64_t{64} * 1024 * 1024 * 1024;
122
+ };
123
+
124
+ // BlockCacheTraceWriter is an abstract class that captures all RocksDB block
125
+ // cache accesses. Every RocksDB operation is passed to WriteBlockAccess()
126
+ // with a BlockCacheTraceRecord.
127
+ class BlockCacheTraceWriter {
128
+ public:
129
+ virtual ~BlockCacheTraceWriter() {}
130
+
131
+ // Pass Slice references to avoid copy.
132
+ virtual Status WriteBlockAccess(const BlockCacheTraceRecord& record,
133
+ const Slice& block_key, const Slice& cf_name,
134
+ const Slice& referenced_key) = 0;
135
+
136
+ // Write a trace header at the beginning, typically on initiating a trace,
137
+ // with some metadata like a magic number and RocksDB version.
138
+ virtual Status WriteHeader() = 0;
139
+ };
140
+
141
+ // Allocate an instance of the built-in BlockCacheTraceWriter implementation,
142
+ // that traces all block cache accesses to a user-provided TraceWriter. Each
143
+ // access is traced to a file with a timestamp and type, followed by the
144
+ // payload.
145
+ std::unique_ptr<BlockCacheTraceWriter> NewBlockCacheTraceWriter(
146
+ SystemClock* clock, const BlockCacheTraceWriterOptions& trace_options,
147
+ std::unique_ptr<TraceWriter>&& trace_writer);
148
+
149
+ } // namespace ROCKSDB_NAMESPACE
@@ -17,6 +17,7 @@
17
17
  #include <unordered_map>
18
18
  #include <vector>
19
19
 
20
+ #include "rocksdb/block_cache_trace_writer.h"
20
21
  #include "rocksdb/iterator.h"
21
22
  #include "rocksdb/listener.h"
22
23
  #include "rocksdb/metadata.h"
@@ -1748,11 +1749,17 @@ class DB {
1748
1749
 
1749
1750
  // Trace block cache accesses. Use EndBlockCacheTrace() to stop tracing.
1750
1751
  virtual Status StartBlockCacheTrace(
1751
- const TraceOptions& /*options*/,
1752
+ const TraceOptions& /*trace_options*/,
1752
1753
  std::unique_ptr<TraceWriter>&& /*trace_writer*/) {
1753
1754
  return Status::NotSupported("StartBlockCacheTrace() is not implemented.");
1754
1755
  }
1755
1756
 
1757
+ virtual Status StartBlockCacheTrace(
1758
+ const BlockCacheTraceOptions& /*options*/,
1759
+ std::unique_ptr<BlockCacheTraceWriter>&& /*trace_writer*/) {
1760
+ return Status::NotSupported("StartBlockCacheTrace() is not implemented.");
1761
+ }
1762
+
1756
1763
  virtual Status EndBlockCacheTrace() {
1757
1764
  return Status::NotSupported("EndBlockCacheTrace() is not implemented.");
1758
1765
  }
@@ -251,7 +251,7 @@ struct BlockBasedTableOptions {
251
251
  // Use the specified checksum type. Newly created table files will be
252
252
  // protected with this checksum type. Old table files will still be readable,
253
253
  // even though they have different checksum type.
254
- ChecksumType checksum = kCRC32c;
254
+ ChecksumType checksum = kXXH3;
255
255
 
256
256
  // Disable block cache. If this is set to true,
257
257
  // then no block cache should be used, and the block_cache should
@@ -404,8 +404,14 @@ class StackableDB : public DB {
404
404
 
405
405
  using DB::StartBlockCacheTrace;
406
406
  Status StartBlockCacheTrace(
407
- const TraceOptions& options,
407
+ const TraceOptions& trace_options,
408
408
  std::unique_ptr<TraceWriter>&& trace_writer) override {
409
+ return db_->StartBlockCacheTrace(trace_options, std::move(trace_writer));
410
+ }
411
+
412
+ Status StartBlockCacheTrace(
413
+ const BlockCacheTraceOptions& options,
414
+ std::unique_ptr<BlockCacheTraceWriter>&& trace_writer) override {
409
415
  return db_->StartBlockCacheTrace(options, std::move(trace_writer));
410
416
  }
411
417
 
@@ -15,10 +15,10 @@
15
15
  #include "folly/experimental/coro/Task.h"
16
16
  #endif
17
17
  #include "rocksdb/slice_transform.h"
18
+ #include "rocksdb/table_reader_caller.h"
18
19
  #include "table/get_context.h"
19
20
  #include "table/internal_iterator.h"
20
21
  #include "table/multiget_context.h"
21
- #include "table/table_reader_caller.h"
22
22
 
23
23
  namespace ROCKSDB_NAMESPACE {
24
24
 
@@ -1147,15 +1147,21 @@ class BlockBasedTableTest
1147
1147
  test_path_ = test::PerThreadDBPath("block_based_table_tracing_test");
1148
1148
  EXPECT_OK(env_->CreateDir(test_path_));
1149
1149
  trace_file_path_ = test_path_ + "/block_cache_trace_file";
1150
- TraceOptions trace_opt;
1150
+
1151
+ BlockCacheTraceWriterOptions trace_writer_opt;
1152
+ BlockCacheTraceOptions trace_opt;
1151
1153
  std::unique_ptr<TraceWriter> trace_writer;
1152
1154
  EXPECT_OK(NewFileTraceWriter(env_, EnvOptions(), trace_file_path_,
1153
1155
  &trace_writer));
1156
+ std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
1157
+ NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
1158
+ std::move(trace_writer));
1159
+ ASSERT_NE(block_cache_trace_writer, nullptr);
1154
1160
  // Always return Status::OK().
1155
1161
  assert(c->block_cache_tracer_
1156
- .StartTrace(env_->GetSystemClock().get(), trace_opt,
1157
- std::move(trace_writer))
1162
+ .StartTrace(trace_opt, std::move(block_cache_trace_writer))
1158
1163
  .ok());
1164
+
1159
1165
  {
1160
1166
  std::string user_key = "k01";
1161
1167
  InternalKey internal_key(user_key, 0, kTypeValue);
@@ -1213,10 +1219,10 @@ class BlockBasedTableTest
1213
1219
  } else {
1214
1220
  EXPECT_EQ(access.referenced_key, "");
1215
1221
  EXPECT_EQ(access.get_id, 0);
1216
- EXPECT_TRUE(access.get_from_user_specified_snapshot == Boolean::kFalse);
1222
+ EXPECT_FALSE(access.get_from_user_specified_snapshot);
1217
1223
  EXPECT_EQ(access.referenced_data_size, 0);
1218
1224
  EXPECT_EQ(access.num_keys_in_block, 0);
1219
- EXPECT_TRUE(access.referenced_key_exist_in_block == Boolean::kFalse);
1225
+ EXPECT_FALSE(access.referenced_key_exist_in_block);
1220
1226
  }
1221
1227
  index++;
1222
1228
  }
@@ -2250,7 +2256,8 @@ TEST_P(BlockBasedTableTest, BadChecksumType) {
2250
2256
  // Corrupt checksum type (123 is invalid)
2251
2257
  auto& sink = *c.TEST_GetSink();
2252
2258
  size_t len = sink.contents_.size();
2253
- ASSERT_EQ(sink.contents_[len - Footer::kNewVersionsEncodedLength], kCRC32c);
2259
+ ASSERT_EQ(sink.contents_[len - Footer::kNewVersionsEncodedLength],
2260
+ table_options.checksum);
2254
2261
  sink.contents_[len - Footer::kNewVersionsEncodedLength] = char{123};
2255
2262
 
2256
2263
  // (Re-)Open table file with bad checksum type
@@ -3051,8 +3058,8 @@ TEST_P(BlockBasedTableTest, TracingGetTest) {
3051
3058
  BlockCacheTraceRecord record;
3052
3059
  record.block_type = TraceType::kBlockTraceIndexBlock;
3053
3060
  record.caller = TableReaderCaller::kPrefetch;
3054
- record.is_cache_hit = Boolean::kFalse;
3055
- record.no_insert = Boolean::kFalse;
3061
+ record.is_cache_hit = false;
3062
+ record.no_insert = false;
3056
3063
  expected_records.push_back(record);
3057
3064
  record.block_type = TraceType::kBlockTraceFilterBlock;
3058
3065
  expected_records.push_back(record);
@@ -3061,22 +3068,22 @@ TEST_P(BlockBasedTableTest, TracingGetTest) {
3061
3068
  record.get_id = 1;
3062
3069
  record.block_type = TraceType::kBlockTraceFilterBlock;
3063
3070
  record.caller = TableReaderCaller::kUserGet;
3064
- record.get_from_user_specified_snapshot = Boolean::kFalse;
3071
+ record.get_from_user_specified_snapshot = false;
3065
3072
  record.referenced_key = encoded_key;
3066
- record.referenced_key_exist_in_block = Boolean::kTrue;
3067
- record.is_cache_hit = Boolean::kTrue;
3073
+ record.referenced_key_exist_in_block = true;
3074
+ record.is_cache_hit = true;
3068
3075
  expected_records.push_back(record);
3069
3076
  record.block_type = TraceType::kBlockTraceIndexBlock;
3070
3077
  expected_records.push_back(record);
3071
- record.is_cache_hit = Boolean::kFalse;
3078
+ record.is_cache_hit = false;
3072
3079
  record.block_type = TraceType::kBlockTraceDataBlock;
3073
3080
  expected_records.push_back(record);
3074
3081
  // The second get should all observe cache hits.
3075
- record.is_cache_hit = Boolean::kTrue;
3082
+ record.is_cache_hit = true;
3076
3083
  record.get_id = 2;
3077
3084
  record.block_type = TraceType::kBlockTraceFilterBlock;
3078
3085
  record.caller = TableReaderCaller::kUserGet;
3079
- record.get_from_user_specified_snapshot = Boolean::kFalse;
3086
+ record.get_from_user_specified_snapshot = false;
3080
3087
  record.referenced_key = encoded_key;
3081
3088
  expected_records.push_back(record);
3082
3089
  record.block_type = TraceType::kBlockTraceIndexBlock;
@@ -3116,15 +3123,15 @@ TEST_P(BlockBasedTableTest, TracingApproximateOffsetOfTest) {
3116
3123
  BlockCacheTraceRecord record;
3117
3124
  record.block_type = TraceType::kBlockTraceIndexBlock;
3118
3125
  record.caller = TableReaderCaller::kPrefetch;
3119
- record.is_cache_hit = Boolean::kFalse;
3120
- record.no_insert = Boolean::kFalse;
3126
+ record.is_cache_hit = false;
3127
+ record.no_insert = false;
3121
3128
  expected_records.push_back(record);
3122
3129
  record.block_type = TraceType::kBlockTraceFilterBlock;
3123
3130
  expected_records.push_back(record);
3124
3131
  // Then we should have two records for only index blocks.
3125
3132
  record.block_type = TraceType::kBlockTraceIndexBlock;
3126
3133
  record.caller = TableReaderCaller::kUserApproximateSize;
3127
- record.is_cache_hit = Boolean::kTrue;
3134
+ record.is_cache_hit = true;
3128
3135
  expected_records.push_back(record);
3129
3136
  expected_records.push_back(record);
3130
3137
  VerifyBlockAccessTrace(&c, expected_records);
@@ -3169,24 +3176,24 @@ TEST_P(BlockBasedTableTest, TracingIterator) {
3169
3176
  BlockCacheTraceRecord record;
3170
3177
  record.block_type = TraceType::kBlockTraceIndexBlock;
3171
3178
  record.caller = TableReaderCaller::kPrefetch;
3172
- record.is_cache_hit = Boolean::kFalse;
3173
- record.no_insert = Boolean::kFalse;
3179
+ record.is_cache_hit = false;
3180
+ record.no_insert = false;
3174
3181
  expected_records.push_back(record);
3175
3182
  record.block_type = TraceType::kBlockTraceFilterBlock;
3176
3183
  expected_records.push_back(record);
3177
3184
  // Then we should have three records for index and two data block access.
3178
3185
  record.block_type = TraceType::kBlockTraceIndexBlock;
3179
3186
  record.caller = TableReaderCaller::kUserIterator;
3180
- record.is_cache_hit = Boolean::kTrue;
3187
+ record.is_cache_hit = true;
3181
3188
  expected_records.push_back(record);
3182
3189
  record.block_type = TraceType::kBlockTraceDataBlock;
3183
- record.is_cache_hit = Boolean::kFalse;
3190
+ record.is_cache_hit = false;
3184
3191
  expected_records.push_back(record);
3185
3192
  expected_records.push_back(record);
3186
3193
  // When we iterate this file for the second time, we should observe all cache
3187
3194
  // hits.
3188
3195
  record.block_type = TraceType::kBlockTraceIndexBlock;
3189
- record.is_cache_hit = Boolean::kTrue;
3196
+ record.is_cache_hit = true;
3190
3197
  expected_records.push_back(record);
3191
3198
  record.block_type = TraceType::kBlockTraceDataBlock;
3192
3199
  expected_records.push_back(record);
@@ -1568,7 +1568,7 @@ Status BlockCacheTraceAnalyzer::Analyze() {
1568
1568
  trace_end_timestamp_in_seconds_ = access.access_timestamp / kMicrosInSecond;
1569
1569
  miss_ratio_stats_.UpdateMetrics(access.access_timestamp,
1570
1570
  is_user_access(access.caller),
1571
- access.is_cache_hit == Boolean::kFalse);
1571
+ !access.is_cache_hit);
1572
1572
  if (cache_simulator_) {
1573
1573
  cache_simulator_->Access(access);
1574
1574
  }
@@ -95,7 +95,7 @@ struct BlockAccessInfo {
95
95
  if (BlockCacheTraceHelper::IsGetOrMultiGetOnDataBlock(access.block_type,
96
96
  access.caller)) {
97
97
  num_keys = access.num_keys_in_block;
98
- if (access.referenced_key_exist_in_block == Boolean::kTrue) {
98
+ if (access.referenced_key_exist_in_block) {
99
99
  if (key_num_access_map.find(access.referenced_key) ==
100
100
  key_num_access_map.end()) {
101
101
  referenced_data_size += access.referenced_data_size;
@@ -114,14 +114,14 @@ class BlockCacheTracerTest : public testing::Test {
114
114
  } else {
115
115
  record.sst_fd_number = kSSTStoringOddKeys;
116
116
  }
117
- record.is_cache_hit = Boolean::kFalse;
118
- record.no_insert = Boolean::kFalse;
117
+ record.is_cache_hit = false;
118
+ record.no_insert = false;
119
119
  // Provide these fields for all block types.
120
120
  // The writer should only write these fields for data blocks and the
121
121
  // caller is either GET or MGET.
122
122
  record.referenced_key =
123
123
  kRefKeyPrefix + std::to_string(key_id) + std::string(8, 0);
124
- record.referenced_key_exist_in_block = Boolean::kTrue;
124
+ record.referenced_key_exist_in_block = true;
125
125
  record.num_keys_in_block = kNumKeysInBlock;
126
126
  ASSERT_OK(writer->WriteBlockAccess(
127
127
  record, record.block_key, record.cf_name, record.referenced_key));
@@ -223,15 +223,18 @@ class BlockCacheTracerTest : public testing::Test {
223
223
  TEST_F(BlockCacheTracerTest, BlockCacheAnalyzer) {
224
224
  {
225
225
  // Generate a trace file.
226
- TraceOptions trace_opt;
226
+ BlockCacheTraceWriterOptions trace_writer_opt;
227
227
  std::unique_ptr<TraceWriter> trace_writer;
228
228
  ASSERT_OK(NewFileTraceWriter(env_, env_options_, trace_file_path_,
229
229
  &trace_writer));
230
230
  const auto& clock = env_->GetSystemClock();
231
- BlockCacheTraceWriter writer(clock.get(), trace_opt,
231
+ std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
232
+ NewBlockCacheTraceWriter(clock.get(), trace_writer_opt,
232
233
  std::move(trace_writer));
233
- ASSERT_OK(writer.WriteHeader());
234
- WriteBlockAccess(&writer, 0, TraceType::kBlockTraceDataBlock, 50);
234
+ ASSERT_NE(block_cache_trace_writer, nullptr);
235
+ ASSERT_OK(block_cache_trace_writer->WriteHeader());
236
+ WriteBlockAccess(block_cache_trace_writer.get(), 0,
237
+ TraceType::kBlockTraceDataBlock, 50);
235
238
  ASSERT_OK(env_->FileExists(trace_file_path_));
236
239
  }
237
240
  {
@@ -612,21 +615,27 @@ TEST_F(BlockCacheTracerTest, MixedBlocks) {
612
615
  // It contains two SST files with 25 blocks of odd numbered block_key in
613
616
  // kSSTStoringOddKeys and 25 blocks of even numbered blocks_key in
614
617
  // kSSTStoringEvenKeys.
615
- TraceOptions trace_opt;
618
+ BlockCacheTraceWriterOptions trace_writer_opt;
616
619
  std::unique_ptr<TraceWriter> trace_writer;
617
620
  const auto& clock = env_->GetSystemClock();
618
621
  ASSERT_OK(NewFileTraceWriter(env_, env_options_, trace_file_path_,
619
622
  &trace_writer));
620
- BlockCacheTraceWriter writer(clock.get(), trace_opt,
623
+ std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
624
+ NewBlockCacheTraceWriter(clock.get(), trace_writer_opt,
621
625
  std::move(trace_writer));
622
- ASSERT_OK(writer.WriteHeader());
626
+ ASSERT_NE(block_cache_trace_writer, nullptr);
627
+ ASSERT_OK(block_cache_trace_writer->WriteHeader());
623
628
  // Write blocks of different types.
624
- WriteBlockAccess(&writer, 0, TraceType::kBlockTraceUncompressionDictBlock,
625
- 10);
626
- WriteBlockAccess(&writer, 10, TraceType::kBlockTraceDataBlock, 10);
627
- WriteBlockAccess(&writer, 20, TraceType::kBlockTraceFilterBlock, 10);
628
- WriteBlockAccess(&writer, 30, TraceType::kBlockTraceIndexBlock, 10);
629
- WriteBlockAccess(&writer, 40, TraceType::kBlockTraceRangeDeletionBlock, 10);
629
+ WriteBlockAccess(block_cache_trace_writer.get(), 0,
630
+ TraceType::kBlockTraceUncompressionDictBlock, 10);
631
+ WriteBlockAccess(block_cache_trace_writer.get(), 10,
632
+ TraceType::kBlockTraceDataBlock, 10);
633
+ WriteBlockAccess(block_cache_trace_writer.get(), 20,
634
+ TraceType::kBlockTraceFilterBlock, 10);
635
+ WriteBlockAccess(block_cache_trace_writer.get(), 30,
636
+ TraceType::kBlockTraceIndexBlock, 10);
637
+ WriteBlockAccess(block_cache_trace_writer.get(), 40,
638
+ TraceType::kBlockTraceRangeDeletionBlock, 10);
630
639
  ASSERT_OK(env_->FileExists(trace_file_path_));
631
640
  }
632
641
 
@@ -20,7 +20,8 @@
20
20
  namespace ROCKSDB_NAMESPACE {
21
21
 
22
22
  namespace {
23
- bool ShouldTrace(const Slice& block_key, const TraceOptions& trace_options) {
23
+ bool ShouldTrace(const Slice& block_key,
24
+ const BlockCacheTraceOptions& trace_options) {
24
25
  if (trace_options.sampling_frequency == 0 ||
25
26
  trace_options.sampling_frequency == 1) {
26
27
  return true;
@@ -36,6 +37,7 @@ const uint64_t kSecondInMinute = 60;
36
37
  const uint64_t kSecondInHour = 3600;
37
38
  const std::string BlockCacheTraceHelper::kUnknownColumnFamilyName =
38
39
  "UnknownColumnFamily";
40
+ const uint64_t BlockCacheTraceRecord::kReservedGetId = 0;
39
41
  const uint64_t BlockCacheTraceHelper::kReservedGetId = 0;
40
42
 
41
43
  bool BlockCacheTraceHelper::IsGetOrMultiGetOnDataBlock(
@@ -79,9 +81,9 @@ uint64_t BlockCacheTraceHelper::GetSequenceNumber(
79
81
  if (!IsGetOrMultiGet(access.caller)) {
80
82
  return 0;
81
83
  }
82
- return access.get_from_user_specified_snapshot == Boolean::kFalse
83
- ? 0
84
- : 1 + GetInternalKeySeqno(access.referenced_key);
84
+ return access.get_from_user_specified_snapshot
85
+ ? 1 + GetInternalKeySeqno(access.referenced_key)
86
+ : 0;
85
87
  }
86
88
 
87
89
  uint64_t BlockCacheTraceHelper::GetBlockOffsetInFile(
@@ -99,14 +101,14 @@ uint64_t BlockCacheTraceHelper::GetBlockOffsetInFile(
99
101
  return offset;
100
102
  }
101
103
 
102
- BlockCacheTraceWriter::BlockCacheTraceWriter(
103
- SystemClock* clock, const TraceOptions& trace_options,
104
+ BlockCacheTraceWriterImpl::BlockCacheTraceWriterImpl(
105
+ SystemClock* clock, const BlockCacheTraceWriterOptions& trace_options,
104
106
  std::unique_ptr<TraceWriter>&& trace_writer)
105
107
  : clock_(clock),
106
108
  trace_options_(trace_options),
107
109
  trace_writer_(std::move(trace_writer)) {}
108
110
 
109
- Status BlockCacheTraceWriter::WriteBlockAccess(
111
+ Status BlockCacheTraceWriterImpl::WriteBlockAccess(
110
112
  const BlockCacheTraceRecord& record, const Slice& block_key,
111
113
  const Slice& cf_name, const Slice& referenced_key) {
112
114
  uint64_t trace_file_size = trace_writer_->GetFileSize();
@@ -141,7 +143,7 @@ Status BlockCacheTraceWriter::WriteBlockAccess(
141
143
  return trace_writer_->Write(encoded_trace);
142
144
  }
143
145
 
144
- Status BlockCacheTraceWriter::WriteHeader() {
146
+ Status BlockCacheTraceWriterImpl::WriteHeader() {
145
147
  Trace trace;
146
148
  trace.ts = clock_->NowMicros();
147
149
  trace.type = TraceType::kTraceBegin;
@@ -255,13 +257,13 @@ Status BlockCacheTraceReader::ReadAccess(BlockCacheTraceRecord* record) {
255
257
  return Status::Incomplete(
256
258
  "Incomplete access record: Failed to read is_cache_hit.");
257
259
  }
258
- record->is_cache_hit = static_cast<Boolean>(enc_slice[0]);
260
+ record->is_cache_hit = static_cast<char>(enc_slice[0]);
259
261
  enc_slice.remove_prefix(kCharSize);
260
262
  if (enc_slice.empty()) {
261
263
  return Status::Incomplete(
262
264
  "Incomplete access record: Failed to read no_insert.");
263
265
  }
264
- record->no_insert = static_cast<Boolean>(enc_slice[0]);
266
+ record->no_insert = static_cast<char>(enc_slice[0]);
265
267
  enc_slice.remove_prefix(kCharSize);
266
268
  if (BlockCacheTraceHelper::IsGetOrMultiGet(record->caller)) {
267
269
  if (!GetFixed64(&enc_slice, &record->get_id)) {
@@ -273,8 +275,7 @@ Status BlockCacheTraceReader::ReadAccess(BlockCacheTraceRecord* record) {
273
275
  "Incomplete access record: Failed to read "
274
276
  "get_from_user_specified_snapshot.");
275
277
  }
276
- record->get_from_user_specified_snapshot =
277
- static_cast<Boolean>(enc_slice[0]);
278
+ record->get_from_user_specified_snapshot = static_cast<char>(enc_slice[0]);
278
279
  enc_slice.remove_prefix(kCharSize);
279
280
  Slice referenced_key;
280
281
  if (!GetLengthPrefixedSlice(&enc_slice, &referenced_key)) {
@@ -299,7 +300,7 @@ Status BlockCacheTraceReader::ReadAccess(BlockCacheTraceRecord* record) {
299
300
  "Incomplete access record: Failed to read "
300
301
  "referenced_key_exist_in_block.");
301
302
  }
302
- record->referenced_key_exist_in_block = static_cast<Boolean>(enc_slice[0]);
303
+ record->referenced_key_exist_in_block = static_cast<char>(enc_slice[0]);
303
304
  }
304
305
  return Status::OK();
305
306
  }
@@ -391,14 +392,14 @@ Status BlockCacheHumanReadableTraceReader::ReadAccess(
391
392
  record->level = static_cast<uint32_t>(ParseUint64(record_strs[6]));
392
393
  record->sst_fd_number = ParseUint64(record_strs[7]);
393
394
  record->caller = static_cast<TableReaderCaller>(ParseUint64(record_strs[8]));
394
- record->no_insert = static_cast<Boolean>(ParseUint64(record_strs[9]));
395
+ record->no_insert = static_cast<char>(ParseUint64(record_strs[9]));
395
396
  record->get_id = ParseUint64(record_strs[10]);
396
397
  uint64_t get_key_id = ParseUint64(record_strs[11]);
397
398
 
398
399
  record->referenced_data_size = ParseUint64(record_strs[12]);
399
- record->is_cache_hit = static_cast<Boolean>(ParseUint64(record_strs[13]));
400
+ record->is_cache_hit = static_cast<char>(ParseUint64(record_strs[13]));
400
401
  record->referenced_key_exist_in_block =
401
- static_cast<Boolean>(ParseUint64(record_strs[14]));
402
+ static_cast<char>(ParseUint64(record_strs[14]));
402
403
  record->num_keys_in_block = ParseUint64(record_strs[15]);
403
404
  uint64_t table_id = ParseUint64(record_strs[16]);
404
405
  if (table_id > 0) {
@@ -408,7 +409,7 @@ Status BlockCacheHumanReadableTraceReader::ReadAccess(
408
409
  }
409
410
  uint64_t get_sequence_number = ParseUint64(record_strs[17]);
410
411
  if (get_sequence_number > 0) {
411
- record->get_from_user_specified_snapshot = Boolean::kTrue;
412
+ record->get_from_user_specified_snapshot = true;
412
413
  // Decrement since valid seq number in the trace file equals traced seq
413
414
  // number + 1.
414
415
  get_sequence_number -= 1;
@@ -445,16 +446,15 @@ BlockCacheTracer::BlockCacheTracer() { writer_.store(nullptr); }
445
446
  BlockCacheTracer::~BlockCacheTracer() { EndTrace(); }
446
447
 
447
448
  Status BlockCacheTracer::StartTrace(
448
- SystemClock* clock, const TraceOptions& trace_options,
449
- std::unique_ptr<TraceWriter>&& trace_writer) {
449
+ const BlockCacheTraceOptions& trace_options,
450
+ std::unique_ptr<BlockCacheTraceWriter>&& trace_writer) {
450
451
  InstrumentedMutexLock lock_guard(&trace_writer_mutex_);
451
452
  if (writer_.load()) {
452
453
  return Status::Busy();
453
454
  }
454
455
  get_id_counter_.store(1);
455
456
  trace_options_ = trace_options;
456
- writer_.store(
457
- new BlockCacheTraceWriter(clock, trace_options, std::move(trace_writer)));
457
+ writer_.store(trace_writer.release());
458
458
  return writer_.load()->WriteHeader();
459
459
  }
460
460
 
@@ -494,4 +494,11 @@ uint64_t BlockCacheTracer::NextGetId() {
494
494
  return prev_value;
495
495
  }
496
496
 
497
+ std::unique_ptr<BlockCacheTraceWriter> NewBlockCacheTraceWriter(
498
+ SystemClock* clock, const BlockCacheTraceWriterOptions& trace_options,
499
+ std::unique_ptr<TraceWriter>&& trace_writer) {
500
+ return std::unique_ptr<BlockCacheTraceWriter>(new BlockCacheTraceWriterImpl(
501
+ clock, trace_options, std::move(trace_writer)));
502
+ }
503
+
497
504
  } // namespace ROCKSDB_NAMESPACE
@@ -9,9 +9,10 @@
9
9
  #include <fstream>
10
10
 
11
11
  #include "monitoring/instrumented_mutex.h"
12
+ #include "rocksdb/block_cache_trace_writer.h"
12
13
  #include "rocksdb/options.h"
14
+ #include "rocksdb/table_reader_caller.h"
13
15
  #include "rocksdb/trace_reader_writer.h"
14
- #include "table/table_reader_caller.h"
15
16
  #include "trace_replay/trace_replay.h"
16
17
 
17
18
  namespace ROCKSDB_NAMESPACE {
@@ -102,65 +103,6 @@ struct BlockCacheLookupContext {
102
103
  }
103
104
  };
104
105
 
105
- enum Boolean : char { kTrue = 1, kFalse = 0 };
106
-
107
- struct BlockCacheTraceRecord {
108
- // Required fields for all accesses.
109
- uint64_t access_timestamp = 0;
110
- std::string block_key;
111
- TraceType block_type = TraceType::kTraceMax;
112
- uint64_t block_size = 0;
113
- uint64_t cf_id = 0;
114
- std::string cf_name;
115
- uint32_t level = 0;
116
- uint64_t sst_fd_number = 0;
117
- TableReaderCaller caller = TableReaderCaller::kMaxBlockCacheLookupCaller;
118
- Boolean is_cache_hit = Boolean::kFalse;
119
- Boolean no_insert = Boolean::kFalse;
120
- // Required field for Get and MultiGet
121
- uint64_t get_id = BlockCacheTraceHelper::kReservedGetId;
122
- Boolean get_from_user_specified_snapshot = Boolean::kFalse;
123
- std::string referenced_key;
124
- // Required fields for data block and user Get/Multi-Get only.
125
- uint64_t referenced_data_size = 0;
126
- uint64_t num_keys_in_block = 0;
127
- Boolean referenced_key_exist_in_block = Boolean::kFalse;
128
-
129
- BlockCacheTraceRecord() {}
130
-
131
- BlockCacheTraceRecord(
132
- uint64_t _access_timestamp, std::string _block_key, TraceType _block_type,
133
- uint64_t _block_size, uint64_t _cf_id, std::string _cf_name,
134
- uint32_t _level, uint64_t _sst_fd_number, TableReaderCaller _caller,
135
- bool _is_cache_hit, bool _no_insert,
136
- uint64_t _get_id = BlockCacheTraceHelper::kReservedGetId,
137
- bool _get_from_user_specified_snapshot = false,
138
- std::string _referenced_key = "", uint64_t _referenced_data_size = 0,
139
- uint64_t _num_keys_in_block = 0,
140
- bool _referenced_key_exist_in_block = false)
141
- : access_timestamp(_access_timestamp),
142
- block_key(_block_key),
143
- block_type(_block_type),
144
- block_size(_block_size),
145
- cf_id(_cf_id),
146
- cf_name(_cf_name),
147
- level(_level),
148
- sst_fd_number(_sst_fd_number),
149
- caller(_caller),
150
- is_cache_hit(_is_cache_hit ? Boolean::kTrue : Boolean::kFalse),
151
- no_insert(_no_insert ? Boolean::kTrue : Boolean::kFalse),
152
- get_id(_get_id),
153
- get_from_user_specified_snapshot(_get_from_user_specified_snapshot
154
- ? Boolean::kTrue
155
- : Boolean::kFalse),
156
- referenced_key(_referenced_key),
157
- referenced_data_size(_referenced_data_size),
158
- num_keys_in_block(_num_keys_in_block),
159
- referenced_key_exist_in_block(
160
- _referenced_key_exist_in_block ? Boolean::kTrue : Boolean::kFalse) {
161
- }
162
- };
163
-
164
106
  struct BlockCacheTraceHeader {
165
107
  uint64_t start_time;
166
108
  uint32_t rocksdb_major_version;
@@ -171,16 +113,18 @@ struct BlockCacheTraceHeader {
171
113
  // user-provided TraceWriter. Every RocksDB operation is written as a single
172
114
  // trace. Each trace will have a timestamp and type, followed by the trace
173
115
  // payload.
174
- class BlockCacheTraceWriter {
116
+ class BlockCacheTraceWriterImpl : public BlockCacheTraceWriter {
175
117
  public:
176
- BlockCacheTraceWriter(SystemClock* clock, const TraceOptions& trace_options,
177
- std::unique_ptr<TraceWriter>&& trace_writer);
178
- ~BlockCacheTraceWriter() = default;
118
+ BlockCacheTraceWriterImpl(SystemClock* clock,
119
+ const BlockCacheTraceWriterOptions& trace_options,
120
+ std::unique_ptr<TraceWriter>&& trace_writer);
121
+ ~BlockCacheTraceWriterImpl() = default;
179
122
  // No copy and move.
180
- BlockCacheTraceWriter(const BlockCacheTraceWriter&) = delete;
181
- BlockCacheTraceWriter& operator=(const BlockCacheTraceWriter&) = delete;
182
- BlockCacheTraceWriter(BlockCacheTraceWriter&&) = delete;
183
- BlockCacheTraceWriter& operator=(BlockCacheTraceWriter&&) = delete;
123
+ BlockCacheTraceWriterImpl(const BlockCacheTraceWriterImpl&) = delete;
124
+ BlockCacheTraceWriterImpl& operator=(const BlockCacheTraceWriterImpl&) =
125
+ delete;
126
+ BlockCacheTraceWriterImpl(BlockCacheTraceWriterImpl&&) = delete;
127
+ BlockCacheTraceWriterImpl& operator=(BlockCacheTraceWriterImpl&&) = delete;
184
128
 
185
129
  // Pass Slice references to avoid copy.
186
130
  Status WriteBlockAccess(const BlockCacheTraceRecord& record,
@@ -193,7 +137,7 @@ class BlockCacheTraceWriter {
193
137
 
194
138
  private:
195
139
  SystemClock* clock_;
196
- TraceOptions trace_options_;
140
+ BlockCacheTraceWriterOptions trace_options_;
197
141
  std::unique_ptr<TraceWriter> trace_writer_;
198
142
  };
199
143
 
@@ -267,8 +211,8 @@ class BlockCacheTracer {
267
211
  BlockCacheTracer& operator=(BlockCacheTracer&&) = delete;
268
212
 
269
213
  // Start writing block cache accesses to the trace_writer.
270
- Status StartTrace(SystemClock* clock, const TraceOptions& trace_options,
271
- std::unique_ptr<TraceWriter>&& trace_writer);
214
+ Status StartTrace(const BlockCacheTraceOptions& trace_options,
215
+ std::unique_ptr<BlockCacheTraceWriter>&& trace_writer);
272
216
 
273
217
  // Stop writing block cache accesses to the trace_writer.
274
218
  void EndTrace();
@@ -285,7 +229,7 @@ class BlockCacheTracer {
285
229
  uint64_t NextGetId();
286
230
 
287
231
  private:
288
- TraceOptions trace_options_;
232
+ BlockCacheTraceOptions trace_options_;
289
233
  // A mutex protects the writer_.
290
234
  InstrumentedMutex trace_writer_mutex_;
291
235
  std::atomic<BlockCacheTraceWriter*> writer_;
@@ -74,17 +74,17 @@ class BlockCacheTracerTest : public testing::Test {
74
74
  record.caller = GetCaller(key_id);
75
75
  record.level = kLevel;
76
76
  record.sst_fd_number = kSSTFDNumber + key_id;
77
- record.is_cache_hit = Boolean::kFalse;
78
- record.no_insert = Boolean::kFalse;
77
+ record.is_cache_hit = false;
78
+ record.no_insert = false;
79
79
  // Provide get_id for all callers. The writer should only write get_id
80
80
  // when the caller is either GET or MGET.
81
81
  record.get_id = key_id + 1;
82
- record.get_from_user_specified_snapshot = Boolean::kTrue;
82
+ record.get_from_user_specified_snapshot = true;
83
83
  // Provide these fields for all block types.
84
84
  // The writer should only write these fields for data blocks and the
85
85
  // caller is either GET or MGET.
86
86
  record.referenced_key = (kRefKeyPrefix + std::to_string(key_id));
87
- record.referenced_key_exist_in_block = Boolean::kTrue;
87
+ record.referenced_key_exist_in_block = true;
88
88
  record.num_keys_in_block = kNumKeysInBlock;
89
89
  record.referenced_data_size = kReferencedDataSize + key_id;
90
90
  ASSERT_OK(writer->WriteBlockAccess(
@@ -104,10 +104,10 @@ class BlockCacheTracerTest : public testing::Test {
104
104
  record.caller = GetCaller(key_id);
105
105
  record.level = kLevel;
106
106
  record.sst_fd_number = kSSTFDNumber + key_id;
107
- record.is_cache_hit = Boolean::kFalse;
108
- record.no_insert = Boolean::kFalse;
107
+ record.is_cache_hit = false;
108
+ record.no_insert = false;
109
109
  record.referenced_key = kRefKeyPrefix + std::to_string(key_id);
110
- record.referenced_key_exist_in_block = Boolean::kTrue;
110
+ record.referenced_key_exist_in_block = true;
111
111
  record.num_keys_in_block = kNumKeysInBlock;
112
112
  return record;
113
113
  }
@@ -127,28 +127,28 @@ class BlockCacheTracerTest : public testing::Test {
127
127
  ASSERT_EQ(GetCaller(key_id), record.caller);
128
128
  ASSERT_EQ(kLevel, record.level);
129
129
  ASSERT_EQ(kSSTFDNumber + key_id, record.sst_fd_number);
130
- ASSERT_EQ(Boolean::kFalse, record.is_cache_hit);
131
- ASSERT_EQ(Boolean::kFalse, record.no_insert);
130
+ ASSERT_FALSE(record.is_cache_hit);
131
+ ASSERT_FALSE(record.no_insert);
132
132
  if (record.caller == TableReaderCaller::kUserGet ||
133
133
  record.caller == TableReaderCaller::kUserMultiGet) {
134
134
  ASSERT_EQ(key_id + 1, record.get_id);
135
- ASSERT_EQ(Boolean::kTrue, record.get_from_user_specified_snapshot);
135
+ ASSERT_TRUE(record.get_from_user_specified_snapshot);
136
136
  ASSERT_EQ(kRefKeyPrefix + std::to_string(key_id),
137
137
  record.referenced_key);
138
138
  } else {
139
139
  ASSERT_EQ(BlockCacheTraceHelper::kReservedGetId, record.get_id);
140
- ASSERT_EQ(Boolean::kFalse, record.get_from_user_specified_snapshot);
140
+ ASSERT_FALSE(record.get_from_user_specified_snapshot);
141
141
  ASSERT_EQ("", record.referenced_key);
142
142
  }
143
143
  if (block_type == TraceType::kBlockTraceDataBlock &&
144
144
  (record.caller == TableReaderCaller::kUserGet ||
145
145
  record.caller == TableReaderCaller::kUserMultiGet)) {
146
- ASSERT_EQ(Boolean::kTrue, record.referenced_key_exist_in_block);
146
+ ASSERT_TRUE(record.referenced_key_exist_in_block);
147
147
  ASSERT_EQ(kNumKeysInBlock, record.num_keys_in_block);
148
148
  ASSERT_EQ(kReferencedDataSize + key_id, record.referenced_data_size);
149
149
  continue;
150
150
  }
151
- ASSERT_EQ(Boolean::kFalse, record.referenced_key_exist_in_block);
151
+ ASSERT_FALSE(record.referenced_key_exist_in_block);
152
152
  ASSERT_EQ(0, record.num_keys_in_block);
153
153
  ASSERT_EQ(0, record.referenced_data_size);
154
154
  }
@@ -188,12 +188,18 @@ TEST_F(BlockCacheTracerTest, AtomicWriteBeforeStartTrace) {
188
188
  TEST_F(BlockCacheTracerTest, AtomicWrite) {
189
189
  BlockCacheTraceRecord record = GenerateAccessRecord();
190
190
  {
191
- TraceOptions trace_opt;
191
+ BlockCacheTraceWriterOptions trace_writer_opt;
192
+ BlockCacheTraceOptions trace_opt;
192
193
  std::unique_ptr<TraceWriter> trace_writer;
193
194
  ASSERT_OK(NewFileTraceWriter(env_, env_options_, trace_file_path_,
194
195
  &trace_writer));
196
+ std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
197
+ NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
198
+ std::move(trace_writer));
199
+ ASSERT_NE(block_cache_trace_writer, nullptr);
195
200
  BlockCacheTracer writer;
196
- ASSERT_OK(writer.StartTrace(clock_, trace_opt, std::move(trace_writer)));
201
+ ASSERT_OK(
202
+ writer.StartTrace(trace_opt, std::move(block_cache_trace_writer)));
197
203
  ASSERT_OK(writer.WriteBlockAccess(record, record.block_key, record.cf_name,
198
204
  record.referenced_key));
199
205
  ASSERT_OK(env_->FileExists(trace_file_path_));
@@ -214,25 +220,36 @@ TEST_F(BlockCacheTracerTest, AtomicWrite) {
214
220
  }
215
221
 
216
222
  TEST_F(BlockCacheTracerTest, ConsecutiveStartTrace) {
217
- TraceOptions trace_opt;
223
+ BlockCacheTraceWriterOptions trace_writer_opt;
224
+ BlockCacheTraceOptions trace_opt;
218
225
  std::unique_ptr<TraceWriter> trace_writer;
219
226
  ASSERT_OK(
220
227
  NewFileTraceWriter(env_, env_options_, trace_file_path_, &trace_writer));
228
+ std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
229
+ NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
230
+ std::move(trace_writer));
231
+ ASSERT_NE(block_cache_trace_writer, nullptr);
221
232
  BlockCacheTracer writer;
222
- ASSERT_OK(writer.StartTrace(clock_, trace_opt, std::move(trace_writer)));
223
- ASSERT_NOK(writer.StartTrace(clock_, trace_opt, std::move(trace_writer)));
233
+ ASSERT_OK(writer.StartTrace(trace_opt, std::move(block_cache_trace_writer)));
234
+ ASSERT_NOK(writer.StartTrace(trace_opt, std::move(block_cache_trace_writer)));
224
235
  ASSERT_OK(env_->FileExists(trace_file_path_));
225
236
  }
226
237
 
227
238
  TEST_F(BlockCacheTracerTest, AtomicNoWriteAfterEndTrace) {
228
239
  BlockCacheTraceRecord record = GenerateAccessRecord();
229
240
  {
230
- TraceOptions trace_opt;
241
+ BlockCacheTraceWriterOptions trace_writer_opt;
242
+ BlockCacheTraceOptions trace_opt;
231
243
  std::unique_ptr<TraceWriter> trace_writer;
232
244
  ASSERT_OK(NewFileTraceWriter(env_, env_options_, trace_file_path_,
233
245
  &trace_writer));
246
+ std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
247
+ NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
248
+ std::move(trace_writer));
249
+ ASSERT_NE(block_cache_trace_writer, nullptr);
234
250
  BlockCacheTracer writer;
235
- ASSERT_OK(writer.StartTrace(clock_, trace_opt, std::move(trace_writer)));
251
+ ASSERT_OK(
252
+ writer.StartTrace(trace_opt, std::move(block_cache_trace_writer)));
236
253
  ASSERT_OK(writer.WriteBlockAccess(record, record.block_key, record.cf_name,
237
254
  record.referenced_key));
238
255
  writer.EndTrace();
@@ -260,14 +277,20 @@ TEST_F(BlockCacheTracerTest, AtomicNoWriteAfterEndTrace) {
260
277
  TEST_F(BlockCacheTracerTest, NextGetId) {
261
278
  BlockCacheTracer writer;
262
279
  {
263
- TraceOptions trace_opt;
280
+ BlockCacheTraceWriterOptions trace_writer_opt;
281
+ BlockCacheTraceOptions trace_opt;
264
282
  std::unique_ptr<TraceWriter> trace_writer;
265
283
  ASSERT_OK(NewFileTraceWriter(env_, env_options_, trace_file_path_,
266
284
  &trace_writer));
285
+ std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
286
+ NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
287
+ std::move(trace_writer));
288
+ ASSERT_NE(block_cache_trace_writer, nullptr);
267
289
  // next get id should always return 0 before we call StartTrace.
268
290
  ASSERT_EQ(0, writer.NextGetId());
269
291
  ASSERT_EQ(0, writer.NextGetId());
270
- ASSERT_OK(writer.StartTrace(clock_, trace_opt, std::move(trace_writer)));
292
+ ASSERT_OK(
293
+ writer.StartTrace(trace_opt, std::move(block_cache_trace_writer)));
271
294
  ASSERT_EQ(1, writer.NextGetId());
272
295
  ASSERT_EQ(2, writer.NextGetId());
273
296
  writer.EndTrace();
@@ -277,11 +300,17 @@ TEST_F(BlockCacheTracerTest, NextGetId) {
277
300
 
278
301
  // Start trace again and next get id should return 1.
279
302
  {
280
- TraceOptions trace_opt;
303
+ BlockCacheTraceWriterOptions trace_writer_opt;
304
+ BlockCacheTraceOptions trace_opt;
281
305
  std::unique_ptr<TraceWriter> trace_writer;
282
306
  ASSERT_OK(NewFileTraceWriter(env_, env_options_, trace_file_path_,
283
307
  &trace_writer));
284
- ASSERT_OK(writer.StartTrace(clock_, trace_opt, std::move(trace_writer)));
308
+ std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
309
+ NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
310
+ std::move(trace_writer));
311
+ ASSERT_NE(block_cache_trace_writer, nullptr);
312
+ ASSERT_OK(
313
+ writer.StartTrace(trace_opt, std::move(block_cache_trace_writer)));
285
314
  ASSERT_EQ(1, writer.NextGetId());
286
315
  }
287
316
  }
@@ -289,19 +318,26 @@ TEST_F(BlockCacheTracerTest, NextGetId) {
289
318
  TEST_F(BlockCacheTracerTest, MixedBlocks) {
290
319
  {
291
320
  // Generate a trace file containing a mix of blocks.
292
- TraceOptions trace_opt;
321
+ BlockCacheTraceWriterOptions trace_writer_opt;
293
322
  std::unique_ptr<TraceWriter> trace_writer;
294
323
  ASSERT_OK(NewFileTraceWriter(env_, env_options_, trace_file_path_,
295
324
  &trace_writer));
296
- BlockCacheTraceWriter writer(clock_, trace_opt, std::move(trace_writer));
297
- ASSERT_OK(writer.WriteHeader());
325
+ std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
326
+ NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
327
+ std::move(trace_writer));
328
+ ASSERT_NE(block_cache_trace_writer, nullptr);
329
+ ASSERT_OK(block_cache_trace_writer->WriteHeader());
298
330
  // Write blocks of different types.
299
- WriteBlockAccess(&writer, 0, TraceType::kBlockTraceUncompressionDictBlock,
300
- 10);
301
- WriteBlockAccess(&writer, 10, TraceType::kBlockTraceDataBlock, 10);
302
- WriteBlockAccess(&writer, 20, TraceType::kBlockTraceFilterBlock, 10);
303
- WriteBlockAccess(&writer, 30, TraceType::kBlockTraceIndexBlock, 10);
304
- WriteBlockAccess(&writer, 40, TraceType::kBlockTraceRangeDeletionBlock, 10);
331
+ WriteBlockAccess(block_cache_trace_writer.get(), 0,
332
+ TraceType::kBlockTraceUncompressionDictBlock, 10);
333
+ WriteBlockAccess(block_cache_trace_writer.get(), 10,
334
+ TraceType::kBlockTraceDataBlock, 10);
335
+ WriteBlockAccess(block_cache_trace_writer.get(), 20,
336
+ TraceType::kBlockTraceFilterBlock, 10);
337
+ WriteBlockAccess(block_cache_trace_writer.get(), 30,
338
+ TraceType::kBlockTraceIndexBlock, 10);
339
+ WriteBlockAccess(block_cache_trace_writer.get(), 40,
340
+ TraceType::kBlockTraceRangeDeletionBlock, 10);
305
341
  ASSERT_OK(env_->FileExists(trace_file_path_));
306
342
  }
307
343
 
@@ -332,7 +368,7 @@ TEST_F(BlockCacheTracerTest, HumanReadableTrace) {
332
368
  record.get_id = 1;
333
369
  record.referenced_key = "";
334
370
  record.caller = TableReaderCaller::kUserGet;
335
- record.get_from_user_specified_snapshot = Boolean::kTrue;
371
+ record.get_from_user_specified_snapshot = true;
336
372
  record.referenced_data_size = kReferencedDataSize;
337
373
  PutFixed32(&record.referenced_key, 111);
338
374
  PutLengthPrefixedSlice(&record.referenced_key, "get_key");
@@ -359,11 +395,11 @@ TEST_F(BlockCacheTracerTest, HumanReadableTrace) {
359
395
  ASSERT_EQ(TableReaderCaller::kUserGet, read_record.caller);
360
396
  ASSERT_EQ(kLevel, read_record.level);
361
397
  ASSERT_EQ(kSSTFDNumber, read_record.sst_fd_number);
362
- ASSERT_EQ(Boolean::kFalse, read_record.is_cache_hit);
363
- ASSERT_EQ(Boolean::kFalse, read_record.no_insert);
398
+ ASSERT_FALSE(read_record.is_cache_hit);
399
+ ASSERT_FALSE(read_record.no_insert);
364
400
  ASSERT_EQ(1, read_record.get_id);
365
- ASSERT_EQ(Boolean::kTrue, read_record.get_from_user_specified_snapshot);
366
- ASSERT_EQ(Boolean::kTrue, read_record.referenced_key_exist_in_block);
401
+ ASSERT_TRUE(read_record.get_from_user_specified_snapshot);
402
+ ASSERT_TRUE(read_record.referenced_key_exist_in_block);
367
403
  ASSERT_EQ(kNumKeysInBlock, read_record.num_keys_in_block);
368
404
  ASSERT_EQ(kReferencedDataSize, read_record.referenced_data_size);
369
405
  ASSERT_EQ(record.block_key.size(), read_record.block_key.size());
@@ -15,65 +15,45 @@ namespace ROCKSDB_NAMESPACE {
15
15
 
16
16
  // Wrapper of user comparator, with auto increment to
17
17
  // perf_context.user_key_comparison_count.
18
- class UserComparatorWrapper final : public Comparator {
18
+ class UserComparatorWrapper {
19
19
  public:
20
20
  // `UserComparatorWrapper`s constructed with the default constructor are not
21
21
  // usable and will segfault on any attempt to use them for comparisons.
22
22
  UserComparatorWrapper() : user_comparator_(nullptr) {}
23
23
 
24
24
  explicit UserComparatorWrapper(const Comparator* const user_cmp)
25
- : Comparator(user_cmp->timestamp_size()), user_comparator_(user_cmp) {}
25
+ : user_comparator_(user_cmp) {}
26
26
 
27
27
  ~UserComparatorWrapper() = default;
28
28
 
29
29
  const Comparator* user_comparator() const { return user_comparator_; }
30
30
 
31
- int Compare(const Slice& a, const Slice& b) const override {
31
+ int Compare(const Slice& a, const Slice& b) const {
32
32
  PERF_COUNTER_ADD(user_key_comparison_count, 1);
33
33
  return user_comparator_->Compare(a, b);
34
34
  }
35
35
 
36
- bool Equal(const Slice& a, const Slice& b) const override {
36
+ bool Equal(const Slice& a, const Slice& b) const {
37
37
  PERF_COUNTER_ADD(user_key_comparison_count, 1);
38
38
  return user_comparator_->Equal(a, b);
39
39
  }
40
40
 
41
- const char* Name() const override { return user_comparator_->Name(); }
42
-
43
- void FindShortestSeparator(std::string* start,
44
- const Slice& limit) const override {
45
- return user_comparator_->FindShortestSeparator(start, limit);
46
- }
47
-
48
- void FindShortSuccessor(std::string* key) const override {
49
- return user_comparator_->FindShortSuccessor(key);
50
- }
51
-
52
- const Comparator* GetRootComparator() const override {
53
- return user_comparator_->GetRootComparator();
54
- }
55
-
56
- bool IsSameLengthImmediateSuccessor(const Slice& s,
57
- const Slice& t) const override {
58
- return user_comparator_->IsSameLengthImmediateSuccessor(s, t);
59
- }
60
-
61
- bool CanKeysWithDifferentByteContentsBeEqual() const override {
62
- return user_comparator_->CanKeysWithDifferentByteContentsBeEqual();
41
+ int CompareTimestamp(const Slice& ts1, const Slice& ts2) const {
42
+ return user_comparator_->CompareTimestamp(ts1, ts2);
63
43
  }
64
44
 
65
- int CompareTimestamp(const Slice& ts1, const Slice& ts2) const override {
66
- return user_comparator_->CompareTimestamp(ts1, ts2);
45
+ int CompareWithoutTimestamp(const Slice& a, const Slice& b) const {
46
+ PERF_COUNTER_ADD(user_key_comparison_count, 1);
47
+ return user_comparator_->CompareWithoutTimestamp(a, b);
67
48
  }
68
49
 
69
- using Comparator::CompareWithoutTimestamp;
70
50
  int CompareWithoutTimestamp(const Slice& a, bool a_has_ts, const Slice& b,
71
- bool b_has_ts) const override {
51
+ bool b_has_ts) const {
72
52
  PERF_COUNTER_ADD(user_key_comparison_count, 1);
73
53
  return user_comparator_->CompareWithoutTimestamp(a, a_has_ts, b, b_has_ts);
74
54
  }
75
55
 
76
- bool EqualWithoutTimestamp(const Slice& a, const Slice& b) const override {
56
+ bool EqualWithoutTimestamp(const Slice& a, const Slice& b) const {
77
57
  return user_comparator_->EqualWithoutTimestamp(a, b);
78
58
  }
79
59
 
@@ -41,7 +41,7 @@ void CacheSimulator::Access(const BlockCacheTraceRecord& access) {
41
41
  const bool is_user_access =
42
42
  BlockCacheTraceHelper::IsUserAccess(access.caller);
43
43
  bool is_cache_miss = true;
44
- if (ghost_cache_ && access.no_insert == Boolean::kFalse) {
44
+ if (ghost_cache_ && !access.no_insert) {
45
45
  admit = ghost_cache_->Admit(access.block_key);
46
46
  }
47
47
  auto handle = sim_cache_->Lookup(access.block_key);
@@ -49,7 +49,7 @@ void CacheSimulator::Access(const BlockCacheTraceRecord& access) {
49
49
  sim_cache_->Release(handle);
50
50
  is_cache_miss = false;
51
51
  } else {
52
- if (access.no_insert == Boolean::kFalse && admit && access.block_size > 0) {
52
+ if (!access.no_insert && admit && access.block_size > 0) {
53
53
  // Ignore errors on insert
54
54
  auto s = sim_cache_->Insert(access.block_key, /*value=*/nullptr,
55
55
  access.block_size,
@@ -43,11 +43,11 @@ class CacheSimulatorTest : public testing::Test {
43
43
  record.level = 6;
44
44
  record.sst_fd_number = 0;
45
45
  record.get_id = getid;
46
- record.is_cache_hit = Boolean::kFalse;
47
- record.no_insert = Boolean::kFalse;
46
+ record.is_cache_hit = false;
47
+ record.no_insert = false;
48
48
  record.referenced_key =
49
49
  kRefKeyPrefix + std::to_string(kGetId) + kRefKeySequenceNumber;
50
- record.referenced_key_exist_in_block = Boolean::kTrue;
50
+ record.referenced_key_exist_in_block = true;
51
51
  record.referenced_data_size = 100;
52
52
  record.num_keys_in_block = 300;
53
53
  return record;
@@ -64,8 +64,8 @@ class CacheSimulatorTest : public testing::Test {
64
64
  record.caller = TableReaderCaller::kCompaction;
65
65
  record.level = 6;
66
66
  record.sst_fd_number = kCompactionBlockId;
67
- record.is_cache_hit = Boolean::kFalse;
68
- record.no_insert = Boolean::kTrue;
67
+ record.is_cache_hit = false;
68
+ record.no_insert = true;
69
69
  return record;
70
70
  }
71
71
 
@@ -200,17 +200,17 @@ TEST_F(CacheSimulatorTest, GhostPrioritizedCacheSimulator) {
200
200
  TEST_F(CacheSimulatorTest, HybridRowBlockCacheSimulator) {
201
201
  uint64_t block_id = 100;
202
202
  BlockCacheTraceRecord first_get = GenerateGetRecord(kGetId);
203
- first_get.get_from_user_specified_snapshot = Boolean::kTrue;
203
+ first_get.get_from_user_specified_snapshot = true;
204
204
  BlockCacheTraceRecord second_get = GenerateGetRecord(kGetId + 1);
205
205
  second_get.referenced_data_size = 0;
206
- second_get.referenced_key_exist_in_block = Boolean::kFalse;
207
- second_get.get_from_user_specified_snapshot = Boolean::kTrue;
206
+ second_get.referenced_key_exist_in_block = false;
207
+ second_get.get_from_user_specified_snapshot = true;
208
208
  BlockCacheTraceRecord third_get = GenerateGetRecord(kGetId + 2);
209
209
  third_get.referenced_data_size = 0;
210
- third_get.referenced_key_exist_in_block = Boolean::kFalse;
210
+ third_get.referenced_key_exist_in_block = false;
211
211
  third_get.referenced_key = kRefKeyPrefix + "third_get";
212
212
  // We didn't find the referenced key in the third get.
213
- third_get.referenced_key_exist_in_block = Boolean::kFalse;
213
+ third_get.referenced_key_exist_in_block = false;
214
214
  third_get.referenced_data_size = 0;
215
215
  std::shared_ptr<Cache> sim_cache =
216
216
  NewLRUCache(/*capacity=*/kCacheSize, /*num_shard_bits=*/1,
@@ -308,12 +308,12 @@ TEST_F(CacheSimulatorTest, HybridRowBlockCacheSimulatorGetTest) {
308
308
  get.access_timestamp = 0;
309
309
  get.block_key = "1";
310
310
  get.get_id = 1;
311
- get.get_from_user_specified_snapshot = Boolean::kFalse;
311
+ get.get_from_user_specified_snapshot = false;
312
312
  get.referenced_key =
313
313
  kRefKeyPrefix + std::to_string(1) + kRefKeySequenceNumber;
314
- get.no_insert = Boolean::kFalse;
314
+ get.no_insert = false;
315
315
  get.sst_fd_number = 0;
316
- get.get_from_user_specified_snapshot = Boolean::kFalse;
316
+ get.get_from_user_specified_snapshot = false;
317
317
 
318
318
  LRUCacheOptions co;
319
319
  co.capacity = 16;
@@ -311,6 +311,7 @@
311
311
  "rocksdb/options/options.cc",
312
312
  "rocksdb/options/options_helper.cc",
313
313
  "rocksdb/options/options_parser.cc",
314
+ "rocksdb/port/mmap.cc",
314
315
  "rocksdb/port/stack_trace.cc",
315
316
  "rocksdb/table/adaptive/adaptive_table_factory.cc",
316
317
  "rocksdb/table/block_based/binary_search_index_reader.cc",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/rocksdb",
3
- "version": "7.1.25",
3
+ "version": "7.1.26",
4
4
  "description": "A low-level Node.js RocksDB binding",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
Binary file