This is an automated email from the ASF dual-hosted git repository.

liaoxin01 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 28eb75d0d3d [fix](cloud) Skip global packed index probe when opening 
files of committed rowsets (#69980)
28eb75d0d3d is described below

commit 28eb75d0d3dbf481c7e00c7e4e0c2ec9b1307347
Author: Xin Liao <[email protected]>
AuthorDate: Thu Nov 5 10:02:15 2026 +0800

    [fix](cloud) Skip global packed index probe when opening files of committed 
rowsets (#69980)
    
    ### What problem does this PR solve?
    
    Issue Number: None
    
    Related PR: #64995
    
    Problem Summary:
    
    A cloud BE logs a burst of WARN lines with a full stack trace like
    
    meet error status: [NOT_FOUND]File not found in global packed index:
    data/<tablet>/<rowset>_0.idx
    
    while compaction reads its input rowsets. In one instance a 4-hour BE
    log had 42k
    such lines over 21k paths in 158 tablets, yet every compaction
    succeeded.
    
    Reproduce: write a rowset whose segment file is smaller than
    small_file_threshold_bytes (so it is packed) but whose inverted index
    file is
    larger (so it is uploaded as a regular object), then compact or query
    it. Each
    open of the regular .idx file prints the WARN with a stack, twice per
    compaction
    (eligibility check and the merge itself).
    
    Root cause: #64995 made PackedFileSystem::open_file_impl fall back to
    PackedFileManager::get_packed_slice_location when a path is not in
    _index_map,
    so that the file cache preload can read back a segment of the rowset
    being
    written, whose rowset meta does not exist yet. The fallback was added
    unconditionally, so it also runs for a PackedFileSystem built from a
    rowset
    meta. That index map already holds every packed slice of the rowset, so
    a miss
    means a regular file, and the probe can only fail. The failure is a
    Status::NotFound, and NOT_FOUND records a stack trace and logs a WARN as
    soon as
    it is constructed, before the caller falls back to opening the regular
    file.
    
    Fix:
    - Only consult the manager when the index map is not initialized, i.e.
    on the
    write path, the same split exists_impl and file_size_impl already make.
    - Return NOT_FOUND without a stack trace from get_packed_slice_location:
    on the
      write path a miss is also expected, for files too large to be packed.
    
    After the fix, reading committed rowsets no longer takes the global
    index lock
    or logs anything for regular files; the write-path preload still finds
    packed
    slices through the manager.
    
    ### Release note
    
    Fix noisy "File not found in global packed index" WARN logs with stack
    traces
    when reading rowsets that mix packed and regular files in cloud mode.
---
 be/src/io/fs/packed_file_manager.cpp      |  4 ++-
 be/src/io/fs/packed_file_system.cpp       |  7 ++++-
 be/test/io/fs/packed_file_system_test.cpp | 50 +++++++++++++++++++++++++++++++
 3 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/be/src/io/fs/packed_file_manager.cpp 
b/be/src/io/fs/packed_file_manager.cpp
index ccbc64f975f..a0a367debd8 100644
--- a/be/src/io/fs/packed_file_manager.cpp
+++ b/be/src/io/fs/packed_file_manager.cpp
@@ -524,7 +524,9 @@ Status PackedFileManager::get_packed_slice_location(const 
std::string& path,
     std::lock_guard<std::mutex> lock(_global_index_mutex);
     auto it = _global_slice_locations.find(path);
     if (it == _global_slice_locations.end()) {
-        return Status::NotFound("File not found in global packed index: {}", 
path);
+        // Not an error for the caller: a file too large to be packed is never 
indexed here
+        return Status::Error<ErrorCode::NOT_FOUND, false>(
+                "File not found in global packed index: {}", path);
     }
 
     *location = it->second->location();
diff --git a/be/src/io/fs/packed_file_system.cpp 
b/be/src/io/fs/packed_file_system.cpp
index fe45970e882..02ef672cfe0 100644
--- a/be/src/io/fs/packed_file_system.cpp
+++ b/be/src/io/fs/packed_file_system.cpp
@@ -119,9 +119,14 @@ Status PackedFileSystem::open_file_impl(const Path& file, 
FileReaderSPtr* reader
     const PackedSliceLocation* packed_location = nullptr;
     if (it != _index_map.end()) {
         packed_location = &it->second;
-    } else if (PackedFileManager::instance()
+    } else if (!_index_map_initialized &&
+               PackedFileManager::instance()
                        ->get_packed_slice_location(file_path, 
&manager_location)
                        .ok()) {
+        // Write path: the rowset meta is not built yet, so a file of the 
rowset being written
+        // (e.g. a segment read back for file cache preload) can only be found 
in the manager.
+        // A rowset opened from its meta has every packed slice in the index 
map, so a miss
+        // there means a regular file and the manager is not consulted.
         packed_location = &manager_location;
     }
 
diff --git a/be/test/io/fs/packed_file_system_test.cpp 
b/be/test/io/fs/packed_file_system_test.cpp
index f4333a1bcab..6abb68c34d8 100644
--- a/be/test/io/fs/packed_file_system_test.cpp
+++ b/be/test/io/fs/packed_file_system_test.cpp
@@ -30,6 +30,7 @@
 #include "io/fs/file_reader.h"
 #include "io/fs/file_system.h"
 #include "io/fs/file_writer.h"
+#include "io/fs/packed_file_manager.h"
 #include "io/fs/packed_file_writer.h"
 #include "io/fs/path.h"
 #include "util/slice.h"
@@ -131,6 +132,7 @@ public:
     void set_file_size(int64_t size) { _file_size = size; }
 
     MockFileWriterForMerge* last_writer() const { return _last_writer; }
+    const std::string& last_opened_path() const { return _last_opened_path; }
 
 protected:
     Status create_file_impl(const Path& file, FileWriterPtr* writer,
@@ -149,6 +151,7 @@ protected:
         if (!_open_status.ok()) {
             return _open_status;
         }
+        _last_opened_path = file.native();
         // Create a mock reader with some content
         auto mock_reader = std::make_shared<MockFileReader>("mock_content");
         *reader = std::move(mock_reader);
@@ -196,6 +199,7 @@ private:
     bool _exists_result = true;
     int64_t _file_size = 0;
     MockFileWriterForMerge* _last_writer = nullptr;
+    std::string _last_opened_path;
 };
 
 // Test fixture for PackedFileSystem
@@ -380,6 +384,52 @@ TEST_F(PackedFileSystemTest, OpenFileInMergeFile) {
     EXPECT_EQ(reader->size(), index.size);
 }
 
+// A file of the rowset being written is not in any index map yet, so the 
writer side file
+// system has to find its slice through the manager
+TEST_F(PackedFileSystemTest, OpenFileOfRowsetBeingWrittenUsesManagerLocation) {
+    PackedSliceLocation location;
+    location.packed_file_path = "packed_file_being_written";
+    location.offset = 4;
+    location.size = 6;
+    auto& global_locations = 
PackedFileManager::instance()->global_slice_locations_for_test();
+    global_locations["being_written"] = 
std::make_shared<PackedSliceHandle>(location);
+
+    PackedFileSystem merge_fs(_inner_fs, _append_info);
+
+    FileReaderSPtr reader;
+    Status st = merge_fs.open_file(Path("being_written"), &reader, nullptr);
+    global_locations.erase("being_written");
+    ASSERT_TRUE(st.ok()) << st;
+    EXPECT_EQ(_inner_fs->last_opened_path(), location.packed_file_path);
+    EXPECT_EQ(reader->size(), location.size);
+}
+
+// The index map of a rowset opened from its meta holds every packed slice of 
the rowset, so a
+// file missing from it is a regular file, whatever the manager still 
remembers about the path
+TEST_F(PackedFileSystemTest, OpenRegularFileOfOpenedRowsetIgnoresManager) {
+    PackedSliceLocation stale_location;
+    stale_location.packed_file_path = "stale_packed_file";
+    stale_location.offset = 4;
+    stale_location.size = 6;
+    auto& global_locations = 
PackedFileManager::instance()->global_slice_locations_for_test();
+    global_locations["regular_file"] = 
std::make_shared<PackedSliceHandle>(stale_location);
+
+    std::unordered_map<std::string, PackedSliceLocation> index_map;
+    PackedSliceLocation index;
+    index.packed_file_path = "packed_file_path";
+    index.offset = 10;
+    index.size = 20;
+    index_map["packed_file"] = index;
+    PackedFileSystem merge_fs(_inner_fs, index_map, _append_info);
+
+    FileReaderSPtr reader;
+    Status st = merge_fs.open_file(Path("regular_file"), &reader, nullptr);
+    global_locations.erase("regular_file");
+    ASSERT_TRUE(st.ok()) << st;
+    EXPECT_EQ(_inner_fs->last_opened_path(), "regular_file");
+    EXPECT_EQ(reader->size(), std::string("mock_content").size());
+}
+
 TEST_F(PackedFileSystemTest, ExistsForMergeFile) {
     std::unordered_map<std::string, PackedSliceLocation> index_map;
     PackedSliceLocation index;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to