@nxtedition/rocksdb 8.0.1 → 8.0.3

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 (129) hide show
  1. package/deps/rocksdb/rocksdb/CMakeLists.txt +2 -1
  2. package/deps/rocksdb/rocksdb/Makefile +2 -2
  3. package/deps/rocksdb/rocksdb/TARGETS +4 -2
  4. package/deps/rocksdb/rocksdb/cache/cache_bench_tool.cc +0 -5
  5. package/deps/rocksdb/rocksdb/cache/cache_test.cc +8 -29
  6. package/deps/rocksdb/rocksdb/cache/clock_cache.cc +146 -0
  7. package/deps/rocksdb/rocksdb/cache/clock_cache.h +13 -1
  8. package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +20 -146
  9. package/deps/rocksdb/rocksdb/cache/secondary_cache.cc +32 -0
  10. package/deps/rocksdb/rocksdb/db/blob/blob_counting_iterator.h +11 -0
  11. package/deps/rocksdb/rocksdb/db/column_family.cc +11 -9
  12. package/deps/rocksdb/rocksdb/db/column_family.h +20 -0
  13. package/deps/rocksdb/rocksdb/db/compaction/clipping_iterator.h +5 -0
  14. package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +13 -33
  15. package/deps/rocksdb/rocksdb/db/compaction/compaction.h +5 -0
  16. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +27 -8
  17. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +17 -1
  18. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +2 -1
  19. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +4 -2
  20. package/deps/rocksdb/rocksdb/db/compaction/compaction_job_test.cc +8 -6
  21. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +65 -7
  22. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +5 -0
  23. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.cc +10 -32
  24. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.h +28 -47
  25. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.cc +28 -22
  26. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.h +8 -14
  27. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.cc +8 -8
  28. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.h +5 -4
  29. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +170 -140
  30. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +5 -1
  31. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.h +5 -4
  32. package/deps/rocksdb/rocksdb/db/compaction/compaction_service_job.cc +8 -2
  33. package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.h +8 -0
  34. package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +266 -138
  35. package/deps/rocksdb/rocksdb/db/corruption_test.cc +86 -1
  36. package/deps/rocksdb/rocksdb/db/db_basic_test.cc +72 -5
  37. package/deps/rocksdb/rocksdb/db/db_block_cache_test.cc +119 -10
  38. package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +585 -264
  39. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +46 -18
  40. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +5 -1
  41. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +6 -15
  42. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_debug.cc +1 -1
  43. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_experimental.cc +1 -1
  44. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +3 -0
  45. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +8 -8
  46. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_write.cc +10 -0
  47. package/deps/rocksdb/rocksdb/db/db_range_del_test.cc +250 -2
  48. package/deps/rocksdb/rocksdb/db/db_test.cc +3 -0
  49. package/deps/rocksdb/rocksdb/db/db_test2.cc +307 -8
  50. package/deps/rocksdb/rocksdb/db/db_wal_test.cc +129 -0
  51. package/deps/rocksdb/rocksdb/db/db_with_timestamp_compaction_test.cc +21 -0
  52. package/deps/rocksdb/rocksdb/db/dbformat.cc +25 -0
  53. package/deps/rocksdb/rocksdb/db/dbformat.h +2 -0
  54. package/deps/rocksdb/rocksdb/db/experimental.cc +1 -1
  55. package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +5 -2
  56. package/deps/rocksdb/rocksdb/db/flush_job.cc +5 -2
  57. package/deps/rocksdb/rocksdb/db/history_trimming_iterator.h +4 -0
  58. package/deps/rocksdb/rocksdb/db/import_column_family_job.cc +56 -53
  59. package/deps/rocksdb/rocksdb/db/import_column_family_test.cc +3 -4
  60. package/deps/rocksdb/rocksdb/db/merge_helper.cc +4 -0
  61. package/deps/rocksdb/rocksdb/db/periodic_task_scheduler_test.cc +10 -10
  62. package/deps/rocksdb/rocksdb/db/repair.cc +64 -22
  63. package/deps/rocksdb/rocksdb/db/repair_test.cc +54 -0
  64. package/deps/rocksdb/rocksdb/db/seqno_time_test.cc +26 -26
  65. package/deps/rocksdb/rocksdb/db/table_cache.cc +2 -0
  66. package/deps/rocksdb/rocksdb/db/table_properties_collector.h +3 -1
  67. package/deps/rocksdb/rocksdb/db/version_builder.cc +90 -43
  68. package/deps/rocksdb/rocksdb/db/version_builder.h +20 -0
  69. package/deps/rocksdb/rocksdb/db/version_builder_test.cc +190 -67
  70. package/deps/rocksdb/rocksdb/db/version_edit.cc +15 -1
  71. package/deps/rocksdb/rocksdb/db/version_edit.h +16 -4
  72. package/deps/rocksdb/rocksdb/db/version_edit_handler.cc +41 -11
  73. package/deps/rocksdb/rocksdb/db/version_edit_handler.h +27 -12
  74. package/deps/rocksdb/rocksdb/db/version_edit_test.cc +18 -16
  75. package/deps/rocksdb/rocksdb/db/version_set.cc +212 -35
  76. package/deps/rocksdb/rocksdb/db/version_set.h +34 -4
  77. package/deps/rocksdb/rocksdb/db/version_set_test.cc +45 -25
  78. package/deps/rocksdb/rocksdb/db/write_thread.cc +5 -2
  79. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +0 -1
  80. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +0 -4
  81. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +12 -17
  82. package/deps/rocksdb/rocksdb/db_stress_tool/no_batched_ops_stress.cc +6 -4
  83. package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.h +1 -0
  84. package/deps/rocksdb/rocksdb/file/prefetch_test.cc +0 -48
  85. package/deps/rocksdb/rocksdb/file/random_access_file_reader.cc +8 -0
  86. package/deps/rocksdb/rocksdb/include/rocksdb/cache.h +196 -171
  87. package/deps/rocksdb/rocksdb/include/rocksdb/db.h +6 -0
  88. package/deps/rocksdb/rocksdb/include/rocksdb/metadata.h +9 -3
  89. package/deps/rocksdb/rocksdb/include/rocksdb/options.h +25 -18
  90. package/deps/rocksdb/rocksdb/include/rocksdb/secondary_cache.h +27 -5
  91. package/deps/rocksdb/rocksdb/include/rocksdb/statistics.h +5 -0
  92. package/deps/rocksdb/rocksdb/include/rocksdb/status.h +3 -0
  93. package/deps/rocksdb/rocksdb/include/rocksdb/version.h +1 -1
  94. package/deps/rocksdb/rocksdb/logging/logging.h +13 -19
  95. package/deps/rocksdb/rocksdb/memory/arena.cc +4 -3
  96. package/deps/rocksdb/rocksdb/memory/arena_test.cc +30 -0
  97. package/deps/rocksdb/rocksdb/monitoring/statistics.cc +3 -1
  98. package/deps/rocksdb/rocksdb/monitoring/stats_history_test.cc +26 -26
  99. package/deps/rocksdb/rocksdb/src.mk +2 -1
  100. package/deps/rocksdb/rocksdb/table/adaptive/adaptive_table_factory.cc +3 -2
  101. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +3 -2
  102. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_test.cc +1 -1
  103. package/deps/rocksdb/rocksdb/table/block_fetcher_test.cc +3 -3
  104. package/deps/rocksdb/rocksdb/table/compaction_merging_iterator.cc +142 -0
  105. package/deps/rocksdb/rocksdb/table/compaction_merging_iterator.h +241 -0
  106. package/deps/rocksdb/rocksdb/table/format.cc +24 -20
  107. package/deps/rocksdb/rocksdb/table/format.h +5 -2
  108. package/deps/rocksdb/rocksdb/table/merging_iterator.cc +97 -115
  109. package/deps/rocksdb/rocksdb/table/merging_iterator.h +82 -1
  110. package/deps/rocksdb/rocksdb/table/meta_blocks.cc +2 -2
  111. package/deps/rocksdb/rocksdb/table/sst_file_dumper.cc +1 -1
  112. package/deps/rocksdb/rocksdb/table/table_test.cc +7 -6
  113. package/deps/rocksdb/rocksdb/test_util/testutil.h +10 -0
  114. package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +0 -6
  115. package/deps/rocksdb/rocksdb/trace_replay/block_cache_tracer.h +2 -2
  116. package/deps/rocksdb/rocksdb/util/bloom_test.cc +1 -1
  117. package/deps/rocksdb/rocksdb/util/status.cc +7 -0
  118. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine.cc +5 -0
  119. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +4 -0
  120. package/deps/rocksdb/rocksdb/utilities/cache_dump_load_impl.cc +7 -67
  121. package/deps/rocksdb/rocksdb/utilities/cache_dump_load_impl.h +1 -3
  122. package/deps/rocksdb/rocksdb/utilities/checkpoint/checkpoint_impl.cc +1 -0
  123. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.cc +59 -0
  124. package/deps/rocksdb/rocksdb.gyp +2 -1
  125. package/package.json +1 -1
  126. package/prebuilds/darwin-arm64/node.napi.node +0 -0
  127. package/prebuilds/linux-x64/node.napi.node +0 -0
  128. package/deps/rocksdb/rocksdb/cache/fast_lru_cache.cc +0 -580
  129. package/deps/rocksdb/rocksdb/cache/fast_lru_cache.h +0 -476
