Skip to content
This repository has been archived by the owner on Jun 27, 2019. It is now read-only.

Commit

Permalink
flow: Add helper to get node types from modules
Browse files Browse the repository at this point in the history
Add the macro sol_flow_get_node_type() (and the underlying helper
function) to get node types from modules regardless of whether they are
built-in or not, or even if modules support is disabled.

Signed-off-by: Iván Briano <ivan.briano@intel.com>
  • Loading branch information
ibriano committed Sep 28, 2015
1 parent 0fb36da commit 45548bc
Show file tree
Hide file tree
Showing 9 changed files with 399 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/lib/common/sol-common-buildopts.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ st.on_value("PLATFORM_CONTIKI", "y", "#define SOL_PLATFORM_CONTIKI 1", "")
st.on_value("LOG", "y", "#define SOL_LOG_ENABLED 1", "")
}}

{{
st.on_value("MODULES", "y", "#define SOL_DYNAMIC_MODULES 1", "")
}}

#ifdef SOL_PLATFORM_LINUX
#define SOL_MAINLOOP_FD_ENABLED 1
#define SOL_MAINLOOP_FORK_WATCH_ENABLED 1
Expand Down
2 changes: 2 additions & 0 deletions src/lib/common/sol-mainloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

#include "sol-mainloop-impl.h"
#include "sol-macros.h"
#include "sol-modules.h"
#include "sol-util.h"

#include "sol-platform.h"
Expand Down Expand Up @@ -223,6 +224,7 @@ sol_shutdown(void)
sol_pin_mux_shutdown();
sol_platform_shutdown();
sol_mainloop_impl_shutdown();
sol_modules_clear_cache();
sol_log_shutdown();
}

Expand Down
1 change: 1 addition & 0 deletions src/lib/flow/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ obj-flow-$(NODE_DESCRIPTION) += \
sol-flow-builder.o

obj-flow-$(ENABLE_DYNAMIC_MODULES) += \
sol-flow-modules.o \
sol-flow-parser-dynamic.o

ifeq (y,$(RESOLVER_CONFFILE))
Expand Down
21 changes: 21 additions & 0 deletions src/lib/flow/include/sol-flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,27 @@ struct sol_flow_port_type_in {
int (*disconnect)(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id); /**< member function issued everytime a connection is unmade on the port */
};

#ifdef SOL_DYNAMIC_MODULES

/**
* Gets the specified node type, loading the necessary module if required.
*
* Checks if the node type @a _type is built-in, if not, it loads the module
* @a _mod and fetches the type's symbol there. The result is stored in @a _var.
*
* @param _mod The name of the module to load if the symbol is not built-in.
* @param _type The node type's symbol.
* @param _var Variable where to store the type.
*
* @return 0 on success, < 0 on error.
*/
#define sol_flow_get_node_type(_mod, _type, _var) sol_flow_internal_get_node_type(_mod, #_type, _var)

int sol_flow_internal_get_node_type(const char *module, const char *symbol, const struct sol_flow_node_type **type);
#else
#define sol_flow_get_node_type(_mod, _type, _var) ({ (*(_var)) = _type; 0; })
#endif /* SOL_DYNAMIC_MODULES */

/**
* @}
*/
Expand Down
2 changes: 2 additions & 0 deletions src/lib/flow/sol-flow-buildopts.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

#pragma once

#include "sol-common-buildopts.h"

