[asterisk-commits] murf: branch group/newcdr r115108 - /team/group/newcdr/cel/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu May 1 18:22:09 CDT 2008


Author: murf
Date: Thu May  1 18:22:08 2008
New Revision: 115108

URL: http://svn.digium.com/view/asterisk?view=rev&rev=115108
Log:
updated cel_csv, cel_manager.c, and a bit of cel_odbc.c; more to come

Modified:
    team/group/newcdr/cel/cel_csv.c
    team/group/newcdr/cel/cel_custom.c
    team/group/newcdr/cel/cel_manager.c
    team/group/newcdr/cel/cel_odbc.c

Modified: team/group/newcdr/cel/cel_csv.c
URL: http://svn.digium.com/view/asterisk/team/group/newcdr/cel/cel_csv.c?view=diff&rev=115108&r1=115107&r2=115108
==============================================================================
--- team/group/newcdr/cel/cel_csv.c (original)
+++ team/group/newcdr/cel/cel_csv.c Thu May  1 18:22:08 2008
@@ -40,6 +40,7 @@
 #include <unistd.h>
 #include <time.h>
 
+#include "asterisk/paths.h"    /* use ast_config_AST_LOG_DIR */
 #include "asterisk/config.h"
 #include "asterisk/channel.h"
 #include "asterisk/cel.h"
@@ -48,6 +49,7 @@
 #include "asterisk/options.h"
 #include "asterisk/logger.h"
 #include "asterisk/utils.h"
+#include "asterisk/lock.h"
 
 #define CSV_LOG_DIR "/cel-csv"
 #define CSV_MASTER  "/Master.csv"
@@ -57,6 +59,7 @@
 static int usegmtime = 0;
 static int loguniqueid = 0;
 static int loguserfield = 0;
+static int loaded = 0;
 static char *config = "cel.conf";
 static struct ast_event_sub *event_sub = 0;
 
@@ -87,12 +90,14 @@
 
 static FILE *mf = NULL;
 
