aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authordvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b>2009-06-09 16:22:04 +0000
committerdvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b>2009-06-09 16:22:04 +0000
commit114afd3010423ad96144ae3121458e18d06c75a7 (patch)
tree977456b473f32698ff9021a10c7f811501922037 /main
parent6b30a865c0d0f4636253df8ade3ff54fd73144e0 (diff)
module load priority
This patch adds the option to give a module a load priority. The value represents the order in which a module's load() function is initialized. The lower the value, the higher the priority. The value is only checked if the AST_MODFLAG_LOAD_ORDER flag is set. If the AST_MODFLAG_LOAD_ORDER flag is not set, the value will never be read and the module will be given the lowest possible priority on load. Since some modules are reliant on a timing interface, the timing modules have been given a high load priorty. (closes issue #15191) Reported by: alecdavis Tested by: dvossel Review: https://reviewboard.asterisk.org/r/262/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@199743 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main')
-rw-r--r--main/loader.c192
1 files changed, 130 insertions, 62 deletions
diff --git a/main/loader.c b/main/loader.c
index 8ce96be72..48e9bbb22 100644
--- a/main/loader.c
+++ b/main/loader.c
@@ -48,6 +48,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/features.h"
#include "asterisk/dsp.h"
#include "asterisk/udptl.h"
+#include "asterisk/heap.h"
#include <dlfcn.h>
@@ -712,11 +713,57 @@ static unsigned int inspect_module(const struct ast_module *mod)
return 0;
}
-static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only)
+static enum ast_module_load_result start_resource(struct ast_module *mod)
+{
+ char tmp[256];
+ enum ast_module_load_result res;
+
+ if (!mod->info->load) {
+ return AST_MODULE_LOAD_FAILURE;
+ }
+
+ res = mod->info->load();
+
+ switch (res) {
+ case AST_MODULE_LOAD_SUCCESS:
+ if (!ast_fully_booted) {
+ ast_verb(1, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
+ if (ast_opt_console && !option_verbose)
+ ast_verbose( ".");
+ } else {
+ ast_verb(1, "Loaded %s => (%s)\n", mod->resource, mod->info->description);
+ }
+
+ mod->flags.running = 1;
+
+ ast_update_use_count();
+ break;
+ case AST_MODULE_LOAD_DECLINE:
+ mod->flags.declined = 1;
+ break;
+ case AST_MODULE_LOAD_FAILURE:
+ break;
+ case AST_MODULE_LOAD_SKIP:
+ /* modules should never return this value */
+ break;
+ }
+
+ return res;
+}
+
+/*! loads a resource based upon resource_name. If global_symbols_only is set
+ * only modules with global symbols will be loaded.
+ *
+ * If the ast_heap is provided (not NULL) the module is found and added to the
+ * heap without running the module's load() function. By doing this, modules
+ * added to the resource_heap can be initilized later in order by priority.
+ *
+ * If the ast_heap is not provided, the module's load function will be executed
+ * immediately */
+static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, struct ast_heap *resource_heap)
{
struct ast_module *mod;
enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
- char tmp[256];
if ((mod = find_resource(resource_name, 0))) {
if (mod->flags.running) {
@@ -757,31 +804,11 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi
mod->flags.declined = 0;
- if (mod->info->load)
- res = mod->info->load();
-
- switch (res) {
- case AST_MODULE_LOAD_SUCCESS:
- if (!ast_fully_booted) {
- ast_verb(1, "%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
- if (ast_opt_console && !option_verbose)
- ast_verbose( ".");
- } else {
- ast_verb(1, "Loaded %s => (%s)\n", resource_name, mod->info->description);
- }
-
- mod->flags.running = 1;
-
- ast_update_use_count();
- break;
- case AST_MODULE_LOAD_DECLINE:
- mod->flags.declined = 1;
- break;
- case AST_MODULE_LOAD_FAILURE:
- break;
- case AST_MODULE_LOAD_SKIP:
- /* modules should never return this value */
- break;
+ if (resource_heap) {
+ ast_heap_push(resource_heap, mod);
+ res = AST_MODULE_LOAD_SKIP;
+ } else {
+ res = start_resource(mod);
}
return res;
@@ -791,7 +818,7 @@ int ast_load_resource(const char *resource_name)
{
int res;
AST_LIST_LOCK(&module_list);
- res = load_resource(resource_name, 0);
+ res = load_resource(resource_name, 0, NULL);
AST_LIST_UNLOCK(&module_list);
return res;
@@ -822,6 +849,77 @@ static struct load_order_entry *add_to_load_order(const char *resource, struct l
return order;
}
+static int mod_load_cmp(void *a, void *b)
+{
+ struct ast_module *a_mod = (struct ast_module *) a;
+ struct ast_module *b_mod = (struct ast_module *) b;
+ int res = -1;
+ /* if load_pri is not set, default is 255. Lower is better*/
+ unsigned char a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 255;
+ unsigned char b_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 255;
+ if (a_pri == b_pri) {
+ res = 0;
+ } else if (a_pri < b_pri) {
+ res = 1;
+ }
+ return res;
+}
+
+/*! loads modules in order by load_pri, updates mod_count */
+static int load_resource_list(struct load_order *load_order, unsigned int global_symbols, int *mod_count)
+{
+ struct ast_heap *resource_heap;
+ struct load_order_entry *order;
+ struct ast_module *mod;
+ int count = 0;
+ int res = 0;
+
+ if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) {
+ return -1;
+ }
+
+ /* first, add find and add modules to heap */
+ AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {
+ switch (load_resource(order->resource, global_symbols, resource_heap)) {
+ case AST_MODULE_LOAD_SUCCESS:
+ case AST_MODULE_LOAD_DECLINE:
+ AST_LIST_REMOVE_CURRENT(entry);
+ ast_free(order->resource);
+ ast_free(order);
+ break;
+ case AST_MODULE_LOAD_FAILURE:
+ res = -1;
+ goto done;
+ case AST_MODULE_LOAD_SKIP:
+ break;
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+
+ /* second remove modules from heap sorted by priority */
+ while ((mod = ast_heap_pop(resource_heap))) {
+ switch (start_resource(mod)) {
+ case AST_MODULE_LOAD_SUCCESS:
+ count++;
+ case AST_MODULE_LOAD_DECLINE:
+ break;
+ case AST_MODULE_LOAD_FAILURE:
+ res = -1;
+ goto done;
+ case AST_MODULE_LOAD_SKIP:
+ break;
+ }
+ }
+
+done:
+ if (mod_count) {
+ *mod_count += count;
+ }
+ ast_heap_destroy(resource_heap);
+
+ return res;
+}
+
int load_modules(unsigned int preload_only)
{
struct ast_config *cfg;
@@ -941,44 +1039,14 @@ int load_modules(unsigned int preload_only)
ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
/* first, load only modules that provide global symbols */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
- switch (load_resource(order->resource, 1)) {
- case AST_MODULE_LOAD_SUCCESS:
- modulecount++;
- case AST_MODULE_LOAD_DECLINE:
- AST_LIST_REMOVE_CURRENT(entry);
- ast_free(order->resource);
- ast_free(order);
- break;
- case AST_MODULE_LOAD_FAILURE:
- res = -1;
- goto done;
- case AST_MODULE_LOAD_SKIP:
- /* try again later */
- break;
- }
+ if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) {
+ goto done;
}
- AST_LIST_TRAVERSE_SAFE_END;
/* now load everything else */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
- switch (load_resource(order->resource, 0)) {
- case AST_MODULE_LOAD_SUCCESS:
- modulecount++;
- case AST_MODULE_LOAD_DECLINE:
- AST_LIST_REMOVE_CURRENT(entry);
- ast_free(order->resource);
- ast_free(order);
- break;
- case AST_MODULE_LOAD_FAILURE:
- res = -1;
- goto done;
- case AST_MODULE_LOAD_SKIP:
- /* should not happen */
- break;
- }
+ if ((res = load_resource_list(&load_order, 0, &modulecount)) < 0) {
+ goto done;
}
- AST_LIST_TRAVERSE_SAFE_END;
done:
while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {