[Asterisk-cvs] asterisk-addons res_config_mysql.c,1.5,1.6

markster at lists.digium.com markster at lists.digium.com
Wed Jan 26 20:53:21 CST 2005


Update of /usr/cvsroot/asterisk-addons
In directory mongoose.digium.com:/tmp/cvs-serv7142

Modified Files:
	res_config_mysql.c 
Log Message:
Fix mysql config stuff (bug #3433)


Index: res_config_mysql.c
===================================================================
RCS file: /usr/cvsroot/asterisk-addons/res_config_mysql.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- res_config_mysql.c	22 Jan 2005 21:09:56 -0000	1.5
+++ res_config_mysql.c	27 Jan 2005 02:55:26 -0000	1.6
@@ -1,29 +1,33 @@
 /*
  * Asterisk -- A telephony toolkit for Linux.
  *
- * Copyright (C) 1999-2004, Digium, Inc.
+ * Copyright (C) 1999-2005, Digium, Inc.
  *
  * Mark Spencer <markster at digium.com>  - Asterisk Author
  * Matthew Boehm <mboehm at cytelcom.com> - MySQL RealTime Driver Author
  *
  * res_config_mysql.c <mysql plugin for RealTime configuration engine >
  *
- * v1.4 - (12-02-04) - Added realtime_multi_mysql function
- *                      This function will return an ast_config with categories,
- *                      unlike standard realtime_mysql which only returns
- *                      a linked list of ast_variables
+ * v1.5.1 - (01-26-05) - Added better(?) locking stuff
  *
- * v1.3 - (12-01-04) - Added support other operators
- *                     Ex: =, !=, LIKE, NOT LIKE, RLIKE, etc...
+ * v1.5   - (01-26-05) - Brought up to date with new config.h changes (bug #3406)
+ *                     - Added in extra locking provided by georg (bug #3248)
  *
- * v1.2 - (11-DD-04) - Added reload. Updated load and unload.
- *                     Code beautification (doc/CODING-GUIDELINES)
+ * v1.4   - (12-02-04) - Added realtime_multi_mysql function
+ *                        This function will return an ast_config with categories,
+ *                        unlike standard realtime_mysql which only returns
+ *                        a linked list of ast_variables
+ *
+ * v1.3   - (12-01-04) - Added support other operators
+ *                       Ex: =, !=, LIKE, NOT LIKE, RLIKE, etc...
+ *
+ * v1.2   - (11-DD-04) - Added reload. Updated load and unload.
+ *                       Code beautification (doc/CODING-GUIDELINES)
  */
 
 #include <asterisk/channel.h>
 #include <asterisk/logger.h>
 #include <asterisk/config.h>
-#include <asterisk/config_pvt.h>
 #include <asterisk/module.h>
 #include <asterisk/lock.h>
 #include <asterisk/options.h>
@@ -36,7 +40,6 @@
 #include <errmsg.h>
 
 static char *res_config_mysql_desc = "MySQL RealTime Configuration Driver";
-static struct ast_config_reg reg_mysql;
 
 AST_MUTEX_DEFINE_STATIC(mysql_lock);
 #define RES_CONFIG_MYSQL_CONF "res_mysql.conf"
@@ -122,36 +125,30 @@
 		return NULL;
 	}
 
-	/* Toss up here. Each has its pros and cons. Gonna use store result cause most people will be running database
-           either locally or on same network. And since the tables are small text based, shouldn't be that big of a problem
-           unless you're retrieving a few million rows.
-           mysql_store_result: Will copy all the rows returned by the query to local memory. This save network time,
-                               but could possibly use up lots of memory if the result set is large.
-             mysql_use_result: Will keep the result set on the server and will retrieve each row at a time from server.
-                               Reduces local memory usage, but increases network traffic for large sets. Also, the server
-                               could go down part way thru our retrieval process and we wouldn't get all the rows. */
-
-	result = mysql_store_result(&mysql);
-	numFields = mysql_num_fields(result);
-	fields = mysql_fetch_fields(result);
+	if((result = mysql_store_result(&mysql))) {
+		numFields = mysql_num_fields(result);
+		fields = mysql_fetch_fields(result);
 
-	while((row = mysql_fetch_row(result))) {
-		for(i = 0; i < numFields; i++) {
-			stringp = row[i];
-			while(stringp) {
-				chunk = strsep(&stringp, ";");
-				if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
-					if(prev) {
-						prev->next = ast_new_variable(fields[i].name, chunk);
-						if (prev->next) {
-							prev = prev->next;
+		while((row = mysql_fetch_row(result))) {
+			for(i = 0; i < numFields; i++) {
+				stringp = row[i];
+				while(stringp) {
+					chunk = strsep(&stringp, ";");
+					if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
+						if(prev) {
+							prev->next = ast_variable_new(fields[i].name, chunk);
+							if (prev->next) {
+								prev = prev->next;
+							}
+						} else {
+							prev = var = ast_variable_new(fields[i].name, chunk);
 						}
-					} else {
-						prev = var = ast_new_variable(fields[i].name, chunk);
 					}
 				}
 			}
 		}
+	} else {                                
+		ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
 	}
 
 	ast_mutex_unlock(&mysql_lock);
@@ -168,13 +165,12 @@
 	int numFields, i;
 	char sql[256];
 	const char *initfield = NULL;
-	char *title = NULL;
 	char *stringp;
 	char *chunk;
 	char *op;
 	const char *newparam, *newval;
 	struct ast_realloca ra;
-	struct ast_variable *var=NULL, *prev=NULL;
+	struct ast_variable *var=NULL;
 	struct ast_config *cfg = NULL;
 	struct ast_category *cat = NULL;
 
@@ -185,6 +181,13 @@
 	
 	memset(&ra, 0, sizeof(ra));
 
+	cfg = ast_config_new();
+	if (!cfg) {
+		/* If I can't alloc memory at this point, why bother doing anything else? */
+		ast_log(LOG_WARNING, "Out of memory!\n");
+		return NULL;
+	}
+
 	/* Get the first parameter and first value in our list of passed paramater/value pairs */
 	newparam = va_arg(ap, const char *);
 	newval = va_arg(ap, const char *);
@@ -233,50 +236,29 @@
 		return NULL;
 	}
 
-	result = mysql_store_result(&mysql);
-	numFields = mysql_num_fields(result);
-	fields = mysql_fetch_fields(result);
+	if((result = mysql_store_result(&mysql))) {
+		numFields = mysql_num_fields(result);
+		fields = mysql_fetch_fields(result);
 
-	while ((row = mysql_fetch_row(result))) {
-		var = NULL;
-		prev = NULL;
-		title = NULL;
-		for(i = 0; i < numFields; i++) {
-			stringp = row[i];
-			while(stringp) {
-				chunk = strsep(&stringp, ";");
-				if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
-					if (initfield && !strcmp(initfield, fields[i].name) && !title) {
-						title = ast_restrdupa(&ra, chunk);
-					}
-					if (prev) {
-						prev->next = ast_new_variable(fields[i].name, chunk);
-						if (prev->next) {
-							prev = prev->next;
+		while((row = mysql_fetch_row(result))) {
+			var = NULL;
+			for(i = 0; i < numFields; i++) {
+				stringp = row[i];
+				while(stringp) {
+					chunk = strsep(&stringp, ";");
+					if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
+						if(initfield && !strcmp(initfield, fields[i].name)) {
+							ast_category_rename(cat, chunk);
 						}
-					} else {
-						prev = var = ast_new_variable(fields[i].name, chunk);
+						var = ast_variable_new(fields[i].name, chunk);
+						ast_variable_append(cat, var);
 					}
 				}
 			}
+			ast_category_append(cfg, cat);
 		}
-		if(var) {
-			cat = ast_new_category(title ? title : "");
-			if(cat) {
-				cat->root = var;
-				if(!cfg) {
-					cfg = ast_new_config();
-				}
-				if(cfg) {
-					ast_category_append(cfg, cat);
-				} else {
-					ast_category_destroy(cat);
-				}
-			} else {
-				ast_log(LOG_WARNING, "Out of memory!\n");
-				ast_destroy_realtime(var);
-			}
-		}
+	} else {
+		ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
 	}
 
 	ast_mutex_unlock(&mysql_lock);
@@ -344,7 +326,7 @@
 	return -1;
 }
 
-static struct ast_config *config_mysql(const char *database, const char *table, const char *file, struct ast_config *new_config_s, struct ast_category **new_cat_p, struct ast_variable **new_v_p, int recur)
+static struct ast_config *config_mysql(const char *database, const char *table, const char *file, struct ast_config *cfg)
 {
 	MYSQL_RES *result;
 	MYSQL_ROW row;
@@ -367,18 +349,6 @@
 
 	snprintf(sql, sizeof(sql), "SELECT category, var_name, var_val, cat_metric FROM %s WHERE filename='%s' and commented=0 ORDER BY filename, cat_metric desc, var_metric asc, category, var_name, var_val, id", table, file);
 
-	if(new_config_s) {
-		new = new_config_s;
-		cat_started++;
-	} else {
-		new = ast_new_config();
-	}
-	
-	if(!new) {
-		ast_log(LOG_WARNING, "MySQL RealTime: Cannot create new config. Out of memory!\n");
-		return NULL;
-	}
-
 	ast_log(LOG_DEBUG, "MySQL RealTime: Static SQL: %s\n", sql);
 
 	/* We now have our complete statement; Lets connect to the server and execute it. */
@@ -399,65 +369,50 @@
 		num_rows = mysql_num_rows(result);
 		ast_log(LOG_DEBUG, "MySQL RealTime: Found %llu rows.\n", num_rows);
 
-		cat_started = 0;
-
-		cur_cat = *new_cat_p;
-		cur_v = *new_v_p;
-
-		if(cur_cat) {
-			cat_started = 1;
-		}
-
-		if(cur_v) {
-			var_started = 1;
-		}
-
 		/* There might exist a better way to access the column names other than counting,
                    but I believe that would require another loop that we don't need. */
 
 		while((row = mysql_fetch_row(result))) {
-			if(!strcmp(row[1], "#include") && recur < MAX_INCLUDE_LEVEL) {
-				config_mysql(database, table, row[2], new, &cur_cat, &cur_v, recur + 1);
-			} else {
-				if(strcmp(last, row[0]) || last_cat_metric != atoi(row[3])) {
-					strncpy(last, row[0], sizeof(last) - 1);
-					last_cat_metric	= atoi(row[3]);
-					new_cat = (struct ast_category *) ast_new_category(row[0]);
-
-					if(!cat_started) {
-						cat_started++;
-						new->root = new_cat;
-						cur_cat = new->root;
-					} else {
-						cur_cat->next = new_cat;
-						cur_cat = cur_cat->next;
-					}
-					var_started = 0;
+			if(!strcmp(row[1], "#include")) {
+				if (!ast_config_internal_load(row[2], cfg)) {
+					mysql_free_result(result);
+					ast_mutex_unlock(&mysql_lock);
+					return NULL;
 				}
+				continue;
+			}
 
-				new_v = ast_new_variable(row[1], row[2]);
-
-				if (!var_started) {
-					var_started++;
-					cur_cat->root = new_v;
-					cur_v = cur_cat->root;
-				} else {
-					cur_v->next = new_v;
-					cur_v = cur_v->next;
+			if(strcmp(last, row[0]) || last_cat_metric != atoi(row[3])) {
+				cur_cat = ast_category_new(row[0]);
+				if (!cur_cat) {
+					ast_log(LOG_WARNING, "Out of memory!\n");
+					break;
 				}
+				strcpy(last, row[0]);
+				last_cat_metric = atoi(row[3]);
+				ast_category_append(cfg, cur_cat);
 			}
+			new_v = ast_variable_new(row[1], row[2]);
+			ast_variable_append(cur_cat, new_v);
 		}
-		mysql_free_result(result);
-		ast_mutex_unlock(&mysql_lock);
 	} else {
 		ast_log(LOG_WARNING, "MySQL RealTime: Could not find config '%s' in database.\n", file);
-		mysql_free_result(result);
-		ast_mutex_unlock(&mysql_lock);
 	}
 
-	return new;
+	mysql_free_result(result);
+	ast_mutex_unlock(&mysql_lock);
+
+	return cfg;
 }
 
+static struct ast_config_engine mysql_engine = {
+	.name = "mysql",
+	.load_func = config_mysql,
+	.realtime_func = realtime_mysql,
+	.realtime_multi_func = realtime_multi_mysql,
+	.update_func = update_mysql
+};
+
 int load_module (void)
 {
 	parse_config();
@@ -467,56 +422,54 @@
 		ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
 	}
 
-	memset(&reg_mysql, 0, sizeof(struct ast_config_reg));
-	strncpy(reg_mysql.name, "mysql", sizeof(reg_mysql.name) - 1);
-
-	reg_mysql.static_func = config_mysql;
-	reg_mysql.realtime_func = realtime_mysql;
-	reg_mysql.update_func = update_mysql;
-	reg_mysql.realtime_multi_func = realtime_multi_mysql;
-
-	ast_cust_config_register(&reg_mysql);
-	ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime driver loaded.\n");
+	ast_config_engine_register(&mysql_engine);
+	if(option_verbose) {
+		ast_verbose("MySQL RealTime driver loaded.\n");
+	}
 	ast_cli_register(&cli_realtime_mysql_status);
+
 	return 0;
 }
 
 int unload_module (void)
 {
+	/* Aquire control before doing anything to the module itself. */
+	ast_mutex_lock(&mysql_lock);
+
 	mysql_close(&mysql);
 	ast_cli_unregister(&cli_realtime_mysql_status);
-	ast_cust_config_deregister(&reg_mysql);
-	ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime unloaded.\n");
-
-	if(ast_mutex_lock(&mysql_lock)) {
-		ast_mutex_unlock(&mysql_lock);
+	ast_config_engine_deregister(&mysql_engine);
+	if(option_verbose) {
+		ast_verbose("MySQL RealTime unloaded.\n");
 	}
 
 	STANDARD_HANGUP_LOCALUSERS;
 
+	/* Unlock so something else can destroy the lock. */
+	ast_mutex_unlock(&mysql_lock);
+
 	return 0;
 }
 
 int reload (void)
 {
-	if(ast_mutex_lock(&mysql_lock)) {
-		ast_log(LOG_WARNING, "MySQL RealTime: Couldn't reload. Use count %i.\n", usecount());
-		return 1;   
-	}
+	/* Aquire control before doing anything to the module itself. */
+	ast_mutex_lock(&mysql_lock);
 
-	ast_mutex_unlock(&mysql_lock);
 	mysql_close(&mysql);
-
 	connected = 0;
-
 	parse_config();
 
+	/* Need to unlock so that mysql_reconnect can regain the lock. */
+	ast_mutex_unlock(&mysql_lock);
+
 	if(!mysql_reconnect()) {
 		ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish connection. Check debug.\n");
 		ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
 	}
 
 	ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime reloaded.\n");
+
 	return 0;
 }
 
@@ -525,7 +478,7 @@
 	struct ast_config *config;
 	char *s;
 
-	config = ast_load(RES_CONFIG_MYSQL_CONF);
+	config = ast_config_load(RES_CONFIG_MYSQL_CONF);
 
 	if(config) {
 		if(!(s=ast_variable_retrieve(config, "general", "dbuser"))) {
@@ -570,7 +523,7 @@
                         strncpy(dbsock, s, sizeof(dbsock) - 1);
                 }
 	}
-	ast_destroy(config);
+	ast_config_destroy(config);
 
 	if(dbhost) {
 		ast_log(LOG_DEBUG, "MySQL RealTime Host: %s\n", dbhost);
@@ -591,10 +544,9 @@
 
 int usecount (void)
 {
-	/* Try and get a lock. If unsuccessful, than that means a query is currently being run.
-	   Lets be nice and don't interrupt the query. */
-	if(ast_mutex_lock(&mysql_lock)) {
-		ast_log(LOG_DEBUG, "MySQL RealTime: Usecount 1. Query in progress.\n");
+	/* Try and get a lock. If unsuccessful, than that means another thread is using the mysql object. */
+	if(ast_mutex_trylock(&mysql_lock)) {
+		ast_log(LOG_DEBUG, "MySQL RealTime: Module usage count is 1.\n");
 		return 1;
 	}
 	ast_mutex_unlock(&mysql_lock);




More information about the svn-commits mailing list