-
-static int load_config(void)
+AST_MUTEX_DEFINE_STATIC(mf_lock);
+AST_MUTEX_DEFINE_STATIC(acf_lock);
+
+static int load_config(int reload)
 {
 	struct ast_config *cfg;
 	struct ast_variable *var;
-	struct ast_flags config_flags = { 0 };
+	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
 	const char *tmp;
 
 	usegmtime = 0;
@@ -104,7 +109,10 @@
 	if (!cfg) {
 		ast_log(LOG_WARNING, "unable to load config: %s\n", config);
 		return 0;
-	}	
+	} else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
+		return 0;
+	
+
 	var = ast_variable_browse(cfg, "csv");
 	if (!var) {
 		ast_config_destroy(cfg);
@@ -146,11 +154,13 @@
 {
 	int pos = strlen(buf);
 	int spos = 0;
-	int error = 0;
+	int error = -1;
+
 	if (pos >= bufsize - 4)
 		return -1;
+
 	buf[pos++] = '\"';
-	error = -1;
+
 	while(pos < bufsize - 3) {
 		if (!s[spos]) {
 			error = 0;
@@ -161,9 +171,11 @@
 		buf[pos++] = s[spos];
 		spos++;
 	}
+
 	buf[pos++] = '\"';
 	buf[pos++] = ',';
 	buf[pos++] = '\0';
+
 	return error;
 }
 
@@ -181,18 +193,22 @@
 	return 0;
 	} */
 
-static int append_date(char *buf, struct timeval t, size_t bufsize)
+static int append_date(char *buf, struct timeval tv, size_t bufsize)
 {
 	char tmp[80] = "";
 	struct ast_tm tm;
+
 	if (strlen(buf) > bufsize - 3)
 		return -1;
-	if (ast_tvzero(t)) {
+
+	if (ast_tvzero(tv)) {
 		strncat(buf, ",", bufsize - strlen(buf) - 1);
 		return 0;
 	}
-	ast_localtime(&t, &tm, usegmtime? "GMT" : NULL);
+
+	ast_localtime(&tv, &tm, usegmtime ? "GMT" : NULL);
 	ast_strftime(tmp, sizeof(tmp), DATE_FORMAT, &tm);
+
 	return append_string(buf, tmp, bufsize);
 }
 
@@ -206,7 +222,7 @@
 {
 
 	buf[0] = '\0';
-	/* Start Time */
+	/* Event Time */
 	append_date(buf, eventtime, bufsize);
 	/* EventType */
 	if (eventtype==CEL_USER_DEFINED)
@@ -253,17 +269,28 @@
 {
 	char tmp[PATH_MAX];
 	FILE *f;
+
 	if (strchr(acc, '/') || (acc[0] == '.')) {
 		ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n", acc);
 		return -1;
 	}
-	snprintf(tmp, sizeof(tmp), "%s/%s/%s.csv", (char *)ast_config_AST_LOG_DIR,CSV_LOG_DIR, acc);
+
+	snprintf(tmp, sizeof(tmp), "%s/%s/%s.csv", ast_config_AST_LOG_DIR,CSV_LOG_DIR, acc);
+
+	ast_mutex_lock(&acf_lock);
+
 	f = fopen(tmp, "a");
-	if (!f)
+	if (!f) {
+		ast_mutex_unlock(&acf_lock);
+		ast_log(LOG_ERROR, "Unable to open file %s : %s\n", tmp, strerror(errno));
 		return -1;
+	}
+	
 	fputs(s, f);
 	fflush(f);
 	fclose(f);
+	ast_mutex_unlock(&acf_lock);
+
 	return 0;
 }
 
@@ -310,16 +337,17 @@
 		/* because of the absolutely unconditional need for the
 		   highest reliability possible in writing billing records,
 		   we open write and close the log file each time */
+		ast_mutex_lock(&mf_lock);
 		mf = fopen(csvmaster, "a");
 		if (!mf) {
 			ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", csvmaster, strerror(errno));
-		}
-		if (mf) {
+		} else {
 			fputs(buf, mf);
 			fflush(mf); /* be particularly anal here */
 			fclose(mf);
 			mf = NULL;
 		}
+		ast_mutex_unlock(&mf_lock);
 		if (!ast_strlen_zero(accountcode)) {
 			if (writefile(buf, (char*)accountcode))
 				ast_log(LOG_WARNING, "Unable to write CSV record to account file '%s' : %s\n", accountcode, strerror(errno));
@@ -330,34 +358,48 @@
 
 static int unload_module(void)
 {
-	if (mf)
+	if (mf) {
 		fclose(mf);
+		mf = NULL;
+	}
+	
 	if (event_sub)
 		ast_event_unsubscribe(event_sub);
 	event_sub = 0;
-	
+	loaded = 0;
 	return 0;
 }
 
 static int load_module(void)
 {
-	if(!load_config())
+	if(!load_config(0))
 		return AST_MODULE_LOAD_DECLINE;
 
 	event_sub = ast_event_subscribe(AST_EVENT_CEL, csv_log, "CSV Event Logging", NULL, AST_EVENT_IE_END);
 	
 	if (!event_sub) {
 		ast_log(LOG_ERROR, "Unable to register CSV CEL handling\n");
-		if (mf)
+		if (mf) {
+			mf = NULL;
 			fclose(mf);
-	}
+			loaded = 0;
+		}
+	} else {
+		loaded = 1;
+	}
+	
 	return 0;
 }
 
 static int reload(void)
 {
-	load_config();
-
+	if (load_config(1)) {
+		loaded = 1;
+	} else {
+		loaded = 0;
+		ast_log(LOG_WARNING, "No [csv] section in cel.conf.\n");
+	}
+	
 	return 0;
 }
 

Modified: team/group/newcdr/cel/cel_custom.c
URL: http://svn.digium.com/view/asterisk/team/group/newcdr/cel/cel_custom.c?view=diff&rev=115108&r1=115107&r2=115108
==============================================================================
--- team/group/newcdr/cel/cel_custom.c (original)
+++ team/group/newcdr/cel/cel_custom.c Thu May  1 18:22:08 2008
@@ -1,10 +1,10 @@
 /*
  * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 2007, Digium, Inc.
+ * Copyright (C) 2008, Digium, Inc.
  *
  * Steve Murphy <murf at digium.com>
- * much borrowed from cdr code, author Mark Spencer
+ * much borrowed from cdr code (cdr_custom.c), author Mark Spencer
  *
  * See http://www.asterisk.org for more information about
  * the Asterisk project. Please do not directly contact
@@ -42,6 +42,7 @@
 #include <unistd.h>
 #include <time.h>
 
+#include "asterisk/paths.h"    /* use ast_config_AST_LOG_DIR */
 #include "asterisk/channel.h"
 #include "asterisk/cel.h"
 #include "asterisk/module.h"
@@ -55,6 +56,7 @@
 #define DATE_FORMAT "%Y-%m-%d %T"
 
 AST_MUTEX_DEFINE_STATIC(lock);
+AST_MUTEX_DEFINE_STATIC(mf_lock);
 
 static char *name = "cel-custom";
 
@@ -71,19 +73,22 @@
 	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
 	int res = -1;
 
+	if ((cfg = ast_config_load("cdr_custom.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
+		return 0;
+	
 	strcpy(format, "");
 	strcpy(master, "");
-	if((cfg = ast_config_load("cel_custom.conf", config_flags))) {
+	ast_mutex_lock(&lock);
+
+	if(cfg) {
 		var = ast_variable_browse(cfg, "mappings");
 		while(var) {
-			ast_mutex_lock(&lock);
 			if (!ast_strlen_zero(var->name) && !ast_strlen_zero(var->value)) {
 				if (strlen(var->value) > (sizeof(format) - 1))
 					ast_log(LOG_WARNING, "Format string too long, will be truncated, at line %d\n", var->lineno);
 				ast_copy_string(format, var->value, sizeof(format) - 1);
 				strcat(format,"\n");
 				snprintf(master, sizeof(master),"%s/%s/%s", ast_config_AST_LOG_DIR, name, var->name);
-				ast_mutex_unlock(&lock);
 			} else
 				ast_log(LOG_NOTICE, "Mapping must have both filename and format at line %d\n", var->lineno);
 			if (var->next)
@@ -98,6 +103,7 @@
 		else
 			ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
 	}
+	ast_mutex_unlock(&lock);
 	
 	return res;
 }
@@ -178,23 +184,26 @@
 	/* because of the absolutely unconditional need for the
 	   highest reliability possible in writing billing records,
 	   we open write and close the log file each time */
+	ast_mutex_lock(&mf_lock);
 	mf = fopen(master, "a");
 	if (!mf) {
 		ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", master, strerror(errno));
-	}
-	if (mf) {
+	} else {
 		fputs(buf, mf);
 		fflush(mf); /* be particularly anal here */
 		fclose(mf);
 		mf = NULL;
 	}
+	ast_mutex_unlock(&mf_lock);
 	return;
 }
 
 static int unload_module(void)
 {
-	if (mf)
+	if (mf) {
 		fclose(mf);
+		mf = NULL;
+	}
 	if (event_sub)
 		ast_event_unsubscribe(event_sub);
 	event_sub = 0;
@@ -207,12 +216,15 @@
 	if (!load_config(0)) {
 		event_sub = ast_event_subscribe(AST_EVENT_CEL, custom_log, "Custom CSV logging", NULL, AST_EVENT_IE_END);
 
-		if (!event_sub)
+		if (mf)
+		{
+			fclose(mf);
+			mf = NULL;
+		}
+		if (!event_sub) {
 			ast_log(LOG_ERROR, "Unable to register custom CEL handling\n");
-		if (mf)
-			fclose(mf);
-		if (!event_sub)
 			return AST_MODULE_LOAD_DECLINE;
+		}
 		return 0;
 	} else 
 		return AST_MODULE_LOAD_DECLINE;

Modified: team/group/newcdr/cel/cel_manager.c
URL: http://svn.digium.com/view/asterisk/team/group/newcdr/cel/cel_manager.c?view=diff&rev=115108&r1=115107&r2=115108
==============================================================================
--- team/group/newcdr/cel/cel_manager.c (original)
+++ team/group/newcdr/cel/cel_manager.c Thu May  1 18:22:08 2008
@@ -1,11 +1,11 @@
 /*
  * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 2007 Digium, Inc
+ * Copyright (C) 2008 Digium, Inc
  *
  * Steve Murphy <murf at digium.com>
  * who freely borrowed code from the cdr equivalents
- *
+ *     (see cdr/cdr_manager.c)
  * 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;
@@ -48,34 +48,64 @@
 #define DATE_FORMAT 	"%Y-%m-%d %T"
 #define CONF_FILE	"cel_manager.conf"
 
+#define CUSTOM_FIELDS_BUF_SIZE 1024
+
+struct ast_str *customfields;
+
 static int enablecel = 0;
 static struct ast_event_sub *event_sub = 0;
+static void manager_log(const struct ast_event *event, void *userdata);
 
 static int load_config(int reload)
 {
-	char *cat;
+	char *cat = NULL;
 	struct ast_config *cfg;
 	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
 	struct ast_variable *v;
+	int newenablecel = 0;
 	
 	cfg = ast_config_load(CONF_FILE, config_flags);
+	if (cfg == CONFIG_STATUS_FILEUNCHANGED)
+		return 0;
+	
+	if (reload && customfields) {
+		ast_free(customfields);
+	}
+	customfields = NULL;
+	
 	if (!cfg) {
+		ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
 		/* Standard configuration */
 		enablecel = 0;
 		return 0;
 	}
 	
-	cat = ast_category_browse(cfg, NULL);
-	while (cat) {
+	while ( (cat = ast_category_browse(cfg, cat)) ) {
 		if (!strcasecmp(cat, "general")) {
 			v = ast_variable_browse(cfg, cat);
 			while (v) {
 				if (!strcasecmp(v->name, "enabled")) {
-					enablecel = ast_true(v->value);
+					newenablecel = ast_true(v->value);
 				}
 				
 				v = v->next;
 			}
+			
+		} else if (!strcasecmp(cat, "mappings")) {
+			customfields = ast_str_create(CUSTOM_FIELDS_BUF_SIZE);
+			v = ast_variable_browse(cfg, cat);
+			while (v) {
+				if (customfields && !ast_strlen_zero(v->name) && !ast_strlen_zero(v->value)) {
+					if( (customfields->used + strlen(v->value) + strlen(v->name) + 14) < customfields->len) {
+						ast_str_append(&customfields, -1, "%s: ${CDR(%s)}\r\n", v->value, v->name);
+						ast_log(LOG_NOTICE, "Added mapping %s: ${CDR(%s)}\n", v->value, v->name);
+					} else {
+						ast_log(LOG_WARNING, "No more buffer space to add other custom fields\n");
+						break;
+					}
+					
+				}
+			}
 		}
 	
 		/* Next category */
@@ -83,6 +113,19 @@
 	}
 	
 	ast_config_destroy(cfg);
+
+	if (enablecel && !newenablecel) {
+		if (event_sub)
+			ast_event_unsubscribe(event_sub);
+		event_sub = 0;
+	} else if (!enablecel && newenablecel) {
+		event_sub = ast_event_subscribe(AST_EVENT_CEL, manager_log, "Manager Event Logging", NULL, AST_EVENT_IE_END);
+		if (!event_sub) {
+			ast_log(LOG_ERROR, "Unable to register Asterisk Call Manager CEL handling\n");
+		}
+	}
+	enablecel = newenablecel;
+	
 	return 1;
 }
 
@@ -156,6 +199,9 @@
 {
 	if (event_sub)
 		ast_event_unsubscribe(event_sub);
+	if (customfields)
+		ast_free(customfields);
+	customfields = NULL;
 	event_sub = 0;
 	return 0;
 }
@@ -166,14 +212,7 @@
 	if (!load_config(0))
 		return AST_MODULE_LOAD_DECLINE;
 	
-	event_sub = ast_event_subscribe(AST_EVENT_CEL, manager_log, "Manager Event Logging", NULL, AST_EVENT_IE_END);
-	if (!event_sub) {
-		ast_log(LOG_ERROR, "Unable to register Asterisk Call Manager CEL handling\n");
-	}
-	if (!event_sub)
-		return AST_MODULE_LOAD_DECLINE;
-	else
-		return 0;
+	return AST_MODULE_LOAD_SUCCESS;
 }
 
 static int reload(void)

Modified: team/group/newcdr/cel/cel_odbc.c
URL: http://svn.digium.com/view/asterisk/team/group/newcdr/cel/cel_odbc.c?view=diff&rev=115108&r1=115107&r2=115108
==============================================================================
--- team/group/newcdr/cel/cel_odbc.c (original)
+++ team/group/newcdr/cel/cel_odbc.c Thu May  1 18:22:08 2008
@@ -1,7 +1,7 @@
 /*
  * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 2007, Digium, Inc.
+ * Copyright (C) 2008, Digium, Inc.
  *
  * Brian K. West <brian at bkw.org> original CDR version
  * Steve Murphy <murf at digium.com> Adaptation to CEL
@@ -31,6 +31,7 @@
 
 /*** MODULEINFO
 	<depend>unixodbc</depend>
+	<depend>ltdl</depend>
  ***/
 
 #include "asterisk.h"
@@ -56,16 +57,22 @@
 #include <w32api/sqltypes.h>
 #endif
 
+enum {
+	CONFIG_LOGUNIQUEID =       1 << 0,
+	CONFIG_USEGMTIME =         1 << 1,
+	CONFIG_DISPOSITIONSTRING = 1 << 2,
+};
 #include "asterisk/config.h"
 #include "asterisk/options.h"
 #include "asterisk/channel.h"
 #include "asterisk/cel.h"
 #include "asterisk/module.h"
+#include "asterisk/res_odbc.h"
 #include "asterisk/logger.h"
 
 #define DATE_FORMAT "%Y-%m-%d %T"
 
-static char *config = "cel_odbc.conf";
+static char *config_file = "cel_odbc.conf";
 static char *dsn = NULL, *username = NULL, *password = NULL, *table = NULL;
 static int loguniqueid = 0;
 static int usegmtime = 0;
@@ -82,6 +89,8 @@
 static SQLHSTMT	ODBC_stmt;			/* global ODBC Statement Handle */
 static struct ast_event_sub *event_sub = 0;
 
+static struct ast_flags config = { 0 };
+
 static void odbc_disconnect(void)
 {
 	SQLDisconnect(ODBC_con);
@@ -90,12 +99,13 @@
 	connected = 0;
 }
 
-static void odbc_log(const struct ast_event *event, void *userdata)
-{
-	int ODBC_res;
+static SQLHSTMT execute_cb(struct odbc_obj *obj, void *data)
+{
+	SQLRETURN ODBC_res;
 	char sqlcmd[2048] = "", timestr[128];
-	int res = 0;
+	struct ast_event *event = data;
 	struct ast_tm tm;
+	SQLHSTMT stmt;
 	enum ast_cel_eventtype eventtype;
 	const char *userdefname = 0;
 	struct timeval eventtime = {0};
@@ -129,10 +139,8 @@
 
 	ast_localtime(&eventtime, &tm, usegmtime ? "GMT" : NULL);
 
-	ast_mutex_lock(&odbc_lock);
 	ast_strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
-	memset(sqlcmd,0,2048);
-	if (loguniqueid) {
+	if (ast_test_flag(&config, CONFIG_LOGUNIQUEID)) {
 		snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO %s "
 		"(eventtime,eventtype,cidname,cidnum,cidani,cidrdnis,ciddnid,exten,context,channel,app,"
 		"appdata,amaflags,accountcode,userfield,peer,uniqueid) "
@@ -143,119 +151,77 @@
 		"amaflags,accountcode,userfield,peer) "
 		"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", table);
 	}
-
-	if (!connected) {
-		res = odbc_init();
-		if (res < 0) {
-			odbc_disconnect();
-			ast_mutex_unlock(&odbc_lock);
-			return;
-		}				
-	}
-
-	ODBC_res = SQLAllocHandle(SQL_HANDLE_STMT, ODBC_con, &ODBC_stmt);
+	
+	ODBC_res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
 
 	if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
-		if (option_verbose > 10)
-			ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Failure in AllocStatement %d\n", ODBC_res);
-		SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
-		odbc_disconnect();
-		ast_mutex_unlock(&odbc_lock);
+		ast_verb(11, "cel_odbc: Failure in AllocStatement %d\n", ODBC_res);
+		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+		return NULL;
+	}
+
+	SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(timestr), 0, &timestr, 0, NULL);
+	SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(userdefname), 0, (char*)userdefname, 0, NULL);
+	SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cid_name), 0, (char*)cid_name, 0, NULL);
+	SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cid_num), 0,  (char*)cid_num, 0, NULL);
+	SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cid_ani), 0,  (char*)cid_ani, 0, NULL);
+	SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cid_rdnis), 0,  (char*)cid_rdnis, 0, NULL);
+	SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cid_dnid), 0,  (char*)cid_dnid, 0, NULL);
+	SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(exten), 0, (char*)exten, 0, NULL);
+	SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(context), 0, (char*)context, 0, NULL);
+	SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(channame), 0, (char*)channame, 0, NULL);
+	SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(appname), 0, (char*)appname, 0, NULL);
+	SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(appdata), 0, (char*)appdata, 0, NULL);
+	SQLBindParameter(stmt, 13, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, (int*)&amaflag, 0, NULL);
+	SQLBindParameter(stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(accountcode), 0, (char*)accountcode, 0, NULL);
+	SQLBindParameter(stmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(userfield), 0, (char*)userfield, 0, NULL);
+	SQLBindParameter(stmt, 16, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(peer), 0, (char*)peer, 0, NULL);
+
+	if (ast_test_flag(&config, CONFIG_LOGUNIQUEID)) {
+		SQLBindParameter(stmt, 17, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(uniqueid), 0, (char*)uniqueid, 0, NULL);
+	}
+
+	ODBC_res = SQLExecDirect(stmt, (unsigned char *)sqlcmd, SQL_NTS);
+
+	if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
+		ast_verb(11, "cdr_odbc: Error in ExecDirect: %d\n", ODBC_res);
+		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+		return NULL;
+	}
+
+	return stmt;
+}
+
+static void odbc_log(const struct ast_event *event, void *userdata)
+{
+	struct odbc_obj *obj = ast_odbc_request_obj(dsn, 0);
+	SQLHSTMT stmt;
+	if (!obj) {
+		ast_log(LOG_ERROR, "Unable to retrieve database handle.  CDR failed.\n");
 		return;
 	}
-
-	/* We really should only have to do this once.  But for some
-	   strange reason if I don't it blows holes in memory like
-	   like a shotgun.  So we just do this so its safe. */
-
-	ODBC_res = SQLPrepare(ODBC_stmt, (unsigned char *)sqlcmd, SQL_NTS);
-	
-	if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
-		if (option_verbose > 10)
-			ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Error in PREPARE %d\n", ODBC_res);
-		SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
-		odbc_disconnect();
-		ast_mutex_unlock(&odbc_lock);
-		return;
-	}
-
-	SQLBindParameter(ODBC_stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(timestr), 0, &timestr, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(userdefname), 0, (char*)userdefname, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cid_name), 0, (char*)cid_name, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cid_num), 0,  (char*)cid_num, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cid_ani), 0,  (char*)cid_ani, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cid_rdnis), 0,  (char*)cid_rdnis, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cid_dnid), 0,  (char*)cid_dnid, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(exten), 0, (char*)exten, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(context), 0, (char*)context, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(channame), 0, (char*)channame, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(appname), 0, (char*)appname, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(appdata), 0, (char*)appdata, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 13, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, (int*)&amaflag, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(accountcode), 0, (char*)accountcode, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(userfield), 0, (char*)userfield, 0, NULL);
-	SQLBindParameter(ODBC_stmt, 16, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(peer), 0, (char*)peer, 0, NULL);
-
-	if (loguniqueid) {
-		SQLBindParameter(ODBC_stmt, 17, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(uniqueid), 0, (char*)uniqueid, 0, NULL);
-	}
-
-	if (connected) {
-		res = odbc_do_query();
-		if (res < 0) {
-			if (option_verbose > 10)		
-				ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Query FAILED Call not logged!\n");
-			if (option_verbose > 10)
-				ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Reconnecting to dsn %s\n", dsn);
-			SQLDisconnect(ODBC_con);
-			res = odbc_init();
-			if (res < 0) {
-				if (option_verbose > 10)
-					ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: %s has gone away!\n", dsn);
-				odbc_disconnect();
-			} else {
-				if (option_verbose > 10)
-					ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Trying Query again!\n");
-				res = odbc_do_query();
-				if (res < 0) {
-					if (option_verbose > 10)
-						ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Query FAILED Call not logged!\n");
-				}
-			}
-		}
-	} else {
-		if (option_verbose > 10)
-			ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Query FAILED Call not logged!\n");
-	}
-	SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
-	ast_mutex_unlock(&odbc_lock);
-	return;
-}
+	stmt = ast_odbc_direct_execute(obj, execute_cb, event);
+	if (stmt) {
+		SQLLEN rows = 0;
+		
+		SQLRowCount(stmt, &rows);
+		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+		
+		if (rows == 0)
+			ast_log(LOG_WARNING, "CEL successfully ran, but inserted 0 rows?\n");
+	} else
+		ast_log(LOG_ERROR, "CEL direct execute failed\n");
+	ast_odbc_release_obj(obj);
+}
+
 
 static int odbc_unload_module(void)
 {
-	ast_mutex_lock(&odbc_lock);
-	if (connected) {
-		if (option_verbose > 10)
-			ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Disconnecting from %s\n", dsn);
-		SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
-		odbc_disconnect();
-	}
 	if (dsn) {
 		if (option_verbose > 10)
 			ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: free dsn\n");
 		free(dsn);
 	}
-	if (username) {
-		if (option_verbose > 10)
-			ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: free username\n");
-		free(username);
-	}
-	if (password) {
-		if (option_verbose > 10)
-			ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: free password\n");
-		free(password);
-	}
 	if (table) {
 		if (option_verbose > 10)
 			ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: free table\n");
@@ -265,7 +231,6 @@
 	if (event_sub)
 		ast_event_unsubscribe(event_sub);
 	event_sub = 0;
-	ast_mutex_unlock(&odbc_lock);
 	return 0;
 }
 
@@ -274,212 +239,91 @@
 	int res = 0;
 	struct ast_config *cfg;
 	struct ast_variable *var;
+	const char *tmp;
 	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
-	const char *tmp;
-
-	ast_mutex_lock(&odbc_lock);
-
-	cfg = ast_config_load(config, config_flags);
-	if (!cfg) {
-		ast_log(LOG_WARNING, "cel_odbc: Unable to load config for ODBC CEL's: %s\n", config);
-		res = AST_MODULE_LOAD_DECLINE;
-		goto out;
-	}
-	
-	var = ast_variable_browse(cfg, "global");
-	if (!var) {
-		/* nothing configured */
-		goto out;
-	}
-
-	tmp = ast_variable_retrieve(cfg,"global","dsn");
-	if (tmp == NULL) {
-		ast_log(LOG_WARNING,"cel_odbc: dsn not specified.  Assuming asteriskdb\n");
-		tmp = "asteriskdb";
-	}
-	dsn = strdup(tmp);
-	if (dsn == NULL) {
-		ast_log(LOG_ERROR,"cel_odbc: Out of memory error.\n");
-		res = -1;
-		goto out;
-	}
-
-	tmp = ast_variable_retrieve(cfg,"global","dispositionstring");
-	if (tmp) {
-		dispositionstring = ast_true(tmp);
-	} else {
-		dispositionstring = 0;
-	}
-		
-	tmp = ast_variable_retrieve(cfg,"global","username");
-	if (tmp) {
-		username = strdup(tmp);
-		if (username == NULL) {
+
+	do 
+	{
+		
+		cfg = ast_config_load(config_file, config_flags);
+		if (!cfg) {
+			ast_log(LOG_WARNING, "cel_odbc: Unable to load config for ODBC CEL's: %s\n", config_file);
+			res = AST_MODULE_LOAD_DECLINE;
+			break;
+		} else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
+			break;
+		
+		var = ast_variable_browse(cfg, "global");
+		if (!var) {
+			/* nothing configured */
+			break;
+		}
+		
+		tmp = ast_variable_retrieve(cfg,"global","dsn");
+		if (tmp == NULL) {
+			ast_log(LOG_WARNING,"cel_odbc: dsn not specified.  Assuming asteriskdb\n");
+			tmp = "asteriskdb";
+		}
+		if (dsn)
+			ast_free(dsn);
+		dsn = strdup(tmp);
+		if (dsn == NULL) {
 			ast_log(LOG_ERROR,"cel_odbc: Out of memory error.\n");
 			res = -1;
-			goto out;
-		}
-	}
-
-	tmp = ast_variable_retrieve(cfg,"global","password");
-	if (tmp) {
-		password = strdup(tmp);
-		if (password == NULL) {
+			break;
+		}
+		
+		tmp = ast_variable_retrieve(cfg,"global","dispositionstring");
+		if (ast_true(tmp)) {
+			ast_set_flag(&config, CONFIG_DISPOSITIONSTRING);
+		} else {
+			ast_clear_flag(&config, CONFIG_DISPOSITIONSTRING);
+		}
+		
+		tmp = ast_variable_retrieve(cfg,"global","loguniqueid");
+		if (ast_true(tmp)) {
+			ast_set_flag(&config, CONFIG_LOGUNIQUEID);
+			ast_debug(1,"cel_odbc: Logging uniqueid\n");
+		} else {
+			ast_debug(1,"cel_odbc: Not logging uniqueid\n");
+			ast_clear_flag(&config, CONFIG_LOGUNIQUEID);
+		}
+		
+		tmp = ast_variable_retrieve(cfg,"global","usegmtime");
+		if (ast_true(tmp)) {
+			ast_set_flag(&config, CONFIG_USEGMTIME);
+			ast_debug(1, "cdr_odbc: Logging in GMT\n");
+		} else {
+			ast_debug(1, "cdr_odbc: Logging in local time\n");
+			ast_clear_flag(&config, CONFIG_USEGMTIME);
+		}
+		
+		tmp = ast_variable_retrieve(cfg,"global","table");
+		if (tmp == NULL) {
+			ast_log(LOG_WARNING,"cel_odbc: table not specified.  Assuming cel\n");
+			tmp = "cel";
+		}
+		if (table)
+			ast_free(table);
+		table = strdup(tmp);
+		if (table == NULL) {
 			ast_log(LOG_ERROR,"cel_odbc: Out of memory error.\n");
 			res = -1;
-			goto out;
-		}
-	}
-
-	tmp = ast_variable_retrieve(cfg,"global","loguniqueid");
-	if (tmp) {
-		loguniqueid = ast_true(tmp);
-		if (loguniqueid) {
-			if (option_debug)
-				ast_log(LOG_DEBUG,"cel_odbc: Logging uniqueid\n");
-		} else {
-			if (option_debug)
-				ast_log(LOG_DEBUG,"cel_odbc: Not logging uniqueid\n");
-		}
-	} else {
-		if (option_debug)
-			ast_log(LOG_DEBUG,"cel_odbc: Not logging uniqueid\n");
-		loguniqueid = 0;
-	}
-
-	tmp = ast_variable_retrieve(cfg,"global","usegmtime");
-	if (tmp) {
-		usegmtime = ast_true(tmp);
-		if (usegmtime) {
-			if (option_debug)
-				ast_log(LOG_DEBUG,"cel_odbc: Logging in GMT\n");
-		} else {
-			if (option_debug)
-				ast_log(LOG_DEBUG,"cel_odbc: Not logging in GMT\n");
-		}
-	} else {
-		if (option_debug)
-			ast_log(LOG_DEBUG,"cel_odbc: Not logging in GMT\n");
-		usegmtime = 0;
-	}
-
-	tmp = ast_variable_retrieve(cfg,"global","table");
-	if (tmp == NULL) {
-		ast_log(LOG_WARNING,"cel_odbc: table not specified.  Assuming cel\n");
-		tmp = "cel";
-	}
-	table = strdup(tmp);
-	if (table == NULL) {
-		ast_log(LOG_ERROR,"cel_odbc: Out of memory error.\n");
-		res = -1;
-		goto out;
-	}
-
-	if (option_verbose > 2) {
-		ast_verbose( VERBOSE_PREFIX_3 "cel_odbc: dsn is %s\n",dsn);
-		if (username)
-		{
-			ast_verbose( VERBOSE_PREFIX_3 "cel_odbc: username is %s\n",username);
-			ast_verbose( VERBOSE_PREFIX_3 "cel_odbc: password is [secret]\n");
-		}
-		else
-			ast_verbose( VERBOSE_PREFIX_3 "cel_odbc: retreiving username and password from odbc config\n");
-		ast_verbose( VERBOSE_PREFIX_3 "cel_odbc: table is %s\n",table);
-	}
+			break;
+		}
+		
+		ast_verb(3, "cdr_odbc: dsn is %s\n", dsn);
+		ast_verb(3, "cdr_odbc: table is %s\n", table);
+		
+		event_sub = ast_event_subscribe(AST_EVENT_CEL, odbc_log, "CEL ODBC backend", NULL, AST_EVENT_IE_END);
+		if (!event_sub) {
+			ast_log(LOG_ERROR, "cel_odbc: Unable to register ODBC CEL handling\n");
+		}
+	} while(0);
 	
-	res = odbc_init();
-	if (res < 0) {
-		ast_log(LOG_ERROR, "cel_odbc: Unable to connect to datasource: %s\n", dsn);
-		if (option_verbose > 2) {
-			ast_verbose( VERBOSE_PREFIX_3 "cel_odbc: Unable to connect to datasource: %s\n", dsn);
-		}
-	}
-	event_sub = ast_event_subscribe(AST_EVENT_CEL, odbc_log, "CEL ODBC backend", NULL, AST_EVENT_IE_END);
-	if (!event_sub) {
-		ast_log(LOG_ERROR, "cel_odbc: Unable to register ODBC CEL handling\n");
-	}
-out:
-	if (cfg)
+	if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED)
 		ast_config_destroy(cfg);
