@nxtedition/rocksdb 8.0.0 → 8.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/BUILDING.md +2 -2
  2. package/binding.cc +2 -7
  3. package/deps/rocksdb/rocksdb/CMakeLists.txt +10 -9
  4. package/deps/rocksdb/rocksdb/Makefile +2 -2
  5. package/deps/rocksdb/rocksdb/TARGETS +4 -2
  6. package/deps/rocksdb/rocksdb/cache/cache_bench_tool.cc +0 -5
  7. package/deps/rocksdb/rocksdb/cache/cache_test.cc +8 -29
  8. package/deps/rocksdb/rocksdb/cache/clock_cache.cc +146 -0
  9. package/deps/rocksdb/rocksdb/cache/clock_cache.h +13 -1
  10. package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +57 -146
  11. package/deps/rocksdb/rocksdb/cache/secondary_cache.cc +32 -0
  12. package/deps/rocksdb/rocksdb/db/blob/blob_counting_iterator.h +11 -0
  13. package/deps/rocksdb/rocksdb/db/column_family.cc +11 -9
  14. package/deps/rocksdb/rocksdb/db/column_family.h +20 -0
  15. package/deps/rocksdb/rocksdb/db/compaction/clipping_iterator.h +5 -0
  16. package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +13 -33
  17. package/deps/rocksdb/rocksdb/db/compaction/compaction.h +5 -0
  18. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +27 -8
  19. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +17 -1
  20. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +2 -1
  21. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +4 -2
  22. package/deps/rocksdb/rocksdb/db/compaction/compaction_job_test.cc +8 -6
  23. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +65 -7
  24. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +5 -0
  25. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.cc +10 -32
  26. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.h +28 -47
  27. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.cc +28 -22
  28. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.h +8 -14
  29. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.cc +8 -8
  30. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.h +5 -4
  31. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +170 -140
  32. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +5 -1
  33. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.h +5 -4
  34. package/deps/rocksdb/rocksdb/db/compaction/compaction_service_job.cc +8 -2
  35. package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.h +8 -0
  36. package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +266 -138
  37. package/deps/rocksdb/rocksdb/db/corruption_test.cc +86 -1
  38. package/deps/rocksdb/rocksdb/db/db_basic_test.cc +72 -5
  39. package/deps/rocksdb/rocksdb/db/db_block_cache_test.cc +119 -10
  40. package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +585 -264
  41. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +46 -18
  42. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +5 -1
  43. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +6 -15
  44. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_debug.cc +1 -1
  45. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_experimental.cc +1 -1
  46. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +3 -0
  47. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +8 -8
  48. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_write.cc +10 -0
  49. package/deps/rocksdb/rocksdb/db/db_iter.cc +57 -36
  50. package/deps/rocksdb/rocksdb/db/db_iter.h +2 -1
  51. package/deps/rocksdb/rocksdb/db/db_range_del_test.cc +250 -2
  52. package/deps/rocksdb/rocksdb/db/db_test.cc +3 -0
  53. package/deps/rocksdb/rocksdb/db/db_test2.cc +307 -8
  54. package/deps/rocksdb/rocksdb/db/db_wal_test.cc +129 -0
  55. package/deps/rocksdb/rocksdb/db/db_with_timestamp_compaction_test.cc +21 -0
  56. package/deps/rocksdb/rocksdb/db/dbformat.cc +25 -0
  57. package/deps/rocksdb/rocksdb/db/dbformat.h +2 -0
  58. package/deps/rocksdb/rocksdb/db/experimental.cc +1 -1
  59. package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +5 -2
  60. package/deps/rocksdb/rocksdb/db/flush_job.cc +5 -2
  61. package/deps/rocksdb/rocksdb/db/history_trimming_iterator.h +4 -0
  62. package/deps/rocksdb/rocksdb/db/import_column_family_job.cc +56 -53
  63. package/deps/rocksdb/rocksdb/db/import_column_family_test.cc +3 -4
  64. package/deps/rocksdb/rocksdb/db/memtable.cc +55 -9
  65. package/deps/rocksdb/rocksdb/db/merge_helper.cc +76 -102
  66. package/deps/rocksdb/rocksdb/db/merge_helper.h +2 -11
  67. package/deps/rocksdb/rocksdb/db/periodic_task_scheduler_test.cc +10 -10
  68. package/deps/rocksdb/rocksdb/db/repair.cc +64 -22
  69. package/deps/rocksdb/rocksdb/db/repair_test.cc +54 -0
  70. package/deps/rocksdb/rocksdb/db/seqno_time_test.cc +26 -26
  71. package/deps/rocksdb/rocksdb/db/table_cache.cc +2 -0
  72. package/deps/rocksdb/rocksdb/db/table_properties_collector.h +3 -1
  73. package/deps/rocksdb/rocksdb/db/version_builder.cc +90 -43
  74. package/deps/rocksdb/rocksdb/db/version_builder.h +20 -0
  75. package/deps/rocksdb/rocksdb/db/version_builder_test.cc +190 -67
  76. package/deps/rocksdb/rocksdb/db/version_edit.cc +15 -1
  77. package/deps/rocksdb/rocksdb/db/version_edit.h +16 -4
  78. package/deps/rocksdb/rocksdb/db/version_edit_handler.cc +41 -11
  79. package/deps/rocksdb/rocksdb/db/version_edit_handler.h +27 -12
  80. package/deps/rocksdb/rocksdb/db/version_edit_test.cc +18 -16
  81. package/deps/rocksdb/rocksdb/db/version_set.cc +219 -38
  82. package/deps/rocksdb/rocksdb/db/version_set.h +34 -4
  83. package/deps/rocksdb/rocksdb/db/version_set_test.cc +45 -25
  84. package/deps/rocksdb/rocksdb/db/wide/db_wide_basic_test.cc +122 -61
  85. package/deps/rocksdb/rocksdb/db/write_thread.cc +5 -2
  86. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +0 -1
  87. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +0 -4
  88. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +12 -17
  89. package/deps/rocksdb/rocksdb/db_stress_tool/no_batched_ops_stress.cc +6 -4
  90. package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.cc +1 -1
  91. package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.h +1 -0
  92. package/deps/rocksdb/rocksdb/file/prefetch_test.cc +0 -48
  93. package/deps/rocksdb/rocksdb/file/random_access_file_reader.cc +8 -0
  94. package/deps/rocksdb/rocksdb/include/rocksdb/cache.h +196 -171
  95. package/deps/rocksdb/rocksdb/include/rocksdb/db.h +6 -0
  96. package/deps/rocksdb/rocksdb/include/rocksdb/metadata.h +9 -3
  97. package/deps/rocksdb/rocksdb/include/rocksdb/options.h +25 -18
  98. package/deps/rocksdb/rocksdb/include/rocksdb/secondary_cache.h +27 -5
  99. package/deps/rocksdb/rocksdb/include/rocksdb/statistics.h +5 -0
  100. package/deps/rocksdb/rocksdb/include/rocksdb/status.h +3 -0
  101. package/deps/rocksdb/rocksdb/include/rocksdb/table.h +3 -0
  102. package/deps/rocksdb/rocksdb/include/rocksdb/version.h +1 -1
  103. package/deps/rocksdb/rocksdb/logging/logging.h +13 -19
  104. package/deps/rocksdb/rocksdb/memory/arena.cc +4 -3
  105. package/deps/rocksdb/rocksdb/memory/arena_test.cc +30 -0
  106. package/deps/rocksdb/rocksdb/monitoring/statistics.cc +3 -1
  107. package/deps/rocksdb/rocksdb/monitoring/stats_history_test.cc +26 -26
  108. package/deps/rocksdb/rocksdb/src.mk +2 -1
  109. package/deps/rocksdb/rocksdb/table/adaptive/adaptive_table_factory.cc +3 -2
  110. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +2 -10
  111. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +12 -29
  112. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_test.cc +1 -1
  113. package/deps/rocksdb/rocksdb/table/block_based/block_like_traits.h +0 -39
  114. package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.cc +0 -1
  115. package/deps/rocksdb/rocksdb/table/block_fetcher_test.cc +3 -3
  116. package/deps/rocksdb/rocksdb/table/compaction_merging_iterator.cc +142 -0
  117. package/deps/rocksdb/rocksdb/table/compaction_merging_iterator.h +241 -0
  118. package/deps/rocksdb/rocksdb/table/format.cc +24 -20
  119. package/deps/rocksdb/rocksdb/table/format.h +5 -2
  120. package/deps/rocksdb/rocksdb/table/get_context.cc +52 -11
  121. package/deps/rocksdb/rocksdb/table/merging_iterator.cc +97 -115
  122. package/deps/rocksdb/rocksdb/table/merging_iterator.h +82 -1
  123. package/deps/rocksdb/rocksdb/table/meta_blocks.cc +2 -2
  124. package/deps/rocksdb/rocksdb/table/sst_file_dumper.cc +1 -1
  125. package/deps/rocksdb/rocksdb/table/table_test.cc +7 -6
  126. package/deps/rocksdb/rocksdb/test_util/testutil.h +10 -0
  127. package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +0 -6
  128. package/deps/rocksdb/rocksdb/trace_replay/block_cache_tracer.h +2 -2
  129. package/deps/rocksdb/rocksdb/util/bloom_test.cc +1 -1
  130. package/deps/rocksdb/rocksdb/util/crc32c.cc +1 -1
  131. package/deps/rocksdb/rocksdb/util/status.cc +7 -0
  132. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine.cc +5 -0
  133. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +4 -0
  134. package/deps/rocksdb/rocksdb/utilities/cache_dump_load_impl.cc +7 -67
  135. package/deps/rocksdb/rocksdb/utilities/cache_dump_load_impl.h +1 -3
  136. package/deps/rocksdb/rocksdb/utilities/checkpoint/checkpoint_impl.cc +1 -0
  137. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.cc +59 -0
  138. package/deps/rocksdb/rocksdb.gyp +2 -1
  139. package/package.json +1 -1
  140. package/prebuilds/darwin-arm64/node.napi.node +0 -0
  141. package/prebuilds/linux-x64/node.napi.node +0 -0
  142. package/deps/rocksdb/rocksdb/cache/fast_lru_cache.cc +0 -580
  143. package/deps/rocksdb/rocksdb/cache/fast_lru_cache.h +0 -476
  144. package/max_rev_operator.h +0 -100
