.. note:: Use ``B, K, M, G`` bytes units prefixes.
Opens cache with a size limit. The cache will be reopened if already open.
-Note that the maximum size cannot be lowered, only increased due to how cache is implemented.
+Note that lowering the maximum size removes all cached data;
+increasing the size removes usage statistics of the stored entries used by garbage collector,
+but keeps the actual data.
.. code-block:: yaml
(int)ver, (int)CACHE_VERSION);
}
}
- ret = cache_op(cache, clear);
+ ret = cache_op(cache, clear, 0);
}
/* Rewrite the entry even if it isn't needed. Because of cache-size-changing
* possibility it's good to always perform some write during opening of cache. */
size_t maxsize = 0;
if (ret == 0) {
maxsize = cache->api->get_maxsize(cache->db);
- if (opts->maxsize && (maxsize > opts->maxsize)) kr_log_warning(CACHE,
- "Warning: real cache size is %zu instead of the requested %zu bytes."
- " To reduce the size you need to remove the file '%s' by hand.\n",
- maxsize, opts->maxsize, fpath); // TODO remove file instead
+ if (opts->maxsize && (maxsize > opts->maxsize)) {
+ kr_log_warning(CACHE,
+ "Warning: real cache size is %zu instead of the requested %zu bytes, removing all data.",
+ maxsize, opts->maxsize, fpath);
+ cache_op(cache, clear, opts->maxsize);
+ maxsize = cache->api->get_maxsize(cache->db);
+ }
}
if (ret != 0)
return ret;
if (!cache_isvalid(cache)) {
return kr_error(EINVAL);
}
- int ret = cache_op(cache, clear);
+ int ret = cache_op(cache, clear, 0);
if (ret == 0) {
kr_cache_make_checkpoint(cache);
ret = assert_right_version(cache);
int (*open)(kr_cdb_pt *db, struct kr_cdb_stats *stat, struct kr_cdb_opts *opts, knot_mm_t *mm);
void (*close)(kr_cdb_pt db, struct kr_cdb_stats *stat);
int (*count)(kr_cdb_pt db, struct kr_cdb_stats *stat);
- int (*clear)(kr_cdb_pt db, struct kr_cdb_stats *stat);
+
+ /** Clear cache, possibly changing its size unless maxsize == 0. */
+ int (*clear)(kr_cdb_pt db, struct kr_cdb_stats *stat, const size_t maxsize);
/** Run after a row of operations to release transaction/lock if needed.
* \param accept_rw whether the RW transaction should accept changes (commit vs. abort)
/** Obtain exclusive (advisory) lock by creating a file, returning FD or negative kr_error().
* The lock is auto-released by OS in case the process finishes in any way (file remains). */
-static int lockfile_get(const char *path)
+static int lockfile_get(const char *path, bool wait)
{
if (kr_fails_assert(path))
return kr_error(EINVAL);
lock_info.l_len = 1; // it's OK for locks to extend beyond the end of the file
int err;
do {
- err = fcntl(fd, F_SETLK, &lock_info);
+ err = fcntl(fd, (wait ? F_SETLKW : F_SETLK), &lock_info);
} while (err == -1 && errno == EINTR);
if (err) {
close(fd);
}
}
-static int cdb_clear(kr_cdb_pt db, struct kr_cdb_stats *stats)
+static int cdb_clear(kr_cdb_pt db, struct kr_cdb_stats *stats, const size_t mapsize)
{
struct lmdb_env *env = db2env(db);
stats->clear++;
- /* First try mdb_drop() to clear the DB; this may fail with ENOSPC. */
- {
+ /* First try mdb_drop() to clear the DB unless size change is requested; this may fail with ENOSPC. */
+ if (mapsize == 0) {
MDB_txn *txn = NULL;
int ret = txn_get(env, &txn, false);
if (ret == kr_ok()) {
}
/* Find if we get a lock on lockfile. */
- const int lockfile_fd = lockfile_get(lockfile);
+ const int lockfile_fd = lockfile_get(lockfile, mapsize != 0);
if (lockfile_fd < 0) {
kr_log_error(MDB, "clearing failed to get ./krcachelock (%s); retry later\n",
kr_strerror(lockfile_fd));
// coverity[toctou]
unlink(env->mdb_data_path);
unlink(mdb_lockfile);
- ret = reopen_env(env, stats, env->mapsize);
+ ret = reopen_env(env, stats, mapsize ? mapsize : env->mapsize);
}
/* Environment updated, release lockfile. */
};
int ret = the_rules->api->open(&the_rules->db, &the_rules->stats, &opts, NULL);
- if (ret == 0 && overwrite) ret = ruledb_op(clear);
+ if (ret == 0 && overwrite) ret = ruledb_op(clear, 0);
if (ret != 0) goto failure;
kr_require(the_rules->db);
async def load_policy_rules(self, _old: KresConfig, new: KresConfig) -> Result[NoneType, str]:
try:
async with self._manager_lock:
+ if _old.cache.size_max != new.cache.size_max:
+ logger.debug("Unlinking shared cache top memory")
+ try:
+ os.unlink(str(_old.cache.storage) + "/top")
+ except FileNotFoundError:
+ pass
+
logger.debug("Running kresd 'policy-loader'")
await self._run_policy_loader(new)