]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
cache: restore kr_cache_match and kr_cache_remove
authorAnbang Wen <xofyarg@gmail.com>
Sun, 13 May 2018 21:55:24 +0000 (14:55 -0700)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Fri, 17 Aug 2018 13:58:44 +0000 (15:58 +0200)
1. Restore two cache op which got dropped in 2.0;
2. Add kr_unpack_cache_key to parse cache key;
3. Fix the lua binding for cache.get and cache.clear.

daemon/bindings.c
lib/cache/api.c
lib/cache/api.h
lib/cache/cdb_lmdb.c

index 5922c519e17fa6a7b759e261d75f6aaae169d140..95823d210f2e01adc590e3420d8ec39d8d40b321 100644 (file)
@@ -1075,18 +1075,9 @@ static int cache_close(lua_State *L)
        return 1;
 }
 
-#if 0
 /** @internal Prefix walk. */
 static int cache_prefixed(struct kr_cache *cache, const char *args, knot_db_val_t *results, int maxresults)
 {
-       /* Decode parameters */
-       uint8_t namespace = 'R';
-       char *extra = strchr(args, ' ');
-       if (extra != NULL) {
-               extra[0] = '\0';
-               namespace = extra[1];
-       }
-
        /* Convert to domain name */
        uint8_t buf[KNOT_DNAME_MAXLEN];
        if (!knot_dname_from_str(buf, args, sizeof(buf))) {
@@ -1094,7 +1085,7 @@ static int cache_prefixed(struct kr_cache *cache, const char *args, knot_db_val_
        }
 
        /* Start prefix search */
-       int ret = kr_cache_match(cache, namespace, buf, results, maxresults);
+       int ret = kr_cache_match(cache, buf, results, maxresults);
        kr_cache_sync(cache);
        return ret;
 }
@@ -1129,7 +1120,6 @@ static int cache_remove_prefix(struct kr_cache *cache, const char *args)
        }
        return ret;
 }
-#endif
 
 /** Prune expired/invalid records. */
 static int cache_prune(lua_State *L)
