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))) {
}
/* 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;
}
}
return ret;
}
-#endif
/** Prune expired/invalid records. */
static int cache_prune(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);
/** @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);
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. */
}
/* 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);
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();
+}
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);
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) {