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

yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.1 by this push:
     new 57e556ff721 branch-4.1:[fix](filecache) Limit LRU recorder shadow 
queue size(pick#64798) (#66132)
57e556ff721 is described below

commit 57e556ff721a95c408c5a4fcf09d15541a01ec5e
Author: zhengyu <[email protected]>
AuthorDate: Wed Jul 29 13:56:47 2026 +0800

    branch-4.1:[fix](filecache) Limit LRU recorder shadow queue 
size(pick#64798) (#66132)
    
    ### What problem does this PR solve?
    
    Issue Number: N/A
    
    Related PR: #64798
    
    Problem Summary: Pick apache/doris#64798 into branch-4.1. SelectDB
    reference: selectdb/selectdb-core#10567.
    
    ### Release note
    
    None
    
    ### Check List (For Author)
    
    - Test:
    - Format: git diff --check passed; modified C++ files checked with
    build-support/run_clang_format.py using clang-format v16. Full
    build-support/check-format.sh reports pre-existing unrelated
    be/src/format_v2/json/json_reader.cpp, not included in this PR.
    - BE: JAVA_HOME=/mnt/disk1/zhangzhengyu/build-dep/jdk-17.0.2/
    DORIS_TOOLCHAIN=clang DISABLE_BE_JAVA_EXTENSIONS=ON
    ENABLE_INJECTION_POINT=ON ENABLE_CACHE_LOCK_DEBUG=0 ENABLE_PCH=0
    ./build.sh --be
    - BE UT: same environment, sh run-be-ut.sh --run
    --filter=CacheLRUDumperTest.*
    - Behavior changed: No
    - Does this need documentation: No
---
 be/src/io/cache/block_file_cache.cpp               |  43 ++++++++
 be/src/io/cache/block_file_cache.h                 |   2 +
 be/src/io/cache/file_cache_common.h                |   2 +
 be/src/io/cache/lru_queue_recorder.cpp             | 121 ++++++++++++++-------
 be/src/io/cache/lru_queue_recorder.h               |   4 +
 .../io/cache/block_file_cache_test_meta_store.cpp  |  14 +--
 be/test/io/cache/cache_lru_dumper_test.cpp         | 106 ++++++++++++++++++
 7 files changed, 244 insertions(+), 48 deletions(-)

diff --git a/be/src/io/cache/block_file_cache.cpp 
b/be/src/io/cache/block_file_cache.cpp
index 19a4264a851..07486de65f7 100644
--- a/be/src/io/cache/block_file_cache.cpp
+++ b/be/src/io/cache/block_file_cache.cpp
@@ -408,6 +408,12 @@ BlockFileCache::BlockFileCache(const std::string& 
cache_base_path,
                 _cache_base_path.c_str(), metric_prefix + "_produce");
         _lru_recorder_queue_consume_metrics[idx] = 
std::make_shared<bvar::Adder<size_t>>(
                 _cache_base_path.c_str(), metric_prefix + "_consume");
+        _lru_recorder_shadow_queue_element_count_metrics[idx] =
+                
std::make_shared<bvar::Status<size_t>>(_cache_base_path.c_str(),
+                                                       
"file_cache_lru_recorder_" +
+                                                               
cache_type_to_string(type) +
+                                                               
"_shadow_queue_element_count",
+                                                       0);
     }
     _lru_recorder_log_replay_idle_metrics = 
std::make_shared<bvar::Adder<size_t>>(
             _cache_base_path.c_str(), 
"file_cache_lru_recorder_log_replay_idle");
@@ -1681,6 +1687,17 @@ void LRUQueue::remove_all(std::lock_guard<std::mutex>& 
/* cache_lock */) {
     cache_size = 0;
 }
 
+bool LRUQueue::pop_front(std::lock_guard<std::mutex>& /* cache_lock */) {
+    if (queue.empty()) {
+        return false;
+    }
+    auto queue_it = queue.begin();
+    cache_size -= queue_it->size;
+    map.erase(std::make_pair(queue_it->hash, queue_it->offset));
+    queue.erase(queue_it);
+    return true;
+}
+
 void LRUQueue::move_to_end(Iterator queue_it, std::lock_guard<std::mutex>& /* 
cache_lock */) {
     queue.splice(queue.end(), queue, queue_it);
 }
@@ -2094,6 +2111,7 @@ void BlockFileCache::run_background_monitor() {
                         (double)_no_warmup_num_read_blocks_1h->get_value());
             }
         }
+        _lru_recorder->update_shadow_queue_element_count_metrics();
     }
 }
 
@@ -2403,6 +2421,19 @@ std::map<std::string, double> 
BlockFileCache::get_stats() {
     stats["disposable_queue_curr_elements"] =
             (double)_cur_disposable_queue_element_count_metrics->get_value();
 
+    stats["lru_recorder_index_shadow_queue_curr_elements"] =
+            
(double)_lru_recorder_shadow_queue_element_count_metrics[FileCacheType::INDEX]
+                    ->get_value();
+    stats["lru_recorder_ttl_shadow_queue_curr_elements"] =
+            
(double)_lru_recorder_shadow_queue_element_count_metrics[FileCacheType::TTL]
+                    ->get_value();
+    stats["lru_recorder_normal_shadow_queue_curr_elements"] =
+            
(double)_lru_recorder_shadow_queue_element_count_metrics[FileCacheType::NORMAL]
+                    ->get_value();
+    stats["lru_recorder_disposable_shadow_queue_curr_elements"] =
+            
(double)_lru_recorder_shadow_queue_element_count_metrics[FileCacheType::DISPOSABLE]
+                    ->get_value();
+
     stats["need_evict_cache_in_advance"] = 
(double)_need_evict_cache_in_advance;
     stats["disk_resource_limit_mode"] = (double)_disk_resource_limit_mode;
 
@@ -2443,6 +2474,18 @@ std::map<std::string, double> 
BlockFileCache::get_stats_unsafe() {
     stats["disposable_queue_curr_size"] = 
(double)_disposable_queue.get_capacity_unsafe();
     stats["disposable_queue_max_elements"] = 
(double)_disposable_queue.get_max_element_size();
     stats["disposable_queue_curr_elements"] = 
(double)_disposable_queue.get_elements_num_unsafe();
+    stats["lru_recorder_index_shadow_queue_curr_elements"] =
+            
(double)_lru_recorder_shadow_queue_element_count_metrics[FileCacheType::INDEX]
+                    ->get_value();
+    stats["lru_recorder_ttl_shadow_queue_curr_elements"] =
+            
(double)_lru_recorder_shadow_queue_element_count_metrics[FileCacheType::TTL]
+                    ->get_value();
+    stats["lru_recorder_normal_shadow_queue_curr_elements"] =
+            
(double)_lru_recorder_shadow_queue_element_count_metrics[FileCacheType::NORMAL]
+                    ->get_value();
+    stats["lru_recorder_disposable_shadow_queue_curr_elements"] =
+            
(double)_lru_recorder_shadow_queue_element_count_metrics[FileCacheType::DISPOSABLE]
+                    ->get_value();
 
     stats["need_evict_cache_in_advance"] = 
(double)_need_evict_cache_in_advance;
     stats["disk_resource_limit_mode"] = (double)_disk_resource_limit_mode;
diff --git a/be/src/io/cache/block_file_cache.h 
b/be/src/io/cache/block_file_cache.h
index 849ea72f16f..187eabae4d5 100644
--- a/be/src/io/cache/block_file_cache.h
+++ b/be/src/io/cache/block_file_cache.h
@@ -625,6 +625,8 @@ private:
     std::array<std::shared_ptr<bvar::LatencyRecorder>, 4> 
_lru_recorder_queue_length_recorder;
     std::array<std::shared_ptr<bvar::Adder<size_t>>, 4> 
_lru_recorder_queue_produce_metrics;
     std::array<std::shared_ptr<bvar::Adder<size_t>>, 4> 
_lru_recorder_queue_consume_metrics;
+    std::array<std::shared_ptr<bvar::Status<size_t>>, 4>
+            _lru_recorder_shadow_queue_element_count_metrics;
     std::shared_ptr<bvar::Adder<size_t>> _lru_recorder_log_replay_idle_metrics;
     // keep _storage last so it will deconstruct first
     // otherwise, load_cache_info_into_memory might crash
diff --git a/be/src/io/cache/file_cache_common.h 
b/be/src/io/cache/file_cache_common.h
index a336f7237f2..8846df3e2d8 100644
--- a/be/src/io/cache/file_cache_common.h
+++ b/be/src/io/cache/file_cache_common.h
@@ -250,6 +250,8 @@ public:
 
     void remove_all(std::lock_guard<std::mutex>& cache_lock);
 
+    bool pop_front(std::lock_guard<std::mutex>& cache_lock);
+
     Iterator get(const UInt128Wrapper& hash, size_t offset,
                  std::lock_guard<std::mutex>& /* cache_lock */) const;
 
diff --git a/be/src/io/cache/lru_queue_recorder.cpp 
b/be/src/io/cache/lru_queue_recorder.cpp
index 7d8cc8a7408..c8227129bda 100644
--- a/be/src/io/cache/lru_queue_recorder.cpp
+++ b/be/src/io/cache/lru_queue_recorder.cpp
@@ -58,54 +58,62 @@ size_t LRUQueueRecorder::replay_queue_event(FileCacheType 
type) {
     CacheLRULogQueue& log_queue = get_lru_log_queue(type);
     LRUQueue& shadow_queue = get_shadow_queue(type);
 
-    std::lock_guard<std::mutex> lru_log_lock(_mutex_lru_log);
-    std::unique_ptr<CacheLRULog> log;
+    size_t idx = file_cache_type_index(type);
     size_t replayed = 0;
-    while (log_queue.try_dequeue(log)) {
-        release_lru_log_queue_slot(type);
-        ++replayed;
-        try {
-            switch (log->type) {
-            case CacheLRULogType::ADD: {
-                shadow_queue.add(log->hash, log->offset, log->size, 
lru_log_lock);
-                break;
-            }
-            case CacheLRULogType::REMOVE: {
-                auto it = shadow_queue.get(log->hash, log->offset, 
lru_log_lock);
-                if (it != std::list<LRUQueue::FileKeyAndOffset>::iterator()) {
-                    shadow_queue.remove(it, lru_log_lock);
-                } else {
-                    VLOG_DEBUG << "REMOVE failed, doesn't exist in shadow 
queue";
+    {
+        std::lock_guard<std::mutex> lru_log_lock(_mutex_lru_log);
+        std::unique_ptr<CacheLRULog> log;
+        while (log_queue.try_dequeue(log)) {
+            release_lru_log_queue_slot(type);
+            ++replayed;
+            try {
+                switch (log->type) {
+                case CacheLRULogType::ADD: {
+                    shadow_queue.add(log->hash, log->offset, log->size, 
lru_log_lock);
+                    limit_shadow_queue_size(shadow_queue, lru_log_lock);
+                    break;
                 }
-                break;
-            }
-            case CacheLRULogType::MOVETOBACK: {
-                auto it = shadow_queue.get(log->hash, log->offset, 
lru_log_lock);
-                if (it != std::list<LRUQueue::FileKeyAndOffset>::iterator()) {
-                    shadow_queue.move_to_end(it, lru_log_lock);
-                } else {
-                    VLOG_DEBUG << "MOVETOBACK failed, doesn't exist in shadow 
queue";
+                case CacheLRULogType::REMOVE: {
+                    auto it = shadow_queue.get(log->hash, log->offset, 
lru_log_lock);
+                    if (it != 
std::list<LRUQueue::FileKeyAndOffset>::iterator()) {
+                        shadow_queue.remove(it, lru_log_lock);
+                    } else {
+                        VLOG_DEBUG << "REMOVE failed, doesn't exist in shadow 
queue";
+                    }
+                    limit_shadow_queue_size(shadow_queue, lru_log_lock);
+                    break;
                 }
-                break;
-            }
-            case CacheLRULogType::RESIZE: {
-                auto it = shadow_queue.get(log->hash, log->offset, 
lru_log_lock);
-                if (it != std::list<LRUQueue::FileKeyAndOffset>::iterator()) {
-                    shadow_queue.resize(it, log->size, lru_log_lock);
-                } else {
-                    VLOG_DEBUG << "RESIZE failed, doesn't exist in shadow 
queue";
+                case CacheLRULogType::MOVETOBACK: {
+                    auto it = shadow_queue.get(log->hash, log->offset, 
lru_log_lock);
+                    if (it != 
std::list<LRUQueue::FileKeyAndOffset>::iterator()) {
+                        shadow_queue.move_to_end(it, lru_log_lock);
+                    } else {
+                        VLOG_DEBUG << "MOVETOBACK failed, doesn't exist in 
shadow queue";
+                    }
+                    break;
                 }
-                break;
-            }
-            default:
-                LOG(WARNING) << "Unknown CacheLRULogType: " << 
static_cast<int>(log->type);
-                break;
+                case CacheLRULogType::RESIZE: {
+                    auto it = shadow_queue.get(log->hash, log->offset, 
lru_log_lock);
+                    if (it != 
std::list<LRUQueue::FileKeyAndOffset>::iterator()) {
+                        shadow_queue.resize(it, log->size, lru_log_lock);
+                    } else {
+                        VLOG_DEBUG << "RESIZE failed, doesn't exist in shadow 
queue";
+                    }
+                    break;
+                }
+                default:
+                    LOG(WARNING) << "Unknown CacheLRULogType: " << 
static_cast<int>(log->type);
+                    break;
+                }
+            } catch (const std::exception& e) {
+                LOG(WARNING) << "Failed to replay queue event: " << e.what();
             }
-        } catch (const std::exception& e) {
-            LOG(WARNING) << "Failed to replay queue event: " << e.what();
+        }
+        if (replayed > 0) {
+            
_mgr->_lru_recorder_shadow_queue_element_count_metrics[idx]->set_value(
+                    shadow_queue.get_elements_num(lru_log_lock));
         }
     }
-    size_t idx = file_cache_type_index(type);
     if (replayed > 0) {
         *(_mgr->_lru_recorder_queue_consume_metrics[idx]) << replayed;
     }
@@ -173,6 +181,37 @@ size_t LRUQueueRecorder::lru_log_queue_size(FileCacheType 
type) const {
     return 
_lru_log_queue_size[file_cache_type_index(type)].load(std::memory_order_relaxed);
 }
 
+void LRUQueueRecorder::update_shadow_queue_element_count_metrics() {
+    std::lock_guard<std::mutex> lru_log_lock(_mutex_lru_log);
+    update_shadow_queue_element_count_metrics_unlocked(lru_log_lock);
+}
+
+void LRUQueueRecorder::limit_shadow_queue_size(LRUQueue& shadow_queue,
+                                               std::lock_guard<std::mutex>& 
lru_log_lock) {
+    int64_t queue_limit = 
config::file_cache_background_lru_dump_tail_record_num;
+    if (queue_limit <= 0) {
+        return;
+    }
+    size_t limit = static_cast<size_t>(queue_limit);
+    size_t queue_size = shadow_queue.get_elements_num(lru_log_lock);
+    while (queue_size > limit) {
+        if (!shadow_queue.pop_front(lru_log_lock)) {
+            return;
+        }
+        --queue_size;
+    }
+}
+
+void LRUQueueRecorder::update_shadow_queue_element_count_metrics_unlocked(
+        std::lock_guard<std::mutex>& lru_log_lock) {
+    for (FileCacheType type : {FileCacheType::DISPOSABLE, 
FileCacheType::NORMAL,
+                               FileCacheType::INDEX, FileCacheType::TTL}) {
+        size_t idx = file_cache_type_index(type);
+        _mgr->_lru_recorder_shadow_queue_element_count_metrics[idx]->set_value(
+                get_shadow_queue(type).get_elements_num(lru_log_lock));
+    }
+}
+
 bool LRUQueueRecorder::reserve_lru_log_queue_slot(FileCacheType type) {
     int64_t queue_limit = config::file_cache_background_lru_log_queue_max_size;
     if (queue_limit <= 0) {
diff --git a/be/src/io/cache/lru_queue_recorder.h 
b/be/src/io/cache/lru_queue_recorder.h
index 5ffa777e437..1edd0f5ab85 100644
--- a/be/src/io/cache/lru_queue_recorder.h
+++ b/be/src/io/cache/lru_queue_recorder.h
@@ -67,6 +67,7 @@ public:
     size_t get_lru_queue_update_cnt_from_last_dump(FileCacheType type);
     void reset_lru_queue_update_cnt_from_last_dump(FileCacheType type);
     size_t lru_log_queue_size(FileCacheType type) const;
+    void update_shadow_queue_element_count_metrics();
 
     CacheLRULogQueue& get_lru_log_queue(FileCacheType type);
     LRUQueue& get_shadow_queue(FileCacheType type);
@@ -92,6 +93,9 @@ private:
 
     bool reserve_lru_log_queue_slot(FileCacheType type);
     void release_lru_log_queue_slot(FileCacheType type);
+    void limit_shadow_queue_size(LRUQueue& shadow_queue, 
std::lock_guard<std::mutex>& lru_log_lock);
+    void update_shadow_queue_element_count_metrics_unlocked(
+            std::lock_guard<std::mutex>& lru_log_lock);
 };
 
 } // namespace doris::io
diff --git a/be/test/io/cache/block_file_cache_test_meta_store.cpp 
b/be/test/io/cache/block_file_cache_test_meta_store.cpp
index a77b267f089..0272153b2c7 100644
--- a/be/test/io/cache/block_file_cache_test_meta_store.cpp
+++ b/be/test/io/cache/block_file_cache_test_meta_store.cpp
@@ -260,10 +260,10 @@ TEST_F(BlockFileCacheTest, version3_add_remove_restart) {
 
         // then check the log replay
         ASSERT_EQ(cache.replay_lru_logs_once(), 20);
-        
ASSERT_EQ(cache._lru_recorder->_shadow_ttl_queue.get_elements_num_unsafe(), 5);
-        
ASSERT_EQ(cache._lru_recorder->_shadow_index_queue.get_elements_num_unsafe(), 
5);
-        
ASSERT_EQ(cache._lru_recorder->_shadow_normal_queue.get_elements_num_unsafe(), 
5);
-        
ASSERT_EQ(cache._lru_recorder->_shadow_disposable_queue.get_elements_num_unsafe(),
 5);
+        
ASSERT_EQ(cache._lru_recorder->_shadow_ttl_queue.get_elements_num_unsafe(), 2);
+        
ASSERT_EQ(cache._lru_recorder->_shadow_index_queue.get_elements_num_unsafe(), 
2);
+        
ASSERT_EQ(cache._lru_recorder->_shadow_normal_queue.get_elements_num_unsafe(), 
2);
+        
ASSERT_EQ(cache._lru_recorder->_shadow_disposable_queue.get_elements_num_unsafe(),
 2);
 
         // do some REMOVE
         {
@@ -271,10 +271,10 @@ TEST_F(BlockFileCacheTest, version3_add_remove_restart) {
         }
 
         ASSERT_EQ(cache.replay_lru_logs_once(), 5);
-        
ASSERT_EQ(cache._lru_recorder->_shadow_ttl_queue.get_elements_num_unsafe(), 5);
+        
ASSERT_EQ(cache._lru_recorder->_shadow_ttl_queue.get_elements_num_unsafe(), 2);
         
ASSERT_EQ(cache._lru_recorder->_shadow_index_queue.get_elements_num_unsafe(), 
0);
-        
ASSERT_EQ(cache._lru_recorder->_shadow_normal_queue.get_elements_num_unsafe(), 
5);
-        
ASSERT_EQ(cache._lru_recorder->_shadow_disposable_queue.get_elements_num_unsafe(),
 5);
+        
ASSERT_EQ(cache._lru_recorder->_shadow_normal_queue.get_elements_num_unsafe(), 
2);
+        
ASSERT_EQ(cache._lru_recorder->_shadow_disposable_queue.get_elements_num_unsafe(),
 2);
         EXPECT_EQ(cache.replay_lru_logs_once(), 0);
         EXPECT_EQ(cache._lru_recorder_log_replay_idle_metrics->get_value(), 1);
         cache.dump_lru_queues(true);
diff --git a/be/test/io/cache/cache_lru_dumper_test.cpp 
b/be/test/io/cache/cache_lru_dumper_test.cpp
index e8a6bb4e674..6256f52d74a 100644
--- a/be/test/io/cache/cache_lru_dumper_test.cpp
+++ b/be/test/io/cache/cache_lru_dumper_test.cpp
@@ -249,4 +249,110 @@ TEST_F(CacheLRUDumperTest, 
test_lru_log_record_queue_hard_cap) {
     
EXPECT_EQ(recorder->get_shadow_queue(FileCacheType::INDEX).get_elements_num_unsafe(),
 2);
 }
 
+TEST_F(CacheLRUDumperTest, 
test_shadow_queue_keeps_tail_when_replay_exceeds_limit) {
+    const auto old_tail_record_num = 
config::file_cache_background_lru_dump_tail_record_num;
+    const auto old_queue_limit = 
config::file_cache_background_lru_log_queue_max_size;
+    Defer defer {[old_tail_record_num, old_queue_limit] {
+        config::file_cache_background_lru_dump_tail_record_num = 
old_tail_record_num;
+        config::file_cache_background_lru_log_queue_max_size = old_queue_limit;
+    }};
+
+    config::file_cache_background_lru_dump_tail_record_num = 3;
+    config::file_cache_background_lru_log_queue_max_size = 10;
+
+    UInt128Wrapper hash(112233ULL);
+    for (size_t offset = 0; offset < 5; ++offset) {
+        recorder->record_queue_event(FileCacheType::NORMAL, 
CacheLRULogType::ADD, hash, offset,
+                                     4096);
+    }
+
+    EXPECT_EQ(recorder->replay_queue_event(FileCacheType::NORMAL), 5);
+    auto& shadow_queue = recorder->get_shadow_queue(FileCacheType::NORMAL);
+    ASSERT_EQ(shadow_queue.get_elements_num_unsafe(), 3);
+    auto stats = mock_cache->get_stats_unsafe();
+    EXPECT_EQ(stats["lru_recorder_normal_shadow_queue_curr_elements"], 3);
+
+    std::vector<size_t> offsets;
+    for (auto it = shadow_queue.begin(); it != shadow_queue.end(); ++it) {
+        offsets.push_back(it->offset);
+    }
+    EXPECT_EQ(offsets, std::vector<size_t>({2, 3, 4}));
+}
+
+TEST_F(CacheLRUDumperTest, 
test_remove_event_trims_existing_oversized_shadow_queue) {
+    const auto old_tail_record_num = 
config::file_cache_background_lru_dump_tail_record_num;
+    const auto old_queue_limit = 
config::file_cache_background_lru_log_queue_max_size;
+    Defer defer {[old_tail_record_num, old_queue_limit] {
+        config::file_cache_background_lru_dump_tail_record_num = 
old_tail_record_num;
+        config::file_cache_background_lru_log_queue_max_size = old_queue_limit;
+    }};
+
+    config::file_cache_background_lru_dump_tail_record_num = 2;
+    config::file_cache_background_lru_log_queue_max_size = 10;
+
+    UInt128Wrapper hash(556677ULL);
+    {
+        std::lock_guard lru_log_lock(recorder->_mutex_lru_log);
+        auto& shadow_queue = recorder->get_shadow_queue(FileCacheType::NORMAL);
+        for (size_t offset = 0; offset < 4; ++offset) {
+            shadow_queue.add(hash, offset, 4096, lru_log_lock);
+        }
+    }
+    recorder->record_queue_event(FileCacheType::NORMAL, 
CacheLRULogType::REMOVE, hash, 3, 4096);
+
+    EXPECT_EQ(recorder->replay_queue_event(FileCacheType::NORMAL), 1);
+    auto& shadow_queue = recorder->get_shadow_queue(FileCacheType::NORMAL);
+    ASSERT_EQ(shadow_queue.get_elements_num_unsafe(), 2);
+
+    std::vector<size_t> offsets;
+    for (auto it = shadow_queue.begin(); it != shadow_queue.end(); ++it) {
+        offsets.push_back(it->offset);
+    }
+    EXPECT_EQ(offsets, std::vector<size_t>({1, 2}));
+}
+
+TEST_F(CacheLRUDumperTest, 
test_update_shadow_queue_metric_does_not_trim_queue) {
+    const auto old_tail_record_num = 
config::file_cache_background_lru_dump_tail_record_num;
+    Defer defer {[old_tail_record_num] {
+        config::file_cache_background_lru_dump_tail_record_num = 
old_tail_record_num;
+    }};
+
+    config::file_cache_background_lru_dump_tail_record_num = 1;
+
+    UInt128Wrapper hash(778899ULL);
+    {
+        std::lock_guard lru_log_lock(recorder->_mutex_lru_log);
+        auto& shadow_queue = recorder->get_shadow_queue(FileCacheType::INDEX);
+        for (size_t offset = 0; offset < 3; ++offset) {
+            shadow_queue.add(hash, offset, 4096, lru_log_lock);
+        }
+    }
+
+    recorder->update_shadow_queue_element_count_metrics();
+
+    
EXPECT_EQ(recorder->get_shadow_queue(FileCacheType::INDEX).get_elements_num_unsafe(),
 3);
+    auto stats = mock_cache->get_stats_unsafe();
+    EXPECT_EQ(stats["lru_recorder_index_shadow_queue_curr_elements"], 3);
+}
+
+TEST_F(CacheLRUDumperTest, test_remove_event_still_obeys_replay_queue_cap) {
+    const auto old_tail_record_num = 
config::file_cache_background_lru_dump_tail_record_num;
+    const auto old_queue_limit = 
config::file_cache_background_lru_log_queue_max_size;
+    Defer defer {[old_tail_record_num, old_queue_limit] {
+        config::file_cache_background_lru_dump_tail_record_num = 
old_tail_record_num;
+        config::file_cache_background_lru_log_queue_max_size = old_queue_limit;
+    }};
+
+    config::file_cache_background_lru_dump_tail_record_num = 100;
+    config::file_cache_background_lru_log_queue_max_size = 1;
+
+    UInt128Wrapper hash(445566ULL);
+    recorder->record_queue_event(FileCacheType::INDEX, CacheLRULogType::ADD, 
hash, 0, 4096);
+    recorder->record_queue_event(FileCacheType::INDEX, 
CacheLRULogType::REMOVE, hash, 0, 4096);
+
+    EXPECT_EQ(recorder->lru_log_queue_size(FileCacheType::INDEX), 1);
+    EXPECT_EQ(recorder->replay_queue_event(FileCacheType::INDEX), 1);
+    
EXPECT_EQ(recorder->get_shadow_queue(FileCacheType::INDEX).get_elements_num_unsafe(),
 1);
+}
+
 } // namespace doris::io


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

Reply via email to