mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	Merged revisions 199743 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ........ r199743 | dvossel | 2009-06-09 11:22:04 -0500 (Tue, 09 Jun 2009) | 11 lines 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: https://origsvn.digium.com/svn/asterisk/branches/1.6.1@199745 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		
							
								
								
									
										192
									
								
								main/loader.c
									
									
									
									
									
								
							
							
						
						
									
										192
									
								
								main/loader.c
									
									
									
									
									
								
							| @@ -49,6 +49,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> | ||||
|  | ||||
| @@ -713,11 +714,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) { | ||||
| @@ -758,31 +805,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; | ||||
| @@ -792,7 +819,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; | ||||
| @@ -823,6 +850,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))) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user