diff --git a/src/iocore/cache/CacheProcessor.cc b/src/iocore/cache/CacheProcessor.cc index 8d75053e59c..3e436353662 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. @@ -1038,6 +1039,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; @@ -1154,6 +1163,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() { @@ -1165,12 +1185,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 6c7c8154271..a4165ff0660 100644 --- a/tests/gold_tests/cache/cache_volume_features.replay.yaml +++ b/tests/gold_tests/cache/cache_volume_features.replay.yaml @@ -18,15 +18,24 @@ meta: version: "1.0" # This test proves that multi-parameter volume.config lines are parsed -# correctly. The generated volume.config lines are: +# 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 volume.config lines are: # -# volume=1 scheme=http size=50% ram_cache_size=32M ram_cache_cutoff=8K -# volume=2 scheme=http size=50% +# volume=1 scheme=http size=50% ram_cache_size=32M ram_cache_cutoff=8K avg_obj_size=2000 fragment_size=1M +# volume=2 scheme=http size=50% ramcache=false # # All 5 key=value pairs on line 1 must be parsed from the single line. # If the inner loop's "tmp = line_end" advancement were broken (as claimed # in a PR review), only "volume=1" would be parsed, scheme and size would -# be missing, and the volume would be rejected -- disabling the cache. +# be missing, and the volume would be rejected -- disabling the cache, 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 (ramcache: 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" @@ -57,10 +66,13 @@ autest: size: "50%" ram_cache_size: "32M" ram_cache_cutoff: "8K" + avg_obj_size: 2000 + fragment_size: 1M # Volume 2 — simple line, no extra params - volume: 2 scheme: "http" size: "50%" + ramcache: false 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 c52575ef564..48fba56124c 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 '''