[asterisk-commits] seanbright: branch seanbright/dependency-loader r411654 - in /team/seanbright...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Apr 2 08:31:26 CDT 2014
Author: seanbright
Date: Wed Apr 2 08:31:20 2014
New Revision: 411654
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=411654
Log:
Add support for dynamic dependency loading based on menuselect-tree.
This patch introduces a new build tool, make_loader_dep, that generates a module
dependency list from menuselect-tree that is used by the module loader when a
module load is requested by the user (autoload is unaffected).
I've tested with autoload=no and executing 'module load chan_pjsip.so' from the
CLI and all modules are loaded correctly. I had to modify res_pjsip's dependency
list to include res_sorcery_astdb and res_sorcery_memory as that module will not
load without them.
Added:
team/seanbright/dependency-loader/build_tools/make_loader_dep.c (with props)
Modified:
team/seanbright/dependency-loader/Makefile
team/seanbright/dependency-loader/build_tools/ (props changed)
team/seanbright/dependency-loader/include/asterisk/module.h
team/seanbright/dependency-loader/main/ (props changed)
team/seanbright/dependency-loader/main/loader.c
team/seanbright/dependency-loader/res/res_pjsip.c
Modified: team/seanbright/dependency-loader/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/seanbright/dependency-loader/Makefile?view=diff&rev=411654&r1=411653&r2=411654
==============================================================================
--- team/seanbright/dependency-loader/Makefile (original)
+++ team/seanbright/dependency-loader/Makefile Wed Apr 2 08:31:20 2014
@@ -356,7 +356,7 @@
+@$(SUBMAKE) $(MOD_SUBDIRS_EMBED_LDFLAGS)
+@$(SUBMAKE) $(MOD_SUBDIRS_EMBED_LIBS)
-$(SUBDIRS): makeopts .lastclean main/version.c include/asterisk/build.h include/asterisk/buildopts.h defaults.h makeopts.embed_rules
+$(SUBDIRS): makeopts .lastclean main/version.c include/asterisk/build.h include/asterisk/buildopts.h defaults.h makeopts.embed_rules main/loader_deps.c
ifeq ($(findstring $(OSARCH), mingw32 cygwin ),)
ifeq ($(shell grep ^MENUSELECT_EMBED=$$ menuselect.makeopts 2>/dev/null),)
@@ -396,6 +396,10 @@
@cmp -s $@.tmp $@ || mv $@.tmp $@
@rm -f $@.tmp
+main/loader_deps.c: build_tools/make_loader_dep.c menuselect-tree
+ +@$(SUBMAKE) -C build_tools make_loader_dep CFLAGS="-g $(LIBXML2_INCLUDE)" LDLIBS="$(LIBXML2_LIB)"
+ @build_tools/make_loader_dep menuselect-tree > $@
+
include/asterisk/buildopts.h: menuselect.makeopts .lastclean
@build_tools/make_buildopts_h > $@.tmp
@cmp -s $@.tmp $@ || mv $@.tmp $@
@@ -418,6 +422,7 @@
rm -f defaults.h
rm -f include/asterisk/build.h
rm -f main/version.c
+ rm -f main/loader_deps.c
rm -f doc/core-en_US.xml
rm -f doc/full-en_US.xml
rm -f doc/rest-api/*.wiki
Propchange: team/seanbright/dependency-loader/build_tools/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Wed Apr 2 08:31:20 2014
@@ -1,3 +1,4 @@
vercomp
+make_loader_dep
menuselect-deps
menuselect
Added: team/seanbright/dependency-loader/build_tools/make_loader_dep.c
URL: http://svnview.digium.com/svn/asterisk/team/seanbright/dependency-loader/build_tools/make_loader_dep.c?view=auto&rev=411654
==============================================================================
--- team/seanbright/dependency-loader/build_tools/make_loader_dep.c (added)
+++ team/seanbright/dependency-loader/build_tools/make_loader_dep.c Wed Apr 2 08:31:20 2014
@@ -1,0 +1,229 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, malleable, LLC.
+ *
+ * Sean Bright <sean at malleable.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+struct dependency {
+ const xmlChar *name;
+ int is_module;
+};
+
+struct module {
+ const xmlChar *name;
+ int dep_count;
+ int dep_mod_count;
+ struct dependency **dependencies;
+};
+
+struct module_context {
+ const char *app;
+ int modcount;
+ struct module **modules;
+};
+
+static struct module *handle_member_element(xmlNode *node, struct module_context *ctx)
+{
+ xmlNode *curr;
+ struct module *module;
+ int count = 0;
+
+ module = calloc(1, sizeof(struct module));
+ module->name = xmlGetProp(node, "name");
+
+ /* One pass through to count the child nodes */
+ for (curr = node->children; curr; curr = curr->next) {
+ if (curr->type != XML_ELEMENT_NODE) {
+ continue;
+ }
+
+ if (!xmlStrcmp(curr->name, "depend")) {
+ count++;
+ }
+ }
+
+ module->dep_count = module->dep_mod_count = count;
+
+ if (count > 0) {
+ module->dependencies = calloc(count, sizeof(struct dependency *));
+
+ /* Second pass to add the nodes */
+ for (count = 0, curr = node->children; curr; curr = curr->next) {
+ if (curr->type != XML_ELEMENT_NODE) {
+ continue;
+ }
+
+ if (!xmlStrcmp(curr->name, "depend")) {
+ module->dependencies[count] = calloc(1, sizeof(struct dependency));
+ module->dependencies[count]->name = xmlNodeGetContent(curr);
+ count++;
+ }
+ }
+ }
+
+ return module;
+}
+
+static void print_header(struct module_context *ctx)
+{
+ printf("/*\n");
+ printf(" * Dependency loader support\n");
+ printf(" * This file is automatically generated by %s, do not modify.\n", ctx->app);
+ printf(" */\n\n");
+ printf("#include \"asterisk.h\"\n");
+ printf("#include \"asterisk/module.h\"\n\n");
+ printf("#include <stddef.h>\n\n");
+ printf("struct ast_module_dep ast_module_deps[] = {\n");
+}
+
+static void print_module(struct module *module)
+{
+ int i;
+
+ printf("\t{ \"%s\", { ", module->name);
+
+ for (i = 0; i < module->dep_count; i++) {
+ struct dependency *dep = module->dependencies[i];
+
+ if (!dep->is_module) {
+ continue;
+ }
+
+ printf("\"%s\", ", dep->name);
+ }
+
+ printf(" NULL } },\n");
+}
+
+static void print_footer(struct module_context *ctx)
+{
+ printf("\t{ NULL, { NULL } },\n");
+ printf("};\n");
+}
+
+static int build_module_tree(const char *filename, struct module_context *ctx)
+{
+ int size, i;
+ xmlDocPtr doc;
+ xmlXPathContextPtr xpathCtx;
+ xmlXPathObjectPtr xpathObj;
+ xmlNodeSetPtr members;
+
+ doc = xmlParseFile(filename);
+ if (!doc) {
+ fprintf(stderr, "Unable to open file `%s'\n", filename);
+ return -1;
+ }
+
+ xpathCtx = xmlXPathNewContext(doc);
+ if (!xpathCtx) {
+ fprintf(stderr, "Unable to create XPath context\n");
+ xmlFreeDoc(doc);
+ return -1;
+ }
+
+ xpathObj = xmlXPathEvalExpression("/menu/category[contains(@remove_on_change, 'modules.link')]/member", xpathCtx);
+ if (!xpathObj) {
+ fprintf(stderr, "Unable to evaluate XPath expression\n");
+ xmlXPathFreeContext(xpathCtx);
+ xmlFreeDoc(doc);
+ return -1;
+ }
+
+ members = xpathObj->nodesetval;
+
+ size = members ? members->nodeNr : 0;
+
+ if (!size) {
+ xmlXPathFreeObject(xpathObj);
+ xmlXPathFreeContext(xpathCtx);
+ xmlFreeDoc(doc);
+ return 0;
+ }
+
+ ctx->modcount = size;
+ ctx->modules = calloc(size, sizeof(struct module *));
+
+ for (i = 0; i < ctx->modcount; i++) {
+ ctx->modules[i] = handle_member_element(members->nodeTab[i], ctx);
+ }
+
+ xmlXPathFreeObject(xpathObj);
+ xmlXPathFreeContext(xpathCtx);
+ xmlFreeDoc(doc);
+
+ print_header(ctx);
+
+ /* For every module... */
+ for (i = 0; i < ctx->modcount; i++) {
+ int depidx;
+ struct module *module = ctx->modules[i];
+
+ /* Go through each dependency... */
+ for (depidx = 0; depidx < module->dep_count; depidx++) {
+ int modidx;
+ struct dependency *dep = module->dependencies[depidx];
+
+ /* And if it is not a module dependency, exclude it. */
+ for (modidx = 0; modidx < ctx->modcount; modidx++) {
+ if (!xmlStrcmp(dep->name, ctx->modules[modidx]->name)) {
+ dep->is_module = 1;
+ break;
+ }
+ }
+
+ if (!dep->is_module) {
+ module->dep_mod_count--;
+ }
+ }
+
+ if (module->dep_mod_count) {
+ print_module(module);
+ }
+ }
+
+ print_footer(ctx);
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ struct module_context context;
+ context.modules = NULL;
+ context.app = argv[0];
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s <menuselect-tree>\n", argv[0]);
+ return -1;
+ }
+
+ xmlInitParser();
+ LIBXML_TEST_VERSION;
+
+ build_module_tree(argv[1], &context);
+
+ xmlCleanupParser();
+ return 0;
+}
Propchange: team/seanbright/dependency-loader/build_tools/make_loader_dep.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/seanbright/dependency-loader/build_tools/make_loader_dep.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/seanbright/dependency-loader/build_tools/make_loader_dep.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/seanbright/dependency-loader/include/asterisk/module.h
URL: http://svnview.digium.com/svn/asterisk/team/seanbright/dependency-loader/include/asterisk/module.h?view=diff&rev=411654&r1=411653&r2=411654
==============================================================================
--- team/seanbright/dependency-loader/include/asterisk/module.h (original)
+++ team/seanbright/dependency-loader/include/asterisk/module.h Wed Apr 2 08:31:20 2014
@@ -482,6 +482,11 @@
#define SCOPED_MODULE_USE(module) \
RAII_VAR(struct ast_module *, __self__ ## __LINE__, ast_module_ref(module), ast_module_unref)
+struct ast_module_dep {
+ const char *resource;
+ const char *dependencies[32];
+};
+
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
Propchange: team/seanbright/dependency-loader/main/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Wed Apr 2 08:31:20 2014
@@ -8,4 +8,5 @@
*.s
*.so*
asterisk
+loader_deps.c
version.c
Modified: team/seanbright/dependency-loader/main/loader.c
URL: http://svnview.digium.com/svn/asterisk/team/seanbright/dependency-loader/main/loader.c?view=diff&rev=411654&r1=411653&r2=411654
==============================================================================
--- team/seanbright/dependency-loader/main/loader.c (original)
+++ team/seanbright/dependency-loader/main/loader.c Wed Apr 2 08:31:20 2014
@@ -128,6 +128,8 @@
char resource[0];
};
+extern struct ast_module_dep ast_module_deps[];
+
static AST_LIST_HEAD_STATIC(module_list, ast_module);
const char *ast_module_name(const struct ast_module *mod)
@@ -1072,14 +1074,66 @@
return res;
}
+static int load_dependencies(const char *resource_name)
+{
+ struct ast_module_dep *curr, *module = NULL;
+ const char **dep;
+
+ for (curr = ast_module_deps; curr->resource; curr++) {
+ if (!resource_name_match(curr->resource, resource_name)) {
+ module = curr;
+ break;
+ }
+ }
+
+ if (!module) {
+ /* No dependencies */
+ return 0;
+ }
+
+ dep = module->dependencies;
+ while (*dep) {
+ int res;
+
+ if (find_resource(*dep, 0)) {
+ dep++;
+ continue;
+ }
+
+ /* If our dependency has dependencies, load them first */
+ if ((res = load_dependencies(*dep))) {
+ return res;
+ }
+
+ /* And now load the dependency */
+ if ((res = load_resource(*dep, 0, NULL, 0))) {
+ return res;
+ } else {
+ ast_test_suite_event_notify("MODULE_LOAD", "Message: %s", *dep);
+ }
+
+ dep++;
+ }
+
+ return 0;
+}
+
int ast_load_resource(const char *resource_name)
{
int res;
+
AST_LIST_LOCK(&module_list);
+
+ if ((res = load_dependencies(resource_name))) {
+ AST_LIST_UNLOCK(&module_list);
+ return res;
+ }
+
res = load_resource(resource_name, 0, NULL, 0);
if (!res) {
ast_test_suite_event_notify("MODULE_LOAD", "Message: %s", resource_name);
}
+
AST_LIST_UNLOCK(&module_list);
return res;
Modified: team/seanbright/dependency-loader/res/res_pjsip.c
URL: http://svnview.digium.com/svn/asterisk/team/seanbright/dependency-loader/res/res_pjsip.c?view=diff&rev=411654&r1=411653&r2=411654
==============================================================================
--- team/seanbright/dependency-loader/res/res_pjsip.c (original)
+++ team/seanbright/dependency-loader/res/res_pjsip.c Wed Apr 2 08:31:20 2014
@@ -38,7 +38,9 @@
/*** MODULEINFO
<depend>pjproject</depend>
+ <depend>res_sorcery_astdb</depend>
<depend>res_sorcery_config</depend>
+ <depend>res_sorcery_memory</depend>
<support_level>core</support_level>
***/
More information about the asterisk-commits
mailing list