[asterisk-addons-commits] tilghman: trunk r653 - /trunk/cdr/cdr_addon_mysql.c

SVN commits to the Asterisk addons project asterisk-addons-commits at lists.digium.com
Thu Aug 28 11:38:25 CDT 2008


Author: tilghman
Date: Thu Aug 28 11:38:24 2008
New Revision: 653

URL: http://svn.digium.com/view/asterisk-addons?view=rev&rev=653
Log:
Don't DESC the MySQL table every time through, but instead cache the state
at module load and reload, just like the other CDR drivers.
(closes issue #13379)
 Reported by: Corydon76
 Patches: 
       20080826__cdr_mysql__2.diff.txt uploaded by Corydon76 (license 14)
 Tested by: chris-mac

Modified:
    trunk/cdr/cdr_addon_mysql.c

Modified: trunk/cdr/cdr_addon_mysql.c
URL: http://svn.digium.com/view/asterisk-addons/trunk/cdr/cdr_addon_mysql.c?view=diff&rev=653&r1=652&r2=653
==============================================================================
--- trunk/cdr/cdr_addon_mysql.c (original)
+++ trunk/cdr/cdr_addon_mysql.c Thu Aug 28 11:38:24 2008
@@ -83,11 +83,12 @@
 struct column {
 	char *name;
 	char *cdrname;
+	char *type;
 	AST_LIST_ENTRY(column) list;
 };
 
 /* Protected with mysql_lock */
-static AST_LIST_HEAD_NOLOCK_STATIC(columns, column);
+static AST_RWLIST_HEAD_STATIC(columns, column);
 
 static MYSQL mysql = { { NULL }, };
 
@@ -149,7 +150,6 @@
 
 static int mysql_log(struct ast_cdr *cdr)
 {
-	char sqldesc[128];
 	char *sql1 = ast_calloc(1, 4096), *sql2 = ast_calloc(1, 2048);
 	int sql1size = 4096, sql2size = 2048;
 	int retries = 5;
@@ -204,54 +204,27 @@
 					ast_log(LOG_ERROR, "Unknown connection error: (%d) %s\n", mysql_errno(&mysql), mysql_error(&mysql));
 			}
 			retries--;
-			if (retries)
+			if (retries) {
 				goto db_reconnect;
-			else
-				ast_log(LOG_ERROR, "Retried to connect fives times, giving up.\n");
+			} else {
+				ast_log(LOG_ERROR, "Retried to connect five times, giving up.\n");
+			}
 		}
 	}
 
 	if (connected) {
-		MYSQL_ROW row;
-		MYSQL_RES *result;
 		int column_count = 0;
+		char *cdrname;
+		char workspace[2048], *value = NULL, *ptr;
+		int sql2len;
+		struct column *entry;
 
 		snprintf(sql1, sql1size, "INSERT INTO %s (", dbtable ? dbtable->str : "cdr");
 		strcpy(sql2, ") VALUES ('");
 
-		/* Get table description */
-		snprintf(sqldesc, sizeof(sqldesc), "DESC %s", dbtable ? dbtable->str : "cdr");
-		if (mysql_query(&mysql, sqldesc)) {
-			ast_log(LOG_ERROR, "Unable to query table description!!\n");
-			mysql_close(&mysql);
-			connected = 0;
-			goto log_exit;
-		}
-
-		if (!(result = mysql_store_result(&mysql))) {
-			ast_log(LOG_ERROR, "Unable to query table description!!\n");
-			mysql_close(&mysql);
-			connected = 0;
-			goto log_exit;
-		}
-
-		while ((row = mysql_fetch_row(result))) {
-			struct column *entry;
-			char *cdrname;
-			char workspace[2048], *value = NULL, *ptr;
-			int sql2len;
-
-			ast_debug(1, "Got a field '%s' of type '%s'\n", row[0], row[1]);
-			/* Check for an alias */
-			AST_LIST_TRAVERSE(&columns, entry, list) {
-				/* This would probably be better off as a hash */
-				if (!strcasecmp(entry->name, row[0]))
-					break;
-			}
-
-			if (entry) {
-				cdrname = entry->cdrname;
-			} else if (!strcmp(row[0], "calldate")) {
+		AST_RWLIST_RDLOCK(&columns);
+		AST_RWLIST_TRAVERSE(&columns, entry, list) {
+			if (!strcmp(entry->name, "calldate")) {
 				/*!\note
 				 * For some dumb reason, "calldate" used to be formulated using
 				 * the datetime the record was posted, rather than the start
@@ -270,7 +243,7 @@
 					cdrname = "start";
 				}
 			} else {
-				cdrname = row[0];
+				cdrname = entry->cdrname;
 			}
 
 			/* Construct SQL */
@@ -279,14 +252,14 @@
 				strcat(sql2, "','");
 			}
 
-			if (strlen(sql1) + 2 + strlen(row[0]) > sql1size) {
+			if (strlen(sql1) + 2 + strlen(entry->name) > sql1size) {
 				char *tmp = ast_realloc(sql1, sql1size * 2);
 				if (!tmp)
 					goto log_exit;
 				sql1size *= 2;
 				sql1 = tmp;
 			}
-			strcat(sql1, row[0]);
+			strcat(sql1, entry->name);
 
 			/* Need the type and value to determine if we want the raw value or not */
 			if ((!strcmp(cdrname, "start") ||
@@ -294,13 +267,13 @@
 				 !strcmp(cdrname, "end") ||
 				 !strcmp(cdrname, "disposition") ||
 				 !strcmp(cdrname, "amaflags")) &&
-				(strstr(row[1], "int") ||
-				 strstr(row[1], "dec") ||
-				 strstr(row[1], "float") ||
-				 strstr(row[1], "double") ||
-				 strstr(row[1], "real") ||
-				 strstr(row[1], "numeric") ||
-				 strstr(row[1], "fixed")))
+				(strstr(entry->type, "int") ||
+				 strstr(entry->type, "dec") ||
+				 strstr(entry->type, "float") ||
+				 strstr(entry->type, "double") ||
+				 strstr(entry->type, "real") ||
+				 strstr(entry->type, "numeric") ||
+				 strstr(entry->type, "fixed")))
 				ast_cdr_getvar(cdr, cdrname, &value, workspace, sizeof(workspace), 0, 1);
 			else
 				ast_cdr_getvar(cdr, cdrname, &value, workspace, sizeof(workspace), 0, 0);
@@ -329,7 +302,7 @@
 				sql2[sql2len] = '\0';
 			}
 		}
-		mysql_free_result(result);
+		AST_RWLIST_UNLOCK(&columns);
 
 		ast_debug(1, "Inserting a CDR record.\n");
 		if (strlen(sql1) + 3 + strlen(sql2) > sql1size) {
@@ -379,8 +352,11 @@
 	}
 	AST_LIST_UNLOCK(&unload_strings);
 
-	while ((entry = AST_LIST_REMOVE_HEAD(&columns, list)))
+	AST_RWLIST_WRLOCK(&columns);
+	while ((entry = AST_RWLIST_REMOVE_HEAD(&columns, list))) {
 		ast_free(entry);
+	}
+	AST_RWLIST_UNLOCK(&columns);
 
 	dbport = 0;
 	ast_cdr_unregister(name);
@@ -435,6 +411,9 @@
 	struct column *entry;
 	char *temp;
 	struct ast_str *compat;
+	MYSQL_ROW row;
+	MYSQL_RES *result;
+	char sqldesc[128];
 #if MYSQL_VERSION_ID >= 50013
 	my_bool my_bool_true = 1;
 #endif
@@ -481,23 +460,10 @@
 		return AST_MODULE_LOAD_FAILURE;
 
 	/* Check for any aliases */
-	while ((entry = AST_LIST_REMOVE_HEAD(&columns, list)))
+	AST_RWLIST_WRLOCK(&columns);
+	while ((entry = AST_LIST_REMOVE_HEAD(&columns, list))) {
 		ast_free(entry);
-
-	for (var = ast_variable_browse(cfg, "aliases"); var; var = var->next) {
-		struct column *entry = ast_calloc(1, sizeof(*entry) + strlen(var->name) + 1 + strlen(var->value) + 1);
-		if (!entry)
-			continue;
-		entry->cdrname = (char *)entry + sizeof(*entry);
-		entry->name = (char *)entry + sizeof(*entry) + strlen(var->name) + 1;
-		strcpy(entry->cdrname, var->name);
-		strcpy(entry->name, var->value);
-
-		AST_LIST_INSERT_TAIL(&columns, entry, list);
-		ast_log(LOG_NOTICE, "Found an alias from CDR variable %s to DB column %s\n", entry->cdrname, entry->name);
-	}
-
-	ast_config_destroy(cfg);
+	}
 
 	ast_debug(1, "Got hostname of %s\n", hostname->str);
 	ast_debug(1, "Got port of %d\n", dbport);
@@ -535,7 +501,70 @@
 		connected = 1;
 		records = 0;
 		connect_time = time(NULL);
-	}
+
+		/* Get table description */
+		snprintf(sqldesc, sizeof(sqldesc), "DESC %s", dbtable ? dbtable->str : "cdr");
+		if (mysql_query(&mysql, sqldesc)) {
+			ast_log(LOG_ERROR, "Unable to query table description!!  Logging disabled.\n");
+			mysql_close(&mysql);
+			connected = 0;
+			AST_RWLIST_UNLOCK(&columns);
+			ast_config_destroy(cfg);
+			return AST_MODULE_LOAD_SUCCESS;
+		}
+
+		if (!(result = mysql_store_result(&mysql))) {
+			ast_log(LOG_ERROR, "Unable to query table description!!  Logging disabled.\n");
+			mysql_close(&mysql);
+			connected = 0;
+			AST_RWLIST_UNLOCK(&columns);
+			ast_config_destroy(cfg);
+			return AST_MODULE_LOAD_SUCCESS;
+		}
+
+		while ((row = mysql_fetch_row(result))) {
+			struct column *entry;
+			int foundalias = 0;
+
+			ast_debug(1, "Got a field '%s' of type '%s'\n", row[0], row[1]);
+			/* Check for an alias */
+			for (var = ast_variable_browse(cfg, "aliases"); var; var = var->next) {
+				if (strcasecmp(var->value, row[0])) {
+					continue;
+				}
+
+				if (!(entry = ast_calloc(1, sizeof(*entry) + strlen(var->name) + 1 + strlen(var->value) + 1 + strlen(row[1]) + 1))) {
+					continue;
+				}
+
+				entry->cdrname = (char *)entry + sizeof(*entry);
+				entry->name = (char *)entry + sizeof(*entry) + strlen(var->name) + 1;
+				entry->type = (char *)entry + sizeof(*entry) + strlen(var->name) + 1 + strlen(var->value) + 1;
+				strcpy(entry->cdrname, var->name);
+				strcpy(entry->name, var->value);
+				strcpy(entry->type, row[1]);
+
+				AST_LIST_INSERT_TAIL(&columns, entry, list);
+				ast_log(LOG_NOTICE, "Found an alias from CDR variable %s to DB column %s, type %s\n", entry->cdrname, entry->name, entry->type);
+				foundalias = 1;
+				break;
+			}
+
+			if (!foundalias && (entry = ast_calloc(1, sizeof(*entry) + strlen(row[0]) + 1 + strlen(row[1]) + 1))) {
+				entry->cdrname = (char *)entry + sizeof(*entry);
+				entry->name = (char *)entry + sizeof(*entry);
+				entry->type = (char *)entry + sizeof(*entry) + strlen(row[0]) + 1;
+				strcpy(entry->name, row[0]);
+				strcpy(entry->type, row[1]);
+
+				AST_LIST_INSERT_TAIL(&columns, entry, list);
+				ast_log(LOG_NOTICE, "Found a DB column %s, type %s\n", entry->name, entry->type);
+			}
+		}
+		mysql_free_result(result);
+	}
+	AST_RWLIST_UNLOCK(&columns);
+	ast_config_destroy(cfg);
 
 	res = ast_cdr_register(name, desc, mysql_log);
 	if (res) {




More information about the asterisk-addons-commits mailing list