github-actions[bot] commented on code in PR #65722:
URL: https://github.com/apache/doris/pull/65722#discussion_r3642691270
##########
be/src/io/cache/block_file_cache.cpp:
##########
@@ -1263,19 +1271,22 @@ bool BlockFileCache::try_reserve(const UInt128Wrapper&
hash, const CacheContext&
}
// use this strategy in scenarios where there is insufficient disk
capacity or insufficient number of inodes remaining
// directly eliminate 5 times the size of the space
- if (_disk_resource_limit_mode) {
- size = 5 * size;
- }
+ const bool disk_resource_limit_mode =
_disk_resource_limit_mode.load(std::memory_order_relaxed);
+ const size_t eviction_size = disk_resource_limit_mode ? 5 * size : size;
auto query_context = config::enable_file_cache_query_limit &&
(context.query_id.hi != 0 ||
context.query_id.lo != 0)
? get_query_context(context.query_id,
cache_lock)
: nullptr;
if (!query_context) {
- return try_reserve_for_lru(hash, nullptr, context, offset, size,
cache_lock);
+ return try_reserve_for_lru(hash, nullptr, context, offset,
eviction_size, cache_lock);
Review Comment:
[P2] Keep the real request size in the soft-limit gate
Now that memory caches can enter resource-limit mode, this passes `5 * size`
downstream as if it were the admission size. For a 10 MiB DISPOSABLE miss with
an empty 30 MiB DISPOSABLE queue and a full, hot NORMAL queue that is above its
own quota, the time-based pass removes nothing; the later soft-limit guard sees
`0 + 50 > 30`, refuses the size-based sibling pass, and the empty current queue
then makes the request return `SKIP_CACHE`. The real 10 MiB block fits its
queue and the sibling can supply the 50 MiB eviction target. Carry the actual
request size and eviction target separately, using only the actual size in the
current-queue quota check, and cover this memory hot-sibling case.
##########
be/src/io/cache/block_file_cache_factory.cpp:
##########
@@ -340,16 +341,35 @@ std::string validate_capacity(const std::string& path,
int64_t new_capacity,
return "";
}
+std::string validate_capacity(BlockFileCache* cache, int64_t new_capacity,
+ int64_t& valid_capacity) {
+ if (cache->get_storage()->get_type() == FileCacheStorageType::MEMORY) {
+ valid_capacity = new_capacity;
Review Comment:
[P2] Keep post-reset query limits overflow-safe
This accepts every positive `int64_t` capacity, including the HTTP
endpoint's advertised `INT64_MAX`. A query created afterward computes
`_capacity * file_cache_query_limit_percent / 100` in `size_t`; at `INT64_MAX`
and a valid 50%, the multiply wraps and produces `184467440737095515` bytes
instead of `4611686018427387903`, so the query starts evicting or rejecting at
about 4% of its intended ceiling. This is separate from the existing
stale-live-context issue because the context is created after RESET. Use
overflow-safe ratio arithmetic or bound the accepted memory capacity, and test
a large accepted reset followed by new query-context creation.
##########
be/src/io/cache/block_file_cache.cpp:
##########
@@ -1998,14 +2037,14 @@ std::string BlockFileCache::reset_capacity(size_t
new_capacity) {
if (need_remove_size <= 0) {
break;
}
- need_remove_size -= entry_size;
- space_released += entry_size;
- queue_released += entry_size;
auto* cell = get_cell(entry_key, entry_offset, cache_lock);
if (!cell->releasable()) {
cell->file_block->set_deleting();
Review Comment:
[P1] Make RESET holder cleanup identity-safe for memory
A held memory block is marked deleting here, and releasing its holder later
calls `remove(..., false)`: the old cell is erased but only its hash/offset is
queued while the payload remains in `ShardMemHashTable`. If the same block is
redownloaded before GC runs, `appendv` replaces that payload; the queued old
removal then erases the replacement, leaving the new cell `DOWNLOADED` while
reads fail with `key not found in in-memory cache map`. This is distinct from
the existing advance-worker thread because making only worker removals
synchronous does not cover holder cleanup after the newly routed memory RESET.
Make queued memory deletes generation-aware (or preserve synchronous deletion
through this cleanup), and test pause-GC -> RESET held block -> release ->
redownload -> resume-GC -> read.
##########
be/test/io/cache/block_file_cache_mem_storage_mode_test.cpp:
##########
@@ -0,0 +1,563 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <functional>
+#include <limits>
+
+#include "io/cache/block_file_cache_factory.h"
+#include "io/cache/block_file_cache_test_common.h"
+
+namespace doris::io {
+
+class BlockFileCacheMemModeTest : public BlockFileCacheTest {
+public:
+ void SetUp() override {
+ const auto* test_info =
::testing::UnitTest::GetInstance()->current_test_info();
+ _cache_path = caches_dir / test_info->name() / "";
+ fs::remove_all(_cache_path);
+ fs::create_directories(_cache_path);
+
+ _origin_enter_need_evict =
config::file_cache_enter_need_evict_cache_in_advance_percent;
+ _origin_exit_need_evict =
config::file_cache_exit_need_evict_cache_in_advance_percent;
+ _origin_enter_disk_limit =
config::file_cache_enter_disk_resource_limit_mode_percent;
+ _origin_exit_disk_limit =
config::file_cache_exit_disk_resource_limit_mode_percent;
+ _origin_enable_evict_in_advance =
config::enable_evict_file_cache_in_advance;
+ _origin_enable_query_limit = config::enable_file_cache_query_limit;
+ _origin_lru_dump_tail_record_num =
config::file_cache_background_lru_dump_tail_record_num;
+ }
+
+ void TearDown() override {
+ config::file_cache_enter_need_evict_cache_in_advance_percent =
_origin_enter_need_evict;
+ config::file_cache_exit_need_evict_cache_in_advance_percent =
_origin_exit_need_evict;
+ config::file_cache_enter_disk_resource_limit_mode_percent =
_origin_enter_disk_limit;
+ config::file_cache_exit_disk_resource_limit_mode_percent =
_origin_exit_disk_limit;
+ config::enable_evict_file_cache_in_advance =
_origin_enable_evict_in_advance;
+ config::enable_file_cache_query_limit = _origin_enable_query_limit;
+ config::file_cache_background_lru_dump_tail_record_num =
_origin_lru_dump_tail_record_num;
+
+ auto* sync_point = SyncPoint::get_instance();
+ sync_point->disable_processing();
+ sync_point->clear_all_call_backs();
+
+ fs::remove_all(_cache_path);
+ }
+
+protected:
+ FileCacheSettings make_settings(const std::string& storage = "memory")
const {
+ FileCacheSettings settings;
+ settings.storage = storage;
+ settings.capacity = 100_mb;
+ settings.max_file_block_size = 10_mb;
+ settings.max_query_cache_size = 100_mb;
+ settings.query_queue_size = 100_mb;
+ settings.query_queue_elements = 16;
+ settings.index_queue_size = 30_mb;
+ settings.index_queue_elements = 8;
+ settings.disposable_queue_size = 30_mb;
+ settings.disposable_queue_elements = 8;
+ settings.ttl_queue_size = 30_mb;
+ settings.ttl_queue_elements = 8;
+ return settings;
+ }
+
+ void wait_async_open(BlockFileCache& cache) const {
+ for (int i = 0; i < 100; ++i) {
+ if (cache.get_async_open_success()) {
+ return;
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ }
+ FAIL() << "cache async open did not finish";
+ }
+
+ bool wait_until(const std::function<bool()>& predicate, int64_t timeout_ms
= 2000) const {
+ auto deadline = std::chrono::steady_clock::now() +
std::chrono::milliseconds(timeout_ms);
+ while (std::chrono::steady_clock::now() < deadline) {
+ if (predicate()) {
+ return true;
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(5));
+ }
+ return predicate();
+ }
+
+ void fill_memory_cache(BlockFileCache& cache, size_t total_size) const {
+ TUniqueId query_id;
+ query_id.hi = 1;
+ query_id.lo = 1;
+ CacheContext context;
+ ReadStatistics rstats;
+ context.stats = &rstats;
+ context.cache_type = FileCacheType::NORMAL;
+ context.query_id = query_id;
+ auto key = BlockFileCache::hash("mem-mode-key");
+
+ for (size_t offset = 0; offset < total_size; offset += 10_mb) {
+ auto holder = cache.get_or_set(key, offset, 10_mb, context);
+ auto blocks = fromHolder(holder);
+ ASSERT_EQ(blocks.size(), 1);
+ ASSERT_TRUE(blocks[0]->get_or_set_downloader() ==
FileBlock::get_caller_id());
+ download_into_memory(blocks[0]);
+ }
+ }
+
+ void fill_cache(BlockFileCache& cache, const UInt128Wrapper& key, size_t
total_size,
+ bool use_memory_download) const {
+ TUniqueId query_id;
+ query_id.hi = 11;
+ query_id.lo = 11;
+ CacheContext context;
+ ReadStatistics rstats;
+ context.stats = &rstats;
+ context.cache_type = FileCacheType::NORMAL;
+ context.query_id = query_id;
+
+ for (size_t offset = 0; offset < total_size; offset += 10_mb) {
+ auto holder = cache.get_or_set(key, offset, 10_mb, context);
+ auto blocks = fromHolder(holder);
+ ASSERT_EQ(blocks.size(), 1);
+ ASSERT_TRUE(blocks[0]->get_or_set_downloader() ==
FileBlock::get_caller_id());
+ if (use_memory_download) {
+ download_into_memory(blocks[0]);
+ } else {
+ download(blocks[0]);
+ }
+ }
+ }
+
+ fs::path _cache_path;
+ int64_t _origin_enter_need_evict = 0;
+ int64_t _origin_exit_need_evict = 0;
+ int64_t _origin_enter_disk_limit = 0;
+ int64_t _origin_exit_disk_limit = 0;
+ bool _origin_enable_evict_in_advance = false;
+ bool _origin_enable_query_limit = false;
+ int64_t _origin_lru_dump_tail_record_num = 0;
+};
+
+TEST_F(BlockFileCacheMemModeTest, check_need_evict_memory_enter_exit) {
+ auto settings = make_settings();
+ BlockFileCache cache(_cache_path.string(), settings);
+
+ config::file_cache_enter_need_evict_cache_in_advance_percent = 70;
+ config::file_cache_exit_need_evict_cache_in_advance_percent = 65;
+
+ cache._cur_cache_size = 80_mb;
+ cache.check_need_evict_cache_in_advance();
+ ASSERT_TRUE(cache._need_evict_cache_in_advance);
+
+ cache._cur_cache_size = 60_mb;
+ cache.check_need_evict_cache_in_advance();
+ ASSERT_FALSE(cache._need_evict_cache_in_advance);
+}
+
+TEST_F(BlockFileCacheMemModeTest,
zero_capacity_memory_should_keep_monitor_and_stats_available) {
+ auto settings = make_settings();
+ settings.capacity = 0;
+ BlockFileCache cache(_cache_path.string(), settings);
+
+ cache.check_disk_resource_limit();
+ cache.check_need_evict_cache_in_advance();
+
EXPECT_FALSE(cache._disk_resource_limit_mode.load(std::memory_order_relaxed));
+
EXPECT_FALSE(cache._need_evict_cache_in_advance.load(std::memory_order_relaxed));
+ EXPECT_EQ(cache.get_stats().at("size_percentage"), 0);
+ EXPECT_EQ(cache.get_stats_unsafe().at("size_percentage"), 0);
+
+ ASSERT_TRUE(cache.initialize().ok());
+ wait_async_open(cache);
+ EXPECT_EQ(cache.get_stats().at("size_percentage"), 0);
+}
+
+TEST_F(BlockFileCacheMemModeTest,
+ tiny_reset_with_held_blocks_should_keep_pressure_checks_available) {
+ auto settings = make_settings();
+ BlockFileCache cache(_cache_path.string(), settings);
+ ASSERT_TRUE(cache.initialize().ok());
+ wait_async_open(cache);
+
+ CacheContext context;
+ ReadStatistics rstats;
+ context.stats = &rstats;
+ context.cache_type = FileCacheType::NORMAL;
+ auto key = BlockFileCache::hash("mem-held-tiny-reset-key");
+ auto holder = cache.get_or_set(key, 0, 30_mb, context);
+ auto blocks = fromHolder(holder);
+ ASSERT_EQ(blocks.size(), 3);
+ for (const auto& block : blocks) {
+ ASSERT_TRUE(block->get_or_set_downloader() ==
FileBlock::get_caller_id());
+ download_into_memory(block);
+ }
+
+ auto message = cache.reset_capacity(1);
+ ASSERT_FALSE(message.empty());
+ ASSERT_EQ(cache._cur_cache_size, 30_mb);
+ {
+ std::lock_guard cache_lock(cache._mutex);
+ ASSERT_GT(cache.calc_size_percentage_unlocked(cache_lock),
std::numeric_limits<int>::max());
+ }
+
+ cache.check_disk_resource_limit();
+ cache.check_need_evict_cache_in_advance();
+
EXPECT_TRUE(cache._disk_resource_limit_mode.load(std::memory_order_relaxed));
+
EXPECT_TRUE(cache._need_evict_cache_in_advance.load(std::memory_order_relaxed));
+}
+
+TEST_F(BlockFileCacheMemModeTest,
pressure_mode_should_account_query_by_actual_block_size) {
+ auto settings = make_settings();
+ config::enable_file_cache_query_limit = false;
+ config::file_cache_enter_disk_resource_limit_mode_percent = 90;
+ config::file_cache_exit_disk_resource_limit_mode_percent = 80;
+ BlockFileCache cache(_cache_path.string(), settings);
+ ASSERT_TRUE(cache.initialize().ok());
+ wait_async_open(cache);
+
+ fill_memory_cache(cache, 100_mb);
+ cache.clear_need_update_lru_blocks();
+ {
+ std::lock_guard cache_lock(cache._mutex);
+ // Keep the prefilled blocks cold regardless of the CI worker's uptime.
+ for (auto& file : cache._files) {
+ for (auto& offset_cell : file.second) {
+ offset_cell.second.atime = std::numeric_limits<int64_t>::min();
+ }
+ }
+ }
+ cache.check_disk_resource_limit();
+
ASSERT_TRUE(cache._disk_resource_limit_mode.load(std::memory_order_relaxed));
+
+ config::enable_file_cache_query_limit = true;
+ TUniqueId query_id;
+ query_id.hi = 19;
+ query_id.lo = 19;
+ auto query_context_holder = cache.get_query_context_holder(query_id, 10);
+ ASSERT_NE(query_context_holder, nullptr);
+ ASSERT_NE(query_context_holder->context, nullptr);
+
+ CacheContext context;
+ ReadStatistics rstats;
+ context.stats = &rstats;
+ context.cache_type = FileCacheType::DISPOSABLE;
+ context.query_id = query_id;
+ auto admit_block = [&](const std::string& key_name) {
+ auto key = BlockFileCache::hash(key_name);
+ auto holder = cache.get_or_set(key, 0, 10_mb, context);
+ auto blocks = fromHolder(holder);
+ ASSERT_EQ(blocks.size(), 1);
+ ASSERT_TRUE(blocks[0]->get_or_set_downloader() ==
FileBlock::get_caller_id());
+ download_into_memory(blocks[0]);
+ };
+
+ admit_block("query-pressure-key-1");
+ cache.clear_need_update_lru_blocks();
+ {
+ std::lock_guard cache_lock(cache._mutex);
+ EXPECT_EQ(query_context_holder->context->get_cache_size(cache_lock),
10_mb);
+ }
+
+ admit_block("query-pressure-key-2");
+ cache.clear_need_update_lru_blocks();
+ {
+ std::lock_guard cache_lock(cache._mutex);
+ EXPECT_EQ(query_context_holder->context->get_cache_size(cache_lock),
10_mb);
+ }
+}
+
+TEST_F(BlockFileCacheMemModeTest, check_need_evict_memory_config_fallback) {
+ auto settings = make_settings();
+ BlockFileCache cache(_cache_path.string(), settings);
+
+ config::file_cache_enter_need_evict_cache_in_advance_percent = 70;
+ config::file_cache_exit_need_evict_cache_in_advance_percent = 75;
+
+ cache._cur_cache_size = 80_mb;
+ cache.check_need_evict_cache_in_advance();
+
+ ASSERT_EQ(config::file_cache_enter_need_evict_cache_in_advance_percent,
78);
+ ASSERT_EQ(config::file_cache_exit_need_evict_cache_in_advance_percent, 75);
+ ASSERT_TRUE(cache._need_evict_cache_in_advance);
+}
+
+TEST_F(BlockFileCacheMemModeTest, check_disk_mode_memory_enter_exit) {
+ auto settings = make_settings();
+ BlockFileCache cache(_cache_path.string(), settings);
+
+ config::file_cache_enter_disk_resource_limit_mode_percent = 90;
+ config::file_cache_exit_disk_resource_limit_mode_percent = 80;
+
+ cache._cur_cache_size = 95_mb;
+ cache.check_disk_resource_limit();
+ ASSERT_TRUE(cache._disk_resource_limit_mode);
+
+ cache._cur_cache_size = 70_mb;
+ cache.check_disk_resource_limit();
+ ASSERT_FALSE(cache._disk_resource_limit_mode);
+}
+
+TEST_F(BlockFileCacheMemModeTest, check_disk_mode_disk_compat) {
+ auto settings = make_settings("disk");
+ BlockFileCache cache(_cache_path.string(), settings);
+
+ config::file_cache_enter_disk_resource_limit_mode_percent = 90;
+ config::file_cache_exit_disk_resource_limit_mode_percent = 80;
+
+ auto* sync_point = SyncPoint::get_instance();
+ sync_point->set_call_back("BlockFileCache::disk_used_percentage:1",
+ [](std::vector<std::any>&& values) {
+ auto* percent = try_any_cast<std::pair<int,
int>*>(values.back());
+ percent->first = 95;
+ percent->second = 70;
+ });
+ sync_point->enable_processing();
+ cache.check_disk_resource_limit();
+ ASSERT_TRUE(cache._disk_resource_limit_mode);
+
+ sync_point->clear_all_call_backs();
+ sync_point->set_call_back("BlockFileCache::disk_used_percentage:1",
+ [](std::vector<std::any>&& values) {
+ auto* percent = try_any_cast<std::pair<int,
int>*>(values.back());
+ percent->first = 70;
+ percent->second = 70;
+ });
+ cache.check_disk_resource_limit();
+ ASSERT_FALSE(cache._disk_resource_limit_mode);
+}
+
+TEST_F(BlockFileCacheMemModeTest,
reset_capacity_memory_should_work_and_mode_converge) {
+ auto settings = make_settings();
+ BlockFileCache cache(_cache_path.string(), settings);
+ ASSERT_TRUE(cache.initialize().ok());
+ wait_async_open(cache);
+
+ fill_memory_cache(cache, 60_mb);
+ ASSERT_EQ(cache._cur_cache_size, 60_mb);
+
+ cache._disk_resource_limit_mode = false;
+ cache._disk_limit_mode_metrics->set_value(0);
+
+ auto message = cache.reset_capacity(30_mb);
+ ASSERT_FALSE(message.empty());
+ ASSERT_LE(cache._cur_cache_size, 30_mb);
+ ASSERT_FALSE(cache._disk_resource_limit_mode);
+
+ config::file_cache_enter_disk_resource_limit_mode_percent = 90;
+ config::file_cache_exit_disk_resource_limit_mode_percent = 80;
+ cache.check_disk_resource_limit();
+ ASSERT_TRUE(cache._disk_resource_limit_mode);
+}
+
+TEST_F(BlockFileCacheMemModeTest,
reset_capacity_memory_should_not_overcount_unreleasable_blocks) {
+ auto settings = make_settings();
+ BlockFileCache cache(_cache_path.string(), settings);
+ ASSERT_TRUE(cache.initialize().ok());
+ wait_async_open(cache);
+
+ TUniqueId query_id;
+ query_id.hi = 7;
+ query_id.lo = 7;
+ CacheContext context;
+ ReadStatistics rstats;
+ context.stats = &rstats;
+ context.cache_type = FileCacheType::NORMAL;
+ context.query_id = query_id;
+ auto key = BlockFileCache::hash("mem-held-key");
+
+ auto holder = cache.get_or_set(key, 0, 10_mb, context);
+ auto blocks = fromHolder(holder);
+ ASSERT_EQ(blocks.size(), 1);
+ ASSERT_TRUE(blocks[0]->get_or_set_downloader() ==
FileBlock::get_caller_id());
+ download_into_memory(blocks[0]);
+
+ fill_memory_cache(cache, 30_mb);
+ ASSERT_EQ(cache._cur_cache_size, 40_mb);
+
+ auto message = cache.reset_capacity(15_mb);
+ ASSERT_FALSE(message.empty());
+ ASSERT_LE(cache._cur_cache_size, 15_mb);
+ ASSERT_EQ(cache._cur_cache_size, 10_mb);
+
+ blocks.clear();
+ holder.file_blocks.clear();
+}
+
+TEST_F(BlockFileCacheMemModeTest, run_background_monitor_memory_mode_flip) {
+ auto settings = make_settings();
+ config::enable_evict_file_cache_in_advance = true;
+ config::file_cache_enter_need_evict_cache_in_advance_percent = 70;
+ config::file_cache_exit_need_evict_cache_in_advance_percent = 65;
+ config::file_cache_enter_disk_resource_limit_mode_percent = 90;
+ config::file_cache_exit_disk_resource_limit_mode_percent = 80;
+
+ auto* sync_point = SyncPoint::get_instance();
+ sync_point->set_call_back("BlockFileCache::set_sleep_time",
+ [](auto&& args) {
*try_any_cast<int64_t*>(args[0]) = 10; });
+ sync_point->enable_processing();
+
+ BlockFileCache cache(_cache_path.string(), settings);
+ ASSERT_TRUE(cache.initialize().ok());
+ wait_async_open(cache);
+
+ {
+ std::lock_guard lock(cache._mutex);
+ cache._cur_cache_size = 95_mb;
+ }
+ ASSERT_TRUE(wait_until([&cache] {
+ return cache._need_evict_cache_in_advance &&
cache._disk_resource_limit_mode;
+ }));
+
+ {
+ std::lock_guard lock(cache._mutex);
+ cache._cur_cache_size = 60_mb;
+ }
+ ASSERT_TRUE(wait_until([&cache] {
+ return !cache._need_evict_cache_in_advance &&
!cache._disk_resource_limit_mode;
+ }));
+}
+
+TEST_F(BlockFileCacheMemModeTest,
stats_memory_contains_storage_type_and_size_percentage) {
+ auto settings = make_settings();
+ BlockFileCache cache(_cache_path.string(), settings);
+
+ cache._cur_cache_size = 25_mb;
+ cache._cur_cache_size_metrics->set_value(cache._cur_cache_size);
+
+ auto stats = cache.get_stats();
+ ASSERT_TRUE(stats.contains("size_percentage"));
+ ASSERT_TRUE(stats.contains("storage_type"));
+ ASSERT_EQ(stats["size_percentage"], 25);
+ ASSERT_EQ(stats["storage_type"], FileCacheStorageType::MEMORY);
+}
+
+TEST_F(BlockFileCacheMemModeTest,
memory_storage_should_skip_lru_restore_and_dump) {
+ config::file_cache_background_lru_dump_tail_record_num = 100;
+ auto settings = make_settings();
+ auto key = BlockFileCache::hash("memory-lru-restore-key");
+ auto memory_dump_dir = fs::current_path() / "memory";
+ fs::remove_all(memory_dump_dir);
+ fs::create_directories(memory_dump_dir);
+
+ {
+ BlockFileCache cache(_cache_path.string(), settings);
+ ASSERT_TRUE(cache.initialize().ok());
+ wait_async_open(cache);
+
+ fill_cache(cache, key, 20_mb, true);
+ ASSERT_EQ(cache._cur_cache_size, 20_mb);
+ cache.dump_lru_queues(true);
+ }
+
+ auto dump_file = memory_dump_dir / "lru_dump_normal.tail";
+ ASSERT_FALSE(fs::exists(dump_file));
+
+ std::ofstream(dump_file, std::ios::binary) << "stale-memory-dump";
+ ASSERT_TRUE(fs::exists(dump_file));
+
+ BlockFileCache cache2(_cache_path.string(), settings);
+ ASSERT_TRUE(cache2.initialize().ok());
+ wait_async_open(cache2);
+
+ ASSERT_EQ(cache2._cur_cache_size, 0);
+ ASSERT_EQ(cache2._normal_queue.get_elements_num_unsafe(), 0);
+ ASSERT_TRUE(cache2.get_blocks_by_key(key).empty());
+
+ fs::remove_all(memory_dump_dir);
+}
+
+TEST_F(BlockFileCacheMemModeTest,
memory_storage_should_skip_lru_queue_recorder) {
+ config::file_cache_background_lru_dump_tail_record_num = 100;
+ auto settings = make_settings();
+ BlockFileCache cache(_cache_path.string(), settings);
+ ASSERT_TRUE(cache.initialize().ok());
+ wait_async_open(cache);
+
+ auto key = BlockFileCache::hash("memory-storage-skip-lru-recorder");
+ fill_cache(cache, key, 10_mb, true);
+
+
EXPECT_EQ(cache._lru_recorder->get_lru_queue_update_cnt_from_last_dump(FileCacheType::NORMAL),
+ 0);
+}
+
+TEST_F(BlockFileCacheMemModeTest, disk_storage_should_keep_lru_restore) {
+ config::file_cache_background_lru_dump_tail_record_num = 100;
+ auto settings = make_settings("disk");
+ auto key = BlockFileCache::hash("disk-lru-restore-key");
+ auto origin_cache_base_path = cache_base_path;
+ cache_base_path = _cache_path.string();
Review Comment:
[P2] Restore shared test state after fatal assertions
This overwrites the process-global `cache_base_path`, but restores it only
after several fatal `ASSERT_*` calls. If any assertion returns early (including
the asynchronous replay failure already raised on this test), `TearDown`
deletes `_cache_path` without restoring the global, so later cache tests run
against a removed per-test directory and produce cascading failures. The
sibling memory-persistence test likewise cleans its shared
`current_path()/memory` directory only at the end. Move both restorations into
fixture teardown or scoped guards so they run on every exit path.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]