This is an automated email from the ASF dual-hosted git repository.
masaori335 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new ec72cf41da cache: apply per-volume settings on first start after clear
(#13252)
ec72cf41da is described below
commit ec72cf41dadf4876be0e83addbb91d8ddf104290
Author: Masaori Koshiba <[email protected]>
AuthorDate: Tue Jun 23 06:59:49 2026 +0900
cache: apply per-volume settings on first start after clear (#13252)
Per-volume tuning (ram_cache, ram_cache_size, ram_cache_cutoff,
avg_obj_size, fragment_size) was only copied onto the CacheVol when
matching an existing on-disk volume, so volumes created fresh (e.g.
the first start after a cache clear) ignored the config until the
next restart. Apply the settings in one pass after all CacheVols
exist.
Extend cache_volume_features to verify the settings take effect via
per-volume metrics.
---
src/iocore/cache/CacheProcessor.cc | 27 +++++++++---
.../cache/cache_volume_features.replay.yaml | 50 ++++++++++++++++++----
.../gold_tests/cache/cache_volume_features.test.py | 3 +-
3 files changed, 64 insertions(+), 16 deletions(-)
diff --git a/src/iocore/cache/CacheProcessor.cc
b/src/iocore/cache/CacheProcessor.cc
index ffff468ef7..b2e874b8dc 100644
--- a/src/iocore/cache/CacheProcessor.cc
+++ b/src/iocore/cache/CacheProcessor.cc
@@ -70,6 +70,7 @@ void register_cache_stats(CacheStatsBlock *rsb,
const std::string &pre
static void cplist_update();
static int create_volume(int volume_number, off_t size_in_blocks,
CacheType scheme, CacheVol *cp);
static int fillExclusiveDisks(CacheVol *cp);
+static void cplist_apply_config_settings(CacheVol *cp, const ConfigVol
*config_vol);
static size_t DEFAULT_RAM_CACHE_MULTIPLIER = 10; // I.e. 10x 1MB per 1GB of
disk.
@@ -1093,6 +1094,14 @@ cplist_reconfigure()
}
}
+ // Apply per-volume settings after all CacheVols exist; otherwise volumes
created on the first
+ // start after a cache clear keep defaults and ignore the config until the
next restart.
+ for (ConfigVol *config_vol = config_volumes.cp_queue.head; config_vol;
config_vol = config_vol->link.next) {
+ if (config_vol->cachep) {
+ cplist_apply_config_settings(config_vol->cachep, config_vol);
+ }
+ }
+
ts::Metrics::Gauge::store(cache_rsb.stripes, gnstripes);
return 0;
@@ -1209,6 +1218,17 @@ register_cache_stats(CacheStatsBlock *rsb, const
std::string &prefix)
rsb->writer_lock_contention = ts::Metrics::Counter::createPtr(prefix +
".writer.lock_contention");
}
+// Copy the per-volume tuning fields from the volume config onto the CacheVol.
+void
+cplist_apply_config_settings(CacheVol *cp, const ConfigVol *config_vol)
+{
+ cp->ramcache_enabled = config_vol->ramcache_enabled;
+ cp->avg_obj_size = config_vol->avg_obj_size;
+ cp->fragment_size = config_vol->fragment_size;
+ cp->ram_cache_size = config_vol->ram_cache_size;
+ cp->ram_cache_cutoff = config_vol->ram_cache_cutoff;
+}
+
void
cplist_update()
{
@@ -1220,12 +1240,7 @@ cplist_update()
for (config_vol = config_volumes.cp_queue.head; config_vol; config_vol =
config_vol->link.next) {
if (config_vol->number == cp->vol_number) {
if (cp->scheme == config_vol->scheme) {
- cp->ramcache_enabled = config_vol->ramcache_enabled;
- cp->avg_obj_size = config_vol->avg_obj_size;
- cp->fragment_size = config_vol->fragment_size;
- cp->ram_cache_size = config_vol->ram_cache_size;
- cp->ram_cache_cutoff = config_vol->ram_cache_cutoff;
- config_vol->cachep = cp;
+ config_vol->cachep = cp;
} else {
/* delete this volume from all the disks */
int d_no;
diff --git a/tests/gold_tests/cache/cache_volume_features.replay.yaml
b/tests/gold_tests/cache/cache_volume_features.replay.yaml
index 3ea0f5a342..cb69a36ff5 100644
--- a/tests/gold_tests/cache/cache_volume_features.replay.yaml
+++ b/tests/gold_tests/cache/cache_volume_features.replay.yaml
@@ -18,20 +18,32 @@ meta:
version: "1.0"
# This test proves that multi-parameter storage.yaml volume entries are parsed
-# correctly. The generated storage.yaml contains:
+# correctly AND that the per-volume settings actually take effect on the first
+# start after a cache clear (AuTest always starts ATS against a fresh cache).
+# The generated storage.yaml contains:
#
# cache:
# volumes:
# - id: 1
# scheme: http
-# size: 50%
+# size: 128M
# ram_cache_size: 32M
# ram_cache_cutoff: 8K
+# avg_obj_size: 2000
+# fragment_size: 1M
# - id: 2
# scheme: http
-# size: 50%
+# size: 128M
+# ram_cache: false
#
-# All volume parameters must be parsed correctly from the YAML format.
+# All volume parameters must be parsed correctly from the YAML format, and the
+# per-volume settings are verified via the metric_checks below:
+# - Volume 1 (ram_cache_size: 32M, single 128MB stripe) -> ram_cache
total_bytes == 32MB
+# - Volume 1 (avg_obj_size: 2000) -> direntries.total
== 66424
+# - Volume 2 (ram_cache: false) -> ram_cache
total_bytes == 0
+# These exercise two distinct downstream paths (the RAM cache sizing in
+# cacheInitialized() and the directory sizing in the StripeSM constructor). On
a
+# build that ignores per-volume settings on first start, none of them match.
autest:
description: "Test cache volume features: per-volume RAM cache and @volume=
directive"
@@ -60,18 +72,38 @@ autest:
spans:
- name: "disk-1"
path: "storage"
- size: "256M"
+ size: "512M"
volumes:
- # Volume 1 with all new parameters
+ # Volume 1 with all new parameters (one 128MB stripe for an exact
RAM cache size).
- id: 1
scheme: "http"
- size: "50%"
+ size: "128M"
ram_cache_size: "32M"
ram_cache_cutoff: "8K"
- # Volume 2 — simple volume, no extra params
+ avg_obj_size: "2000"
+ fragment_size: "1M"
+ # Volume 2 — RAM cache explicitly disabled.
- id: 2
scheme: "http"
- size: "50%"
+ size: "128M"
+ ram_cache: false
+
+ metric_checks:
+ # avg_obj_size=2000 on volume 1 sizes the directory with more entries
than the default
+ # min_average_object_size (8000) would. This exercises the avg_obj_size
-> StripeSM
+ # directory-sizing path, which is distinct from the RAM cache path
below. The value is a
+ # deterministic function of stripe length (one 128MB stripe) and
avg_obj_size; on a build
+ # that ignores the per-volume setting on first start the directory uses
the default size.
+ - metric: "proxy.process.cache.volume_1.direntries.total"
+ value: 66424
+ # ram_cache_size=32M on volume 1 (single 128MB stripe) -> exactly 32 *
1024 * 1024 bytes.
+ # On first start after a cache clear this only holds if the per-volume
setting is applied
+ # to the freshly created CacheVol rather than ignored until the next
restart.
+ - metric: "proxy.process.cache.volume_1.ram_cache.total_bytes"
+ value: 33554432
+ # ramcache=false on volume 2 means no RAM cache is allocated for it.
+ - metric: "proxy.process.cache.volume_2.ram_cache.total_bytes"
+ value: 0
log_validation:
traffic_out:
diff --git a/tests/gold_tests/cache/cache_volume_features.test.py
b/tests/gold_tests/cache/cache_volume_features.test.py
index b6aa8ec13d..8b6c198114 100644
--- a/tests/gold_tests/cache/cache_volume_features.test.py
+++ b/tests/gold_tests/cache/cache_volume_features.test.py
@@ -16,7 +16,8 @@
Test.Summary = '''
Comprehensive test suite for cache volume features:
-- Per-volume RAM cache configuration (ram_cache_size, ram_cache_cutoff)
+- Per-volume RAM cache configuration (ram_cache, ram_cache_size,
ram_cache_cutoff)
+- Per-volume settings take effect on the first start after a cache clear
- @volume= directive in remap.config for volume selection
- Integration between both features
'''