Skip to content

Commit 03cfaf3

Browse files
committed
Make CompactionPicker::CompactFiles() take earliest_snapshot and snapshot_checker (facebook#13816)
Summary: One of the parameters for constructing a Compaction object is `earliest_snapshot`, which is required for Standalone Range Deletion Optimization (introduced in [https://github.com/facebook/rocksdb/pull/13078](https://github.com/facebook/rocksdb/pull/13078)). Remote Compaction has been using the `CompactionPicker::CompactFiles()` API to create the Compaction object, but this API never sets the `earliest_snapshot` parameter. To address this, update `CompactionPicker::CompactFiles()` to optionally accept `earliest_snapshot` and pass it during the call in `DBImplSecondary::CompactWithoutInstallation()`. Pull Request resolved: facebook#13816 Test Plan: ``` ./compaction_service_test --gtest_filter="*CompactionServiceTest.StandaloneDeleteRangeTombstoneOptimization*" ``` \+ Tested in Meta's internal offload infra. Reviewed By: hx235 Differential Revision: D79284769 Pulled By: jaykorean fbshipit-source-id: 164834ef6972d5e0ddfc2970bb9234ef166d6e52
1 parent 1061f74 commit 03cfaf3

4 files changed

Lines changed: 123 additions & 17 deletions

File tree

db/compaction/compaction_picker.cc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,9 @@ Compaction* CompactionPicker::CompactFiles(
337337
const CompactionOptions& compact_options,
338338
const std::vector<CompactionInputFiles>& input_files, int output_level,
339339
VersionStorageInfo* vstorage, const MutableCFOptions& mutable_cf_options,
340-
const MutableDBOptions& mutable_db_options, uint32_t output_path_id) {
340+
const MutableDBOptions& mutable_db_options, uint32_t output_path_id,
341+
std::optional<SequenceNumber> earliest_snapshot,
342+
const SnapshotChecker* snapshot_checker) {
341343
#ifndef NDEBUG
342344
assert(input_files.size());
343345
// This compaction output should not overlap with a running compaction as
@@ -380,8 +382,8 @@ Compaction* CompactionPicker::CompactFiles(
380382
GetCompressionOptions(mutable_cf_options, vstorage, output_level),
381383
mutable_cf_options.default_write_temperature,
382384
compact_options.max_subcompactions,
383-
/* grandparents */ {}, /* earliest_snapshot */ std::nullopt,
384-
/* snapshot_checker */ nullptr, CompactionReason::kManualCompaction);
385+
/* grandparents */ {}, earliest_snapshot, snapshot_checker,
386+
CompactionReason::kManualCompaction);
385387
RegisterCompaction(c);
386388
return c;
387389
}

db/compaction/compaction_picker.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,17 @@ class CompactionPicker {
117117
// Caller must provide a set of input files that has been passed through
118118
// `SanitizeAndConvertCompactionInputFiles` earlier. The lock should not be
119119
// released between that call and this one.
120-
Compaction* CompactFiles(const CompactionOptions& compact_options,
121-
const std::vector<CompactionInputFiles>& input_files,
122-
int output_level, VersionStorageInfo* vstorage,
123-
const MutableCFOptions& mutable_cf_options,
124-
const MutableDBOptions& mutable_db_options,
125-
uint32_t output_path_id);
120+
//
121+
// TODO - Remove default values for earliest_snapshot and snapshot_checker
122+
// and require all callers to pass them in so that DB::CompactFiles() can
123+
// also benefit from Standalone Range Tombstone Optimization
124+
Compaction* CompactFiles(
125+
const CompactionOptions& compact_options,
126+
const std::vector<CompactionInputFiles>& input_files, int output_level,
127+
VersionStorageInfo* vstorage, const MutableCFOptions& mutable_cf_options,
128+
const MutableDBOptions& mutable_db_options, uint32_t output_path_id,
129+
std::optional<SequenceNumber> earliest_snapshot = std::nullopt,
130+
const SnapshotChecker* snapshot_checker = nullptr);
126131

127132
// Converts a set of compaction input file numbers into
128133
// a list of CompactionInputFiles.

db/compaction/compaction_service_test.cc

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,97 @@ TEST_F(CompactionServiceTest, ManualCompaction) {
461461
ASSERT_EQ(handles_[1]->GetName(), info.cf_name);
462462
}
463463

464+
TEST_F(CompactionServiceTest, StandaloneDeleteRangeTombstoneOptimization) {
465+
Options options = CurrentOptions();
466+
options.compaction_style = CompactionStyle::kCompactionStyleUniversal;
467+
ReopenWithCompactionService(&options);
468+
469+
size_t num_files_after_filtered = 0;
470+
SyncPoint::GetInstance()->SetCallBack(
471+
"VersionSet::MakeInputIterator:NewCompactionMergingIterator",
472+
[&](void* arg) {
473+
num_files_after_filtered = *static_cast<size_t*>(arg);
474+
});
475+
476+
SyncPoint::GetInstance()->EnableProcessing();
477+
478+
std::vector<std::string> files;
479+
{
480+
// Writes first version of data in range partitioned files.
481+
SstFileWriter sst_file_writer(EnvOptions(), options);
482+
std::string file1 = dbname_ + "file1.sst";
483+
ASSERT_OK(sst_file_writer.Open(file1));
484+
ASSERT_OK(sst_file_writer.Put("a", "a1"));
485+
ASSERT_OK(sst_file_writer.Put("b", "b1"));
486+
ExternalSstFileInfo file1_info;
487+
ASSERT_OK(sst_file_writer.Finish(&file1_info));
488+
files.push_back(std::move(file1));
489+
490+
std::string file2 = dbname_ + "file2.sst";
491+
ASSERT_OK(sst_file_writer.Open(file2));
492+
ASSERT_OK(sst_file_writer.Put("x", "x1"));
493+
ASSERT_OK(sst_file_writer.Put("y", "y1"));
494+
ExternalSstFileInfo file2_info;
495+
ASSERT_OK(sst_file_writer.Finish(&file2_info));
496+
files.push_back(std::move(file2));
497+
}
498+
499+
IngestExternalFileOptions ifo;
500+
ASSERT_OK(db_->IngestExternalFile(files, ifo));
501+
ASSERT_EQ(Get("a"), "a1");
502+
ASSERT_EQ(Get("b"), "b1");
503+
ASSERT_EQ(Get("x"), "x1");
504+
ASSERT_EQ(Get("y"), "y1");
505+
ASSERT_EQ(2, NumTableFilesAtLevel(6));
506+
507+
auto my_cs = GetCompactionService();
508+
uint64_t comp_num = my_cs->GetCompactionNum();
509+
510+
{
511+
// Atomically delete old version of data with one range delete file.
512+
// And a new batch of range partitioned files with new version of data.
513+
files.clear();
514+
SstFileWriter sst_file_writer(EnvOptions(), options);
515+
std::string file2 = dbname_ + "file2.sst";
516+
ASSERT_OK(sst_file_writer.Open(file2));
517+
ASSERT_OK(sst_file_writer.DeleteRange("a", "z"));
518+
ExternalSstFileInfo file2_info;
519+
ASSERT_OK(sst_file_writer.Finish(&file2_info));
520+
files.push_back(std::move(file2));
521+
522+
std::string file3 = dbname_ + "file3.sst";
523+
ASSERT_OK(sst_file_writer.Open(file3));
524+
ASSERT_OK(sst_file_writer.Put("a", "a2"));
525+
ASSERT_OK(sst_file_writer.Put("b", "b2"));
526+
ExternalSstFileInfo file3_info;
527+
ASSERT_OK(sst_file_writer.Finish(&file3_info));
528+
files.push_back(std::move(file3));
529+
530+
std::string file4 = dbname_ + "file4.sst";
531+
ASSERT_OK(sst_file_writer.Open(file4));
532+
ASSERT_OK(sst_file_writer.Put("x", "x2"));
533+
ASSERT_OK(sst_file_writer.Put("y", "y2"));
534+
ExternalSstFileInfo file4_info;
535+
ASSERT_OK(sst_file_writer.Finish(&file4_info));
536+
files.push_back(std::move(file4));
537+
}
538+
539+
ASSERT_OK(db_->IngestExternalFile(files, ifo));
540+
ASSERT_OK(db_->WaitForCompact(WaitForCompactOptions()));
541+
ASSERT_GE(my_cs->GetCompactionNum(), comp_num + 1);
542+
543+
CompactionServiceResult result;
544+
my_cs->GetResult(&result);
545+
ASSERT_OK(result.status);
546+
ASSERT_TRUE(result.stats.is_manual_compaction);
547+
ASSERT_TRUE(result.stats.is_remote_compaction);
548+
549+
ASSERT_EQ(num_files_after_filtered, 1);
550+
551+
Close();
552+
SyncPoint::GetInstance()->DisableProcessing();
553+
}
554+
464555
TEST_F(CompactionServiceTest, CompactionOutputFileIOError) {
465556
Options options = CurrentOptions();
466557
options.disable_auto_compactions = true;

db/db_impl/db_impl_secondary.cc

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,6 @@ Status DBImplSecondary::CompactWithoutInstallation(
848848

849849
VersionStorageInfo* vstorage = version->storage_info();
850850

851-
// Use comp_options to reuse some CompactFiles functions
852851
CompactionOptions comp_options;
853852
comp_options.compression = kDisableCompressionOption;
854853
comp_options.output_file_size_limit = MaxFileSizeForLevel(
@@ -867,13 +866,27 @@ Status DBImplSecondary::CompactWithoutInstallation(
867866
return s;
868867
}
869868

869+
const int job_id = next_job_id_.fetch_add(1);
870+
JobContext job_context(job_id, true /*create_superversion*/);
871+
std::vector<SequenceNumber> snapshots = input.snapshots;
872+
873+
// TODO - snapshot_checker support in Remote Compaction
874+
job_context.InitSnapshotContext(/*checker=*/nullptr,
875+
/*managed_snapshot=*/nullptr,
876+
kMaxSequenceNumber, std::move(snapshots));
877+
878+
// TODO - consider serializing the entire Compaction object and using it as
879+
// input instead of recreating it in the remote worker
870880
std::unique_ptr<Compaction> c;
871881
assert(cfd->compaction_picker());
872882
c.reset(cfd->compaction_picker()->CompactFiles(
873883
comp_options, input_files, input.output_level, vstorage,
874-
cfd->GetLatestMutableCFOptions(), mutable_db_options_, 0));
884+
cfd->GetLatestMutableCFOptions(), mutable_db_options_, 0,
885+
/*earliest_snapshot=*/job_context.snapshot_seqs.empty()
886+
? kMaxSequenceNumber
887+
: job_context.snapshot_seqs.front(),
888+
job_context.snapshot_checker));
875889
assert(c != nullptr);
876-
877890
c->FinalizeInputInfo(version);
878891

879892
// Create output directory if it's not existed yet
@@ -886,11 +899,6 @@ Status DBImplSecondary::CompactWithoutInstallation(
886899
LogBuffer log_buffer(InfoLogLevel::INFO_LEVEL,
887900
immutable_db_options_.info_log.get());
888901

889-
const int job_id = next_job_id_.fetch_add(1);
890-
JobContext job_context(0, true /*create_superversion*/);
891-
std::vector<SequenceNumber> snapshots = input.snapshots;
892-
job_context.InitSnapshotContext(nullptr, nullptr, kMaxSequenceNumber,
893-
std::move(snapshots));
894902
// use primary host's db_id for running the compaction, but db_session_id is
895903
// using the local one, which is to make sure the unique id is unique from
896904
// the remote compactors. Because the id is generated from db_id,

0 commit comments

Comments
 (0)