Skip to content

Commit 2dfe06b

Browse files
committed
LRU_K: harden param parsing and account for K in obj_md_size
- Replace `strstr("k=") + atoi` with `strsep`-based key=value tokenizer that matches the SLRU pattern. Avoids fragile substring matches (e.g. embedded "k=" in unrelated keys), validates the value with `strtol` (no silent truncation), errors on unknown keys, and adds a `print` parameter consistent with other algos. - Reorder LRU_K_init so parse_params runs before obj_md_size, and scale per-object metadata as `8 * k + 16` (history vtimes + node overhead) instead of a fixed 8 bytes that ignored K.
1 parent 807df4f commit 2dfe06b

1 file changed

Lines changed: 39 additions & 14 deletions

File tree

libCacheSim/cache/eviction/cpp/LRU_K.cpp

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
*/
1414

1515
#include <cassert>
16+
#include <cstdlib>
17+
#include <cstring>
1618
#include <deque>
1719
#include <list>
1820
#include <set>
@@ -81,25 +83,46 @@ static bool LRU_K_remove(cache_t *cache, obj_id_t obj_id);
8183
/**
8284
* @brief parse algorithm-specific parameters
8385
*
84-
* Supported parameters:
85-
* k=<int> number of accesses to track (default: 2)
86+
* Supported parameters (comma-separated key=value pairs):
87+
* k=<int> number of accesses to track (default: 2, must be >= 1)
8688
*/
8789
static void LRU_K_parse_params(cache_t *cache,
88-
const char *cache_specific_params) {
89-
auto *lruk =
90-
reinterpret_cast<eviction::LRU_K *>(cache->eviction_params);
90+
const char *cache_specific_params) {
91+
auto *lruk = reinterpret_cast<eviction::LRU_K *>(cache->eviction_params);
9192
if (cache_specific_params == nullptr || cache_specific_params[0] == '\0')
9293
return;
9394

94-
const char *k_str = strstr(cache_specific_params, "k=");
95-
if (k_str != nullptr) {
96-
int k_val = atoi(k_str + 2);
97-
if (k_val >= 1) {
98-
lruk->k = k_val;
95+
char *params_str = strdup(cache_specific_params);
96+
char *to_free = params_str;
97+
char *end = nullptr;
98+
99+
while (params_str != nullptr && params_str[0] != '\0') {
100+
char *key = strsep(&params_str, "=");
101+
char *value = strsep(&params_str, ",");
102+
103+
while (params_str != nullptr && *params_str == ' ') params_str++;
104+
105+
if (strcasecmp(key, "k") == 0) {
106+
if (value == nullptr || value[0] == '\0') {
107+
ERROR("LRU_K: missing value for k\n");
108+
}
109+
long k_val = strtol(value, &end, 0);
110+
if (end == value || (end != nullptr && *end != '\0')) {
111+
ERROR("LRU_K: invalid k value \"%s\"\n", value);
112+
}
113+
if (k_val < 1) {
114+
ERROR("LRU_K: k must be >= 1, got %ld\n", k_val);
115+
}
116+
lruk->k = static_cast<int>(k_val);
117+
} else if (strcasecmp(key, "print") == 0) {
118+
printf("LRU_K parameters: k=%d\n", lruk->k);
119+
exit(0);
99120
} else {
100-
WARN("LRU_K: invalid k value %d, using default k=2\n", k_val);
121+
ERROR("LRU_K does not have parameter %s\n", key);
101122
}
102123
}
124+
125+
free(to_free);
103126
}
104127

105128
/**
@@ -123,14 +146,16 @@ cache_t *LRU_K_init(const common_cache_params_t ccache_params,
123146
cache->to_evict = LRU_K_to_evict;
124147
cache->remove = LRU_K_remove;
125148

149+
LRU_K_parse_params(cache, cache_specific_params);
150+
126151
if (ccache_params.consider_obj_metadata) {
127-
cache->obj_md_size = 8;
152+
auto *lruk = reinterpret_cast<eviction::LRU_K *>(cache->eviction_params);
153+
/* per-object overhead: K vtimes in history + map entry + queue/set node */
154+
cache->obj_md_size = 8 * lruk->k + 16;
128155
} else {
129156
cache->obj_md_size = 0;
130157
}
131158

132-
LRU_K_parse_params(cache, cache_specific_params);
133-
134159
return cache;
135160
}
136161

0 commit comments

Comments
 (0)