Commit bc0a5dbc authored by Anbang Wen's avatar Anbang Wen Committed by Anbang Wen

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.
parent febd08ce
......@@ -920,18 +920,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))) {
......@@ -939,7 +930,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;
}
......@@ -974,7 +965,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)
......@@ -1024,7 +1014,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);
......@@ -1051,28 +1041,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);
......@@ -1083,7 +1064,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. */
......@@ -1103,9 +1084,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);
......
......@@ -1194,6 +1194,75 @@ static uint8_t get_lowest_rank(const struct kr_request *req, const struct kr_que
return KR_RANK_INITIAL | KR_RANK_AUTH;
}
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();
}
......@@ -137,3 +137,34 @@ int kr_cache_materialize(knot_rdataset_t *dst, const struct kr_cache_p *ref,
uint32_t new_ttl, 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);
......@@ -572,12 +572,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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment