@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.
- package/BUILDING.md +2 -2
- package/binding.cc +2 -7
- package/deps/rocksdb/rocksdb/CMakeLists.txt +10 -9
- package/deps/rocksdb/rocksdb/Makefile +2 -2
- package/deps/rocksdb/rocksdb/TARGETS +4 -2
- package/deps/rocksdb/rocksdb/cache/cache_bench_tool.cc +0 -5
- package/deps/rocksdb/rocksdb/cache/cache_test.cc +8 -29
- package/deps/rocksdb/rocksdb/cache/clock_cache.cc +146 -0
- package/deps/rocksdb/rocksdb/cache/clock_cache.h +13 -1
- package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +57 -146
- package/deps/rocksdb/rocksdb/cache/secondary_cache.cc +32 -0
- package/deps/rocksdb/rocksdb/db/blob/blob_counting_iterator.h +11 -0
- package/deps/rocksdb/rocksdb/db/column_family.cc +11 -9
- package/deps/rocksdb/rocksdb/db/column_family.h +20 -0
- package/deps/rocksdb/rocksdb/db/compaction/clipping_iterator.h +5 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +13 -33
- package/deps/rocksdb/rocksdb/db/compaction/compaction.h +5 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +27 -8
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +17 -1
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +2 -1
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +4 -2
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job_test.cc +8 -6
- package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +65 -7
- package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +5 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.cc +10 -32
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.h +28 -47
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.cc +28 -22
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.h +8 -14
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.cc +8 -8
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.h +5 -4
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +170 -140
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +5 -1
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.h +5 -4
- package/deps/rocksdb/rocksdb/db/compaction/compaction_service_job.cc +8 -2
- package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.h +8 -0
- package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +266 -138
- package/deps/rocksdb/rocksdb/db/corruption_test.cc +86 -1
- package/deps/rocksdb/rocksdb/db/db_basic_test.cc +72 -5
- package/deps/rocksdb/rocksdb/db/db_block_cache_test.cc +119 -10
- package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +585 -264
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +46 -18
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +5 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +6 -15
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_debug.cc +1 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_experimental.cc +1 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +3 -0
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +8 -8
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_write.cc +10 -0
- package/deps/rocksdb/rocksdb/db/db_iter.cc +57 -36
- package/deps/rocksdb/rocksdb/db/db_iter.h +2 -1
- package/deps/rocksdb/rocksdb/db/db_range_del_test.cc +250 -2
- package/deps/rocksdb/rocksdb/db/db_test.cc +3 -0
- package/deps/rocksdb/rocksdb/db/db_test2.cc +307 -8
- package/deps/rocksdb/rocksdb/db/db_wal_test.cc +129 -0
- package/deps/rocksdb/rocksdb/db/db_with_timestamp_compaction_test.cc +21 -0
- package/deps/rocksdb/rocksdb/db/dbformat.cc +25 -0
- package/deps/rocksdb/rocksdb/db/dbformat.h +2 -0
- package/deps/rocksdb/rocksdb/db/experimental.cc +1 -1
- package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +5 -2
- package/deps/rocksdb/rocksdb/db/flush_job.cc +5 -2
- package/deps/rocksdb/rocksdb/db/history_trimming_iterator.h +4 -0
- package/deps/rocksdb/rocksdb/db/import_column_family_job.cc +56 -53
- package/deps/rocksdb/rocksdb/db/import_column_family_test.cc +3 -4
- package/deps/rocksdb/rocksdb/db/memtable.cc +55 -9
- package/deps/rocksdb/rocksdb/db/merge_helper.cc +76 -102
- package/deps/rocksdb/rocksdb/db/merge_helper.h +2 -11
- package/deps/rocksdb/rocksdb/db/periodic_task_scheduler_test.cc +10 -10
- package/deps/rocksdb/rocksdb/db/repair.cc +64 -22
- package/deps/rocksdb/rocksdb/db/repair_test.cc +54 -0
- package/deps/rocksdb/rocksdb/db/seqno_time_test.cc +26 -26
- package/deps/rocksdb/rocksdb/db/table_cache.cc +2 -0
- package/deps/rocksdb/rocksdb/db/table_properties_collector.h +3 -1
- package/deps/rocksdb/rocksdb/db/version_builder.cc +90 -43
- package/deps/rocksdb/rocksdb/db/version_builder.h +20 -0
- package/deps/rocksdb/rocksdb/db/version_builder_test.cc +190 -67
- package/deps/rocksdb/rocksdb/db/version_edit.cc +15 -1
- package/deps/rocksdb/rocksdb/db/version_edit.h +16 -4
- package/deps/rocksdb/rocksdb/db/version_edit_handler.cc +41 -11
- package/deps/rocksdb/rocksdb/db/version_edit_handler.h +27 -12
- package/deps/rocksdb/rocksdb/db/version_edit_test.cc +18 -16
- package/deps/rocksdb/rocksdb/db/version_set.cc +219 -38
- package/deps/rocksdb/rocksdb/db/version_set.h +34 -4
- package/deps/rocksdb/rocksdb/db/version_set_test.cc +45 -25
- package/deps/rocksdb/rocksdb/db/wide/db_wide_basic_test.cc +122 -61
- package/deps/rocksdb/rocksdb/db/write_thread.cc +5 -2
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +0 -1
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +0 -4
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +12 -17
- package/deps/rocksdb/rocksdb/db_stress_tool/no_batched_ops_stress.cc +6 -4
- package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.cc +1 -1
- package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.h +1 -0
- package/deps/rocksdb/rocksdb/file/prefetch_test.cc +0 -48
- package/deps/rocksdb/rocksdb/file/random_access_file_reader.cc +8 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/cache.h +196 -171
- package/deps/rocksdb/rocksdb/include/rocksdb/db.h +6 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/metadata.h +9 -3
- package/deps/rocksdb/rocksdb/include/rocksdb/options.h +25 -18
- package/deps/rocksdb/rocksdb/include/rocksdb/secondary_cache.h +27 -5
- package/deps/rocksdb/rocksdb/include/rocksdb/statistics.h +5 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/status.h +3 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/table.h +3 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/version.h +1 -1
- package/deps/rocksdb/rocksdb/logging/logging.h +13 -19
- package/deps/rocksdb/rocksdb/memory/arena.cc +4 -3
- package/deps/rocksdb/rocksdb/memory/arena_test.cc +30 -0
- package/deps/rocksdb/rocksdb/monitoring/statistics.cc +3 -1
- package/deps/rocksdb/rocksdb/monitoring/stats_history_test.cc +26 -26
- package/deps/rocksdb/rocksdb/src.mk +2 -1
- package/deps/rocksdb/rocksdb/table/adaptive/adaptive_table_factory.cc +3 -2
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +2 -10
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +12 -29
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_test.cc +1 -1
- package/deps/rocksdb/rocksdb/table/block_based/block_like_traits.h +0 -39
- package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.cc +0 -1
- package/deps/rocksdb/rocksdb/table/block_fetcher_test.cc +3 -3
- package/deps/rocksdb/rocksdb/table/compaction_merging_iterator.cc +142 -0
- package/deps/rocksdb/rocksdb/table/compaction_merging_iterator.h +241 -0
- package/deps/rocksdb/rocksdb/table/format.cc +24 -20
- package/deps/rocksdb/rocksdb/table/format.h +5 -2
- package/deps/rocksdb/rocksdb/table/get_context.cc +52 -11
- package/deps/rocksdb/rocksdb/table/merging_iterator.cc +97 -115
- package/deps/rocksdb/rocksdb/table/merging_iterator.h +82 -1
- package/deps/rocksdb/rocksdb/table/meta_blocks.cc +2 -2
- package/deps/rocksdb/rocksdb/table/sst_file_dumper.cc +1 -1
- package/deps/rocksdb/rocksdb/table/table_test.cc +7 -6
- package/deps/rocksdb/rocksdb/test_util/testutil.h +10 -0
- package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +0 -6
- package/deps/rocksdb/rocksdb/trace_replay/block_cache_tracer.h +2 -2
- package/deps/rocksdb/rocksdb/util/bloom_test.cc +1 -1
- package/deps/rocksdb/rocksdb/util/crc32c.cc +1 -1
- package/deps/rocksdb/rocksdb/util/status.cc +7 -0
- package/deps/rocksdb/rocksdb/utilities/backup/backup_engine.cc +5 -0
- package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +4 -0
- package/deps/rocksdb/rocksdb/utilities/cache_dump_load_impl.cc +7 -67
- package/deps/rocksdb/rocksdb/utilities/cache_dump_load_impl.h +1 -3
- package/deps/rocksdb/rocksdb/utilities/checkpoint/checkpoint_impl.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.cc +59 -0
- package/deps/rocksdb/rocksdb.gyp +2 -1
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.node +0 -0
- package/deps/rocksdb/rocksdb/cache/fast_lru_cache.cc +0 -580
- package/deps/rocksdb/rocksdb/cache/fast_lru_cache.h +0 -476
- package/max_rev_operator.h +0 -100
|
@@ -9,8 +9,10 @@
|
|
|
9
9
|
|
|
10
10
|
#include <tuple>
|
|
11
11
|
|
|
12
|
+
#include "compaction/compaction_picker_universal.h"
|
|
12
13
|
#include "db/blob/blob_index.h"
|
|
13
14
|
#include "db/db_test_util.h"
|
|
15
|
+
#include "db/dbformat.h"
|
|
14
16
|
#include "env/mock_env.h"
|
|
15
17
|
#include "port/port.h"
|
|
16
18
|
#include "port/stack_trace.h"
|
|
@@ -186,13 +188,6 @@ class RoundRobinSubcompactionsAgainstResources
|
|
|
186
188
|
int max_compaction_limits_;
|
|
187
189
|
};
|
|
188
190
|
|
|
189
|
-
class DBCompactionTestFIFOCheckConsistencyWithParam
|
|
190
|
-
: public DBCompactionTest,
|
|
191
|
-
public testing::WithParamInterface<std::string> {
|
|
192
|
-
public:
|
|
193
|
-
DBCompactionTestFIFOCheckConsistencyWithParam() : DBCompactionTest() {}
|
|
194
|
-
};
|
|
195
|
-
|
|
196
191
|
namespace {
|
|
197
192
|
class FlushedFileCollector : public EventListener {
|
|
198
193
|
public:
|
|
@@ -6278,327 +6273,653 @@ void IngestOneKeyValue(DBImpl* db, const std::string& key,
|
|
|
6278
6273
|
ASSERT_OK(db->IngestExternalFile({info.file_path}, ingest_opt));
|
|
6279
6274
|
}
|
|
6280
6275
|
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6276
|
+
class DBCompactionTestL0FilesMisorderCorruption : public DBCompactionTest {
|
|
6277
|
+
public:
|
|
6278
|
+
DBCompactionTestL0FilesMisorderCorruption() : DBCompactionTest() {}
|
|
6279
|
+
void SetupOptions(const CompactionStyle compaciton_style,
|
|
6280
|
+
const std::string& compaction_path_to_test = "") {
|
|
6281
|
+
options_ = CurrentOptions();
|
|
6282
|
+
options_.create_if_missing = true;
|
|
6283
|
+
options_.compression = kNoCompression;
|
|
6284
|
+
|
|
6285
|
+
options_.force_consistency_checks = true;
|
|
6286
|
+
options_.compaction_style = compaciton_style;
|
|
6287
|
+
|
|
6288
|
+
if (compaciton_style == CompactionStyle::kCompactionStyleLevel) {
|
|
6289
|
+
options_.num_levels = 7;
|
|
6290
|
+
// Level compaction's PickIntraL0Compaction() impl detail requires
|
|
6291
|
+
// `options.level0_file_num_compaction_trigger` to be
|
|
6292
|
+
// at least 2 files less than the actual number of level 0 files
|
|
6293
|
+
// (i.e, 7 by design in this test)
|
|
6294
|
+
options_.level0_file_num_compaction_trigger = 5;
|
|
6295
|
+
options_.max_background_compactions = 2;
|
|
6296
|
+
options_.write_buffer_size = 2 << 20;
|
|
6297
|
+
options_.max_write_buffer_number = 6;
|
|
6298
|
+
} else if (compaciton_style == CompactionStyle::kCompactionStyleUniversal) {
|
|
6299
|
+
// TODO: expand test coverage to num_lvels > 1 for universal compacion,
|
|
6300
|
+
// which requires careful unit test design to compact to level 0 despite
|
|
6301
|
+
// num_levels > 1
|
|
6302
|
+
options_.num_levels = 1;
|
|
6303
|
+
options_.level0_file_num_compaction_trigger = 5;
|
|
6304
|
+
|
|
6305
|
+
CompactionOptionsUniversal universal_options;
|
|
6306
|
+
if (compaction_path_to_test == "PickCompactionToReduceSizeAmp") {
|
|
6307
|
+
universal_options.max_size_amplification_percent = 50;
|
|
6308
|
+
} else if (compaction_path_to_test ==
|
|
6309
|
+
"PickCompactionToReduceSortedRuns") {
|
|
6310
|
+
universal_options.max_size_amplification_percent = 400;
|
|
6311
|
+
} else if (compaction_path_to_test == "PickDeleteTriggeredCompaction") {
|
|
6312
|
+
universal_options.max_size_amplification_percent = 400;
|
|
6313
|
+
universal_options.min_merge_width = 6;
|
|
6314
|
+
}
|
|
6315
|
+
options_.compaction_options_universal = universal_options;
|
|
6316
|
+
} else if (compaciton_style == CompactionStyle::kCompactionStyleFIFO) {
|
|
6317
|
+
options_.max_open_files = -1;
|
|
6318
|
+
options_.num_levels = 1;
|
|
6319
|
+
options_.level0_file_num_compaction_trigger = 3;
|
|
6320
|
+
|
|
6321
|
+
CompactionOptionsFIFO fifo_options;
|
|
6322
|
+
if (compaction_path_to_test == "FindIntraL0Compaction" ||
|
|
6323
|
+
compaction_path_to_test == "CompactRange") {
|
|
6324
|
+
fifo_options.allow_compaction = true;
|
|
6325
|
+
fifo_options.age_for_warm = 0;
|
|
6326
|
+
} else if (compaction_path_to_test == "CompactFile") {
|
|
6327
|
+
fifo_options.allow_compaction = false;
|
|
6328
|
+
fifo_options.age_for_warm = 0;
|
|
6329
|
+
}
|
|
6330
|
+
options_.compaction_options_fifo = fifo_options;
|
|
6331
|
+
}
|
|
6290
6332
|
|
|
6291
|
-
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
|
|
6333
|
+
if (compaction_path_to_test == "CompactFile" ||
|
|
6334
|
+
compaction_path_to_test == "CompactRange") {
|
|
6335
|
+
options_.disable_auto_compactions = true;
|
|
6336
|
+
} else {
|
|
6337
|
+
options_.disable_auto_compactions = false;
|
|
6338
|
+
}
|
|
6339
|
+
}
|
|
6295
6340
|
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
"CompactionJob::Run():Start"}});
|
|
6305
|
-
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
|
6306
|
-
"FindIntraL0Compaction",
|
|
6307
|
-
[&](void* /*arg*/) { pick_intra_l0_count.fetch_add(1); });
|
|
6341
|
+
void Destroy(const Options& options) {
|
|
6342
|
+
if (snapshot_) {
|
|
6343
|
+
assert(db_);
|
|
6344
|
+
db_->ReleaseSnapshot(snapshot_);
|
|
6345
|
+
snapshot_ = nullptr;
|
|
6346
|
+
}
|
|
6347
|
+
DBTestBase::Destroy(options);
|
|
6348
|
+
}
|
|
6308
6349
|
|
|
6309
|
-
|
|
6350
|
+
void Reopen(const Options& options) {
|
|
6351
|
+
DBTestBase::Reopen(options);
|
|
6352
|
+
if (options.compaction_style != CompactionStyle::kCompactionStyleLevel) {
|
|
6353
|
+
// To force assigning the global seqno to ingested file
|
|
6354
|
+
// for our test purpose.
|
|
6355
|
+
assert(snapshot_ == nullptr);
|
|
6356
|
+
snapshot_ = db_->GetSnapshot();
|
|
6357
|
+
}
|
|
6358
|
+
}
|
|
6310
6359
|
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6360
|
+
void DestroyAndReopen(Options& options) {
|
|
6361
|
+
Destroy(options);
|
|
6362
|
+
Reopen(options);
|
|
6314
6363
|
}
|
|
6315
|
-
ASSERT_OK(Flush());
|
|
6316
|
-
Compact("", Key(99));
|
|
6317
|
-
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
|
6318
6364
|
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6365
|
+
void PauseCompactionThread() {
|
|
6366
|
+
sleeping_task_.reset(new test::SleepingBackgroundTask());
|
|
6367
|
+
env_->SetBackgroundThreads(1, Env::LOW);
|
|
6368
|
+
env_->Schedule(&test::SleepingBackgroundTask::DoSleepTask,
|
|
6369
|
+
sleeping_task_.get(), Env::Priority::LOW);
|
|
6370
|
+
sleeping_task_->WaitUntilSleeping();
|
|
6323
6371
|
}
|
|
6324
|
-
ASSERT_EQ(5, NumTableFilesAtLevel(0));
|
|
6325
6372
|
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6373
|
+
void ResumeCompactionThread() {
|
|
6374
|
+
if (sleeping_task_) {
|
|
6375
|
+
sleeping_task_->WakeUp();
|
|
6376
|
+
sleeping_task_->WaitUntilDone();
|
|
6377
|
+
}
|
|
6378
|
+
}
|
|
6329
6379
|
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6380
|
+
void AddFilesMarkedForPeriodicCompaction(const size_t num_files) {
|
|
6381
|
+
assert(options_.compaction_style ==
|
|
6382
|
+
CompactionStyle::kCompactionStyleUniversal);
|
|
6383
|
+
VersionSet* const versions = dbfull()->GetVersionSet();
|
|
6384
|
+
assert(versions);
|
|
6385
|
+
ColumnFamilyData* const cfd = versions->GetColumnFamilySet()->GetDefault();
|
|
6386
|
+
assert(cfd);
|
|
6387
|
+
Version* const current = cfd->current();
|
|
6388
|
+
assert(current);
|
|
6334
6389
|
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6390
|
+
VersionStorageInfo* const storage_info = current->storage_info();
|
|
6391
|
+
assert(storage_info);
|
|
6392
|
+
|
|
6393
|
+
const std::vector<FileMetaData*> level0_files = storage_info->LevelFiles(0);
|
|
6394
|
+
assert(level0_files.size() == num_files);
|
|
6395
|
+
|
|
6396
|
+
for (FileMetaData* f : level0_files) {
|
|
6397
|
+
storage_info->TEST_AddFileMarkedForPeriodicCompaction(0, f);
|
|
6398
|
+
}
|
|
6339
6399
|
}
|
|
6340
6400
|
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
ASSERT_GT(pick_intra_l0_count.load(), 0);
|
|
6401
|
+
void AddFilesMarkedForCompaction(const size_t num_files) {
|
|
6402
|
+
assert(options_.compaction_style ==
|
|
6403
|
+
CompactionStyle::kCompactionStyleUniversal);
|
|
6404
|
+
VersionSet* const versions = dbfull()->GetVersionSet();
|
|
6405
|
+
assert(versions);
|
|
6406
|
+
ColumnFamilyData* const cfd = versions->GetColumnFamilySet()->GetDefault();
|
|
6407
|
+
assert(cfd);
|
|
6408
|
+
Version* const current = cfd->current();
|
|
6409
|
+
assert(current);
|
|
6351
6410
|
|
|
6352
|
-
|
|
6353
|
-
|
|
6411
|
+
VersionStorageInfo* const storage_info = current->storage_info();
|
|
6412
|
+
assert(storage_info);
|
|
6354
6413
|
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
Options options = CurrentOptions();
|
|
6358
|
-
options.force_consistency_checks = true;
|
|
6359
|
-
options.compression = kNoCompression;
|
|
6360
|
-
options.level0_file_num_compaction_trigger = 5;
|
|
6361
|
-
options.max_background_compactions = 2;
|
|
6362
|
-
options.max_subcompactions = max_subcompactions_;
|
|
6363
|
-
options.write_buffer_size = 2 << 20;
|
|
6364
|
-
options.max_write_buffer_number = 6;
|
|
6365
|
-
DestroyAndReopen(options);
|
|
6414
|
+
const std::vector<FileMetaData*> level0_files = storage_info->LevelFiles(0);
|
|
6415
|
+
assert(level0_files.size() == num_files);
|
|
6366
6416
|
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6417
|
+
for (FileMetaData* f : level0_files) {
|
|
6418
|
+
storage_info->TEST_AddFileMarkedForCompaction(0, f);
|
|
6419
|
+
}
|
|
6420
|
+
}
|
|
6421
|
+
|
|
6422
|
+
void SetupSyncPoints(const std::string& compaction_path_to_test) {
|
|
6423
|
+
compaction_path_sync_point_called_.store(false);
|
|
6424
|
+
if (compaction_path_to_test == "FindIntraL0Compaction" &&
|
|
6425
|
+
options_.compaction_style == CompactionStyle::kCompactionStyleLevel) {
|
|
6426
|
+
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
|
6427
|
+
"PostPickFileToCompact", [&](void* arg) {
|
|
6428
|
+
bool* picked_file_to_compact = (bool*)arg;
|
|
6429
|
+
// To trigger intra-L0 compaction specifically,
|
|
6430
|
+
// we mock PickFileToCompact()'s result to be false
|
|
6431
|
+
*picked_file_to_compact = false;
|
|
6432
|
+
});
|
|
6433
|
+
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
|
6434
|
+
"FindIntraL0Compaction", [&](void* /*arg*/) {
|
|
6435
|
+
compaction_path_sync_point_called_.store(true);
|
|
6436
|
+
});
|
|
6437
|
+
|
|
6438
|
+
} else if (compaction_path_to_test == "PickPeriodicCompaction") {
|
|
6439
|
+
assert(options_.compaction_style ==
|
|
6440
|
+
CompactionStyle::kCompactionStyleUniversal);
|
|
6441
|
+
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
|
6442
|
+
"PostPickPeriodicCompaction", [&](void* compaction_arg) {
|
|
6443
|
+
Compaction* compaction = (Compaction*)compaction_arg;
|
|
6444
|
+
if (compaction != nullptr) {
|
|
6445
|
+
compaction_path_sync_point_called_.store(true);
|
|
6446
|
+
}
|
|
6447
|
+
});
|
|
6448
|
+
} else if (compaction_path_to_test == "PickCompactionToReduceSizeAmp") {
|
|
6449
|
+
assert(options_.compaction_style ==
|
|
6450
|
+
CompactionStyle::kCompactionStyleUniversal);
|
|
6451
|
+
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
|
6452
|
+
"PickCompactionToReduceSizeAmpReturnNonnullptr", [&](void* /*arg*/) {
|
|
6453
|
+
compaction_path_sync_point_called_.store(true);
|
|
6454
|
+
});
|
|
6455
|
+
} else if (compaction_path_to_test == "PickCompactionToReduceSortedRuns") {
|
|
6456
|
+
assert(options_.compaction_style ==
|
|
6457
|
+
CompactionStyle::kCompactionStyleUniversal);
|
|
6458
|
+
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
|
6459
|
+
"PickCompactionToReduceSortedRunsReturnNonnullptr",
|
|
6460
|
+
[&](void* /*arg*/) {
|
|
6461
|
+
compaction_path_sync_point_called_.store(true);
|
|
6462
|
+
});
|
|
6463
|
+
} else if (compaction_path_to_test == "PickDeleteTriggeredCompaction") {
|
|
6464
|
+
assert(options_.compaction_style ==
|
|
6465
|
+
CompactionStyle::kCompactionStyleUniversal);
|
|
6466
|
+
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
|
6467
|
+
"PickDeleteTriggeredCompactionReturnNonnullptr", [&](void* /*arg*/) {
|
|
6468
|
+
compaction_path_sync_point_called_.store(true);
|
|
6469
|
+
});
|
|
6470
|
+
} else if ((compaction_path_to_test == "FindIntraL0Compaction" ||
|
|
6471
|
+
compaction_path_to_test == "CompactRange") &&
|
|
6472
|
+
options_.compaction_style ==
|
|
6473
|
+
CompactionStyle::kCompactionStyleFIFO) {
|
|
6474
|
+
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
|
6475
|
+
"FindIntraL0Compaction", [&](void* /*arg*/) {
|
|
6476
|
+
compaction_path_sync_point_called_.store(true);
|
|
6477
|
+
});
|
|
6478
|
+
}
|
|
6479
|
+
|
|
6480
|
+
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
|
|
6481
|
+
}
|
|
6482
|
+
|
|
6483
|
+
bool SyncPointsCalled() { return compaction_path_sync_point_called_.load(); }
|
|
6484
|
+
|
|
6485
|
+
void DisableSyncPoints() {
|
|
6486
|
+
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
|
|
6487
|
+
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
|
|
6488
|
+
}
|
|
6489
|
+
|
|
6490
|
+
// Return the largest seqno of the latest L0 file based on file number
|
|
6491
|
+
SequenceNumber GetLatestL0FileLargestSeqnoHelper() {
|
|
6492
|
+
VersionSet* const versions = dbfull()->GetVersionSet();
|
|
6493
|
+
assert(versions);
|
|
6494
|
+
ColumnFamilyData* const cfd = versions->GetColumnFamilySet()->GetDefault();
|
|
6495
|
+
assert(cfd);
|
|
6496
|
+
Version* const current = cfd->current();
|
|
6497
|
+
assert(current);
|
|
6498
|
+
VersionStorageInfo* const storage_info = current->storage_info();
|
|
6499
|
+
assert(storage_info);
|
|
6500
|
+
const std::vector<FileMetaData*> level0_files = storage_info->LevelFiles(0);
|
|
6501
|
+
assert(level0_files.size() >= 1);
|
|
6502
|
+
|
|
6503
|
+
uint64_t latest_file_num = 0;
|
|
6504
|
+
uint64_t latest_file_largest_seqno = 0;
|
|
6505
|
+
for (FileMetaData* f : level0_files) {
|
|
6506
|
+
if (f->fd.GetNumber() > latest_file_num) {
|
|
6507
|
+
latest_file_num = f->fd.GetNumber();
|
|
6508
|
+
latest_file_largest_seqno = f->fd.largest_seqno;
|
|
6509
|
+
}
|
|
6510
|
+
}
|
|
6511
|
+
|
|
6512
|
+
return latest_file_largest_seqno;
|
|
6513
|
+
}
|
|
6372
6514
|
|
|
6373
|
-
|
|
6515
|
+
protected:
|
|
6516
|
+
Options options_;
|
|
6517
|
+
|
|
6518
|
+
private:
|
|
6519
|
+
const Snapshot* snapshot_ = nullptr;
|
|
6520
|
+
std::atomic<bool> compaction_path_sync_point_called_;
|
|
6521
|
+
std::shared_ptr<test::SleepingBackgroundTask> sleeping_task_;
|
|
6522
|
+
};
|
|
6523
|
+
|
|
6524
|
+
TEST_F(DBCompactionTestL0FilesMisorderCorruption,
|
|
6525
|
+
FlushAfterIntraL0LevelCompactionWithIngestedFile) {
|
|
6526
|
+
SetupOptions(CompactionStyle::kCompactionStyleLevel, "");
|
|
6527
|
+
DestroyAndReopen(options_);
|
|
6528
|
+
// Prevents trivial move
|
|
6374
6529
|
for (int i = 0; i < 10; ++i) {
|
|
6375
|
-
ASSERT_OK(Put(Key(i), "")); //
|
|
6530
|
+
ASSERT_OK(Put(Key(i), "")); // Prevents trivial move
|
|
6376
6531
|
}
|
|
6377
6532
|
ASSERT_OK(Flush());
|
|
6378
6533
|
Compact("", Key(99));
|
|
6379
6534
|
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
|
6380
6535
|
|
|
6381
|
-
|
|
6382
|
-
//
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
"FindIntraL0Compaction",
|
|
6393
|
-
[&](void* /*arg*/) { pick_intra_l0_count.fetch_add(1); });
|
|
6394
|
-
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
|
|
6395
|
-
// Make 6 L0 sst.
|
|
6536
|
+
// To get accurate NumTableFilesAtLevel(0) when the number reaches
|
|
6537
|
+
// options_.level0_file_num_compaction_trigger
|
|
6538
|
+
PauseCompactionThread();
|
|
6539
|
+
|
|
6540
|
+
// To create below LSM tree
|
|
6541
|
+
// (key:value@n indicates key-value pair has seqno "n", L0 is sorted):
|
|
6542
|
+
//
|
|
6543
|
+
// memtable: m1[ 5:new@12 .. 1:new@8, 0:new@7]
|
|
6544
|
+
// L0: s6[6:new@13], s5[5:old@6] ... s1[1:old@2],s0[0:old@1]
|
|
6545
|
+
//
|
|
6546
|
+
// (1) Make 6 L0 sst (i.e, s0 - s5)
|
|
6396
6547
|
for (int i = 0; i < 6; ++i) {
|
|
6397
6548
|
if (i % 2 == 0) {
|
|
6398
|
-
IngestOneKeyValue(dbfull(), Key(i),
|
|
6549
|
+
IngestOneKeyValue(dbfull(), Key(i), "old", options_);
|
|
6399
6550
|
} else {
|
|
6400
|
-
ASSERT_OK(Put(Key(i),
|
|
6551
|
+
ASSERT_OK(Put(Key(i), "old"));
|
|
6401
6552
|
ASSERT_OK(Flush());
|
|
6402
6553
|
}
|
|
6403
6554
|
}
|
|
6404
|
-
|
|
6405
6555
|
ASSERT_EQ(6, NumTableFilesAtLevel(0));
|
|
6406
6556
|
|
|
6407
|
-
//
|
|
6408
|
-
env_->SetBackgroundThreads(1, Env::HIGH);
|
|
6409
|
-
test::SleepingBackgroundTask sleeping_tasks;
|
|
6410
|
-
env_->Schedule(&test::SleepingBackgroundTask::DoSleepTask, &sleeping_tasks,
|
|
6411
|
-
Env::Priority::HIGH);
|
|
6412
|
-
sleeping_tasks.WaitUntilSleeping();
|
|
6413
|
-
|
|
6414
|
-
// Put many keys to make memtable request to flush
|
|
6557
|
+
// (2) Create m1
|
|
6415
6558
|
for (int i = 0; i < 6; ++i) {
|
|
6416
|
-
ASSERT_OK(Put(Key(i),
|
|
6559
|
+
ASSERT_OK(Put(Key(i), "new"));
|
|
6417
6560
|
}
|
|
6418
|
-
|
|
6419
6561
|
ASSERT_EQ(6, NumTableFilesAtLevel(0));
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
// ingest file to trigger IntraL0Compaction
|
|
6424
|
-
for (int i = 6; i < 10; ++i) {
|
|
6562
|
+
|
|
6563
|
+
// (3) Ingest file (i.e, s6) to trigger IntraL0Compaction()
|
|
6564
|
+
for (int i = 6; i < 7; ++i) {
|
|
6425
6565
|
ASSERT_EQ(i, NumTableFilesAtLevel(0));
|
|
6426
|
-
IngestOneKeyValue(dbfull(), Key(i),
|
|
6566
|
+
IngestOneKeyValue(dbfull(), Key(i), "new", options_);
|
|
6427
6567
|
}
|
|
6428
6568
|
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6569
|
+
SetupSyncPoints("FindIntraL0Compaction");
|
|
6570
|
+
ResumeCompactionThread();
|
|
6571
|
+
|
|
6432
6572
|
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
|
6433
|
-
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
|
|
6434
6573
|
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6574
|
+
ASSERT_TRUE(SyncPointsCalled());
|
|
6575
|
+
DisableSyncPoints();
|
|
6576
|
+
|
|
6577
|
+
// After compaction, we have LSM tree:
|
|
6578
|
+
//
|
|
6579
|
+
// memtable: m1[ 5:new@12 .. 1:new@8, 0:new@7]
|
|
6580
|
+
// L0: s7[6:new@13, 5:old@6 .. 0:old@1]
|
|
6581
|
+
ASSERT_EQ(1, NumTableFilesAtLevel(0));
|
|
6582
|
+
SequenceNumber compact_output_file_largest_seqno =
|
|
6583
|
+
GetLatestL0FileLargestSeqnoHelper();
|
|
6584
|
+
|
|
6585
|
+
ASSERT_OK(Flush());
|
|
6586
|
+
// After flush, we have LSM tree:
|
|
6587
|
+
//
|
|
6588
|
+
// L0: s8[5:new@12 .. 0:new@7],s7[6:new@13, 5:old@5 .. 0:old@1]
|
|
6589
|
+
ASSERT_EQ(2, NumTableFilesAtLevel(0));
|
|
6590
|
+
SequenceNumber flushed_file_largest_seqno =
|
|
6591
|
+
GetLatestL0FileLargestSeqnoHelper();
|
|
6592
|
+
|
|
6593
|
+
// To verify there isn't any file misorder leading to returning a old value
|
|
6594
|
+
// of Key(0) - Key(5) , which is caused by flushed table s8 has a
|
|
6595
|
+
// smaller largest seqno than the compaction output file s7's largest seqno
|
|
6596
|
+
// while the flushed table has the newer version of the values than the
|
|
6597
|
+
// compaction output file's.
|
|
6598
|
+
ASSERT_TRUE(flushed_file_largest_seqno < compact_output_file_largest_seqno);
|
|
6439
6599
|
for (int i = 0; i < 6; ++i) {
|
|
6440
|
-
ASSERT_EQ(
|
|
6600
|
+
ASSERT_EQ("new", Get(Key(i)));
|
|
6441
6601
|
}
|
|
6442
|
-
for (int i = 6; i <
|
|
6443
|
-
ASSERT_EQ(
|
|
6602
|
+
for (int i = 6; i < 7; ++i) {
|
|
6603
|
+
ASSERT_EQ("new", Get(Key(i)));
|
|
6444
6604
|
}
|
|
6445
6605
|
}
|
|
6446
6606
|
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6607
|
+
TEST_F(DBCompactionTestL0FilesMisorderCorruption,
|
|
6608
|
+
FlushAfterIntraL0UniversalCompactionWithIngestedFile) {
|
|
6609
|
+
for (const std::string compaction_path_to_test :
|
|
6610
|
+
{"PickPeriodicCompaction", "PickCompactionToReduceSizeAmp",
|
|
6611
|
+
"PickCompactionToReduceSortedRuns", "PickDeleteTriggeredCompaction"}) {
|
|
6612
|
+
SetupOptions(CompactionStyle::kCompactionStyleUniversal,
|
|
6613
|
+
compaction_path_to_test);
|
|
6614
|
+
DestroyAndReopen(options_);
|
|
6615
|
+
|
|
6616
|
+
// To get accurate NumTableFilesAtLevel(0) when the number reaches
|
|
6617
|
+
// options_.level0_file_num_compaction_trigger
|
|
6618
|
+
PauseCompactionThread();
|
|
6619
|
+
|
|
6620
|
+
// To create below LSM tree
|
|
6621
|
+
// (key:value@n indicates key-value pair has seqno "n", L0 is sorted):
|
|
6622
|
+
//
|
|
6623
|
+
// memtable: m1 [ k2:new@8, k1:new@7]
|
|
6624
|
+
// L0: s4[k9:dummy@10], s3[k8:dummy@9],
|
|
6625
|
+
// s2[k7:old@6, k6:old@5].. s0[k3:old@2, k1:old@1]
|
|
6626
|
+
//
|
|
6627
|
+
// (1) Create 3 existing SST file (i.e, s0 - s2)
|
|
6628
|
+
ASSERT_OK(Put("k1", "old"));
|
|
6629
|
+
ASSERT_OK(Put("k3", "old"));
|
|
6630
|
+
ASSERT_OK(Flush());
|
|
6631
|
+
ASSERT_EQ(1, NumTableFilesAtLevel(0));
|
|
6632
|
+
ASSERT_OK(Put("k4", "old"));
|
|
6633
|
+
ASSERT_OK(Put("k5", "old"));
|
|
6634
|
+
ASSERT_OK(Flush());
|
|
6635
|
+
ASSERT_EQ(2, NumTableFilesAtLevel(0));
|
|
6636
|
+
ASSERT_OK(Put("k6", "old"));
|
|
6637
|
+
ASSERT_OK(Put("k7", "old"));
|
|
6638
|
+
ASSERT_OK(Flush());
|
|
6639
|
+
ASSERT_EQ(3, NumTableFilesAtLevel(0));
|
|
6452
6640
|
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
options.create_if_missing = true;
|
|
6457
|
-
options.compression = kNoCompression;
|
|
6641
|
+
// (2) Create m1. Noted that it contains a overlaped key with s0
|
|
6642
|
+
ASSERT_OK(Put("k1", "new")); // overlapped key
|
|
6643
|
+
ASSERT_OK(Put("k2", "new"));
|
|
6458
6644
|
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6462
|
-
|
|
6463
|
-
|
|
6645
|
+
// (3) Ingest two SST files s3, s4
|
|
6646
|
+
IngestOneKeyValue(dbfull(), "k8", "dummy", options_);
|
|
6647
|
+
IngestOneKeyValue(dbfull(), "k9", "dummy", options_);
|
|
6648
|
+
// Up to now, L0 contains s0 - s4
|
|
6649
|
+
ASSERT_EQ(5, NumTableFilesAtLevel(0));
|
|
6464
6650
|
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
} else if (compaction_path_to_test == "PickCompactionToWarm") {
|
|
6471
|
-
fifo_options.allow_compaction = false;
|
|
6472
|
-
fifo_options.age_for_warm = 2;
|
|
6473
|
-
} else if (compaction_path_to_test == "CompactRange") {
|
|
6474
|
-
// FIFOCompactionPicker::CompactRange() implementes
|
|
6475
|
-
// on top of regular compaction paths. Here we choose
|
|
6476
|
-
// to trigger FIFOCompactionPicker::PickCompactionToWarm()
|
|
6477
|
-
// for simplicity
|
|
6478
|
-
fifo_options.allow_compaction = false;
|
|
6479
|
-
fifo_options.age_for_warm = 2;
|
|
6480
|
-
options.disable_auto_compactions = true;
|
|
6481
|
-
} else if (compaction_path_to_test == "CompactFile") {
|
|
6482
|
-
fifo_options.allow_compaction = false;
|
|
6483
|
-
fifo_options.age_for_warm = 0;
|
|
6484
|
-
options.disable_auto_compactions = true;
|
|
6485
|
-
} else {
|
|
6486
|
-
assert(false);
|
|
6487
|
-
}
|
|
6488
|
-
options.compaction_options_fifo = fifo_options;
|
|
6651
|
+
if (compaction_path_to_test == "PickPeriodicCompaction") {
|
|
6652
|
+
AddFilesMarkedForPeriodicCompaction(5);
|
|
6653
|
+
} else if (compaction_path_to_test == "PickDeleteTriggeredCompaction") {
|
|
6654
|
+
AddFilesMarkedForCompaction(5);
|
|
6655
|
+
}
|
|
6489
6656
|
|
|
6490
|
-
|
|
6657
|
+
SetupSyncPoints(compaction_path_to_test);
|
|
6658
|
+
ResumeCompactionThread();
|
|
6491
6659
|
|
|
6492
|
-
|
|
6493
|
-
// for our test purpose
|
|
6494
|
-
const Snapshot* snapshot = db_->GetSnapshot();
|
|
6660
|
+
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
|
6495
6661
|
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
"FindIntraL0Compaction",
|
|
6500
|
-
[&](void* /*arg*/) { compaction_path_sync_point_called.store(true); });
|
|
6501
|
-
} else if (compaction_path_to_test == "PickCompactionToWarm" ||
|
|
6502
|
-
compaction_path_to_test == "CompactRange") {
|
|
6503
|
-
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
|
6504
|
-
"PickCompactionToWarm",
|
|
6505
|
-
[&](void* /*arg*/) { compaction_path_sync_point_called.store(true); });
|
|
6506
|
-
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
|
6507
|
-
"PickCompactionToWarm::BeforeGetCurrentTime",
|
|
6508
|
-
[&fifo_options](void* current_time_arg) -> void {
|
|
6509
|
-
// The unit test goes so quickly that there is almost no time
|
|
6510
|
-
// elapsed after we ingest a file and before we check whether ingested
|
|
6511
|
-
// files can compact to warm.
|
|
6512
|
-
// Therefore we need this trick to simulate elapsed
|
|
6513
|
-
// time in reality.
|
|
6514
|
-
int64_t* current_time = (int64_t*)current_time_arg;
|
|
6515
|
-
*current_time = *current_time + fifo_options.age_for_warm + 1;
|
|
6516
|
-
});
|
|
6517
|
-
} else if (compaction_path_to_test == "CompactFile") {
|
|
6518
|
-
// Sync point is not needed in this case
|
|
6519
|
-
compaction_path_sync_point_called.store(true);
|
|
6520
|
-
}
|
|
6662
|
+
ASSERT_TRUE(SyncPointsCalled())
|
|
6663
|
+
<< "failed for compaction path to test: " << compaction_path_to_test;
|
|
6664
|
+
DisableSyncPoints();
|
|
6521
6665
|
|
|
6522
|
-
|
|
6666
|
+
// After compaction, we have LSM tree:
|
|
6667
|
+
//
|
|
6668
|
+
// memtable: m1[ k2:new@8, k1:new@7]
|
|
6669
|
+
// L0: s5[k9:dummy@10, k8@dummy@9, k7:old@6 .. k3:old@2, k1:old@1]
|
|
6670
|
+
ASSERT_EQ(1, NumTableFilesAtLevel(0))
|
|
6671
|
+
<< "failed for compaction path to test: " << compaction_path_to_test;
|
|
6672
|
+
SequenceNumber compact_output_file_largest_seqno =
|
|
6673
|
+
GetLatestL0FileLargestSeqnoHelper();
|
|
6674
|
+
|
|
6675
|
+
ASSERT_OK(Flush()) << "failed for compaction path to test: "
|
|
6676
|
+
<< compaction_path_to_test;
|
|
6677
|
+
// After flush, we have LSM tree:
|
|
6678
|
+
//
|
|
6679
|
+
// L0: s6[k2:new@8, k1:new@7],
|
|
6680
|
+
// s5[k9:dummy@10, k8@dummy@9, k7:old@6 .. k3:old@2, k1:old@1]
|
|
6681
|
+
ASSERT_EQ(2, NumTableFilesAtLevel(0))
|
|
6682
|
+
<< "failed for compaction path to test: " << compaction_path_to_test;
|
|
6683
|
+
SequenceNumber flushed_file_largest_seqno =
|
|
6684
|
+
GetLatestL0FileLargestSeqnoHelper();
|
|
6685
|
+
|
|
6686
|
+
// To verify there isn't any file misorder leading to returning a old
|
|
6687
|
+
// value of "k1" , which is caused by flushed table s6 has a
|
|
6688
|
+
// smaller largest seqno than the compaction output file s5's largest seqno
|
|
6689
|
+
// while the flushed table has the newer version of the value
|
|
6690
|
+
// than the compaction output file's.
|
|
6691
|
+
ASSERT_TRUE(flushed_file_largest_seqno < compact_output_file_largest_seqno)
|
|
6692
|
+
<< "failed for compaction path to test: " << compaction_path_to_test;
|
|
6693
|
+
EXPECT_EQ(Get("k1"), "new")
|
|
6694
|
+
<< "failed for compaction path to test: " << compaction_path_to_test;
|
|
6695
|
+
}
|
|
6696
|
+
|
|
6697
|
+
Destroy(options_);
|
|
6698
|
+
}
|
|
6699
|
+
|
|
6700
|
+
TEST_F(DBCompactionTestL0FilesMisorderCorruption,
|
|
6701
|
+
FlushAfterIntraL0FIFOCompactionWithIngestedFile) {
|
|
6702
|
+
for (const std::string compaction_path_to_test : {"FindIntraL0Compaction"}) {
|
|
6703
|
+
SetupOptions(CompactionStyle::kCompactionStyleFIFO,
|
|
6704
|
+
compaction_path_to_test);
|
|
6705
|
+
DestroyAndReopen(options_);
|
|
6706
|
+
|
|
6707
|
+
// To create below LSM tree
|
|
6708
|
+
// (key:value@n indicates key-value pair has seqno "n", L0 is sorted):
|
|
6709
|
+
//
|
|
6710
|
+
// memtable: m1 [ k2:new@4, k1:new@3]
|
|
6711
|
+
// L0: s2[k5:dummy@6], s1[k4:dummy@5], s0[k3:old@2, k1:old@1]
|
|
6712
|
+
//
|
|
6713
|
+
// (1) Create an existing SST file s0
|
|
6714
|
+
ASSERT_OK(Put("k1", "old"));
|
|
6715
|
+
ASSERT_OK(Put("k3", "old"));
|
|
6716
|
+
ASSERT_OK(Flush());
|
|
6717
|
+
ASSERT_EQ(1, NumTableFilesAtLevel(0));
|
|
6718
|
+
|
|
6719
|
+
// (2) Create memtable m1. Noted that it contains a overlaped key with s0
|
|
6720
|
+
ASSERT_OK(Put("k1", "new")); // overlapped key
|
|
6721
|
+
ASSERT_OK(Put("k2", "new"));
|
|
6722
|
+
|
|
6723
|
+
// To get accurate NumTableFilesAtLevel(0) when the number reaches
|
|
6724
|
+
// options_.level0_file_num_compaction_trigger
|
|
6725
|
+
PauseCompactionThread();
|
|
6726
|
+
|
|
6727
|
+
// (3) Ingest two SST files s1, s2
|
|
6728
|
+
IngestOneKeyValue(dbfull(), "k4", "dummy", options_);
|
|
6729
|
+
IngestOneKeyValue(dbfull(), "k5", "dummy", options_);
|
|
6730
|
+
// Up to now, L0 contains s0, s1, s2
|
|
6731
|
+
ASSERT_EQ(3, NumTableFilesAtLevel(0));
|
|
6523
6732
|
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
|
|
6733
|
+
SetupSyncPoints(compaction_path_to_test);
|
|
6734
|
+
ResumeCompactionThread();
|
|
6735
|
+
|
|
6736
|
+
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
|
6737
|
+
|
|
6738
|
+
ASSERT_TRUE(SyncPointsCalled())
|
|
6739
|
+
<< "failed for compaction path to test: " << compaction_path_to_test;
|
|
6740
|
+
DisableSyncPoints();
|
|
6741
|
+
// After compaction, we have LSM tree:
|
|
6742
|
+
//
|
|
6743
|
+
// memtable: m1 [ k2:new@4, k1:new@3]
|
|
6744
|
+
// L0: s3[k5:dummy@6, k4:dummy@5, k3:old@2, k1:old@1]
|
|
6745
|
+
ASSERT_EQ(1, NumTableFilesAtLevel(0))
|
|
6746
|
+
<< "failed for compaction path to test: " << compaction_path_to_test;
|
|
6747
|
+
SequenceNumber compact_output_file_largest_seqno =
|
|
6748
|
+
GetLatestL0FileLargestSeqnoHelper();
|
|
6749
|
+
|
|
6750
|
+
ASSERT_OK(Flush()) << "failed for compaction path to test: "
|
|
6751
|
+
<< compaction_path_to_test;
|
|
6752
|
+
// After flush, we have LSM tree:
|
|
6753
|
+
//
|
|
6754
|
+
// L0: s4[k2:new@4, k1:new@3], s3[k5:dummy@6, k4:dummy@5, k3:old@2,
|
|
6755
|
+
// k1:old@1]
|
|
6756
|
+
ASSERT_EQ(2, NumTableFilesAtLevel(0))
|
|
6757
|
+
<< "failed for compaction path to test: " << compaction_path_to_test;
|
|
6758
|
+
SequenceNumber flushed_file_largest_seqno =
|
|
6759
|
+
GetLatestL0FileLargestSeqnoHelper();
|
|
6760
|
+
|
|
6761
|
+
// To verify there isn't any file misorder leading to returning a old
|
|
6762
|
+
// value of "k1" , which is caused by flushed table s4 has a
|
|
6763
|
+
// smaller largest seqno than the compaction output file s3's largest seqno
|
|
6764
|
+
// while the flushed table has the newer version of the value
|
|
6765
|
+
// than the compaction output file's.
|
|
6766
|
+
ASSERT_TRUE(flushed_file_largest_seqno < compact_output_file_largest_seqno)
|
|
6767
|
+
<< "failed for compaction path to test: " << compaction_path_to_test;
|
|
6768
|
+
EXPECT_EQ(Get("k1"), "new")
|
|
6769
|
+
<< "failed for compaction path to test: " << compaction_path_to_test;
|
|
6770
|
+
}
|
|
6771
|
+
|
|
6772
|
+
Destroy(options_);
|
|
6773
|
+
}
|
|
6774
|
+
|
|
6775
|
+
class DBCompactionTestL0FilesMisorderCorruptionWithParam
|
|
6776
|
+
: public DBCompactionTestL0FilesMisorderCorruption,
|
|
6777
|
+
public testing::WithParamInterface<CompactionStyle> {
|
|
6778
|
+
public:
|
|
6779
|
+
DBCompactionTestL0FilesMisorderCorruptionWithParam()
|
|
6780
|
+
: DBCompactionTestL0FilesMisorderCorruption() {}
|
|
6781
|
+
};
|
|
6782
|
+
|
|
6783
|
+
// TODO: add `CompactionStyle::kCompactionStyleLevel` to testing parameter,
|
|
6784
|
+
// which requires careful unit test
|
|
6785
|
+
// design for ingesting file to L0 and CompactRange()/CompactFile() to L0
|
|
6786
|
+
INSTANTIATE_TEST_CASE_P(
|
|
6787
|
+
DBCompactionTestL0FilesMisorderCorruptionWithParam,
|
|
6788
|
+
DBCompactionTestL0FilesMisorderCorruptionWithParam,
|
|
6789
|
+
::testing::Values(CompactionStyle::kCompactionStyleUniversal,
|
|
6790
|
+
CompactionStyle::kCompactionStyleFIFO));
|
|
6791
|
+
|
|
6792
|
+
TEST_P(DBCompactionTestL0FilesMisorderCorruptionWithParam,
|
|
6793
|
+
FlushAfterIntraL0CompactFileWithIngestedFile) {
|
|
6794
|
+
SetupOptions(GetParam(), "CompactFile");
|
|
6795
|
+
DestroyAndReopen(options_);
|
|
6796
|
+
|
|
6797
|
+
// To create below LSM tree
|
|
6798
|
+
// (key:value@n indicates key-value pair has seqno "n", L0 is sorted):
|
|
6799
|
+
//
|
|
6800
|
+
// memtable: m1 [ k2:new@4, k1:new@3]
|
|
6801
|
+
// L0: s2[k5:dummy@6], s1[k4:dummy@5], s0[k3:old@2, k1:old@1]
|
|
6802
|
+
//
|
|
6803
|
+
// (1) Create an existing SST file s0
|
|
6804
|
+
ASSERT_OK(Put("k1", "old"));
|
|
6805
|
+
ASSERT_OK(Put("k3", "old"));
|
|
6528
6806
|
ASSERT_OK(Flush());
|
|
6529
6807
|
ASSERT_EQ(1, NumTableFilesAtLevel(0));
|
|
6530
6808
|
|
|
6531
|
-
//
|
|
6532
|
-
|
|
6533
|
-
ASSERT_OK(Put("
|
|
6534
|
-
ASSERT_OK(Put("key2", "seq4"));
|
|
6809
|
+
// (2) Create memtable m1. Noted that it contains a overlaped key with s0
|
|
6810
|
+
ASSERT_OK(Put("k1", "new")); // overlapped key
|
|
6811
|
+
ASSERT_OK(Put("k2", "new"));
|
|
6535
6812
|
|
|
6536
|
-
|
|
6537
|
-
|
|
6813
|
+
// (3) Ingest two SST files s1, s2
|
|
6814
|
+
IngestOneKeyValue(dbfull(), "k4", "dummy", options_);
|
|
6815
|
+
IngestOneKeyValue(dbfull(), "k5", "dummy", options_);
|
|
6816
|
+
// Up to now, L0 contains s0, s1, s2
|
|
6817
|
+
ASSERT_EQ(3, NumTableFilesAtLevel(0));
|
|
6538
6818
|
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
Env::Priority::LOW);
|
|
6546
|
-
sleeping_tasks.WaitUntilSleeping();
|
|
6819
|
+
ColumnFamilyMetaData cf_meta_data;
|
|
6820
|
+
db_->GetColumnFamilyMetaData(&cf_meta_data);
|
|
6821
|
+
ASSERT_EQ(cf_meta_data.levels[0].files.size(), 3);
|
|
6822
|
+
std::vector<std::string> input_files;
|
|
6823
|
+
for (const auto& file : cf_meta_data.levels[0].files) {
|
|
6824
|
+
input_files.push_back(file.name);
|
|
6547
6825
|
}
|
|
6826
|
+
ASSERT_EQ(input_files.size(), 3);
|
|
6827
|
+
|
|
6828
|
+
Status s = db_->CompactFiles(CompactionOptions(), input_files, 0);
|
|
6829
|
+
// After compaction, we have LSM tree:
|
|
6830
|
+
//
|
|
6831
|
+
// memtable: m1 [ k2:new@4, k1:new@3]
|
|
6832
|
+
// L0: s3[k5:dummy@6, k4:dummy@5, k3:old@2, k1:old@1]
|
|
6833
|
+
ASSERT_OK(s);
|
|
6834
|
+
ASSERT_EQ(1, NumTableFilesAtLevel(0));
|
|
6835
|
+
SequenceNumber compact_output_file_largest_seqno =
|
|
6836
|
+
GetLatestL0FileLargestSeqnoHelper();
|
|
6548
6837
|
|
|
6549
|
-
|
|
6550
|
-
//
|
|
6551
|
-
|
|
6552
|
-
|
|
6838
|
+
ASSERT_OK(Flush());
|
|
6839
|
+
// After flush, we have LSM tree:
|
|
6840
|
+
//
|
|
6841
|
+
// L0: s4[k2:new@4, k1:new@3], s3[k5:dummy@6, k4:dummy@5, k3:old@2,
|
|
6842
|
+
// k1:old@1]
|
|
6843
|
+
ASSERT_EQ(2, NumTableFilesAtLevel(0));
|
|
6844
|
+
SequenceNumber flushed_file_largest_seqno =
|
|
6845
|
+
GetLatestL0FileLargestSeqnoHelper();
|
|
6846
|
+
|
|
6847
|
+
// To verify there isn't any file misorder leading to returning a old value
|
|
6848
|
+
// of "1" , which is caused by flushed table s4 has a smaller
|
|
6849
|
+
// largest seqno than the compaction output file s3's largest seqno while the
|
|
6850
|
+
// flushed table has the newer version of the value than the
|
|
6851
|
+
// compaction output file's.
|
|
6852
|
+
ASSERT_TRUE(flushed_file_largest_seqno < compact_output_file_largest_seqno);
|
|
6853
|
+
EXPECT_EQ(Get("k1"), "new");
|
|
6854
|
+
|
|
6855
|
+
Destroy(options_);
|
|
6856
|
+
}
|
|
6857
|
+
|
|
6858
|
+
TEST_P(DBCompactionTestL0FilesMisorderCorruptionWithParam,
|
|
6859
|
+
FlushAfterIntraL0CompactRangeWithIngestedFile) {
|
|
6860
|
+
SetupOptions(GetParam(), "CompactRange");
|
|
6861
|
+
DestroyAndReopen(options_);
|
|
6862
|
+
|
|
6863
|
+
// To create below LSM tree
|
|
6864
|
+
// (key:value@n indicates key-value pair has seqno "n", L0 is sorted):
|
|
6865
|
+
//
|
|
6866
|
+
// memtable: m1 [ k2:new@4, k1:new@3]
|
|
6867
|
+
// L0: s2[k5:dummy@6], s1[k4:dummy@5], s0[k3:old@2, k1:old@1]
|
|
6868
|
+
//
|
|
6869
|
+
// (1) Create an existing SST file s0
|
|
6870
|
+
ASSERT_OK(Put("k1", "old"));
|
|
6871
|
+
ASSERT_OK(Put("k3", "old"));
|
|
6872
|
+
ASSERT_OK(Flush());
|
|
6873
|
+
ASSERT_EQ(1, NumTableFilesAtLevel(0));
|
|
6874
|
+
|
|
6875
|
+
// (2) Create memtable m1. Noted that it contains a overlaped key with s0
|
|
6876
|
+
ASSERT_OK(Put("k1", "new")); // overlapped key
|
|
6877
|
+
ASSERT_OK(Put("k2", "new"));
|
|
6878
|
+
|
|
6879
|
+
// (3) Ingest two SST files s1, s2
|
|
6880
|
+
IngestOneKeyValue(dbfull(), "k4", "dummy", options_);
|
|
6881
|
+
IngestOneKeyValue(dbfull(), "k5", "dummy", options_);
|
|
6553
6882
|
// Up to now, L0 contains s0, s1, s2
|
|
6554
6883
|
ASSERT_EQ(3, NumTableFilesAtLevel(0));
|
|
6555
6884
|
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
if (!options.disable_auto_compactions) {
|
|
6559
|
-
sleeping_tasks.WakeUp();
|
|
6560
|
-
sleeping_tasks.WaitUntilDone();
|
|
6561
|
-
}
|
|
6562
|
-
|
|
6563
|
-
if (compaction_path_to_test == "CompactRange") {
|
|
6564
|
-
// `start` and `end` is carefully chosen so that compact range:
|
|
6565
|
-
// (1) doesn't overlap with memtable therefore the memtable won't be flushed
|
|
6566
|
-
// (2) should target at compacting s0 with s1 and s2
|
|
6567
|
-
Slice start("key4"), end("key6");
|
|
6568
|
-
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), &start, &end));
|
|
6569
|
-
} else if (compaction_path_to_test == "CompactFile") {
|
|
6570
|
-
ColumnFamilyMetaData cf_meta_data;
|
|
6571
|
-
db_->GetColumnFamilyMetaData(&cf_meta_data);
|
|
6572
|
-
assert(cf_meta_data.levels[0].files.size() == 3);
|
|
6573
|
-
std::vector<std::string> input_files;
|
|
6574
|
-
for (const auto& file : cf_meta_data.levels[0].files) {
|
|
6575
|
-
input_files.push_back(file.name);
|
|
6576
|
-
}
|
|
6577
|
-
Status s = db_->CompactFiles(CompactionOptions(), input_files, 0);
|
|
6578
|
-
EXPECT_TRUE(s.IsAborted());
|
|
6579
|
-
EXPECT_TRUE(s.ToString().find(
|
|
6580
|
-
"has overlapping seqnos with earliest memtable seqnos") !=
|
|
6581
|
-
std::string::npos);
|
|
6582
|
-
} else {
|
|
6583
|
-
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
|
6885
|
+
if (options_.compaction_style == CompactionStyle::kCompactionStyleFIFO) {
|
|
6886
|
+
SetupSyncPoints("CompactRange");
|
|
6584
6887
|
}
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6888
|
+
// `start` and `end` is carefully chosen so that compact range:
|
|
6889
|
+
// (1) doesn't overlap with memtable therefore the memtable won't be flushed
|
|
6890
|
+
// (2) should target at compacting s0 with s1 and s2
|
|
6891
|
+
Slice start("k3"), end("k5");
|
|
6892
|
+
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), &start, &end));
|
|
6893
|
+
// After compaction, we have LSM tree:
|
|
6894
|
+
//
|
|
6895
|
+
// memtable: m1 [ k2:new@4, k1:new@3]
|
|
6896
|
+
// L0: s3[k5:dummy@6, k4:dummy@5, k3:old@2, k1:old@1]
|
|
6897
|
+
if (options_.compaction_style == CompactionStyle::kCompactionStyleFIFO) {
|
|
6898
|
+
ASSERT_TRUE(SyncPointsCalled());
|
|
6899
|
+
DisableSyncPoints();
|
|
6900
|
+
}
|
|
6901
|
+
ASSERT_EQ(1, NumTableFilesAtLevel(0));
|
|
6902
|
+
SequenceNumber compact_output_file_largest_seqno =
|
|
6903
|
+
GetLatestL0FileLargestSeqnoHelper();
|
|
6589
6904
|
|
|
6590
|
-
|
|
6591
|
-
//
|
|
6905
|
+
ASSERT_OK(Flush());
|
|
6906
|
+
// After flush, we have LSM tree:
|
|
6592
6907
|
//
|
|
6593
|
-
//
|
|
6594
|
-
//
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6908
|
+
// L0: s4[k2:new@4, k1:new@3], s3[k5:dummy@6, k4:dummy@5, k3:old@2,
|
|
6909
|
+
// k1:old@1]
|
|
6910
|
+
ASSERT_EQ(2, NumTableFilesAtLevel(0));
|
|
6911
|
+
SequenceNumber flushed_file_largest_seqno =
|
|
6912
|
+
GetLatestL0FileLargestSeqnoHelper();
|
|
6913
|
+
|
|
6914
|
+
// To verify there isn't any file misorder leading to returning a old value
|
|
6915
|
+
// of "k1" , which is caused by flushed table s4 has a smaller
|
|
6916
|
+
// largest seqno than the compaction output file s3's largest seqno while the
|
|
6917
|
+
// flushed table has the newer version of the value than the
|
|
6918
|
+
// compaction output file's.
|
|
6919
|
+
ASSERT_TRUE(flushed_file_largest_seqno < compact_output_file_largest_seqno);
|
|
6920
|
+
EXPECT_EQ(Get("k1"), "new");
|
|
6921
|
+
|
|
6922
|
+
Destroy(options_);
|
|
6602
6923
|
}
|
|
6603
6924
|
|
|
6604
6925
|
TEST_P(DBCompactionTestWithBottommostParam, SequenceKeysManualCompaction) {
|