@@ -112,44 +112,10 @@ Status MergeHelper::TimedFullMerge(const MergeOperator* merge_operator,
112
112
  return Status::OK();
113
113
  }
114
114
 
115
- Status MergeHelper::TimedFullMerge(const MergeOperator* merge_operator,
116
- const Slice& key, const Slice* base_value,
117
- const std::vector<Slice>& operands,
118
- std::string* value,
119
- PinnableWideColumns* columns, Logger* logger,
120
- Statistics* statistics, SystemClock* clock,
121
- Slice* result_operand,
122
- bool update_num_ops_stats) {
123
- assert(value || columns);
124
- assert(!value || !columns);
125
-
126
- std::string result;
127
- const Status s =
128
- TimedFullMerge(merge_operator, key, base_value, operands, &result, logger,
129
- statistics, clock, result_operand, update_num_ops_stats);
130
- if (!s.ok()) {
131
- return s;
132
- }
133
-
134
- if (value) {
135
- *value = std::move(result);
136
- return Status::OK();
137
- }
138
-
139
- assert(columns);
140
- columns->SetPlainValue(result);
141
-
142
- return Status::OK();
143
- }
144
-
145
115
  Status MergeHelper::TimedFullMergeWithEntity(
146
116
  const MergeOperator* merge_operator, const Slice& key, Slice base_entity,
147
- const std::vector<Slice>& operands, std::string* value,
148
- PinnableWideColumns* columns, Logger* logger, Statistics* statistics,
149
- SystemClock* clock, bool update_num_ops_stats) {
150
- assert(value || columns);
151
- assert(!value || !columns);
152
-
117
+ const std::vector<Slice>& operands, std::string* result, Logger* logger,
118
+ Statistics* statistics, SystemClock* clock, bool update_num_ops_stats) {
153
119
  WideColumns base_columns;
154
120
 
155
121
  {
@@ -168,44 +134,35 @@ Status MergeHelper::TimedFullMergeWithEntity(
168
134
  value_of_default = base_columns[0].value();
169
135
  }
170
136
 
171
- std::string result;
137
+ std::string merge_result;
172
138
 
173
139
  {
174
140
  constexpr Slice* result_operand = nullptr;
175
141
 
176
142
  const Status s = TimedFullMerge(
177
- merge_operator, key, &value_of_default, operands, &result, logger,
143
+ merge_operator, key, &value_of_default, operands, &merge_result, logger,
178
144
  statistics, clock, result_operand, update_num_ops_stats);
179
145
  if (!s.ok()) {
180
146
  return s;
181
147
  }
182
148
  }
183
149
 
184
- if (value) {
185
- *value = std::move(result);
186
- return Status::OK();
187
- }
188
-
189
- assert(columns);
190
-
191
- std::string output;
192
-
193
150
  if (has_default_column) {
194
- base_columns[0].value() = result;
151
+ base_columns[0].value() = merge_result;
195
152
 
196
- const Status s = WideColumnSerialization::Serialize(base_columns, output);
153
+ const Status s = WideColumnSerialization::Serialize(base_columns, *result);
197
154
  if (!s.ok()) {
198
155
  return s;
199
156
  }
200
157
  } else {
201
158
  const Status s =
202
- WideColumnSerialization::Serialize(result, base_columns, output);
159
+ WideColumnSerialization::Serialize(merge_result, base_columns, *result);
203
160
  if (!s.ok()) {
204
161
  return s;
205
162
  }
206
163
  }
207
164
 
208
- return columns->SetWideColumnValue(output);
165
+ return Status::OK();
209
166
  }
210
167
 
211
168
  // PRE: iter points to the first merge type entry
@@ -267,6 +224,10 @@ Status MergeHelper::MergeUntil(InternalIterator* iter,
267
224
  s = Status::ShutdownInProgress();
268
225
  return s;
269
226
  }
227
+ // Skip range tombstones emitted by the compaction iterator.
228
+ if (iter->IsDeleteRangeSentinelKey()) {
229
+ continue;
230
+ }
270
231
 
271
232
  ParsedInternalKey ikey;
272
233
  assert(keys_.size() == merge_context_.GetNumOperands());
@@ -333,66 +294,79 @@ Status MergeHelper::MergeUntil(InternalIterator* iter,
333
294
  // (almost) silently dropping the put/delete. That's probably not what we
334
295
  // want. Also if we're in compaction and it's a put, it would be nice to
335
296
  // run compaction filter on it.
336
- const Slice val = iter->value();
337
- PinnableSlice blob_value;
338
- const Slice* val_ptr;
339
- if ((kTypeValue == ikey.type || kTypeBlobIndex == ikey.type ||
340
- kTypeWideColumnEntity == ikey.type) &&
341
- (range_del_agg == nullptr ||
342
- !range_del_agg->ShouldDelete(
343
- ikey, RangeDelPositioningMode::kForwardTraversal))) {
344
- if (ikey.type == kTypeWideColumnEntity) {
345
- // TODO: support wide-column entities
346
- return Status::NotSupported(
347
- "Merge currently not supported for wide-column entities");
348
- } else if (ikey.type == kTypeBlobIndex) {
349
- BlobIndex blob_index;
350
-
351
- s = blob_index.DecodeFrom(val);
352
- if (!s.ok()) {
353
- return s;
354
- }
355
-
356
- FilePrefetchBuffer* prefetch_buffer =
357
- prefetch_buffers ? prefetch_buffers->GetOrCreatePrefetchBuffer(
358
- blob_index.file_number())
359
- : nullptr;
360
-
361
- uint64_t bytes_read = 0;
362
-
363
- assert(blob_fetcher);
364
-
365
- s = blob_fetcher->FetchBlob(ikey.user_key, blob_index,
366
- prefetch_buffer, &blob_value,
367
- &bytes_read);
368
- if (!s.ok()) {
369
- return s;
370
- }
371
-
372
- val_ptr = &blob_value;
373
-
374
- if (c_iter_stats) {
375
- ++c_iter_stats->num_blobs_read;
376
- c_iter_stats->total_blob_bytes_read += bytes_read;
377
- }
378
- } else {
379
- val_ptr = &val;
297
+ std::string merge_result;
298
+
299
+ if (range_del_agg &&
300
+ range_del_agg->ShouldDelete(
301
+ ikey, RangeDelPositioningMode::kForwardTraversal)) {
302
+ s = TimedFullMerge(user_merge_operator_, ikey.user_key, nullptr,
303
+ merge_context_.GetOperands(), &merge_result, logger_,
304
+ stats_, clock_,
305
+ /* result_operand */ nullptr,
306
+ /* update_num_ops_stats */ false);
307
+ } else if (ikey.type == kTypeValue) {
308
+ const Slice val = iter->value();
309
+
310
+ s = TimedFullMerge(user_merge_operator_, ikey.user_key, &val,
311
+ merge_context_.GetOperands(), &merge_result, logger_,
312
+ stats_, clock_,
313
+ /* result_operand */ nullptr,
314
+ /* update_num_ops_stats */ false);
315
+ } else if (ikey.type == kTypeBlobIndex) {
316
+ BlobIndex blob_index;
317
+
318
+ s = blob_index.DecodeFrom(iter->value());
319
+ if (!s.ok()) {
320
+ return s;
380
321
  }
322
+
323
+ FilePrefetchBuffer* prefetch_buffer =
324
+ prefetch_buffers ? prefetch_buffers->GetOrCreatePrefetchBuffer(
325
+ blob_index.file_number())
326
+ : nullptr;
327
+
328
+ uint64_t bytes_read = 0;
329
+
330
+ assert(blob_fetcher);
331
+
332
+ PinnableSlice blob_value;
333
+ s = blob_fetcher->FetchBlob(ikey.user_key, blob_index, prefetch_buffer,
334
+ &blob_value, &bytes_read);
335
+ if (!s.ok()) {
336
+ return s;
337
+ }
338
+
339
+ if (c_iter_stats) {
340
+ ++c_iter_stats->num_blobs_read;
341
+ c_iter_stats->total_blob_bytes_read += bytes_read;
342
+ }
343
+
344
+ s = TimedFullMerge(user_merge_operator_, ikey.user_key, &blob_value,
345
+ merge_context_.GetOperands(), &merge_result, logger_,
346
+ stats_, clock_,
347
+ /* result_operand */ nullptr,
348
+ /* update_num_ops_stats */ false);
349
+ } else if (ikey.type == kTypeWideColumnEntity) {
350
+ s = TimedFullMergeWithEntity(
351
+ user_merge_operator_, ikey.user_key, iter->value(),
352
+ merge_context_.GetOperands(), &merge_result, logger_, stats_,
353
+ clock_, /* update_num_ops_stats */ false);
381
354
  } else {
382
- val_ptr = nullptr;
355
+ s = TimedFullMerge(user_merge_operator_, ikey.user_key, nullptr,
356
+ merge_context_.GetOperands(), &merge_result, logger_,
357
+ stats_, clock_,
358
+ /* result_operand */ nullptr,
359
+ /* update_num_ops_stats */ false);
383
360
  }
384
- std::string merge_result;
385
- s = TimedFullMerge(
386
- user_merge_operator_, ikey.user_key, val_ptr,
387
- merge_context_.GetOperands(), &merge_result, logger_, stats_, clock_,
388
- /* result_operand */ nullptr, /* update_num_ops_stats */ false);
389
361
 
390
362
  // We store the result in keys_.back() and operands_.back()
391
363
  // if nothing went wrong (i.e.: no operand corruption on disk)
392
364
  if (s.ok()) {
393
365
  // The original key encountered
394
366
  original_key = std::move(keys_.back());
395
- orig_ikey.type = kTypeValue;
367
+ orig_ikey.type = ikey.type == kTypeWideColumnEntity
368
+ ? kTypeWideColumnEntity
369
+ : kTypeValue;
396
370
  UpdateInternalKey(&original_key, orig_ikey.sequence, orig_ikey.type);
397
371
  keys_.clear();
398
372
  merge_context_.Clear();
@@ -57,19 +57,10 @@ class MergeHelper {
57
57
  Slice* result_operand,
58
58
  bool update_num_ops_stats);
59
59
 
60
- static Status TimedFullMerge(const MergeOperator* merge_operator,
61
- const Slice& key, const Slice* base_value,
62
- const std::vector<Slice>& operands,
63
- std::string* value, PinnableWideColumns* columns,
64
- Logger* logger, Statistics* statistics,
65
- SystemClock* clock, Slice* result_operand,
66
- bool update_num_ops_stats);
67
-
68
60
  static Status TimedFullMergeWithEntity(
69
61
  const MergeOperator* merge_operator, const Slice& key, Slice base_entity,
70
- const std::vector<Slice>& operands, std::string* value,
71
- PinnableWideColumns* columns, Logger* logger, Statistics* statistics,
72
- SystemClock* clock, bool update_num_ops_stats);
62
+ const std::vector<Slice>& operands, std::string* result, Logger* logger,
63
+ Statistics* statistics, SystemClock* clock, bool update_num_ops_stats);
73
64
 
74
65
  // During compaction, merge entries until we hit
75
66
  // - a corrupted key
@@ -65,7 +65,7 @@ TEST_F(PeriodicTaskSchedulerTest, Basic) {
65
65
  ASSERT_EQ(kPeriodSec, dbfull()->GetDBOptions().stats_persist_period_sec);
66
66
 
67
67
  ASSERT_GT(kPeriodSec, 1u);
68
- dbfull()->TEST_WaitForPeridicTaskRun([&] {
68
+ dbfull()->TEST_WaitForPeriodicTaskRun([&] {
69
69
  mock_clock_->MockSleepForSeconds(static_cast<int>(kPeriodSec) - 1);
70
70
  });
71
71
 
@@ -77,14 +77,14 @@ TEST_F(PeriodicTaskSchedulerTest, Basic) {
77
77
  ASSERT_EQ(1, pst_st_counter);
78
78
  ASSERT_EQ(1, flush_info_log_counter);
79
79
 
80
- dbfull()->TEST_WaitForPeridicTaskRun(
80
+ dbfull()->TEST_WaitForPeriodicTaskRun(
81
81
  [&] { mock_clock_->MockSleepForSeconds(static_cast<int>(kPeriodSec)); });
82
82
 
83
83
  ASSERT_EQ(2, dump_st_counter);
84
84
  ASSERT_EQ(2, pst_st_counter);
85
85
  ASSERT_EQ(2, flush_info_log_counter);
86
86
 
87
- dbfull()->TEST_WaitForPeridicTaskRun(
87
+ dbfull()->TEST_WaitForPeriodicTaskRun(
88
88
  [&] { mock_clock_->MockSleepForSeconds(static_cast<int>(kPeriodSec)); });
89
89
 
90
90
  ASSERT_EQ(3, dump_st_counter);
@@ -98,7 +98,7 @@ TEST_F(PeriodicTaskSchedulerTest, Basic) {
98
98
  ASSERT_EQ(0u, dbfull()->GetDBOptions().stats_persist_period_sec);
99
99
 
100
100
  // Info log flush should still run.
101
- dbfull()->TEST_WaitForPeridicTaskRun(
101
+ dbfull()->TEST_WaitForPeriodicTaskRun(
102
102
  [&] { mock_clock_->MockSleepForSeconds(static_cast<int>(kPeriodSec)); });
103
103
  ASSERT_EQ(3, dump_st_counter);
104
104
  ASSERT_EQ(3, pst_st_counter);
@@ -113,7 +113,7 @@ TEST_F(PeriodicTaskSchedulerTest, Basic) {
113
113
 
114
114
  ASSERT_EQ(2, scheduler.TEST_GetValidTaskNum());
115
115
 
116
- dbfull()->TEST_WaitForPeridicTaskRun(
116
+ dbfull()->TEST_WaitForPeriodicTaskRun(
117
117
  [&] { mock_clock_->MockSleepForSeconds(static_cast<int>(kPeriodSec)); });
118
118
  ASSERT_EQ(4, dump_st_counter);
119
119
  ASSERT_EQ(3, pst_st_counter);
@@ -154,19 +154,19 @@ TEST_F(PeriodicTaskSchedulerTest, MultiInstances) {
154
154
  ASSERT_EQ(kInstanceNum * 3, scheduler.TEST_GetValidTaskNum());
155
155
 
156
156
  int expected_run = kInstanceNum;
157
- dbi->TEST_WaitForPeridicTaskRun(
157
+ dbi->TEST_WaitForPeriodicTaskRun(
158
158
  [&] { mock_clock_->MockSleepForSeconds(kPeriodSec - 1); });
159
159
  ASSERT_EQ(expected_run, dump_st_counter);
160
160
  ASSERT_EQ(expected_run, pst_st_counter);
161
161
 
162
162
  expected_run += kInstanceNum;
163
- dbi->TEST_WaitForPeridicTaskRun(
163
+ dbi->TEST_WaitForPeriodicTaskRun(
164
164
  [&] { mock_clock_->MockSleepForSeconds(kPeriodSec); });
165
165
  ASSERT_EQ(expected_run, dump_st_counter);
166
166
  ASSERT_EQ(expected_run, pst_st_counter);
167
167
 
168
168
  expected_run += kInstanceNum;
169
- dbi->TEST_WaitForPeridicTaskRun(
169
+ dbi->TEST_WaitForPeriodicTaskRun(
170
170
  [&] { mock_clock_->MockSleepForSeconds(kPeriodSec); });
171
171
  ASSERT_EQ(expected_run, dump_st_counter);
172
172
  ASSERT_EQ(expected_run, pst_st_counter);
@@ -178,9 +178,9 @@ TEST_F(PeriodicTaskSchedulerTest, MultiInstances) {
178
178
 
179
179
  expected_run += (kInstanceNum - half) * 2;
180
180
 
181
- dbi->TEST_WaitForPeridicTaskRun(
181
+ dbi->TEST_WaitForPeriodicTaskRun(
182
182
  [&] { mock_clock_->MockSleepForSeconds(kPeriodSec); });
183
- dbi->TEST_WaitForPeridicTaskRun(
183
+ dbi->TEST_WaitForPeriodicTaskRun(
184
184
  [&] { mock_clock_->MockSleepForSeconds(kPeriodSec); });
185
185
  ASSERT_EQ(expected_run, dump_st_counter);
186
186
  ASSERT_EQ(expected_run, pst_st_counter);
@@ -59,6 +59,7 @@
59
59
  // Store per-table metadata (smallest, largest, largest-seq#, ...)
60
60
  // in the table's meta section to speed up ScanTable.
61
61
 
62
+ #include "db/version_builder.h"
62
63
  #ifndef ROCKSDB_LITE
63
64
 
64
65
  #include <cinttypes>
@@ -640,38 +641,79 @@ class Repairer {
640
641
  for (const auto& cf_id_and_tables : cf_id_to_tables) {
641
642
  auto* cfd =
642
643
  vset_.GetColumnFamilySet()->GetColumnFamily(cf_id_and_tables.first);
643
- VersionEdit edit;
644
- edit.SetComparatorName(cfd->user_comparator()->Name());
645
- edit.SetLogNumber(0);
646
- edit.SetNextFile(next_file_number_);
647
- edit.SetColumnFamily(cfd->GetID());
648
644
 
649
- // TODO(opt): separate out into multiple levels
645
+ // Recover files' epoch number using dummy VersionStorageInfo
646
+ VersionBuilder dummy_version_builder(
647
+ cfd->current()->version_set()->file_options(), cfd->ioptions(),
648
+ cfd->table_cache(), cfd->current()->storage_info(),
649
+ cfd->current()->version_set(),
650
+ cfd->GetFileMetadataCacheReservationManager());
651
+ VersionStorageInfo dummy_vstorage(
652
+ &cfd->internal_comparator(), cfd->user_comparator(),
653
+ cfd->NumberLevels(), cfd->ioptions()->compaction_style,
654
+ nullptr /* src_vstorage */, cfd->ioptions()->force_consistency_checks,
655
+ EpochNumberRequirement::kMightMissing);
656
+ Status s;
657
+ VersionEdit dummy_edit;
650
658
  for (const auto* table : cf_id_and_tables.second) {
651
- edit.AddFile(
659
+ // TODO(opt): separate out into multiple levels
660
+ dummy_edit.AddFile(
652
661
  0, table->meta.fd.GetNumber(), table->meta.fd.GetPathId(),
653
662
  table->meta.fd.GetFileSize(), table->meta.smallest,
654
663
  table->meta.largest, table->meta.fd.smallest_seqno,
655
664
  table->meta.fd.largest_seqno, table->meta.marked_for_compaction,
656
665
  table->meta.temperature, table->meta.oldest_blob_file_number,
657
666
  table->meta.oldest_ancester_time, table->meta.file_creation_time,
658
- table->meta.file_checksum, table->meta.file_checksum_func_name,
659
- table->meta.unique_id);
667
+ table->meta.epoch_number, table->meta.file_checksum,
668
+ table->meta.file_checksum_func_name, table->meta.unique_id);
660
669
  }
661
- assert(next_file_number_ > 0);
662
- vset_.MarkFileNumberUsed(next_file_number_ - 1);
663
- mutex_.Lock();
664
- std::unique_ptr<FSDirectory> db_dir;
665
- Status status = env_->GetFileSystem()->NewDirectory(dbname_, IOOptions(),
666
- &db_dir, nullptr);
667
- if (status.ok()) {
668
- status = vset_.LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(),
669
- &edit, &mutex_, db_dir.get(),
670
- false /* new_descriptor_log */);
670
+ s = dummy_version_builder.Apply(&dummy_edit);
671
+ if (s.ok()) {
672
+ s = dummy_version_builder.SaveTo(&dummy_vstorage);
671
673
  }
672
- mutex_.Unlock();
673
- if (!status.ok()) {
674
- return status;
674
+ if (s.ok()) {
675
+ dummy_vstorage.RecoverEpochNumbers(cfd);
676
+ }
677
+ if (s.ok()) {
678
+ // Record changes from this repair in VersionEdit, including files with
679
+ // recovered epoch numbers
680
+ VersionEdit edit;
681
+ edit.SetComparatorName(cfd->user_comparator()->Name());
682
+ edit.SetLogNumber(0);
683
+ edit.SetNextFile(next_file_number_);
684
+ edit.SetColumnFamily(cfd->GetID());
685
+ for (int level = 0; level < dummy_vstorage.num_levels(); ++level) {
686
+ for (FileMetaData* file_meta : dummy_vstorage.LevelFiles(level)) {
687
+ edit.AddFile(level, *file_meta);
688
+ }
689
+ }
690
+
691
+ // Release resources occupied by the dummy VersionStorageInfo
692
+ for (int level = 0; level < dummy_vstorage.num_levels(); ++level) {
693
+ for (FileMetaData* file_meta : dummy_vstorage.LevelFiles(level)) {
694
+ file_meta->refs--;
695
+ if (file_meta->refs <= 0) {
696
+ delete file_meta;
697
+ }
698
+ }
699
+ }
700
+
701
+ // Persist record of changes
702
+ assert(next_file_number_ > 0);
703
+ vset_.MarkFileNumberUsed(next_file_number_ - 1);
704
+ mutex_.Lock();
705
+ std::unique_ptr<FSDirectory> db_dir;
706
+ s = env_->GetFileSystem()->NewDirectory(dbname_, IOOptions(), &db_dir,
707
+ nullptr);
708
+ if (s.ok()) {
709
+ s = vset_.LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(), &edit,
710
+ &mutex_, db_dir.get(),
711
+ false /* new_descriptor_log */);
712
+ }
713
+ mutex_.Unlock();
714
+ }
715
+ if (!s.ok()) {
716
+ return s;
675
717
  }
676
718
  }
677
719
  return Status::OK();
@@ -62,8 +62,62 @@ class RepairTest : public DBTestBase {
62
62
  ASSERT_GT(verify_passed, 0);
63
63
  SyncPoint::GetInstance()->DisableProcessing();
64
64
  }
65
+
66
+ std::vector<FileMetaData*> GetLevelFileMetadatas(int level, int cf = 0) {
67
+ VersionSet* const versions = dbfull()->GetVersionSet();
68
+ assert(versions);
69
+ ColumnFamilyData* const cfd =
70
+ versions->GetColumnFamilySet()->GetColumnFamily(cf);
71
+ assert(cfd);
72
+ Version* const current = cfd->current();
73
+ assert(current);
74
+ VersionStorageInfo* const storage_info = current->storage_info();
75
+ assert(storage_info);
76
+ return storage_info->LevelFiles(level);
77
+ }
65
78
  };
66
79
 
80
+ TEST_F(RepairTest, SortRepairedDBL0ByEpochNumber) {
81
+ Options options = CurrentOptions();
82
+ DestroyAndReopen(options);
83
+
84
+ ASSERT_OK(Put("k1", "oldest"));
85
+ ASSERT_OK(Put("k1", "older"));
86
+ ASSERT_OK(Flush());
87
+ MoveFilesToLevel(1);
88
+
89
+ ASSERT_OK(Put("k1", "old"));
90
+ ASSERT_OK(Flush());
91
+
92
+ ASSERT_OK(Put("k1", "new"));
93
+
94
+ std::vector<FileMetaData*> level0_files = GetLevelFileMetadatas(0 /* level*/);
95
+ ASSERT_EQ(level0_files.size(), 1);
96
+ ASSERT_EQ(level0_files[0]->epoch_number, 2);
97
+ std::vector<FileMetaData*> level1_files = GetLevelFileMetadatas(1 /* level*/);
98
+ ASSERT_EQ(level1_files.size(), 1);
99
+ ASSERT_EQ(level1_files[0]->epoch_number, 1);
100
+
101
+ std::string manifest_path =
102
+ DescriptorFileName(dbname_, dbfull()->TEST_Current_Manifest_FileNo());
103
+ Close();
104
+ ASSERT_OK(env_->FileExists(manifest_path));
105
+ ASSERT_OK(env_->DeleteFile(manifest_path));
106
+
107
+ ASSERT_OK(RepairDB(dbname_, CurrentOptions()));
108
+ ReopenWithSstIdVerify();
109
+
110
+ EXPECT_EQ(Get("k1"), "new");
111
+
112
+ level0_files = GetLevelFileMetadatas(0 /* level*/);
113
+ ASSERT_EQ(level0_files.size(), 3);
114
+ EXPECT_EQ(level0_files[0]->epoch_number, 3);
115
+ EXPECT_EQ(level0_files[1]->epoch_number, 2);
116
+ EXPECT_EQ(level0_files[2]->epoch_number, 1);
117
+ level1_files = GetLevelFileMetadatas(1 /* level*/);
118
+ ASSERT_EQ(level1_files.size(), 0);
119
+ }
120
+
67
121
  TEST_F(RepairTest, LostManifest) {
68
122
  // Add a couple SST files, delete the manifest, and verify RepairDB() saves
69
123
  // the day.