diff --git a/be/src/apache-orc b/be/src/apache-orc index 0182042e141250..18fb8e2c2888a3 160000 --- a/be/src/apache-orc +++ b/be/src/apache-orc @@ -1 +1 @@ -Subproject commit 0182042e141250802b1a6c1d7a5317b0055c776b +Subproject commit 18fb8e2c2888a3518bf2bbd905f60772f4754739 diff --git a/be/src/clucene b/be/src/clucene index 569398a5c96b4c..4e6a90b47043e0 160000 --- a/be/src/clucene +++ b/be/src/clucene @@ -1 +1 @@ -Subproject commit 569398a5c96b4c626251ccbe81257945a3d2aef4 +Subproject commit 4e6a90b47043e0ed6ba2e126426e60684b606174 diff --git a/be/src/olap/rowset/segment_v2/inverted_index_file_writer.cpp b/be/src/olap/rowset/segment_v2/inverted_index_file_writer.cpp index fd6ae6d54aff76..36d82bad1f2d51 100644 --- a/be/src/olap/rowset/segment_v2/inverted_index_file_writer.cpp +++ b/be/src/olap/rowset/segment_v2/inverted_index_file_writer.cpp @@ -205,6 +205,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; } diff --git a/be/test/olap/rowset/segment_v2/inverted_index_file_writer_test.cpp b/be/test/olap/rowset/segment_v2/inverted_index_file_writer_test.cpp index 44c282b88c9622..48670741693b0e 100644 --- a/be/test/olap/rowset/segment_v2/inverted_index_file_writer_test.cpp +++ b/be/test/olap/rowset/segment_v2/inverted_index_file_writer_test.cpp @@ -520,5 +520,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(); + 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 files = {"_0.fnm", "_0.frq", "_0.tii"}; + for (const auto& file : files) { + auto out_file = + std::unique_ptr(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 \ No newline at end of file