-	ast_mutex_unlock(&odbc_lock);
-	if (event_sub)
-		return 0;
-	else
-		return AST_MODULE_LOAD_DECLINE;
-}
-
-static int odbc_do_query(void)
-{
-	int ODBC_res;
-	
-	ODBC_res = SQLExecute(ODBC_stmt);
-	
-	if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
-		if (option_verbose > 10)
-			ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Error in Query %d\n", ODBC_res);
-		SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
-		odbc_disconnect();
-		return -1;
-	} else {
-		if (option_verbose > 10)
-			ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Query Successful!\n");
-		connected = 1;
-	}
-	return 0;
-}
-
-static int odbc_init(void)
-{
-	int ODBC_res;
-
-	if (ODBC_env == SQL_NULL_HANDLE || connected == 0) {
-		ODBC_res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &ODBC_env);
-		if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
-			if (option_verbose > 10)
-				ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Error AllocHandle\n");
-			connected = 0;
-			return -1;
-		}
-
-		ODBC_res = SQLSetEnvAttr(ODBC_env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
-
-		if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
-			if (option_verbose > 10)
-				ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Error SetEnv\n");
-			SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
-			connected = 0;
-			return -1;
-		}
-
-		ODBC_res = SQLAllocHandle(SQL_HANDLE_DBC, ODBC_env, &ODBC_con);
-
-		if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
-			if (option_verbose > 10)
-				ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Error AllocHDB %d\n", ODBC_res);
-			SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
-			connected = 0;
-			return -1;
-		}
-		SQLSetConnectAttr(ODBC_con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)10, 0);	
-	}
-
-	/* Note that the username and password could be NULL here, but that is allowed in ODBC.
-           In this case, the default username and password will be used from odbc.conf */
-	ODBC_res = SQLConnect(ODBC_con, (SQLCHAR*)dsn, SQL_NTS, (SQLCHAR*)username, SQL_NTS, (SQLCHAR*)password, SQL_NTS);
-
-	if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
-		if (option_verbose > 10)
-			ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Error SQLConnect %d\n", ODBC_res);
-		SQLFreeHandle(SQL_HANDLE_DBC, ODBC_con);
-		SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
-		connected = 0;
-		return -1;
-	} else {
-		if (option_verbose > 10)
-			ast_verbose( VERBOSE_PREFIX_4 "cel_odbc: Connected to %s\n", dsn);
-		connected = 1;
-	}
-	return 0;
+	return res;
 }
 
 static int load_module(void)
@@ -494,7 +338,6 @@
 
 static int reload(void)
 {
-	odbc_unload_module();
 	return odbc_load_module(1);
 }
 




More information about the asterisk-commits mailing list