From: Vladimír Čunát Date: Wed, 3 Jan 2018 08:57:27 +0000 (+0100) Subject: clear cache if overfull X-Git-Tag: v2.0.0~6^2~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=819bcae16246fed28ee10abe2b207d3401dd6fb5;p=thirdparty%2Fknot-resolver.git clear cache if overfull I somehow forgot to migrate that behavior when rewriting cache :-/ --- diff --git a/lib/cache/entry_list.c b/lib/cache/entry_list.c index 70553e5df..f2c40b3ca 100644 --- a/lib/cache/entry_list.c +++ b/lib/cache/entry_list.c @@ -184,6 +184,19 @@ int entry_h_splice( knot_db_val_t val = { .len = storage_size, .data = NULL }; int ret = cache_op(cache, write, &key, &val, 1); if (ret || !val.data || !val.len) { + /* Clear cache if overfull. It's nontrivial to do better with LMDB. + * LATER: some garbage-collection mechanism. */ + if (ret == kr_error(ENOSPC)) { + ret = kr_cache_clear(cache); + const char *msg = "[cache] clearing because overfull, ret = %d\n"; + if (ret) { + kr_log_error(msg, ret); + } else { + kr_log_info(msg, ret); + ret = kr_error(ENOSPC); + } + return ret; + } assert(ret); /* otherwise "succeeding" but `val` is bad */ VERBOSE_MSG(qry, "=> failed backend write, ret = %d\n", ret); return kr_error(ret ? ret : ENOSPC); diff --git a/lib/cdb_lmdb.c b/lib/cdb_lmdb.c index af2495961..cfbfc3847 100644 --- a/lib/cdb_lmdb.c +++ b/lib/cdb_lmdb.c @@ -56,20 +56,21 @@ struct lmdb_env /** @brief Convert LMDB error code. */ static int lmdb_error(int error) { + /* _BAD_TXN may happen with overfull DB, + * even during mdb_get with a single fork :-/ */ + if (error == MDB_BAD_TXN) { + kr_log_info("[cache] MDB_BAD_TXN, probably overfull\n"); + error = ENOSPC; + } switch (error) { case MDB_SUCCESS: return kr_ok(); case MDB_NOTFOUND: return kr_error(ENOENT); - case ENOSPC: case MDB_MAP_FULL: case MDB_TXN_FULL: - case MDB_BAD_TXN: - /* _BAD_TXN in practice happens with overfull DB, - * even during mdb_get with a single fork :-/ */ return kr_error(ENOSPC); - default: kr_log_error("[cache] LMDB error: %s\n", mdb_strerror(error)); assert(false);