@@ -14,6 +14,7 @@
14
14
 
15
15
  #include "db/db_test_util.h"
16
16
  #include "db/read_callback.h"
17
+ #include "db/version_edit.h"
17
18
  #include "options/options_helper.h"
18
19
  #include "port/port.h"
19
20
  #include "port/stack_trace.h"
@@ -33,6 +34,18 @@ namespace ROCKSDB_NAMESPACE {
33
34
  class DBTest2 : public DBTestBase {
34
35
  public:
35
36
  DBTest2() : DBTestBase("db_test2", /*env_do_fsync=*/true) {}
37
+ std::vector<FileMetaData*> GetLevelFileMetadatas(int level, int cf = 0) {
38
+ VersionSet* const versions = dbfull()->GetVersionSet();
39
+ assert(versions);
40
+ ColumnFamilyData* const cfd =
41
+ versions->GetColumnFamilySet()->GetColumnFamily(cf);
42
+ assert(cfd);
43
+ Version* const current = cfd->current();
44
+ assert(current);
45
+ VersionStorageInfo* const storage_info = current->storage_info();
46
+ assert(storage_info);
47
+ return storage_info->LevelFiles(level);
48
+ }
36
49
  };
37
50
 
38
51
  #ifndef ROCKSDB_LITE
@@ -4523,7 +4536,7 @@ TEST_F(DBTest2, TraceAndReplay) {
4523
4536
  ASSERT_OK(replayer->Prepare());
4524
4537
  // Replay using 1 thread, 1x speed.
4525
4538
  ASSERT_OK(replayer->Replay(ReplayOptions(1, 1.0), res_cb));
4526
- ASSERT_GT(res_handler.GetAvgLatency(), 0.0);
4539
+ ASSERT_GE(res_handler.GetAvgLatency(), 0.0);
4527
4540
  ASSERT_EQ(res_handler.GetNumWrites(), 8);
4528
4541
  ASSERT_EQ(res_handler.GetNumGets(), 3);
4529
4542
  ASSERT_EQ(res_handler.GetNumIterSeeks(), 2);
@@ -4549,7 +4562,7 @@ TEST_F(DBTest2, TraceAndReplay) {
4549
4562
  // Re-replay using 2 threads, 2x speed.
4550
4563
  ASSERT_OK(replayer->Prepare());
4551
4564
  ASSERT_OK(replayer->Replay(ReplayOptions(2, 2.0), res_cb));
4552
- ASSERT_GT(res_handler.GetAvgLatency(), 0.0);
4565
+ ASSERT_GE(res_handler.GetAvgLatency(), 0.0);
4553
4566
  ASSERT_EQ(res_handler.GetNumWrites(), 8);
4554
4567
  ASSERT_EQ(res_handler.GetNumGets(), 3);
4555
4568
  ASSERT_EQ(res_handler.GetNumIterSeeks(), 2);
@@ -4559,7 +4572,7 @@ TEST_F(DBTest2, TraceAndReplay) {
4559
4572
  // Re-replay using 2 threads, 1/2 speed.
4560
4573
  ASSERT_OK(replayer->Prepare());
4561
4574
  ASSERT_OK(replayer->Replay(ReplayOptions(2, 0.5), res_cb));
4562
- ASSERT_GT(res_handler.GetAvgLatency(), 0.0);
4575
+ ASSERT_GE(res_handler.GetAvgLatency(), 0.0);
4563
4576
  ASSERT_EQ(res_handler.GetNumWrites(), 8);
4564
4577
  ASSERT_EQ(res_handler.GetNumGets(), 3);
4565
4578
  ASSERT_EQ(res_handler.GetNumIterSeeks(), 2);
@@ -4757,7 +4770,7 @@ TEST_F(DBTest2, TraceAndManualReplay) {
4757
4770
  // end, or Prepare() was not called.
4758
4771
  ASSERT_TRUE(s.IsIncomplete());
4759
4772
  ASSERT_TRUE(replayer->Next(nullptr).IsIncomplete());
4760
- ASSERT_GT(res_handler.GetAvgLatency(), 0.0);
4773
+ ASSERT_GE(res_handler.GetAvgLatency(), 0.0);
4761
4774
  ASSERT_EQ(res_handler.GetNumWrites(), 9);
4762
4775
  ASSERT_EQ(res_handler.GetNumGets(), 3);
4763
4776
  ASSERT_EQ(res_handler.GetNumIterSeeks(), 8);
@@ -4791,7 +4804,7 @@ TEST_F(DBTest2, TraceAndManualReplay) {
4791
4804
  ASSERT_EQ("write1", value);
4792
4805
  ASSERT_OK(db2->Get(ro, handles[0], "trace-record-write2", &value));
4793
4806
  ASSERT_EQ("write2", value);
4794
- ASSERT_GT(res_handler.GetAvgLatency(), 0.0);
4807
+ ASSERT_GE(res_handler.GetAvgLatency(), 0.0);
4795
4808
  ASSERT_EQ(res_handler.GetNumWrites(), 1);
4796
4809
  ASSERT_EQ(res_handler.GetNumGets(), 0);
4797
4810
  ASSERT_EQ(res_handler.GetNumIterSeeks(), 0);
@@ -4816,7 +4829,7 @@ TEST_F(DBTest2, TraceAndManualReplay) {
4816
4829
  record.reset(new GetQueryTraceRecord(invalid_cf_id, "whatever", fake_ts++));
4817
4830
  ASSERT_TRUE(replayer->Execute(record, &result).IsCorruption());
4818
4831
  ASSERT_TRUE(result == nullptr);
4819
- ASSERT_GT(res_handler.GetAvgLatency(), 0.0);
4832
+ ASSERT_GE(res_handler.GetAvgLatency(), 0.0);
4820
4833
  ASSERT_EQ(res_handler.GetNumWrites(), 0);
4821
4834
  ASSERT_EQ(res_handler.GetNumGets(), 2);
4822
4835
  ASSERT_EQ(res_handler.GetNumIterSeeks(), 0);
@@ -4845,7 +4858,7 @@ TEST_F(DBTest2, TraceAndManualReplay) {
4845
4858
  ASSERT_TRUE(replayer->Execute(record, &result).IsCorruption());
4846
4859
  ASSERT_TRUE(result == nullptr);
4847
4860
  }
4848
- ASSERT_GT(res_handler.GetAvgLatency(), 0.0);
4861
+ ASSERT_GE(res_handler.GetAvgLatency(), 0.0);
4849
4862
  ASSERT_EQ(res_handler.GetNumWrites(), 0);
4850
4863
  ASSERT_EQ(res_handler.GetNumGets(), 0);
4851
4864
  ASSERT_EQ(res_handler.GetNumIterSeeks(), 4); // Seek x 2 in two iterations
@@ -4900,7 +4913,7 @@ TEST_F(DBTest2, TraceAndManualReplay) {
4900
4913
  std::vector<std::string>({"a"}), fake_ts++));
4901
4914
  ASSERT_TRUE(replayer->Execute(record, &result).IsInvalidArgument());
4902
4915
  ASSERT_TRUE(result == nullptr);
4903
- ASSERT_GT(res_handler.GetAvgLatency(), 0.0);
4916
+ ASSERT_GE(res_handler.GetAvgLatency(), 0.0);
4904
4917
  ASSERT_EQ(res_handler.GetNumWrites(), 0);
4905
4918
  ASSERT_EQ(res_handler.GetNumGets(), 0);
4906
4919
  ASSERT_EQ(res_handler.GetNumIterSeeks(), 0);
@@ -7325,6 +7338,218 @@ TEST_F(DBTest2, PointInTimeRecoveryWithSyncFailureInCFCreation) {
7325
7338
  ReopenWithColumnFamilies({"default", "test1", "test2"}, options);
7326
7339
  }
7327
7340
 
7341
+ #ifndef ROCKSDB_LITE
7342
+ TEST_F(DBTest2, SortL0FilesByEpochNumber) {
7343
+ Options options = CurrentOptions();
7344
+ options.num_levels = 1;
7345
+ options.compaction_style = kCompactionStyleUniversal;
7346
+ DestroyAndReopen(options);
7347
+
7348
+ // Set up L0 files to be sorted by their epoch_number
7349
+ ASSERT_OK(Put("key1", "seq1"));
7350
+
7351
+ SstFileWriter sst_file_writer{EnvOptions(), options};
7352
+ std::string external_file1 = dbname_ + "/test_files1.sst";
7353
+ std::string external_file2 = dbname_ + "/test_files2.sst";
7354
+ ASSERT_OK(sst_file_writer.Open(external_file1));
7355
+ ASSERT_OK(sst_file_writer.Put("key2", "seq0"));
7356
+ ASSERT_OK(sst_file_writer.Finish());
7357
+ ASSERT_OK(sst_file_writer.Open(external_file2));
7358
+ ASSERT_OK(sst_file_writer.Put("key3", "seq0"));
7359
+ ASSERT_OK(sst_file_writer.Finish());
7360
+
7361
+ ASSERT_OK(Put("key4", "seq2"));
7362
+ ASSERT_OK(Flush());
7363
+
7364
+ auto* handle = db_->DefaultColumnFamily();
7365
+ ASSERT_OK(db_->IngestExternalFile(handle, {external_file1, external_file2},
7366
+ IngestExternalFileOptions()));
7367
+
7368
+ // To verify L0 files are sorted by epoch_number in descending order
7369
+ // instead of largest_seqno
7370
+ std::vector<FileMetaData*> level0_files = GetLevelFileMetadatas(0 /* level*/);
7371
+ ASSERT_EQ(level0_files.size(), 3);
7372
+
7373
+ EXPECT_EQ(level0_files[0]->epoch_number, 3);
7374
+ EXPECT_EQ(level0_files[0]->fd.largest_seqno, 0);
7375
+ ASSERT_EQ(level0_files[0]->num_entries, 1);
7376
+ ASSERT_TRUE(level0_files[0]->largest.user_key() == Slice("key3"));
7377
+
7378
+ EXPECT_EQ(level0_files[1]->epoch_number, 2);
7379
+ EXPECT_EQ(level0_files[1]->fd.largest_seqno, 0);
7380
+ ASSERT_EQ(level0_files[1]->num_entries, 1);
7381
+ ASSERT_TRUE(level0_files[1]->largest.user_key() == Slice("key2"));
7382
+
7383
+ EXPECT_EQ(level0_files[2]->epoch_number, 1);
7384
+ EXPECT_EQ(level0_files[2]->fd.largest_seqno, 2);
7385
+ ASSERT_EQ(level0_files[2]->num_entries, 2);
7386
+ ASSERT_TRUE(level0_files[2]->largest.user_key() == Slice("key4"));
7387
+ ASSERT_TRUE(level0_files[2]->smallest.user_key() == Slice("key1"));
7388
+
7389
+ // To verify compacted file is assigned with the minimum epoch_number
7390
+ // among input files'
7391
+ ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
7392
+
7393
+ level0_files = GetLevelFileMetadatas(0 /* level*/);
7394
+ ASSERT_EQ(level0_files.size(), 1);
7395
+ EXPECT_EQ(level0_files[0]->epoch_number, 1);
7396
+ ASSERT_EQ(level0_files[0]->num_entries, 4);
7397
+ ASSERT_TRUE(level0_files[0]->largest.user_key() == Slice("key4"));
7398
+ ASSERT_TRUE(level0_files[0]->smallest.user_key() == Slice("key1"));
7399
+ }
7400
+
7401
+ TEST_F(DBTest2, SameEpochNumberAfterCompactRangeChangeLevel) {
7402
+ Options options = CurrentOptions();
7403
+ options.num_levels = 7;
7404
+ options.compaction_style = CompactionStyle::kCompactionStyleLevel;
7405
+ options.disable_auto_compactions = true;
7406
+ DestroyAndReopen(options);
7407
+
7408
+ // Set up the file in L1 to be moved to L0 in later step of CompactRange()
7409
+ ASSERT_OK(Put("key1", "seq1"));
7410
+ ASSERT_OK(Flush());
7411
+ MoveFilesToLevel(1, 0);
7412
+ std::vector<FileMetaData*> level0_files = GetLevelFileMetadatas(0 /* level*/);
7413
+ ASSERT_EQ(level0_files.size(), 0);
7414
+ std::vector<FileMetaData*> level1_files = GetLevelFileMetadatas(1 /* level*/);
7415
+ ASSERT_EQ(level1_files.size(), 1);
7416
+ std::vector<FileMetaData*> level2_files = GetLevelFileMetadatas(2 /* level*/);
7417
+ ASSERT_EQ(level2_files.size(), 0);
7418
+
7419
+ ASSERT_EQ(level1_files[0]->epoch_number, 1);
7420
+
7421
+ // To verify CompactRange() moving file to L0 still keeps the file's
7422
+ // epoch_number
7423
+ CompactRangeOptions croptions;
7424
+ croptions.change_level = true;
7425
+ croptions.target_level = 0;
7426
+ ASSERT_OK(db_->CompactRange(croptions, nullptr, nullptr));
7427
+ level0_files = GetLevelFileMetadatas(0 /* level*/);
7428
+ level1_files = GetLevelFileMetadatas(1 /* level*/);
7429
+ ASSERT_EQ(level0_files.size(), 1);
7430
+ ASSERT_EQ(level1_files.size(), 0);
7431
+
7432
+ EXPECT_EQ(level0_files[0]->epoch_number, 1);
7433
+
7434
+ ASSERT_EQ(level0_files[0]->num_entries, 1);
7435
+ ASSERT_TRUE(level0_files[0]->largest.user_key() == Slice("key1"));
7436
+ }
7437
+
7438
+ TEST_F(DBTest2, RecoverEpochNumber) {
7439
+ for (bool allow_ingest_behind : {true, false}) {
7440
+ Options options = CurrentOptions();
7441
+ options.allow_ingest_behind = allow_ingest_behind;
7442
+ options.num_levels = 7;
7443
+ options.compaction_style = kCompactionStyleLevel;
7444
+ options.disable_auto_compactions = true;
7445
+ DestroyAndReopen(options);
7446
+ CreateAndReopenWithCF({"cf1"}, options);
7447
+ VersionSet* versions = dbfull()->GetVersionSet();
7448
+ assert(versions);
7449
+ const ColumnFamilyData* default_cf =
7450
+ versions->GetColumnFamilySet()->GetDefault();
7451
+ const ColumnFamilyData* cf1 =
7452
+ versions->GetColumnFamilySet()->GetColumnFamily("cf1");
7453
+
7454
+ // Set up files in default CF to recover in later step
7455
+ ASSERT_OK(Put("key1", "epoch1"));
7456
+ ASSERT_OK(Flush());
7457
+ MoveFilesToLevel(1 /* level*/, 0 /* cf*/);
7458
+ ASSERT_OK(Put("key2", "epoch2"));
7459
+ ASSERT_OK(Flush());
7460
+
7461
+ std::vector<FileMetaData*> level0_files =
7462
+ GetLevelFileMetadatas(0 /* level*/);
7463
+ ASSERT_EQ(level0_files.size(), 1);
7464
+ ASSERT_EQ(level0_files[0]->epoch_number,
7465
+ allow_ingest_behind
7466
+ ? 2 + kReservedEpochNumberForFileIngestedBehind
7467
+ : 2);
7468
+ ASSERT_EQ(level0_files[0]->num_entries, 1);
7469
+ ASSERT_TRUE(level0_files[0]->largest.user_key() == Slice("key2"));
7470
+
7471
+ std::vector<FileMetaData*> level1_files =
7472
+ GetLevelFileMetadatas(1 /* level*/);
7473
+ ASSERT_EQ(level1_files.size(), 1);
7474
+ ASSERT_EQ(level1_files[0]->epoch_number,
7475
+ allow_ingest_behind
7476
+ ? 1 + kReservedEpochNumberForFileIngestedBehind
7477
+ : 1);
7478
+ ASSERT_EQ(level1_files[0]->num_entries, 1);
7479
+ ASSERT_TRUE(level1_files[0]->largest.user_key() == Slice("key1"));
7480
+
7481
+ // Set up files in cf1 to recover in later step
7482
+ ASSERT_OK(Put(1 /* cf */, "cf1_key1", "epoch1"));
7483
+ ASSERT_OK(Flush(1 /* cf */));
7484
+
7485
+ std::vector<FileMetaData*> level0_files_cf1 =
7486
+ GetLevelFileMetadatas(0 /* level*/, 1 /* cf*/);
7487
+ ASSERT_EQ(level0_files_cf1.size(), 1);
7488
+ ASSERT_EQ(level0_files_cf1[0]->epoch_number,
7489
+ allow_ingest_behind
7490
+ ? 1 + kReservedEpochNumberForFileIngestedBehind
7491
+ : 1);
7492
+ ASSERT_EQ(level0_files_cf1[0]->num_entries, 1);
7493
+ ASSERT_TRUE(level0_files_cf1[0]->largest.user_key() == Slice("cf1_key1"));
7494
+
7495
+ ASSERT_EQ(default_cf->GetNextEpochNumber(),
7496
+ allow_ingest_behind
7497
+ ? 3 + kReservedEpochNumberForFileIngestedBehind
7498
+ : 3);
7499
+ ASSERT_EQ(cf1->GetNextEpochNumber(),
7500
+ allow_ingest_behind
7501
+ ? 2 + kReservedEpochNumberForFileIngestedBehind
7502
+ : 2);
7503
+
7504
+ // To verify epoch_number of files of different levels/CFs are
7505
+ // persisted and recovered correctly
7506
+ ReopenWithColumnFamilies({"default", "cf1"}, options);
7507
+ versions = dbfull()->GetVersionSet();
7508
+ assert(versions);
7509
+ default_cf = versions->GetColumnFamilySet()->GetDefault();
7510
+ cf1 = versions->GetColumnFamilySet()->GetColumnFamily("cf1");
7511
+
7512
+ level0_files = GetLevelFileMetadatas(0 /* level*/);
7513
+ ASSERT_EQ(level0_files.size(), 1);
7514
+ EXPECT_EQ(level0_files[0]->epoch_number,
7515
+ allow_ingest_behind
7516
+ ? 2 + kReservedEpochNumberForFileIngestedBehind
7517
+ : 2);
7518
+ ASSERT_EQ(level0_files[0]->num_entries, 1);
7519
+ ASSERT_TRUE(level0_files[0]->largest.user_key() == Slice("key2"));
7520
+
7521
+ level1_files = GetLevelFileMetadatas(1 /* level*/);
7522
+ ASSERT_EQ(level1_files.size(), 1);
7523
+ EXPECT_EQ(level1_files[0]->epoch_number,
7524
+ allow_ingest_behind
7525
+ ? 1 + kReservedEpochNumberForFileIngestedBehind
7526
+ : 1);
7527
+ ASSERT_EQ(level1_files[0]->num_entries, 1);
7528
+ ASSERT_TRUE(level1_files[0]->largest.user_key() == Slice("key1"));
7529
+
7530
+ level0_files_cf1 = GetLevelFileMetadatas(0 /* level*/, 1 /* cf*/);
7531
+ ASSERT_EQ(level0_files_cf1.size(), 1);
7532
+ EXPECT_EQ(level0_files_cf1[0]->epoch_number,
7533
+ allow_ingest_behind
7534
+ ? 1 + kReservedEpochNumberForFileIngestedBehind
7535
+ : 1);
7536
+ ASSERT_EQ(level0_files_cf1[0]->num_entries, 1);
7537
+ ASSERT_TRUE(level0_files_cf1[0]->largest.user_key() == Slice("cf1_key1"));
7538
+
7539
+ // To verify next epoch number is recovered correctly
7540
+ EXPECT_EQ(default_cf->GetNextEpochNumber(),
7541
+ allow_ingest_behind
7542
+ ? 3 + kReservedEpochNumberForFileIngestedBehind
7543
+ : 3);
7544
+ EXPECT_EQ(cf1->GetNextEpochNumber(),
7545
+ allow_ingest_behind
7546
+ ? 2 + kReservedEpochNumberForFileIngestedBehind
7547
+ : 2);
7548
+ }
7549
+ }
7550
+
7551
+ #endif // ROCKSDB_LITE
7552
+
7328
7553
  TEST_F(DBTest2, RenameDirectory) {
7329
7554
  Options options = CurrentOptions();
7330
7555
  DestroyAndReopen(options);
@@ -7509,6 +7734,80 @@ TEST_F(DBTest2, SstUniqueIdVerifyMultiCFs) {
7509
7734
  ASSERT_TRUE(s.IsCorruption());
7510
7735
  }
7511
7736
 
7737
+ TEST_F(DBTest2, BestEffortsRecoveryWithSstUniqueIdVerification) {
7738
+ const auto tamper_with_uniq_id = [&](void* arg) {
7739
+ auto props = static_cast<TableProperties*>(arg);
7740
+ assert(props);
7741
+ // update table property session_id to a different one
7742
+ props->db_session_id = DBImpl::GenerateDbSessionId(nullptr);
7743
+ };
7744
+
7745
+ const auto assert_db = [&](size_t expected_count,
7746
+ const std::string& expected_v) {
7747
+ std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
7748
+ size_t cnt = 0;
7749
+ for (it->SeekToFirst(); it->Valid(); it->Next(), ++cnt) {
7750
+ ASSERT_EQ(std::to_string(cnt), it->key());
7751
+ ASSERT_EQ(expected_v, it->value());
7752
+ }
7753
+ ASSERT_EQ(expected_count, cnt);
7754
+ };
7755
+
7756
+ const int num_l0_compaction_trigger = 8;
7757
+ const int num_l0 = num_l0_compaction_trigger - 1;
7758
+ Options options = CurrentOptions();
7759
+ options.level0_file_num_compaction_trigger = num_l0_compaction_trigger;
7760
+
7761
+ for (int k = 0; k < num_l0; ++k) {
7762
+ // Allow mismatch for now
7763
+ options.verify_sst_unique_id_in_manifest = false;
7764
+
7765
+ DestroyAndReopen(options);
7766
+
7767
+ constexpr size_t num_keys_per_file = 10;
7768
+ for (int i = 0; i < num_l0; ++i) {
7769
+ for (size_t j = 0; j < num_keys_per_file; ++j) {
7770
+ ASSERT_OK(Put(std::to_string(j), "v" + std::to_string(i)));
7771
+ }
7772
+ if (i == k) {
7773
+ SyncPoint::GetInstance()->DisableProcessing();
7774
+ SyncPoint::GetInstance()->SetCallBack(
7775
+ "PropertyBlockBuilder::AddTableProperty:Start",
7776
+ tamper_with_uniq_id);
7777
+ SyncPoint::GetInstance()->EnableProcessing();
7778
+ }
7779
+ ASSERT_OK(Flush());
7780
+ }
7781
+
7782
+ options.verify_sst_unique_id_in_manifest = true;
7783
+ Status s = TryReopen(options);
7784
+ ASSERT_TRUE(s.IsCorruption());
7785
+
7786
+ options.best_efforts_recovery = true;
7787
+ Reopen(options);
7788
+ assert_db(k == 0 ? 0 : num_keys_per_file, "v" + std::to_string(k - 1));
7789
+
7790
+ // Reopen with regular recovery
7791
+ options.best_efforts_recovery = false;
7792
+ Reopen(options);
7793
+ assert_db(k == 0 ? 0 : num_keys_per_file, "v" + std::to_string(k - 1));
7794
+
7795
+ SyncPoint::GetInstance()->DisableProcessing();
7796
+ SyncPoint::GetInstance()->ClearAllCallBacks();
7797
+
7798
+ for (size_t i = 0; i < num_keys_per_file; ++i) {
7799
+ ASSERT_OK(Put(std::to_string(i), "v"));
7800
+ }
7801
+ ASSERT_OK(Flush());
7802
+ Reopen(options);
7803
+ {
7804
+ for (size_t i = 0; i < num_keys_per_file; ++i) {
7805
+ ASSERT_EQ("v", Get(std::to_string(i)));
7806
+ }
7807
+ }
7808
+ }
7809
+ }
7810
+
7512
7811
  #ifndef ROCKSDB_LITE
7513
7812
  TEST_F(DBTest2, GetLatestSeqAndTsForKey) {
7514
7813
  Destroy(last_options_);
@@ -610,6 +610,52 @@ TEST_F(DBWALTest, WALWithChecksumHandoff) {
610
610
  #endif // ROCKSDB_ASSERT_STATUS_CHECKED
611
611
  }
612
612
 
613
+ #ifndef ROCKSDB_LITE
614
+ TEST_F(DBWALTest, LockWal) {
615
+ do {
616
+ Options options = CurrentOptions();
617
+ options.create_if_missing = true;
618
+ DestroyAndReopen(options);
619
+ SyncPoint::GetInstance()->DisableProcessing();
620
+ SyncPoint::GetInstance()->LoadDependency(
621
+ {{"DBWALTest::LockWal:AfterGetSortedWal",
622
+ "DBWALTest::LockWal:BeforeFlush:1"}});
623
+ SyncPoint::GetInstance()->EnableProcessing();
624
+
625
+ ASSERT_OK(Put("foo", "v"));
626
+ ASSERT_OK(Put("bar", "v"));
627
+ port::Thread worker([&]() {
628
+ TEST_SYNC_POINT("DBWALTest::LockWal:BeforeFlush:1");
629
+ Status tmp_s = db_->Flush(FlushOptions());
630
+ ASSERT_OK(tmp_s);
631
+ });
632
+
633
+ ASSERT_OK(db_->LockWAL());
634
+ // Verify writes are stopped
635
+ WriteOptions wopts;
636
+ wopts.no_slowdown = true;
637
+ Status s = db_->Put(wopts, "foo", "dontcare");
638
+ ASSERT_TRUE(s.IsIncomplete());
639
+ {
640
+ VectorLogPtr wals;
641
+ ASSERT_OK(db_->GetSortedWalFiles(wals));
642
+ ASSERT_FALSE(wals.empty());
643
+ }
644
+ TEST_SYNC_POINT("DBWALTest::LockWal:AfterGetSortedWal");
645
+ FlushOptions flush_opts;
646
+ flush_opts.wait = false;
647
+ s = db_->Flush(flush_opts);
648
+ ASSERT_TRUE(s.IsTryAgain());
649
+ ASSERT_OK(db_->UnlockWAL());
650
+ ASSERT_OK(db_->Put(WriteOptions(), "foo", "dontcare"));
651
+
652
+ worker.join();
653
+
654
+ SyncPoint::GetInstance()->DisableProcessing();
655
+ } while (ChangeWalOptions());
656
+ }
657
+ #endif //! ROCKSDB_LITE
658
+
613
659
  class DBRecoveryTestBlobError
614
660
  : public DBWALTest,
615
661
  public testing::WithParamInterface<std::string> {
@@ -1599,6 +1645,89 @@ TEST_F(DBWALTest, RaceInstallFlushResultsWithWalObsoletion) {
1599
1645
  delete db1;
1600
1646
  }
1601
1647
 
1648
+ TEST_F(DBWALTest, FixSyncWalOnObseletedWalWithNewManifestCausingMissingWAL) {
1649
+ Options options = CurrentOptions();
1650
+ options.track_and_verify_wals_in_manifest = true;
1651
+ DestroyAndReopen(options);
1652
+
1653
+ // Accumulate memtable m1 and create the 1st wal (i.e, 4.log)
1654
+ ASSERT_OK(Put(Key(1), ""));
1655
+ ASSERT_OK(Put(Key(2), ""));
1656
+ ASSERT_OK(Put(Key(3), ""));
1657
+
1658
+ const std::string wal_file_path = db_->GetName() + "/000004.log";
1659
+
1660
+ // Coerce the following sequence of events:
1661
+ // (1) Flush() marks 4.log to be obsoleted, 8.log to be the latest (i.e,
1662
+ // active) log and release the lock
1663
+ // (2) SyncWAL() proceeds with the lock. It
1664
+ // creates a new manifest and syncs all the inactive wals before the latest
1665
+ // (i.e, active log), which is 4.log. Note that SyncWAL() is not aware of the
1666
+ // fact that 4.log has marked as to be obseleted. Prior to the fix, such wal
1667
+ // sync will then add a WAL addition record of 4.log to the new manifest
1668
+ // without any special treatment.
1669
+ // (3) BackgroundFlush() will eventually purge 4.log.
1670
+ bool wal_synced = false;
1671
+ SyncPoint::GetInstance()->SetCallBack(
1672
+ "FindObsoleteFiles::PostMutexUnlock", [&](void*) {
1673
+ ASSERT_OK(env_->FileExists(wal_file_path));
1674
+
1675
+ SyncPoint::GetInstance()->SetCallBack(
1676
+ "VersionSet::ProcessManifestWrites:"
1677
+ "PostDecidingCreateNewManifestOrNot",
1678
+ [&](void* arg) {
1679
+ bool* new_descriptor_log = (bool*)arg;
1680
+ *new_descriptor_log = true;
1681
+ });
1682
+
1683
+ ASSERT_OK(db_->SyncWAL());
1684
+ wal_synced = true;
1685
+ });
1686
+
1687
+ SyncPoint::GetInstance()->SetCallBack(
1688
+ "DBImpl::DeleteObsoleteFileImpl:AfterDeletion2", [&](void* arg) {
1689
+ std::string* file_name = (std::string*)arg;
1690
+ if (*file_name == wal_file_path) {
1691
+ TEST_SYNC_POINT(
1692
+ "DBWALTest::"
1693
+ "FixSyncWalOnObseletedWalWithNewManifestCausingMissingWAL::"
1694
+ "PostDeleteWAL");
1695
+ }
1696
+ });
1697
+
1698
+ SyncPoint::GetInstance()->LoadDependency(
1699
+ {{"DBImpl::BackgroundCallFlush:FilesFound",
1700
+ "PreConfrimObsoletedWALSynced"},
1701
+ {"DBWALTest::FixSyncWalOnObseletedWalWithNewManifestCausingMissingWAL::"
1702
+ "PostDeleteWAL",
1703
+ "PreConfrimWALDeleted"}});
1704
+
1705
+ SyncPoint::GetInstance()->EnableProcessing();
1706
+
1707
+ ASSERT_OK(Flush());
1708
+
1709
+ TEST_SYNC_POINT("PreConfrimObsoletedWALSynced");
1710
+ ASSERT_TRUE(wal_synced);
1711
+
1712
+ TEST_SYNC_POINT("PreConfrimWALDeleted");
1713
+ // BackgroundFlush() purged 4.log
1714
+ // because the memtable associated with the WAL was flushed and new WAL was
1715
+ // created (i.e, 8.log)
1716
+ ASSERT_TRUE(env_->FileExists(wal_file_path).IsNotFound());
1717
+
1718
+ SyncPoint::GetInstance()->ClearAllCallBacks();
1719
+ SyncPoint::GetInstance()->DisableProcessing();
1720
+
1721
+ // To verify the corruption of "Missing WAL with log number: 4" under
1722
+ // `options.track_and_verify_wals_in_manifest = true` is fixed.
1723
+ //
1724
+ // Before the fix, `db_->SyncWAL()` will sync and record WAL addtion of the
1725
+ // obseleted WAL 4.log in a new manifest without any special treament.
1726
+ // This will result in missing-wal corruption in DB::Reopen().
1727
+ Status s = TryReopen(options);
1728
+ EXPECT_OK(s);
1729
+ }
1730
+
1602
1731
  // Test scope:
1603
1732
  // - We expect to open data store under all circumstances
1604
1733
  // - We expect only data upto the point where the first error was encountered
@@ -323,6 +323,27 @@ TEST_F(TimestampCompatibleCompactionTest, CompactFilesRangeCheckL1) {
323
323
  static_cast<int>(compaction_job_info.input_files.size()));
324
324
  }
325
325
  }
326
+
327
+ TEST_F(TimestampCompatibleCompactionTest, EmptyCompactionOutput) {
328
+ Options options = CurrentOptions();
329
+ options.env = env_;
330
+ options.comparator = test::BytewiseComparatorWithU64TsWrapper();
331
+ DestroyAndReopen(options);
332
+
333
+ std::string ts_str = Timestamp(1);
334
+ WriteOptions wopts;
335
+ ASSERT_OK(
336
+ db_->DeleteRange(wopts, db_->DefaultColumnFamily(), "k1", "k3", ts_str));
337
+ ASSERT_OK(Flush());
338
+
339
+ ts_str = Timestamp(3);
340
+ Slice ts = ts_str;
341
+ CompactRangeOptions cro;
342
+ // range tombstone will be dropped during compaction
343
+ cro.full_history_ts_low = &ts;
344
+ cro.bottommost_level_compaction = BottommostLevelCompaction::kForce;
345
+ ASSERT_OK(db_->CompactRange(cro, nullptr, nullptr));
346
+ }
326
347
  #endif // !ROCKSDB_LITE
327
348
 
328
349
  } // namespace ROCKSDB_NAMESPACE
@@ -150,6 +150,31 @@ int InternalKeyComparator::Compare(const ParsedInternalKey& a,
150
150
  return r;
151
151
  }
152
152
 
153
+ int InternalKeyComparator::Compare(const Slice& a,
154
+ const ParsedInternalKey& b) const {
155
+ // Order by:
156
+ // increasing user key (according to user-supplied comparator)
157
+ // decreasing sequence number
158
+ // decreasing type (though sequence# should be enough to disambiguate)
159
+ int r = user_comparator_.Compare(ExtractUserKey(a), b.user_key);
160
+ if (r == 0) {
161
+ const uint64_t anum =
162
+ DecodeFixed64(a.data() + a.size() - kNumInternalBytes);
163
+ const uint64_t bnum = (b.sequence << 8) | b.type;
164
+ if (anum > bnum) {
165
+ r = -1;
166
+ } else if (anum < bnum) {
167
+ r = +1;
168
+ }
169
+ }
170
+ return r;
171
+ }
172
+
173
+ int InternalKeyComparator::Compare(const ParsedInternalKey& a,
174
+ const Slice& b) const {
175
+ return -Compare(b, a);
176
+ }
177
+
153
178
  LookupKey::LookupKey(const Slice& _user_key, SequenceNumber s,
154
179
  const Slice* ts) {
155
180
  size_t usize = _user_key.size();
@@ -283,6 +283,8 @@ class InternalKeyComparator
283
283
 
284
284
  int Compare(const InternalKey& a, const InternalKey& b) const;
285
285
  int Compare(const ParsedInternalKey& a, const ParsedInternalKey& b) const;
286
+ int Compare(const Slice& a, const ParsedInternalKey& b) const;
287
+ int Compare(const ParsedInternalKey& a, const Slice& b) const;
286
288
  // In this `Compare()` overload, the sequence numbers provided in
287
289
  // `a_global_seqno` and `b_global_seqno` override the sequence numbers in `a`
288
290
  // and `b`, respectively. To disable sequence number override(s), provide the
@@ -112,7 +112,7 @@ Status UpdateManifestForFilesState(
112
112
  lf->smallest, lf->largest, lf->fd.smallest_seqno,
113
113
  lf->fd.largest_seqno, lf->marked_for_compaction, temp,
114
114
  lf->oldest_blob_file_number, lf->oldest_ancester_time,
115
- lf->file_creation_time, lf->file_checksum,
115
+ lf->file_creation_time, lf->epoch_number, lf->file_checksum,
116
116
  lf->file_checksum_func_name, lf->unique_id);
117
117
  }
118
118
  }
@@ -469,8 +469,11 @@ Status ExternalSstFileIngestionJob::Run() {
469
469
  f.fd.GetNumber(), f.fd.GetPathId(), f.fd.GetFileSize(),
470
470
  f.smallest_internal_key, f.largest_internal_key, f.assigned_seqno,
471
471
  f.assigned_seqno, false, f.file_temperature, kInvalidBlobFileNumber,
472
- oldest_ancester_time, current_time, f.file_checksum,
473
- f.file_checksum_func_name, f.unique_id);
472
+ oldest_ancester_time, current_time,
473
+ ingestion_options_.ingest_behind
474
+ ? kReservedEpochNumberForFileIngestedBehind
475
+ : cfd_->NewEpochNumber(),
476
+ f.file_checksum, f.file_checksum_func_name, f.unique_id);
474
477
  f_metadata.temperature = f.file_temperature;
475
478
  edit_.AddFile(f.picked_level, f_metadata);
476
479
  }
@@ -23,6 +23,7 @@
23
23
  #include "db/memtable_list.h"
24
24
  #include "db/merge_context.h"
25
25
  #include "db/range_tombstone_fragmenter.h"
26
+ #include "db/version_edit.h"
26
27
  #include "db/version_set.h"
27
28
  #include "file/file_util.h"
28
29
  #include "file/filename.h"
@@ -199,6 +200,7 @@ void FlushJob::PickMemTable() {
199
200
 
200
201
  // path 0 for level 0 file.
201
202
  meta_.fd = FileDescriptor(versions_->NewFileNumber(), 0, 0);
203
+ meta_.epoch_number = cfd_->NewEpochNumber();
202
204
 
203
205
  base_ = cfd_->current();
204
206
  base_->Ref(); // it is likely that we do not need this reference
@@ -999,8 +1001,9 @@ Status FlushJob::WriteLevel0Table() {
999
1001
  meta_.fd.smallest_seqno, meta_.fd.largest_seqno,
1000
1002
  meta_.marked_for_compaction, meta_.temperature,
1001
1003
  meta_.oldest_blob_file_number, meta_.oldest_ancester_time,
1002
- meta_.file_creation_time, meta_.file_checksum,
1003
- meta_.file_checksum_func_name, meta_.unique_id);
1004
+ meta_.file_creation_time, meta_.epoch_number,
1005
+ meta_.file_checksum, meta_.file_checksum_func_name,
1006
+ meta_.unique_id);
1004
1007
 
1005
1008
  edit_->SetBlobFileAdditions(std::move(blob_file_additions));
1006
1009
  }
@@ -82,6 +82,10 @@ class HistoryTrimmingIterator : public InternalIterator {
82
82
 
83
83
  bool IsValuePinned() const override { return input_->IsValuePinned(); }
84
84
 
85
+ bool IsDeleteRangeSentinelKey() const override {
86
+ return input_->IsDeleteRangeSentinelKey();
87
+ }
88
+
85
89
  private:
86
90
  InternalIterator* input_;
87
91
  const std::string filter_ts_;