@@ -1170,7 +1160,7 @@ static int cache_clear(lua_State *L)
 
        /* Clear a sub-tree in cache. */
        if (args && strlen(args) > 0) {
-               int ret = kr_error(ENOSYS); // FIXME cache_remove_prefix(cache, args);
+               int ret = cache_remove_prefix(cache, args);
                if (ret < 0) {
                        format_error(L, kr_strerror(ret));
                        lua_error(L);
@@ -1198,28 +1188,19 @@ static int cache_clear(lua_State *L)
 /** @internal Dump cache key into table on Lua stack. */
 static void cache_dump_key(lua_State *L, knot_db_val_t *key)
 {
-       char buf[KNOT_DNAME_MAXLEN];
-       /* Extract type */
-       uint16_t type = 0;
-       const char *endp = (const char *)key->data + key->len - sizeof(uint16_t);
-       memcpy(&type, endp, sizeof(uint16_t));
-       endp -= 1;
-       /* Extract domain name */
-       char *dst = buf;
-       const char *scan = endp - 1;
-       while (scan > (const char *)key->data) {
-               if (*scan == '\0') {
-                       const size_t lblen = endp - scan - 1;
-                       memcpy(dst, scan + 1, lblen);
-                       dst += lblen;
-                       *dst++ = '.';
-                       endp = scan;
-               }
-               --scan;
+       knot_dname_t dname[KNOT_DNAME_MAXLEN];
+       char name[KNOT_DNAME_MAXLEN];
+       uint16_t type;
+
+       int ret = kr_unpack_cache_key(key, dname, &type);
+       if (ret < 0) {
+               return;
        }
-       memcpy(dst, scan + 1, endp - scan);
+
+       knot_dname_to_str(name, dname, sizeof(dname));
+
        /* If name typemap doesn't exist yet, create it */
-       lua_getfield(L, -1, buf);
+       lua_getfield(L, -1, name);
        if (lua_isnil(L, -1)) {
                lua_pop(L, 1);
                lua_newtable(L);
@@ -1230,7 +1211,7 @@ static void cache_dump_key(lua_State *L, knot_db_val_t *key)
        lua_pushboolean(L, true);
        lua_setfield(L, -2, type_buf);
        /* Set name typemap */
-       lua_setfield(L, -2, buf);
+       lua_setfield(L, -2, name);
 }
 
 /** Query cached records. */
@@ -1246,9 +1227,9 @@ static int cache_get(lua_State *L)
        }
 
        /* Retrieve set of keys */
-       //const char *args = lua_tostring(L, 1);
+       const char *args = lua_tostring(L, 1);
        static knot_db_val_t result_set[100];
-       int ret = kr_error(ENOSYS); // FIXME cache_prefixed(cache, args, result_set, 100);
+       int ret = cache_prefixed(cache, args, result_set, 100);
        if (ret < 0) {
                format_error(L, kr_strerror(ret));
                lua_error(L);
index e08f7e29ee9135a13a219e4c675874efa8bf5117..2ed8290aa741143cb99488e90786ca2743b594cb 100644 (file)
@@ -762,3 +762,72 @@ int kr_cache_peek_exact(struct kr_cache *cache, const knot_dname_t *name, uint16
        return ret;
 }
 
+int kr_cache_remove(struct kr_cache *cache, const knot_dname_t *name,
+                   uint16_t type)
+{
+       if (!cache_isvalid(cache)) {
+               return kr_error(EINVAL);
+       }
+       if (!cache->api->remove) {
+               return kr_error(ENOSYS);
+       }
+       struct key k_storage, *k = &k_storage;
+       int ret = kr_dname_lf(k->buf, name, false);
+       if (ret) return kr_error(ret);
+
+       knot_db_val_t key = key_exact_type(k, type);
+       return cache_op(cache, remove, &key, 1);
+}
+
+int kr_cache_match(struct kr_cache *cache, const knot_dname_t *name,
+                  knot_db_val_t *keys, int max)
+{
+       if (!cache_isvalid(cache)) {
+               return kr_error(EINVAL);
+       }
+       if (!cache->api->match) {
+               return kr_error(ENOSYS);
+       }
+
+       struct key k_storage, *k = &k_storage;
+
+       int ret = kr_dname_lf(k->buf, name, false);
+       if (ret) return kr_error(ret);
+
+       // use a mock type
+       knot_db_val_t key = key_exact_type(k, KNOT_RRTYPE_A);
+       key.len -= sizeof((char)('E')) + sizeof(uint16_t);
+       return cache_op(cache, match, &key, keys, max);
+}
+
+int kr_unpack_cache_key(knot_db_val_t *key, knot_dname_t *buf, uint16_t *type)
+{
+       if (key == NULL || buf == NULL) {
+               return kr_error(EINVAL);
+       }
+
+       int len = -1;
+       const void *endp;
+       for (endp = key->data + 1;
+            endp < key->data + key->len; endp++) {
+               if (*(const char *)(endp-1) == '\0' &&
+                   (*(const char *)endp == 'E')) {
+                       len = endp - key->data - 1;
+                       break;
+               }
+       }
+
+       if (len == -1 || len > KNOT_DNAME_MAXLEN) {
+               return kr_error(EINVAL);
+       }
+
+       int ret = knot_dname_lf2wire(buf, len, key->data);
+       if (ret < 0) {
+               return kr_error(ret);
+       }
+
+       // jump over "\0 E/1"
+       memcpy(type, key->data + len + 2, sizeof(uint16_t));
+
+       return kr_ok();
+}
index ed73eb7c3643e6c716d62f2805353b666b708f09..9404fabd5ef8a1e82048e303a1479ebf30bc1461 100644 (file)
@@ -137,3 +137,34 @@ int kr_cache_materialize(knot_rdataset_t *dst, const struct kr_cache_p *ref,
                         knot_mm_t *pool);
 
 
+/**
+ * Remove an entry from cache.
+ * @param cache cache structure
+ * @param name dname
+ * @param type rr type
+ * @return 0 or an errcode
+ */
+KR_EXPORT
+int kr_cache_remove(struct kr_cache *cache, const knot_dname_t *name,
+                   uint16_t type);
+
+/**
+ * Get keys matching a dname lf prefix
+ * @param cache cache structure
+ * @param name dname
+ * @param keys matched keys
+ * @return result count or an errcode
+ */
+KR_EXPORT
+int kr_cache_match(struct kr_cache *cache, const knot_dname_t *name,
+                  knot_db_val_t *keys, int max);
+
+/**
+ * Unpack dname and type from db key
+ * @param key db key representation
+ * @param buf output buffer of domain name in dname format
+ * @param type output for type
+ * @return length of dname or an errcode
+ */
+KR_EXPORT
+int kr_unpack_cache_key(knot_db_val_t *key, knot_dname_t *buf, uint16_t *type);
index 71d6adc00abba6f3049a90d302501637061145e0..2b07f9a1b8f6cf5f4f15eee1178c819378f2eaca 100644 (file)
@@ -571,12 +571,6 @@ static int cdb_match(knot_db_t *db, knot_db_val_t *key, knot_db_val_t *val, int
                return ret;
        }
 
-       /* Turn wildcard into prefix scan. */
-       const uint8_t *endp = (const uint8_t *)key->data + (key->len - 2);
-       if (key->len > 2 && endp[0] == '*' && endp[1] == '\0') {
-               key->len -= 2; /* Skip '*' label */
-       }
-
        MDB_cursor *cur = NULL;
        ret = mdb_cursor_open(txn, env->dbi, &cur);
        if (ret != 0) {