Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ void InvertedIndexFileWriter::copyFile(const char* fileName, lucene::store::Dire
err.set(CL_ERR_IO, "debug point: copyFile_openInput_error");
});
if (!open) {
if (err.number() == CL_ERR_EmptyIndexSegment) {
LOG(WARNING) << "InvertedIndexFileWriter::copyFile: " << fileName << " is empty";
return;
}
throw err;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -601,5 +601,61 @@ TEST_F(InvertedIndexFileWriterTest, WriteV2ExceptionHandlingTest) {
ASSERT_EQ(status.code(), ErrorCode::INVERTED_INDEX_CLUCENE_ERROR);
}

TEST_F(InvertedIndexFileWriterTest, CopyFileEmptyFileTest) {
// This test uses the existing MockDorisFSDirectoryOpenInput class
auto mock_dir = std::make_shared<MockDorisFSDirectoryOpenInput>();
std::string local_fs_index_path = InvertedIndexDescriptor::get_temporary_index_path(
ExecEnv::GetInstance()->get_tmp_file_dirs()->get_tmp_file_dir().native(), _rowset_id,
_seg_id, 1, "suffix1");
EXPECT_TRUE(io::global_local_filesystem()->delete_directory(local_fs_index_path).ok());
EXPECT_TRUE(io::global_local_filesystem()->create_directory(local_fs_index_path).ok());
mock_dir->init(_fs, local_fs_index_path.c_str());

// Create test files
std::vector<std::string> files = {"_0.fnm", "_0.frq", "_0.tii"};
for (const auto& file : files) {
auto out_file =
std::unique_ptr<lucene::store::IndexOutput>(mock_dir->createOutput(file.c_str()));
out_file->writeString("test content");
out_file->close();
}

InvertedIndexFileWriter writer(_fs, _index_path_prefix, _rowset_id, _seg_id,
InvertedIndexStorageFormatPB::V2);

// Setup mock to simulate CL_ERR_EmptyIndexSegment error for _0.frq file
EXPECT_CALL(*mock_dir,
openInput(::testing::StrEq("_0.frq"), ::testing::_, ::testing::_, ::testing::_))
.WillOnce(::testing::Invoke([&](const char* name, lucene::store::IndexInput*& ret,
CLuceneError& err_ref, int32_t bufferSize) {
err_ref.set(CL_ERR_EmptyIndexSegment,
std::string("Empty index segment for file: ").append(name).c_str());
return false;
}));

// Test copyFile with the mock directory
uint8_t buffer[16384];

// Create a temporary output stream to test copyFile
auto* ram_dir = new lucene::store::RAMDirectory();
auto* output = ram_dir->createOutput("test_output");

// Before the fix, this would throw an exception
// After the fix, this should log a warning and return gracefully
EXPECT_NO_THROW({ writer.copyFile("_0.frq", mock_dir.get(), output, buffer, sizeof(buffer)); });

// The output should remain valid (not corrupted by the exception)
EXPECT_NE(output, nullptr);

// Clean up
output->close();
_CLLDELETE(output);
ram_dir->close();
_CLLDELETE(ram_dir);

// Clean up the test directory
EXPECT_TRUE(io::global_local_filesystem()->delete_directory(local_fs_index_path).ok());
}

} // namespace segment_v2
} // namespace doris
} // namespace doris
Loading