{{
st.on_value("NODE_DESCRIPTION", "y", "#define SOL_FLOW_NODE_TYPE_DESCRIPTION_ENABLED 1", "")
st.on_value("INSPECTOR", "y", "#define SOL_FLOW_INSPECTOR_ENABLED 1", "")
Expand Down
49 changes: 49 additions & 0 deletions src/lib/flow/sol-flow-modules.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* This file is part of the Soletta Project
*
* Copyright (C) 2015 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <errno.h>

#include "sol-flow-internal.h"
#include "sol-modules.h"

SOL_API int
sol_flow_internal_get_node_type(const char *modname, const char *symbol, const struct sol_flow_node_type **type)
{
const struct sol_flow_node_type **ret;

ret = sol_modules_get_symbol("flow", modname, symbol);
if (!ret || !*ret)
return -errno;

*type = *ret;
return 0;
}
1 change: 1 addition & 0 deletions src/shared/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
obj-y += libshared.mod

obj-libshared-y := \
sol-modules.o \
sol-monitors.o \
sol-util.o \
sol-random.o
Expand Down
255 changes: 255 additions & 0 deletions src/shared/sol-modules.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
/*
* This file is part of the Soletta Project
*
* Copyright (C) 2015 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <dlfcn.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

#include "sol-log-internal.h"

#include "sol-modules.h"
#include "sol-util.h"
#include "sol-vector.h"

#ifdef MODULES

SOL_LOG_INTERNAL_DECLARE(_sol_modules_log_domain, "modules");

struct nspace_cache {
char *name;
struct sol_vector modules;
};

struct module_cache {
char *name;
void *handle;
};

static struct sol_vector namespaces = SOL_VECTOR_INIT(struct nspace_cache);

static void
clear_modules_cache(struct sol_vector *cache)
{
struct module_cache *mod;
uint16_t i;

SOL_VECTOR_FOREACH_IDX (cache, mod, i) {
dlclose(mod->handle);
free(mod->name);
}
sol_vector_clear(cache);
}

static void
clear_namespace_cache(struct sol_vector *cache)
{
struct nspace_cache *ns;
uint16_t i;

SOL_VECTOR_FOREACH_IDX (cache, ns, i) {
clear_modules_cache(&ns->modules);
free(ns->name);
}
sol_vector_clear(cache);
}

static int
get_symbol(void *handle, const char *symbol_name, void **symbol)
{
*symbol = dlsym(handle, symbol_name);
if (!*symbol)
return -ENOENT;

return 0;
}

static int
get_internal_symbol(const char *symbol_name, void **symbol)
{
int ret;

if ((ret = get_symbol(RTLD_DEFAULT, symbol_name, symbol)) < 0) {
SOL_DBG("Symbol '%s' is not built-in: %s", symbol_name, dlerror());
return ret;
}

SOL_INF("Symbol '%s' found built-in", symbol_name);

return 0;
}

static struct nspace_cache *
get_namespace(const char *nspace)
{
struct nspace_cache *ns;
uint16_t i;

SOL_VECTOR_FOREACH_IDX (&namespaces, ns, i) {
if (streq(ns->name, nspace))
return ns;
}

ns = sol_vector_append(&namespaces);
SOL_NULL_CHECK(ns, NULL);

ns->name = strdup(nspace);
SOL_NULL_CHECK_GOTO(ns->name, strdup_error);

sol_vector_init(&ns->modules, sizeof(struct module_cache));

return ns;

strdup_error:
free(ns);
return NULL;
}

static int
get_module_path(char *buf, size_t len, const char *nspace, const char *modname)
{
static char rootdir[PATH_MAX] = { };

if (unlikely(!*rootdir)) {
int ret;

ret = sol_util_get_rootdir(rootdir, sizeof(rootdir));
SOL_INT_CHECK(ret, >= (int)sizeof(rootdir), ret);
SOL_INT_CHECK(ret, < 0, ret);
}

return snprintf(buf, len, "%s%s%s/%s.so", rootdir, MODULESDIR, nspace, modname);
}

static void *
get_module_handle(const char *nspace, const char *modname)
{
char path[PATH_MAX];
void *handle;
int ret;

ret = get_module_path(path, sizeof(path), nspace, modname);
SOL_INT_CHECK(ret, >= (int)sizeof(path), NULL);
SOL_INT_CHECK(ret, < 0, NULL);

SOL_INF("Loading module '%s'", path);

handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE);
if (!handle)
SOL_WRN("Could not open module '%s/%s' (%s): %s", nspace, modname, path, dlerror());
return handle;
}

static struct module_cache *
get_module(struct nspace_cache *ns, const char *module)
{
struct module_cache *mod;
uint16_t i;

SOL_VECTOR_FOREACH_IDX (&ns->modules, mod, i) {
if (streq(mod->name, module)) {
SOL_INF("Module '%s/%s' found cached", ns->name, module);
return mod;
}
}

mod = sol_vector_append(&ns->modules);
SOL_NULL_CHECK(mod, NULL);

mod->name = strdup(module);
SOL_NULL_CHECK_GOTO(mod->name, strdup_error);

mod->handle = get_module_handle(ns->name, mod->name);
SOL_NULL_CHECK_GOTO(mod->handle, dlopen_error);

return mod;

dlopen_error:
free(mod->name);
strdup_error:
sol_vector_del(&ns->modules, ns->modules.len - 1);
return NULL;
}

static int
get_module_symbol(const char *nspace, const char *modname, const char *symbol_name, void **symbol)
{
struct nspace_cache *ns;
struct module_cache *mod;
int ret;

ns = get_namespace(nspace);
SOL_NULL_CHECK(ns, -ENOMEM);

mod = get_module(ns, modname);
SOL_NULL_CHECK(mod, -ENOMEM);

if ((ret = get_symbol(mod->handle, symbol_name, symbol)) < 0) {
char path[PATH_MAX];

get_module_path(path, sizeof(path), nspace, modname);
SOL_WRN("Symbol '%s' not found in module '%s/%s' (%s): %s",
symbol_name, nspace, modname, path, dlerror());
return ret;
}

return 0;
}

void *
sol_modules_get_symbol(const char *nspace, const char *modname, const char *symbol)
{
void *sym;
int ret;

SOL_DBG("Trying for symbol '%s' internally", symbol);
if ((ret = get_internal_symbol(symbol, &sym)) < 0) {
SOL_DBG("Trying for symbol '%s' in '%s' module '%s'", symbol, nspace, modname);
if ((ret = get_module_symbol(nspace, modname, symbol, &sym)) < 0) {
SOL_DBG("Symbol '%s' of module '%s/%s' not found.", modname, nspace, symbol);
errno = -ret;
sym = NULL;
}
}

return sym;
}
#endif /* MODULES */

void
sol_modules_clear_cache(void)
{
#ifdef MODULES
clear_namespace_cache(&namespaces);
#endif
}
Loading

0 comments on commit 45548bc

Please sign in to comment.