]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/engine: support for Lua modules, stub etcd module
authorMarek Vavruša <marek.vavrusa@nic.cz>
Wed, 6 May 2015 08:28:21 +0000 (10:28 +0200)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Wed, 6 May 2015 08:28:21 +0000 (10:28 +0200)
daemon/engine.c
modules/ketcd/README.rst [new file with mode: 0644]
modules/ketcd/ketcd.lua [new file with mode: 0644]
modules/ketcd/ketcd.mk [new file with mode: 0644]
modules/modules.mk

index a5eb274eef94149b34b607071dcd5d3873e23b93..8507b0849fa8896e86fa4015c48f0b8ad44fcaba 100644 (file)
@@ -95,6 +95,59 @@ static int l_trampoline(lua_State *L)
        return 0;
 }
 
+/** @internal Helper for retrieving the right function entrypoint. */
+static inline lua_State *l_ffi_preface(struct kr_module *module, const char *call) {
+       lua_State *L = module->lib;
+       lua_rawgeti(L, LUA_REGISTRYINDEX, (intptr_t)module->data);
+       lua_getfield(L, -1, call);
+       lua_pushlightuserdata(L, module);
+       return L;
+}
+
+/** @internal Helper for calling the entrypoint. */
+static inline int l_ffi_call(lua_State *L) {
+       if (engine_pcall(L, 1) != 0) {
+               lua_pop(L, 1);
+               return kr_error(EIO);
+       }
+       return lua_tonumber(L, 1);
+}
+
+static int l_ffi_init(struct kr_module *module)
+{
+       lua_State *L = l_ffi_preface(module, "init");
+       return l_ffi_call(L);
+}
+
+static int l_ffi_config(struct kr_module *module, const char *conf)
+{
+       lua_State *L = l_ffi_preface(module, "config");
+       lua_pushstring(L, conf);
+       return l_ffi_call(L);
+}
+
+static int l_ffi_deinit(struct kr_module *module)
+{
+       lua_State *L = l_ffi_preface(module, "deinit");
+       int ret = l_ffi_call(L);
+       /* Unref module and unset 'lib', so the module
+        * interface doesn't attempt to close it.
+        */
+       luaL_unref(L, LUA_REGISTRYINDEX, (intptr_t)module->data);
+       module->lib = NULL;
+       return ret;
+}
+
+static const knot_layer_api_t* l_ffi_layer(struct kr_module *module)
+{
+       /* lua_State *L = l_ffi_preface(module, "layer"); */
+       /** @todo Pickle access to context somewhere  */
+       /** @todo Store the returned table in the registry */
+       /** @todo Keep the reference in the api_t */
+       /** @todo Make trampoline functions for layer operations. */
+       return NULL;
+}
+
 /*
  * Engine API.
  */
@@ -284,6 +337,41 @@ void engine_stop(struct engine *engine)
        uv_stop(uv_default_loop());
 }
 
+/** @internal Helper macro for function presence check. */
+#define REGISTER_FFI_CALL(L, attr, name, cb) do { \
+       lua_getfield((L), -1, (name)); \
+       if (!lua_isnil((L), -1)) { attr = cb; } \
+       lua_pop((L), 1); \
+       } while (0)
+
+/** Register Lua module as a FFI module */
+static int register_lua_module(struct engine *engine, struct kr_module *module, const char *name)
+{
+       /* Register module in Lua */
+       lua_State *L = engine->L;
+       lua_getglobal(L, "require");
+       lua_pushstring(L, name);
+       if (engine_pcall(L, 1) != 0) {
+               lua_pop(L, 1);
+               return kr_error(ENOENT);
+       }
+       lua_setglobal(L, name);
+       lua_getglobal(L, name);
+
+       /* Create FFI module with trampolined functions. */
+       memset(module, 0, sizeof(*module));
+       module->name = strdup(name);
+       REGISTER_FFI_CALL(L, module->init,   "init",   &l_ffi_init);
+       REGISTER_FFI_CALL(L, module->deinit, "deinit", &l_ffi_deinit);
+       REGISTER_FFI_CALL(L, module->config, "config", &l_ffi_config);
+       REGISTER_FFI_CALL(L, module->layer,  "layer",  &l_ffi_layer);
+       module->lib = L;
+       module->data = (void *)(intptr_t)luaL_ref(L, LUA_REGISTRYINDEX);
+       return module->init(module);
+}
+
+#undef REGISTER_FFI_CALL
+
 /** Register module properties in Lua environment */
 static int register_properties(struct engine *engine, struct kr_module *module)
 {
@@ -316,12 +404,15 @@ int engine_register(struct engine *engine, const char *name)
 
        /* Make sure module is unloaded */
        (void) engine_unregister(engine, name);
-
-       /* Load module */
+       /* Attempt to load binary module */
        size_t next = engine->modules.len;
        array_reserve(engine->modules, next + 1);
        struct kr_module *module = &engine->modules.at[next];
        int ret = kr_module_load(module, name, NULL);
+       /* Load Lua module if not a binary */
+       if (ret == kr_error(ENOENT)) {
+               ret = register_lua_module(engine, module, name);
+       }
        if (ret != 0) {
                return ret;
        } else {
diff --git a/modules/ketcd/README.rst b/modules/ketcd/README.rst
new file mode 100644 (file)
index 0000000..7a48127
--- /dev/null
@@ -0,0 +1,14 @@
+.. _mod-etcd:
+
+Etcd module
+-----------
+
+.. warning:: Work in progress!
+
+Dependencies
+^^^^^^^^^^^^
+
+* `lua-etcd <https://github.com/mah0x211/lua-etcd>`_ available in LuaRocks
+
+    $ luarocks install etcd --from=http://mah0x211.github.io/rocks/
+
diff --git a/modules/ketcd/ketcd.lua b/modules/ketcd/ketcd.lua
new file mode 100644 (file)
index 0000000..d4ee505
--- /dev/null
@@ -0,0 +1,24 @@
+--- @module ketcd
+local ketcd = {}
+local Etcd = require('etcd.luasocket')
+
+function ketcd.init(module)
+       print('wip')
+end
+
+function ketcd.deinit(module)
+       print('wip')
+end
+
+function ketcd.config(module, conf)
+       local cli, err = Etcd.new({
+               peer = conf,
+       });     
+       ketcd._cli = cli
+end
+
+function ketcd.layers(module)
+       return {}
+end
+
+return ketcd
diff --git a/modules/ketcd/ketcd.mk b/modules/ketcd/ketcd.mk
new file mode 100644 (file)
index 0000000..3c45daf
--- /dev/null
@@ -0,0 +1 @@
+$(call make_lua_module,ketcd)
index 2f5ea327d01fb487b8e9e7cb0aa8248865945473..26b8eb977d6d4331bc06337cde3c3ff7ce5925d7 100644 (file)
@@ -2,6 +2,11 @@
 modules_TARGETS := hints \
                    cachectl
 
+# List of Lua modules
+ifeq ($(HAS_lua),yes)
+modules_TARGETS += ketcd 
+endif
+
 # List of Golang modules
 ifeq ($(HAS_gccgo),yes)
 modules_TARGETS += gostats
@@ -12,6 +17,20 @@ define make_c_module
 $(eval $(call make_module,$(1),modules/$(1)))
 endef
 
+# Make Lua module
+define make_lua_module
+$(eval $(call lua_target,$(1),modules/$(1)))
+endef
+
+# Lua target definition
+define lua_target
+$(1) := $(2)/$(1).lua
+$(1)-install: $(2)/$(1).lua
+       $(INSTALL) -d $(PREFIX)/$(MODULEDIR)
+       $(INSTALL) $$^ $(PREFIX)/$(MODULEDIR)
+.PHONY: $(1) $(1)-install
+endef
+
 # Make Go module
 define make_go_module
 $(eval $(call go_target,$(1),modules/$(1)))