Skip to content

Commit 14d3046

Browse files
jaykoreananand1976
authored andcommitted
Skip building remote compaction output file when not OK (#13183)
Summary: During `FinishCompactionOutputFile()` if there's an IOError, we may end up having the output in memory, but table properties are not populated, because `outputs.UpdateTableProperties();` is called only when `s.ok()` is true. However, during remote compaction result serialization, we always try to access the `table_properties` which may be null. This was causing a segfault. We can skip building the output files in the result completely if the status is not ok. # Unit Test New test added ``` ./compaction_service_test --gtest_filter="*CompactionOutputFileIOError*" ``` Before the fix ``` Received signal 11 (Segmentation fault) Invoking GDB for stack trace... #4 0x00000000004708ed in rocksdb::TableProperties::TableProperties (this=0x7fae070fb4e8) at ./include/rocksdb/table_properties.h:212 212 struct TableProperties { #5 0x00007fae0b195b9e in rocksdb::CompactionServiceOutputFile::CompactionServiceOutputFile (this=0x7fae070fb400, name=..., smallest=0, largest=0, _smallest_internal_key=..., _largest_internal_key=..., _oldest_ancester_time=1733335023, _file_creation_time=1733335026, _epoch_number=1, _file_checksum=..., _file_checksum_func_name=..., _paranoid_hash=0, _marked_for_compaction=false, _unique_id=..., _table_properties=...) at ./db/compaction/compaction_job.h:450 450 table_properties(_table_properties) {} ``` After the fix ``` [ RUN ] CompactionServiceTest.CompactionOutputFileIOError [ OK ] CompactionServiceTest.CompactionOutputFileIOError (4499 ms) [----------] 1 test from CompactionServiceTest (4499 ms total) [----------] Global test environment tear-down [==========] 1 test from 1 test case ran. (4499 ms total) [ PASSED ] 1 test. ``` Pull Request resolved: #13183 Reviewed By: anand1976 Differential Revision: D66770876 Pulled By: jaykorean fbshipit-source-id: 63df7c2786ce0353f38a93e493ae4e7b591f4ed9
1 parent a78fa58 commit 14d3046

File tree

3 files changed

+46
-10
lines changed

3 files changed

+46
-10
lines changed

db/compaction/compaction_job.cc

+2
Original file line numberDiff line numberDiff line change
@@ -1586,6 +1586,8 @@ Status CompactionJob::FinishCompactionOutputFile(
15861586
const uint64_t current_entries = outputs.NumEntries();
15871587

15881588
s = outputs.Finish(s, seqno_to_time_mapping_);
1589+
TEST_SYNC_POINT_CALLBACK(
1590+
"CompactionJob::FinishCompactionOutputFile()::AfterFinish", &s);
15891591

15901592
if (s.ok()) {
15911593
// With accurate smallest and largest key, we can get a slightly more

db/compaction/compaction_service_job.cc

+12-10
Original file line numberDiff line numberDiff line change
@@ -376,16 +376,18 @@ Status CompactionServiceCompactionJob::Run() {
376376
// Build Output
377377
compaction_result_->output_level = compact_->compaction->output_level();
378378
compaction_result_->output_path = output_path_;
379-
for (const auto& output_file : sub_compact->GetOutputs()) {
380-
auto& meta = output_file.meta;
381-
compaction_result_->output_files.emplace_back(
382-
MakeTableFileName(meta.fd.GetNumber()), meta.fd.smallest_seqno,
383-
meta.fd.largest_seqno, meta.smallest.Encode().ToString(),
384-
meta.largest.Encode().ToString(), meta.oldest_ancester_time,
385-
meta.file_creation_time, meta.epoch_number, meta.file_checksum,
386-
meta.file_checksum_func_name, output_file.validator.GetHash(),
387-
meta.marked_for_compaction, meta.unique_id,
388-
*output_file.table_properties);
379+
if (status.ok()) {
380+
for (const auto& output_file : sub_compact->GetOutputs()) {
381+
auto& meta = output_file.meta;
382+
compaction_result_->output_files.emplace_back(
383+
MakeTableFileName(meta.fd.GetNumber()), meta.fd.smallest_seqno,
384+
meta.fd.largest_seqno, meta.smallest.Encode().ToString(),
385+
meta.largest.Encode().ToString(), meta.oldest_ancester_time,
386+
meta.file_creation_time, meta.epoch_number, meta.file_checksum,
387+
meta.file_checksum_func_name, output_file.validator.GetHash(),
388+
meta.marked_for_compaction, meta.unique_id,
389+
*output_file.table_properties);
390+
}
389391
}
390392

391393
TEST_SYNC_POINT_CALLBACK("CompactionServiceCompactionJob::Run:0",

db/compaction/compaction_service_test.cc

+32
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,38 @@ TEST_F(CompactionServiceTest, ManualCompaction) {
416416
ASSERT_TRUE(result.stats.is_remote_compaction);
417417
}
418418

419+
TEST_F(CompactionServiceTest, CompactionOutputFileIOError) {
420+
Options options = CurrentOptions();
421+
options.disable_auto_compactions = true;
422+
ReopenWithCompactionService(&options);
423+
GenerateTestData();
424+
425+
auto my_cs = GetCompactionService();
426+
427+
SyncPoint::GetInstance()->SetCallBack(
428+
"CompactionJob::FinishCompactionOutputFile()::AfterFinish",
429+
[&](void* status) {
430+
// override status
431+
auto s = static_cast<Status*>(status);
432+
*s = Status::IOError("Injected IOError!");
433+
});
434+
SyncPoint::GetInstance()->EnableProcessing();
435+
436+
std::string start_str = Key(15);
437+
std::string end_str = Key(45);
438+
Slice start(start_str);
439+
Slice end(end_str);
440+
uint64_t comp_num = my_cs->GetCompactionNum();
441+
ASSERT_NOK(db_->CompactRange(CompactRangeOptions(), &start, &end));
442+
ASSERT_GE(my_cs->GetCompactionNum(), comp_num + 1);
443+
444+
CompactionServiceResult result;
445+
my_cs->GetResult(&result);
446+
ASSERT_NOK(result.status);
447+
ASSERT_TRUE(result.stats.is_manual_compaction);
448+
ASSERT_TRUE(result.stats.is_remote_compaction);
449+
}
450+
419451
TEST_F(CompactionServiceTest, PreservedOptionsLocalCompaction) {
420452
Options options = CurrentOptions();
421453
options.level0_file_num_compaction_trigger = 2;

0 commit comments

Comments
 (0)