From: Anbang Wen Date: Sun, 13 May 2018 21:55:24 +0000 (-0700) Subject: cache: restore kr_cache_match and kr_cache_remove X-Git-Tag: v3.0.0~1^2~24 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f5b29467ef23800d3f063bd56d5c357eb4ff888a;p=thirdparty%2Fknot-resolver.git cache: restore kr_cache_match and kr_cache_remove 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. --- diff --git a/daemon/bindings.c b/daemon/bindings.c index 5922c519e..95823d210 100644 --- a/daemon/bindings.c +++ b/daemon/bindings.c @@ -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); diff --git a/lib/cache/api.c b/lib/cache/api.c index e08f7e29e..2ed8290aa 100644 --- a/lib/cache/api.c +++ b/lib/cache/api.c @@ -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(); +} diff --git a/lib/cache/api.h b/lib/cache/api.h index ed73eb7c3..9404fabd5 100644 --- a/lib/cache/api.h +++ b/lib/cache/api.h @@ -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); diff --git a/lib/cache/cdb_lmdb.c b/lib/cache/cdb_lmdb.c index 71d6adc00..2b07f9a1b 100644 --- a/lib/cache/cdb_lmdb.c +++ b/lib/cache/cdb_lmdb.c @@ -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) {