diff --git a/daemon/bindings.c b/daemon/bindings.c index 6b6c7ccfcc8d5a9fd282983ddeb955be288eac32..cff98a205ab664190c4d85798c80ebca99e738c3 100644 --- a/daemon/bindings.c +++ b/daemon/bindings.c @@ -304,6 +304,26 @@ static int cache_count(lua_State *L) return 1; } +static struct storage_api *cache_select_storage(struct engine *engine, const char **conf) +{ + /* Return default backend */ + storage_registry_t *registry = &engine->storage_registry; + if (!*conf || !strstr(*conf, "://")) { + return ®istry->at[0]; + } + + /* Find storage backend from config prefix */ + for (unsigned i = 0; i < registry->len; ++i) { + struct storage_api *storage = ®istry->at[i]; + if (strncmp(*conf, storage->prefix, strlen(storage->prefix)) == 0) { + *conf += strlen(storage->prefix); + return storage; + } + } + + return NULL; +} + /** Open cache */ static int cache_open(lua_State *L) { @@ -314,16 +334,26 @@ static int cache_open(lua_State *L) lua_error(L); } - /* Close if already open */ + /* Select cache storage backend */ struct engine *engine = engine_luaget(L); + const char *conf = n > 1 ? lua_tostring(L, 2) : NULL; + struct storage_api *storage = cache_select_storage(engine, &conf); + if (!storage) { + format_error(L, "unsupported cache backend"); + lua_error(L); + } + kr_cache_storage_set(storage->api); + + /* Close if already open */ if (engine->resolver.cache != NULL) { kr_cache_close(engine->resolver.cache); } - - /* Open resolution context cache */ - engine->resolver.cache = kr_cache_open(".", engine->pool, lua_tointeger(L, 1)); + /* Reopen cache */ + void *storage_opts = storage->opts_create(conf, lua_tointeger(L, 1)); + engine->resolver.cache = kr_cache_open(storage_opts, engine->pool); + free(storage_opts); if (engine->resolver.cache == NULL) { - format_error(L, "can't open cache in rundir"); + format_error(L, "can't open cache"); lua_error(L); } diff --git a/daemon/engine.c b/daemon/engine.c index f902354005efd891329335cd9de03a48f3fd2425..d6b562780fe45a8c5de51b5ab8bb587b06cce6cd 100644 --- a/daemon/engine.c +++ b/daemon/engine.c @@ -17,6 +17,8 @@ #include <uv.h> #include <unistd.h> #include <libknot/internal/mempattern.h> +/* #include <libknot/internal/namedb/namedb_trie.h> @todo Not supported (doesn't keep value copy) */ +#include <libknot/internal/namedb/namedb_lmdb.h> #include "daemon/engine.h" #include "daemon/bindings.h" @@ -97,6 +99,18 @@ static int l_trampoline(lua_State *L) * Engine API. */ +/** @internal Make lmdb options. */ +void *namedb_lmdb_mkopts(const char *conf, size_t maxsize) +{ + struct namedb_lmdb_opts *opts = malloc(sizeof(*opts)); + if (opts) { + memset(opts, 0, sizeof(*opts)); + opts->path = conf ? conf : "."; + opts->mapsize = maxsize; + } + return opts; +} + static int init_resolver(struct engine *engine) { /* Open resolution context */ @@ -106,7 +120,12 @@ static int init_resolver(struct engine *engine) engine_register(engine, "iterate"); engine_register(engine, "itercache"); - return kr_ok(); + /* Initialize storage backends */ + struct storage_api lmdb = { + "lmdb://", namedb_lmdb_api, namedb_lmdb_mkopts + }; + + return array_push(engine->storage_registry, lmdb); } static int init_state(struct engine *engine) @@ -168,6 +187,7 @@ void engine_deinit(struct engine *engine) kr_module_unload(&engine->modules.at[i]); } array_clear(engine->modules); + array_clear(engine->storage_registry); if (engine->L) { lua_close(engine->L); diff --git a/daemon/engine.h b/daemon/engine.h index 3918ee4b3ee127b4c46d9159ee4db1c7b2902c19..063bdff9ebbb7a2215ba5123e0a4e2528d53cf33 100644 --- a/daemon/engine.h +++ b/daemon/engine.h @@ -24,10 +24,21 @@ struct lua_State; #include "lib/resolve.h" #include "daemon/network.h" +/** Cache storage backend. */ +struct storage_api { + const char *prefix; /**< Storage prefix, e.g. 'lmdb://' */ + const namedb_api_t *(*api)(void); /**< Storage API implementation */ + void *(*opts_create)(const char *, size_t); /**< Storage options factory */ +}; + +/** @internal Array of cache backend options. */ +typedef array_t(struct storage_api) storage_registry_t; + struct engine { struct kr_context resolver; struct network net; module_array_t modules; + storage_registry_t storage_registry; mm_ctx_t *pool; struct lua_State *L; };