]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
cache: wrapped namedb_t+txn into structure, counters
authorMarek Vavruša <marek.vavrusa@nic.cz>
Wed, 27 May 2015 17:25:04 +0000 (19:25 +0200)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Wed, 27 May 2015 17:25:04 +0000 (19:25 +0200)
this prepares cache/txn structures to hold API as well, so we can get
rid of the global api

14 files changed:
daemon/bindings.c
daemon/engine.c
lib/cache.c
lib/cache.h
lib/layer/pktcache.c
lib/layer/rrcache.c
lib/resolve.c
lib/resolve.h
lib/zonecut.c
lib/zonecut.h
modules/README.rst
modules/cachectl/cachectl.c
tests/test_cache.c
tests/test_integration.c

index 28a826b98121f42e9b7e30ee9d6e5c5100c7d859..77e558a610def730fc0d2cc95037744c30214d22 100644 (file)
@@ -312,14 +312,14 @@ static int cache_count(lua_State *L)
        const namedb_api_t *storage = kr_cache_storage();
 
        /* Fetch item count */
-       namedb_txn_t txn;
-       int ret = kr_cache_txn_begin(engine->resolver.cache, &txn, NAMEDB_RDONLY);
+       struct kr_cache_txn txn;
+       int ret = kr_cache_txn_begin(&engine->resolver.cache, &txn, NAMEDB_RDONLY);
        if (ret != 0) {
                format_error(L, kr_strerror(ret));
                lua_error(L);
        }
 
-       lua_pushinteger(L, storage->count(&txn));
+       lua_pushinteger(L, storage->count((namedb_txn_t *)&txn));
        kr_cache_txn_abort(&txn);
        return 1;
 }
@@ -366,16 +366,14 @@ static int cache_open(lua_State *L)
        }
 
        /* Close if already open */
-       if (engine->resolver.cache != NULL) {
-               kr_cache_close(engine->resolver.cache);
-       }
+       kr_cache_close(&engine->resolver.cache);
 
        /* Reopen cache */
        kr_cache_storage_set(storage->api);
        void *storage_opts = storage->opts_create(conf, cache_size);
-       engine->resolver.cache = kr_cache_open(storage_opts, engine->pool);
+       int ret = kr_cache_open(&engine->resolver.cache, storage_opts, engine->pool);
        free(storage_opts);
-       if (engine->resolver.cache == NULL) {
+       if (ret != 0) {
                format_error(L, "can't open cache");
                lua_error(L);
        }
@@ -396,12 +394,7 @@ static int cache_open(lua_State *L)
 static int cache_close(lua_State *L)
 {
        struct engine *engine = engine_luaget(L);
-       if (engine->resolver.cache != NULL) {
-               struct kr_cache *cache = engine->resolver.cache;
-               engine->resolver.cache = NULL;
-               kr_cache_close(cache);
-       }
-
+       kr_cache_close(&engine->resolver.cache);
        lua_pushboolean(L, 1);
        return 1;
 }
index b31cac6667fd0614b935b0f0de784bf861c73a5b..5b70184a3c5fa8ac02fa27afef095013fccb2bca 100644 (file)
@@ -237,8 +237,7 @@ void engine_deinit(struct engine *engine)
        }
 
        network_deinit(&engine->net);
