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
4 changes: 4 additions & 0 deletions be/src/olap/rowset/segment_v2/inverted_index_file_writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,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";
Copy link

Copilot AI Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider including the full file path or segment identifiers in the log message for better traceability when debugging.

Suggested change
LOG(WARNING) << "InvertedIndexFileWriter::copyFile: " << fileName << " is empty";
LOG(WARNING) << "InvertedIndexFileWriter::copyFile: " << dir->getFullPath(fileName) << " is empty";

Copilot uses AI. Check for mistakes.
return;
}
throw err;
}

Expand Down
56 changes: 56 additions & 0 deletions be/test/olap/rowset/segment_v2/inverted_index_file_writer_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1525,4 +1525,60 @@ TEST_F(InvertedIndexFileWriterTest, MultipleIndicesCreateOutputStreamException)
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 doris::segment_v2
Loading