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)
{
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);
}
#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"
* 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 */
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)
kr_module_unload(&engine->modules.at[i]);
}
array_clear(engine->modules);
+ array_clear(engine->storage_registry);
if (engine->L) {
lua_close(engine->L);
#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;
};