-       kr_cache_close(engine->resolver.cache);
-       engine->resolver.cache = NULL;
+       kr_cache_close(&engine->resolver.cache);
 
        /* Unload modules. */
        for (size_t i = 0; i < engine->modules.len; ++i) {
index 67d4634bd2797672528700ea77138c28ac3cb699..4757555529a33ba289155d87de65bd2c0a6b17d3 100644 (file)
 const namedb_api_t *(*kr_cache_storage)(void) = namedb_lmdb_api;
 #define db_api kr_cache_storage()
 
-namedb_t *kr_cache_open(void *opts, mm_ctx_t *mm)
+int kr_cache_open(struct kr_cache *cache, void *opts, mm_ctx_t *mm)
 {
-       namedb_t *db = NULL;
-       int ret = db_api->init(&db, mm, opts);
+       if (!cache) {
+               return kr_error(EINVAL);
+       }
+       int ret = db_api->init(&cache->db, mm, opts);
        if (ret != 0) {
-               return NULL;
+               return ret;
        }
-
-       return db;
+       memset(&cache->stats, 0, sizeof(cache->stats));
+       return kr_ok();
 }
 
-void kr_cache_close(namedb_t *cache)
+void kr_cache_close(struct kr_cache *cache)
 {
-       if (cache && db_api) {
-               db_api->deinit(cache);
+       if (cache && cache->db) {
+               if (db_api) {
+                       db_api->deinit(cache->db);
+               }
+               cache->db = NULL;
        }
 }
 
-int kr_cache_txn_begin(namedb_t *cache, namedb_txn_t *txn, unsigned flags)
+int kr_cache_txn_begin(struct kr_cache *cache, struct kr_cache_txn *txn, unsigned flags)
 {
-       if (!cache || !txn) {
+       if (!cache || !cache->db || !txn) {
                return kr_error(EINVAL);
        }
 
-       return db_api->txn_begin(cache, txn, flags);
+       if (flags & NAMEDB_RDONLY) {
+               cache->stats.txn_read += 1;
+       } else {
+               cache->stats.txn_write += 1;
+       }
+       txn->owner = cache;
+       return db_api->txn_begin(cache->db, (namedb_txn_t *)txn, flags);
 }
 
-int kr_cache_txn_commit(namedb_txn_t *txn)
+int kr_cache_txn_commit(struct kr_cache_txn *txn)
 {
        if (!txn) {
                return kr_error(EINVAL);
        }
 
-       int ret = db_api->txn_commit(txn);
+       int ret = db_api->txn_commit((namedb_txn_t *)txn);
        if (ret != 0) {
                kr_cache_txn_abort(txn);
        }
        return ret;
 }
 
-void kr_cache_txn_abort(namedb_txn_t *txn)
+void kr_cache_txn_abort(struct kr_cache_txn *txn)
 {
        if (txn) {
-               db_api->txn_abort(txn);
+               db_api->txn_abort((namedb_txn_t *)txn);
        }
 }
 
@@ -113,34 +124,39 @@ static struct kr_cache_entry *cache_entry(namedb_txn_t *txn, uint8_t tag, const
        return (struct kr_cache_entry *)val.data;
 }
 
-struct kr_cache_entry *kr_cache_peek(namedb_txn_t *txn, uint8_t tag, const knot_dname_t *name,
+struct kr_cache_entry *kr_cache_peek(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name,
                                      uint16_t type, uint32_t *timestamp)
 {
-       if (!txn || !tag || !name) {
+       if (!txn || !txn->owner || !tag || !name) {
                return NULL;
        }
 
-       struct kr_cache_entry *entry = cache_entry(txn, tag, name, type);
+       struct kr_cache_entry *entry = cache_entry((namedb_txn_t *)txn, tag, name, type);
        if (!entry) {
+               txn->owner->stats.miss += 1;
                return NULL;
        }       
 
        /* No time constraint */
        if (!timestamp) {
+               txn->owner->stats.hit += 1;
                return entry;
        } else if (*timestamp <= entry->timestamp) {
                /* John Connor record cached in the future. */
                *timestamp = 0;
+               txn->owner->stats.hit += 1;
                return entry;
        } else {
                /* Check if the record is still valid. */
                uint32_t drift = *timestamp - entry->timestamp;
                if (drift < entry->ttl) {
                        *timestamp = drift;
+                       txn->owner->stats.hit += 1;
                        return entry;
                }
        }
 
+       txn->owner->stats.miss += 1;
        return NULL;    
 }
 
@@ -151,7 +167,7 @@ static void entry_write(struct kr_cache_entry *dst, struct kr_cache_entry *heade
        memcpy(dst->data, data.data, data.len);
 }
 
-int kr_cache_insert(namedb_txn_t *txn, uint8_t tag, const knot_dname_t *name, uint16_t type,
+int kr_cache_insert(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name, uint16_t type,
                     struct kr_cache_entry *header, namedb_val_t data)
 {
        if (!txn || !name || !tag || !header) {
@@ -166,7 +182,7 @@ int kr_cache_insert(namedb_txn_t *txn, uint8_t tag, const knot_dname_t *name, ui
 
        /* LMDB can do late write and avoid copy */
        if (db_api == namedb_lmdb_api()) {
-               int ret = db_api->insert(txn, &key, &entry, 0);
+               int ret = db_api->insert((namedb_txn_t *)txn, &key, &entry, 0);
                if (ret != 0) {
                        return ret;
                }
@@ -178,7 +194,7 @@ int kr_cache_insert(namedb_txn_t *txn, uint8_t tag, const knot_dname_t *name, ui
                        return kr_error(ENOMEM);
                }
                entry_write(entry.data, header, data);
-               int ret = db_api->insert(txn, &key, &entry, 0);
+               int ret = db_api->insert((namedb_txn_t *)txn, &key, &entry, 0);
                free(entry.data);
                if (ret != 0) {
                        return ret;
@@ -188,7 +204,7 @@ int kr_cache_insert(namedb_txn_t *txn, uint8_t tag, const knot_dname_t *name, ui
        return kr_ok();
 }
 
-int kr_cache_remove(namedb_txn_t *txn, uint8_t tag, const knot_dname_t *name, uint16_t type)
+int kr_cache_remove(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name, uint16_t type)
 {
        if (!txn || !tag || !name ) {
                return kr_error(EINVAL);
@@ -197,19 +213,20 @@ int kr_cache_remove(namedb_txn_t *txn, uint8_t tag, const knot_dname_t *name, ui
        uint8_t keybuf[KEY_SIZE];
        size_t key_len = cache_key(keybuf, tag, name, type);
        namedb_val_t key = { keybuf, key_len };
-       return db_api->del(txn, &key);
+       txn->owner->stats.delete += 1;
+       return db_api->del((namedb_txn_t *)txn, &key);
 }
 
-int kr_cache_clear(namedb_txn_t *txn)
+int kr_cache_clear(struct kr_cache_txn *txn)
 {
        if (!txn) {
                return kr_error(EINVAL);
        }
 
-       return db_api->clear(txn);
+       return db_api->clear((namedb_txn_t *)txn);
 }
 
-int kr_cache_peek_rr(namedb_txn_t *txn, knot_rrset_t *rr, uint32_t *timestamp)
+int kr_cache_peek_rr(struct kr_cache_txn *txn, knot_rrset_t *rr, uint32_t *timestamp)
 {
        if (!txn || !rr || !timestamp) {
                return kr_error(EINVAL);
@@ -258,7 +275,7 @@ knot_rrset_t kr_cache_materialize(const knot_rrset_t *src, uint32_t drift, mm_ct
        return copy;
 }
 
-int kr_cache_insert_rr(namedb_txn_t *txn, const knot_rrset_t *rr, uint32_t timestamp)
+int kr_cache_insert_rr(struct kr_cache_txn *txn, const knot_rrset_t *rr, uint32_t timestamp)
 {
        if (!txn || !rr) {
                return kr_error(EINVAL);
index 647169caa7416ce32953512b4aad1529ded3c993..55c2eb027d1250af9896ed5664501fae2e4fc436 100644 (file)
@@ -38,6 +38,28 @@ struct kr_cache_entry
        uint8_t  data[];
 };
 
+/**
+ * Cache structure, keeps API, instance and metadata.
+ */
+struct kr_cache
+{
+    namedb_t *db;             /**< Storage instance */
+    struct {
+        uint32_t hit;         /**< Number of cache hits */
+        uint32_t miss;        /**< Number of cache misses */
+        uint32_t insert;      /**< Number of insertions */
+        uint32_t delete;      /**< Number of deletions */
+        uint32_t txn_read;    /**< Number of read transactions */
+        uint32_t txn_write;   /**< Number of write transactions */
+    } stats;
+};
+
+/** Cache transaction */
+struct kr_cache_txn {
+    namedb_txn_t txn;        /**< Storage transaction */  
+    struct kr_cache *owner;  /**< Transaction owner */
+};
+
 /** Used storage backend for cache (default LMDB) */
 extern const namedb_api_t *(*kr_cache_storage)(void);
 
@@ -49,18 +71,19 @@ static inline void kr_cache_storage_set(const namedb_api_t *(*api)(void))
 
 /**
  * Open/create cache with provided storage options.
+ * @param cache cache structure to be initialized
  * @param storage_opts Storage-specific options (may be NULL for default)
  * @param mm Memory context.
- * @return database instance or NULL
+ * @return 0 or an error code
  */
-namedb_t *kr_cache_open(void *storage_opts, mm_ctx_t *mm);
+int kr_cache_open(struct kr_cache *cache, void *opts, mm_ctx_t *mm);
 
 /**
  * Close persistent cache.
  * @note This doesn't clear the data, just closes the connection to the database.
  * @param cache database instance
  */
-void kr_cache_close(namedb_t *cache);
+void kr_cache_close(struct kr_cache *cache);
 
 /**
  * Begin cache transaction (read-only or write).
@@ -70,20 +93,20 @@ void kr_cache_close(namedb_t *cache);
  * @param flags transaction flags (see namedb.h in libknot)
  * @return 0 or an errcode
  */
-int kr_cache_txn_begin(namedb_t *cache, namedb_txn_t *txn, unsigned flags);
+int kr_cache_txn_begin(struct kr_cache *cache, struct kr_cache_txn *txn, unsigned flags);
 
 /**
  * Commit existing transaction.
  * @param txn transaction instance
  * @return 0 or an errcode
  */
-int kr_cache_txn_commit(namedb_txn_t *txn);
+int kr_cache_txn_commit(struct kr_cache_txn *txn);
 
 /**
  * Abort existing transaction instance.
  * @param txn transaction instance
  */
-void kr_cache_txn_abort(namedb_txn_t *txn);
+void kr_cache_txn_abort(struct kr_cache_txn *txn);
 
 /**
  * Peek the cache for asset (name, type, tag)
@@ -95,7 +118,7 @@ void kr_cache_txn_abort(namedb_txn_t *txn);
  * @param timestamp current time (will be replaced with drift if successful)
  * @return cache entry or NULL
  */
-struct kr_cache_entry *kr_cache_peek(namedb_txn_t *txn, uint8_t tag, const knot_dname_t *name,
+struct kr_cache_entry *kr_cache_peek(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name,
                                      uint16_t type, uint32_t *timestamp);
 
 /**
@@ -108,7 +131,7 @@ struct kr_cache_entry *kr_cache_peek(namedb_txn_t *txn, uint8_t tag, const knot_
  * @param data inserted data
  * @return 0 or an errcode
  */
-int kr_cache_insert(namedb_txn_t *txn, uint8_t tag, const knot_dname_t *name, uint16_t type,
+int kr_cache_insert(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name, uint16_t type,
                     struct kr_cache_entry *header, namedb_val_t data);
 
 /**
@@ -119,14 +142,14 @@ int kr_cache_insert(namedb_txn_t *txn, uint8_t tag, const knot_dname_t *name, ui
  * @param type record type
  * @return 0 or an errcode
  */
-int kr_cache_remove(namedb_txn_t *txn, uint8_t tag, const knot_dname_t *name, uint16_t type);
+int kr_cache_remove(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name, uint16_t type);
 
 /**
  * Clear all items from the cache.
  * @param txn transaction instance
  * @return 0 or an errcode
  */
-int kr_cache_clear(namedb_txn_t *txn);
+int kr_cache_clear(struct kr_cache_txn *txn);
 
 /**
  * Peek the cache for given RRSet (name, type)
@@ -136,7 +159,7 @@ int kr_cache_clear(namedb_txn_t *txn);
  * @param timestamp current time (will be replaced with drift if successful)
  * @return 0 or an errcode
  */
-int kr_cache_peek_rr(namedb_txn_t *txn, knot_rrset_t *rr, uint32_t *timestamp);
+int kr_cache_peek_rr(struct kr_cache_txn *txn, knot_rrset_t *rr, uint32_t *timestamp);
 
 /**
  * Clone read-only RRSet and adjust TTLs.
@@ -154,4 +177,4 @@ knot_rrset_t kr_cache_materialize(const knot_rrset_t *src, uint32_t drift, mm_ct
  * @param timestamp current time
  * @return 0 or an errcode
  */
-int kr_cache_insert_rr(namedb_txn_t *txn, const knot_rrset_t *rr, uint32_t timestamp);
+int kr_cache_insert_rr(struct kr_cache_txn *txn, const knot_rrset_t *rr, uint32_t timestamp);
index 15891294a1c874a3e10611f8787bbb53cc8acfa1..e45ac13510e86b76122e133bbc055b55d15ea4e6 100644 (file)
@@ -54,7 +54,7 @@ static void adjust_ttl(knot_rrset_t *rr, uint32_t drift)
        }
 }
 
-static int loot_cache_pkt(namedb_txn_t *txn, knot_pkt_t *pkt, const knot_dname_t *qname,
+static int loot_cache_pkt(struct kr_cache_txn *txn, knot_pkt_t *pkt, const knot_dname_t *qname,
                           uint16_t rrtype, uint8_t tag, uint32_t timestamp)
 {
        struct kr_cache_entry *entry;
@@ -91,7 +91,7 @@ static int loot_cache_pkt(namedb_txn_t *txn, knot_pkt_t *pkt, const knot_dname_t
 }
 
 /** @internal Try to find a shortcut directly to searched packet, otherwise try to find minimised QNAME. */
-static int loot_cache(namedb_txn_t *txn, knot_pkt_t *pkt, uint8_t tag, struct kr_query *qry)
+static int loot_cache(struct kr_cache_txn *txn, knot_pkt_t *pkt, uint8_t tag, struct kr_query *qry)
 {
        uint32_t timestamp = qry->timestamp.tv_sec;
        const knot_dname_t *qname = qry->sname;
@@ -122,8 +122,8 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt)
        }
 
        /* Prepare read transaction */
-       namedb_txn_t txn;
-       struct kr_cache *cache = req->ctx->cache;
+       struct kr_cache_txn txn;
+       struct kr_cache *cache = &req->ctx->cache;
        if (kr_cache_txn_begin(cache, &txn, NAMEDB_RDONLY) != 0) {
                return ctx->state;
        }
@@ -196,8 +196,8 @@ static int stash(knot_layer_t *ctx)
        }
 
        /* Open write transaction and prepare answer */
-       namedb_txn_t txn;
-       if (kr_cache_txn_begin(req->ctx->cache, &txn, 0) != 0) {
+       struct kr_cache_txn txn;
+       if (kr_cache_txn_begin(&req->ctx->cache, &txn, 0) != 0) {
                return ctx->state; /* Couldn't acquire cache, ignore. */
        }
        const knot_dname_t *qname = knot_pkt_qname(pkt);
index 7722320bdad993dc90832cbbd7fba77f84620fe8..b907760b0615bd2343b74def60922a8939457633 100644 (file)
@@ -32,7 +32,7 @@ static int begin(knot_layer_t *ctx, void *module_param)
        return ctx->state;
 }
 
-static int loot_rr(namedb_txn_t *txn, knot_pkt_t *pkt, const knot_dname_t *name,
+static int loot_rr(struct kr_cache_txn *txn, knot_pkt_t *pkt, const knot_dname_t *name,
                   uint16_t rrclass, uint16_t rrtype, struct kr_query *qry)
 {
        /* Check if record exists in cache */
@@ -63,7 +63,7 @@ static int loot_rr(namedb_txn_t *txn, knot_pkt_t *pkt, const knot_dname_t *name,
        return kr_ok();
 }
 
-static int loot_cache_set(namedb_txn_t *txn, knot_pkt_t *pkt, const knot_dname_t *qname,
+static int loot_cache_set(struct kr_cache_txn *txn, knot_pkt_t *pkt, const knot_dname_t *qname,
                           uint16_t rrclass, uint16_t rrtype, struct kr_query *qry)
 {
        int ret = loot_rr(txn, pkt, qname, rrclass, rrtype, qry);
@@ -74,7 +74,7 @@ static int loot_cache_set(namedb_txn_t *txn, knot_pkt_t *pkt, const knot_dname_t
 }
 
 /** @internal Try to find a shortcut directly to searched record, otherwise try to find minimised QNAME. */
-static int loot_cache(namedb_txn_t *txn, knot_pkt_t *pkt, struct kr_query *qry)
+static int loot_cache(struct kr_cache_txn *txn, knot_pkt_t *pkt, struct kr_query *qry)
 {
        const knot_dname_t *qname = qry->sname;
        uint16_t rrclass = qry->sclass;
@@ -101,8 +101,8 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt)
                return ctx->state;
        }
 
-       namedb_txn_t txn;
-       struct kr_cache *cache = req->ctx->cache;
+       struct kr_cache_txn txn;
+       struct kr_cache *cache = &req->ctx->cache;
        if (kr_cache_txn_begin(cache, &txn, NAMEDB_RDONLY) != 0) {
                return ctx->state;
        }
@@ -152,7 +152,7 @@ static int merge_in_section(knot_rrset_t *cache_rr, const knot_pktsection_t *sec
 }
 
 /** Cache direct answer. */
-static int write_cache_rr(const knot_pktsection_t *section, knot_rrset_t *rr, namedb_txn_t *txn, mm_ctx_t *pool, uint32_t timestamp)
+static int write_cache_rr(const knot_pktsection_t *section, knot_rrset_t *rr, struct kr_cache_txn *txn, mm_ctx_t *pool, uint32_t timestamp)
 {
        /* Check if already cached. */
        knot_rrset_t query_rr;
@@ -192,7 +192,7 @@ static int write_cache_rr(const knot_pktsection_t *section, knot_rrset_t *rr, na
 }
 
 /** Cache direct answer. */
-static int write_cache_answer(knot_pkt_t *pkt, namedb_txn_t *txn, mm_ctx_t *pool, uint32_t timestamp)
+static int write_cache_answer(knot_pkt_t *pkt, struct kr_cache_txn *txn, mm_ctx_t *pool, uint32_t timestamp)
 {
        knot_rrset_t cache_rr;
        knot_rrset_init(&cache_rr, (knot_dname_t *)knot_pkt_qname(pkt), knot_pkt_qtype(pkt), knot_pkt_qclass(pkt));
@@ -202,7 +202,7 @@ static int write_cache_answer(knot_pkt_t *pkt, namedb_txn_t *txn, mm_ctx_t *pool
 }
 
 /** Cache stub nameservers. */
-static int write_cache_authority(knot_pkt_t *pkt, namedb_txn_t *txn, mm_ctx_t *pool, uint32_t timestamp)
+static int write_cache_authority(knot_pkt_t *pkt, struct kr_cache_txn *txn, mm_ctx_t *pool, uint32_t timestamp)
 {
        knot_rrset_t glue_rr = { NULL, 0, 0 };
        knot_rrset_t cache_rr = { NULL, 0, 0 };
@@ -252,8 +252,8 @@ static int stash(knot_layer_t *ctx, knot_pkt_t *pkt)
        /* Open write transaction */
        mm_ctx_t *pool = rplan->pool;
        uint32_t timestamp = query->timestamp.tv_sec;
-       struct kr_cache *cache = req->ctx->cache;
-       namedb_txn_t txn;
+       struct kr_cache *cache = &req->ctx->cache;
+       struct kr_cache_txn txn;
        if (kr_cache_txn_begin(cache, &txn, 0) != 0) {
                return ctx->state; /* Couldn't acquire cache, ignore. */
        }
index 9f0425381a17cb0129adeda34428f8084d56014f..ec50f7c129b96732fa1bbc899c5836156846e900 100644 (file)
@@ -290,8 +290,8 @@ int kr_resolve_query(struct kr_request *request, const knot_dname_t *qname, uint
        }
 
        /* Find closest zone cut for this query. */
-       namedb_txn_t txn;
-       if (kr_cache_txn_begin(rplan->context->cache, &txn, NAMEDB_RDONLY) != 0) {
+       struct kr_cache_txn txn;
+       if (kr_cache_txn_begin(&rplan->context->cache, &txn, NAMEDB_RDONLY) != 0) {
                kr_zonecut_set_sbelt(&qry->zone_cut);
        } else {
                kr_zonecut_find_cached(&qry->zone_cut, &txn, qry->timestamp.tv_sec);
index 70f72de6bbeeb2d1a5286be8065148df2cec93ee..1b17d8b23be972a277f78cfa92b1bdea57c31c19 100644 (file)
@@ -23,6 +23,7 @@
 #include "lib/generic/array.h"
 #include "lib/rplan.h"
 #include "lib/module.h"
+#include "lib/cache.h"
 
 /**
  * @file resolve.h
@@ -98,7 +99,7 @@ typedef array_t(struct kr_module *) module_array_t;
 struct kr_context
 {
        mm_ctx_t *pool;
-       struct kr_cache *cache;
+       struct kr_cache cache;
        module_array_t *modules;
        uint32_t options;
 };
index fef8061ee93212e6767e04e8721d93c20233394b..51ede9b151323a79dd2dac199ee0ef3cb53d57d0 100644 (file)
@@ -189,7 +189,7 @@ int kr_zonecut_set_sbelt(struct kr_zonecut *cut)
 }
 
 /** Fetch best NS for zone cut. */
-static int fetch_ns(struct kr_zonecut *cut, const knot_dname_t *name, namedb_txn_t *txn, uint32_t timestamp)
+static int fetch_ns(struct kr_zonecut *cut, const knot_dname_t *name, struct kr_cache_txn *txn, uint32_t timestamp)
 {
        uint32_t drift = timestamp;
        knot_rrset_t cached_rr;
@@ -209,7 +209,7 @@ static int fetch_ns(struct kr_zonecut *cut, const knot_dname_t *name, namedb_txn
        return kr_ok();
 }
 
-int kr_zonecut_find_cached(struct kr_zonecut *cut, namedb_txn_t *txn, uint32_t timestamp)
+int kr_zonecut_find_cached(struct kr_zonecut *cut, struct kr_cache_txn *txn, uint32_t timestamp)
 {
        if (cut == NULL) {
                return kr_error(EINVAL);
@@ -222,11 +222,11 @@ int kr_zonecut_find_cached(struct kr_zonecut *cut, namedb_txn_t *txn, uint32_t t
                        update_cut_name(cut, name);
                        return kr_ok();
                }
+               name = knot_wire_next_label(name, NULL);
                /* Subtract label from QNAME. */
                if (name[0] == '\0') {
                        break;
                }
-               name = knot_wire_next_label(name, NULL);
        }
 
        /* Name server not found, start with SBELT. */
index fd708c1b0577fa6a577a0df4233945751c12b3ac..0c4670699454c02f23aa498ca3ef2510a53492ca 100644 (file)
@@ -104,4 +104,4 @@ int kr_zonecut_set_sbelt(struct kr_zonecut *cut);
  * @param timestamp transaction timestamp
  * @return 0 or error code
  */
-int kr_zonecut_find_cached(struct kr_zonecut *cut, namedb_txn_t *txn, uint32_t timestamp);
+int kr_zonecut_find_cached(struct kr_zonecut *cut, struct kr_cache_txn *txn, uint32_t timestamp);
index a39f7a593c5c26767e6a21f3bf3f95626f67caa1..5dad0fc38c822e2904d4e5791c7169843eccbcdb 100644 (file)
@@ -283,7 +283,7 @@ Here's an example how a module can expose its property:
                namedb_t *cache = engine->resolver.cache;
 
                /* Open read transaction */
-               namedb_txn_t txn;
+               struct kr_cache_txn txn;
                int ret = kr_cache_txn_begin(cache, &txn, NAMEDB_RDONLY);
                if (ret != 0) {
                        return NULL;
index d0e438e4d0542db3147fd0da9fe30886b6719e03..39cf66110f414f699cc9a011308b43e6053d3a89 100644 (file)
@@ -53,8 +53,8 @@ static char* prune(void *env, struct kr_module *module, const char *args)
        struct engine *engine = env;
        const namedb_api_t *storage = kr_cache_storage();
 
-       namedb_txn_t txn;
-       int ret = kr_cache_txn_begin(engine->resolver.cache, &txn, 0);
+       struct kr_cache_txn txn;
+       int ret = kr_cache_txn_begin(&engine->resolver.cache, &txn, 0);
        if (ret != 0) {
                return NULL;
        }
@@ -62,7 +62,7 @@ static char* prune(void *env, struct kr_module *module, const char *args)
        /* Iterate cache and find expired records. */
        int pruned = 0;
        uint32_t now = time(NULL);
-       namedb_iter_t *it = storage->iter_begin(&txn, 0);
+       namedb_iter_t *it = storage->iter_begin((namedb_txn_t *)&txn, 0);
        while (it) {
                /* Fetch RR from cache */
                namedb_val_t key, val;
@@ -73,7 +73,7 @@ static char* prune(void *env, struct kr_module *module, const char *args)
                /* Prune expired records. */
                struct kr_cache_entry *entry = val.data;
                if (is_expired(entry, now - entry->timestamp)) {
-                       storage->del(&txn, &key);
+                       storage->del((namedb_txn_t *)&txn, &key);
                        pruned += 1;
                }
                it = storage->iter_next(it);
@@ -101,8 +101,8 @@ static char* clear(void *env, struct kr_module *module, const char *args)
 {
        struct engine *engine = env;
 
-       namedb_txn_t txn;
-       int ret = kr_cache_txn_begin(engine->resolver.cache, &txn, 0);
+       struct kr_cache_txn txn;
+       int ret = kr_cache_txn_begin(&engine->resolver.cache, &txn, 0);
        if (ret != 0) {
                return NULL;
        }
index 7e5e73cfa6daf11d3c6855557040f84db095f347..a4125d834516c0ff8f8cb60b07e7a04534a44344 100644 (file)
@@ -24,7 +24,7 @@
 #include <time.h>
 
 mm_ctx_t global_mm;
-namedb_txn_t global_txn;
+struct kr_cache_txn global_txn;
 knot_rrset_t global_rr;
 const char *global_env;
 struct kr_cache_entry global_fake_ce;
@@ -81,6 +81,42 @@ static int test_ins(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, uns
        return err;
 }
 
+/* Test cache open */
+static void test_open(void **state)
+{
+       static struct kr_cache cache;
+       struct namedb_lmdb_opts opts;
+       memset(&opts, 0, sizeof(opts));
+       opts.path = global_env;
+       opts.mapsize = CACHE_SIZE;
+       int ret = kr_cache_open(&cache, &opts, &global_mm);
+       assert_int_equal(ret, 0);
+       *state = &cache;
+}
+
+/* Test cache teardown. */
+static void test_close(void **state)
+{
+       kr_cache_close(*state);
+       *state = NULL;
+}
+
+
+/* Open transaction */
+static struct kr_cache_txn *test_txn_write(void **state)
+{
+       assert_non_null(*state);
+       assert_int_equal(kr_cache_txn_begin(*state, &global_txn, 0), KNOT_EOK);
+       return &global_txn;
+}
+
+/* Open transaction */
+static struct kr_cache_txn *test_txn_rdonly(void **state)
+{
+       assert_non_null(*state);
+       assert_int_equal(kr_cache_txn_begin(*state, &global_txn, NAMEDB_RDONLY), 0);
+       return &global_txn;
+}
 
 /* Fake api */
 static const namedb_api_t *namedb_lmdb_api_fake(void)
@@ -96,18 +132,41 @@ static const namedb_api_t *namedb_lmdb_api_fake(void)
        return &api_fake;
 }
 
+static void test_failures(void **state)
+{
+       const namedb_api_t *(*kr_cache_storage_saved)(void);
+       void *ret_cache_peek;
+       int ret_commit;
+       int ret_open;
+       knot_dname_t dname[] = "";
+
+       /* Get read transaction */
+       struct kr_cache_txn *txn = test_txn_rdonly(state);
+       /* save original api */
+       kr_cache_storage_saved = kr_cache_storage;
+       /* fake to simulate failures or constant success */
+       kr_cache_storage_set(namedb_lmdb_api_fake);
+
+       /* call kr_cache_peek() with no time constraint */
+       ret_cache_peek = kr_cache_peek(txn, KR_CACHE_USER, dname, KNOT_RRTYPE_TSIG, 0);
+       ret_open = kr_cache_open(NULL, NULL, NULL);
+       ret_commit = kr_cache_txn_commit(txn);
+
+       /* restore */
+       kr_cache_storage_set(kr_cache_storage_saved);
+       assert_int_equal(ret_cache_peek, &global_fake_ce);
+       assert_int_not_equal(ret_open, KNOT_EOK);
+       assert_int_not_equal(ret_commit, KNOT_EOK);
+}
 
 /* Test invalid parameters and some api failures. */
 static void test_invalid(void **state)
 {
-       const namedb_api_t *(*kr_cache_storage_saved)(void);
-       void *ret_open, *ret_cache_peek;
-       int ret_commit;
-       uint32_t timestamp = CACHE_TIME;
        knot_dname_t dname[] = "";
+       uint32_t timestamp = CACHE_TIME;
 
        assert_int_not_equal(kr_cache_txn_begin(NULL, &global_txn, 0), 0);
-       assert_int_not_equal(kr_cache_txn_begin(&global_env, NULL, 0), 0);
+       assert_int_not_equal(kr_cache_txn_begin(*state, NULL, 0), 0);
        assert_int_not_equal(kr_cache_txn_commit(NULL), 0);
        assert_null(kr_cache_peek(NULL, KR_CACHE_USER, dname, KNOT_RRTYPE_TSIG, &timestamp));
        assert_null(kr_cache_peek(&global_txn, 0, dname, KNOT_RRTYPE_TSIG, &timestamp));
@@ -128,57 +187,6 @@ static void test_invalid(void **state)
        assert_int_not_equal(kr_cache_remove(&global_txn, KR_CACHE_RR, NULL, 0), 0);
        assert_int_not_equal(kr_cache_remove(NULL, 0, NULL, 0), 0);
        assert_int_not_equal(kr_cache_clear(NULL), 0);
-
-       /* save original api */
-       kr_cache_storage_saved = kr_cache_storage;
-       /* fake to simulate failures or constant success */
-       kr_cache_storage_set(namedb_lmdb_api_fake);
-
-       /* call kr_cache_peek() with no time constraint */
-       ret_cache_peek = kr_cache_peek(&global_txn, KR_CACHE_USER, dname, KNOT_RRTYPE_TSIG, 0);
-       ret_open = kr_cache_open(NULL, NULL);
-       ret_commit = kr_cache_txn_commit(&global_txn);
-
-       /* restore */
-       kr_cache_storage_set(kr_cache_storage_saved);
-       assert_int_equal(ret_cache_peek, &global_fake_ce);
-       assert_null(ret_open);
-       assert_int_not_equal(ret_commit, KNOT_EOK);
-}
-
-/* Test cache open */
-static void test_open(void **state)
-{
-       struct namedb_lmdb_opts opts;
-       memset(&opts, 0, sizeof(opts));
-       opts.path = global_env;
-       opts.mapsize = CACHE_SIZE;
-       *state = kr_cache_open(&opts, &global_mm);
-       assert_non_null(*state);
-}
-
-/* Test cache teardown. */
-static void test_close(void **state)
-{
-       kr_cache_close(*state);
-       *state = NULL;
-}
-
-
-/* Open transaction */
-static namedb_txn_t *test_txn_write(void **state)
-{
-       assert_non_null(*state);
-       assert_int_equal(kr_cache_txn_begin(*state, &global_txn, 0), KNOT_EOK);
-       return &global_txn;
-}
-
-/* Open transaction */
-static namedb_txn_t *test_txn_rdonly(void **state)
-{
-       assert_non_null(*state);
-       assert_int_equal(kr_cache_txn_begin(*state, &global_txn, NAMEDB_RDONLY), 0);
-       return &global_txn;
 }
 
 /* Test cache write */
@@ -189,7 +197,7 @@ static void test_insert(void **state)
        knot_dname_t dname[] = "";
        test_random_rr(&global_rr, CACHE_TTL);
 
-       namedb_txn_t *txn = test_txn_write(state);
+       struct kr_cache_txn *txn = test_txn_write(state);
        int ret = kr_cache_insert_rr(txn, &global_rr, CACHE_TIME);
        if (ret == KNOT_EOK) {
                ret = kr_cache_txn_commit(txn);
@@ -225,7 +233,7 @@ static void test_query(void **state)
        knot_rrset_t cache_rr;
        knot_rrset_init(&cache_rr, global_rr.owner, global_rr.type, global_rr.rclass);
 
-       namedb_txn_t *txn = test_txn_rdonly(state);
+       struct kr_cache_txn *txn = test_txn_rdonly(state);
 
        for (uint32_t timestamp = CACHE_TIME; timestamp < CACHE_TIME + CACHE_TTL; ++timestamp) {
                uint32_t drift = timestamp;
@@ -245,7 +253,7 @@ static void test_query_aged(void **state)
        knot_rrset_t cache_rr;
        knot_rrset_init(&cache_rr, global_rr.owner, global_rr.type, global_rr.rclass);
 
-       namedb_txn_t *txn = test_txn_rdonly(state);
+       struct kr_cache_txn *txn = test_txn_rdonly(state);
        int ret = kr_cache_peek_rr(txn, &cache_rr, &timestamp);
        assert_int_equal(ret, KNOT_ENOENT);
        kr_cache_txn_abort(txn);
@@ -258,7 +266,7 @@ static void test_remove(void **state)
        knot_rrset_t cache_rr;
        knot_rrset_init(&cache_rr, global_rr.owner, global_rr.type, global_rr.rclass);
 
-       namedb_txn_t *txn = test_txn_write(state);
+       struct kr_cache_txn *txn = test_txn_write(state);
        int ret = kr_cache_remove(txn, KR_CACHE_RR, cache_rr.owner, cache_rr.type);
        assert_int_equal(ret, KNOT_EOK);
        ret = kr_cache_peek_rr(txn, &cache_rr, &timestamp);
@@ -269,7 +277,7 @@ static void test_remove(void **state)
 /* Test cache fill */
 static void test_fill(void **state)
 {
-       namedb_txn_t *txn = test_txn_write(state);
+       struct kr_cache_txn *txn = test_txn_write(state);
 
        /* Fill with random values. */
        int ret = KNOT_EOK;
@@ -301,7 +309,7 @@ static void test_fill(void **state)
 /* Test cache clear */
 static void test_clear(void **state)
 {
-       namedb_txn_t *txn = test_txn_write(state);
+       struct kr_cache_txn *txn = test_txn_write(state);
        int preempt_ret = kr_cache_clear(txn);
        int commit_ret = kr_cache_txn_commit(txn);
        assert_int_equal(preempt_ret, KNOT_EOK);
@@ -314,9 +322,15 @@ int main(void)
        test_mm_ctx_init(&global_mm);
        global_env = test_tmpdir_create();
 
-       const UnitTest tests[] = {
-               /* Invalid input */
+       /* Invalid input */
+       const UnitTest tests_bad[] = {
+               group_test_setup(test_open),
                unit_test(test_invalid),
+               unit_test(test_failures),
+               group_test_teardown(test_close)
+       };
+
+       const UnitTest tests[] = {
                /* Cache persistence */
                group_test_setup(test_open),
                unit_test(test_insert),
@@ -331,10 +345,12 @@ int main(void)
                group_test_teardown(test_close)
        };
 
-       int ret = run_group_tests(tests);
+       int ret = run_group_tests(tests_bad);
+       if (ret == 0) {
+               ret = run_group_tests(tests);
+       }
 
        /* Cleanup */
        test_tmpdir_remove(global_env);
-
        return ret;
 }
index 2d65d720a7be39aa8c715cfa026994ef32268a5f..357129c8e501bfbafd53e8bcee95906d2e33eb75 100644 (file)
@@ -72,8 +72,8 @@ static PyObject* init(PyObject* self, PyObject* args)
        opts.path = global_tmpdir;
        opts.mapsize = 100 * 4096;
        kr_cache_storage_set(namedb_lmdb_api);
-       global_context.cache = kr_cache_open(&opts, &global_mm);
-       assert(global_context.cache);
+       int ret = kr_cache_open(&global_context.cache, &opts, &global_mm);
+       assert(ret == 0);
 
        /* No configuration parsing support yet. */
        if (strstr(config, "query-minimization: on") == NULL) {