Index: include/asterisk/cdr.h =================================================================== --- include/asterisk/cdr.h (revision 82624) +++ include/asterisk/cdr.h (working copy) @@ -180,18 +180,12 @@ /*! * \brief Unregister a CDR handling engine * \param name name of CDR handler to unregister - * \param name_detail name of CDR handler sink to unregister + * \param name_detail name of CDR handler sink to unregister, or + * NULL for all sinks for the specfied handler * Unregisters a CDR by it's name */ void ast_cdr_unregister(const char *name, const char *name_detail); -/*! - * \brief Unregister all sinks for a specific CDR handling engine - * \param name name of CDR handler to unregister - * Unregisters all CDR engine sinks by handler name - */ -void ast_cdr_unregister_all(const char *name); - /*! * \brief Start a call * \param cdr the cdr you wish to associate with the call Index: main/cdr.c =================================================================== --- main/cdr.c (revision 82624) +++ main/cdr.c (working copy) @@ -150,7 +150,7 @@ AST_RWLIST_WRLOCK(&be_list); AST_RWLIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) { - if (!strcasecmp(name, i->name) && !strcasecmp(name_detail, i->name_detail)) { + if (!strcasecmp(name, i->name) && (!name_detail || !strcasecmp(name_detail, i->name_detail))) { i->cancel_thread = 1; /* signal the thread so it can exit */ ast_cond_signal(&i->cdr_pending_cond); @@ -164,36 +164,9 @@ ast_verbose(VERBOSE_PREFIX_2 "Unregistered '%s - %s' CDR backend\n", i->name, i->name_detail); if (i->cleanup) i->cleanup(i->be_data); - ast_free(i); - break; - } - } - AST_RWLIST_TRAVERSE_SAFE_END; - AST_RWLIST_UNLOCK(&be_list); -} - -/*! unregister all CDR drivers using the specifed name */ -void ast_cdr_unregister_all(const char *name) -{ - struct ast_cdr_beitem *i = NULL; - - AST_RWLIST_WRLOCK(&be_list); - AST_RWLIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) { - if (!strcasecmp(name, i->name)) { - i->cancel_thread = 1; - /* signal the thread so it can exit */ - ast_cond_signal(&i->cdr_pending_cond); - /* wait for thread to exit so we can clean up */ - pthread_join(i->cdr_thread, NULL); - i->cdr_thread = AST_PTHREADT_NULL; - ast_cond_destroy(&i->cdr_pending_cond); - ast_cond_destroy(&i->cdr_retry_cond); - AST_RWLIST_REMOVE_CURRENT(&be_list, list); - if (option_verbose > 1) - ast_verbose(VERBOSE_PREFIX_2 "Unregistered '%s - %s' CDR backend\n", i->name, i->name_detail); - if (i->cleanup) - i->cleanup(i->be_data); ast_free(i); + if (name_detail) + break; } } AST_RWLIST_TRAVERSE_SAFE_END; @@ -896,20 +869,27 @@ if (argc > 2) return RESULT_SHOWUSAGE; - // what if there are no backends? - ast_cli(fd, "CDR logging: %s\n", enabled ? "enabled" : "disabled"); + /* What if there are no backends? */ + ast_cli(fd, "\nCall Detail Recording (CDR) Status\n"); + ast_cli(fd, "----------------------------------\n"); + ast_cli(fd, " Engine status: %s\n", enabled ? "Enabled" : "Disabled"); + + /* Since we unregister the CLI command when enabled=no, we will never get when !enabled */ if (enabled) { - ast_cli(fd, "CDR safe shut down: %s\n", safeshutdown ? "enabled" : "disabled"); + ast_cli(fd, " Safe shutdown: %s\n\n", safeshutdown ? "Enabled" : "Disabled"); + ast_cli(fd, "* Registered Backends:\n"); + ast_cli(fd, " --------------------\n"); AST_RWLIST_RDLOCK(&be_list); AST_RWLIST_TRAVERSE(&be_list, beitem, list) { if (ast_strlen_zero(beitem->name_detail)) { - ast_cli(fd, "CDR registered backend: %s\n", beitem->name); + ast_cli(fd, " %s\n", beitem->desc); } else { - ast_cli(fd, "CDR registered backend: %s (%s)\n", beitem->name, beitem->name_detail); + ast_cli(fd, " %s (%s)\n", beitem->desc, beitem->name_detail); } } AST_RWLIST_UNLOCK(&be_list); } + ast_cli(fd, "\n"); return 0; } @@ -971,13 +951,12 @@ if ((end_before_h_value = ast_variable_retrieve(config, "general", "endbeforehexten"))) ast_set2_flag(&ast_options, ast_true(end_before_h_value), AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN); - } if (enabled) { ast_log(LOG_NOTICE, "CDR simple logging enabled.\n"); } else { - ast_log(LOG_NOTICE, "CDR logging disabled, data will be lost.\n"); + ast_log(LOG_NOTICE, "CDR logging disabled, no data will be stored.\n"); } if (was_enabled && !enabled) { Index: cdr/cdr_csv.c =================================================================== --- cdr/cdr_csv.c (revision 82624) +++ cdr/cdr_csv.c (working copy) @@ -314,7 +314,7 @@ { if (mf) fclose(mf); - ast_cdr_unregister_all(name); + ast_cdr_unregister(name, NULL); return 0; } Index: cdr/cdr_adaptive_odbc.c =================================================================== --- cdr/cdr_adaptive_odbc.c (revision 82624) +++ cdr/cdr_adaptive_odbc.c (working copy) @@ -53,9 +53,10 @@ #include "asterisk/module.h" #include "asterisk/logger.h" -#define CONFIG "cdr_adaptive_odbc.conf" +#define CONFIG "cdr_adaptive_odbc.conf" static char *name = "Adaptive ODBC"; + /* Optimization to reduce number of memory allocations */ static int maxsize = 512, maxsize2 = 512; @@ -201,12 +202,12 @@ } else /* Point to same place as the column name */ entry->cdrname = (char *)entry + sizeof(*entry); - SQLGetData(stmt, 5, SQL_C_SHORT, &entry->type, sizeof(entry->type), NULL); - SQLGetData(stmt, 7, SQL_C_LONG, &entry->size, sizeof(entry->size), NULL); + SQLGetData(stmt, 5, SQL_C_SHORT, &entry->type, sizeof(entry->type), NULL); + SQLGetData(stmt, 7, SQL_C_LONG, &entry->size, sizeof(entry->size), NULL); SQLGetData(stmt, 9, SQL_C_SHORT, &entry->decimals, sizeof(entry->decimals), NULL); - SQLGetData(stmt, 10, SQL_C_SHORT, &entry->radix, sizeof(entry->radix), NULL); + SQLGetData(stmt, 10, SQL_C_SHORT, &entry->radix, sizeof(entry->radix), NULL); SQLGetData(stmt, 11, SQL_C_SHORT, &entry->nullable, sizeof(entry->nullable), NULL); - SQLGetData(stmt, 16, SQL_C_LONG, &entry->octetlen, sizeof(entry->octetlen), NULL); + SQLGetData(stmt, 16, SQL_C_LONG, &entry->octetlen, sizeof(entry->octetlen), NULL); /* Specification states that the octenlen should be the maximum number of bytes * returned in a char or binary column, but it seems that some drivers just set @@ -316,252 +317,253 @@ tableptr = (struct table *) data; - lensql = snprintf(sql, sizesql, "INSERT INTO %s (", tableptr->table); - lensql2 = snprintf(sql2, sizesql2, " VALUES ("); + lensql = snprintf(sql, sizesql, "INSERT INTO %s (", tableptr->table); + lensql2 = snprintf(sql2, sizesql2, " VALUES ("); - AST_LIST_TRAVERSE(&(tableptr->columns), entry, list) { - /* Check if we have a similarly named variable */ - ast_cdr_getvar(cdr, entry->cdrname, &colptr, colbuf, sizeof(colbuf), 0, - (strcasecmp(entry->cdrname, "start") == 0 || - strcasecmp(entry->cdrname, "answer") == 0 || - strcasecmp(entry->cdrname, "end") == 0) ? 0 : 1); + AST_LIST_TRAVERSE(&(tableptr->columns), entry, list) { + /* Check if we have a similarly named variable */ + ast_cdr_getvar(cdr, entry->cdrname, &colptr, colbuf, sizeof(colbuf), 0, + (strcasecmp(entry->cdrname, "start") == 0 || + strcasecmp(entry->cdrname, "answer") == 0 || + strcasecmp(entry->cdrname, "end") == 0) ? 0 : 1); - if (colptr) { - LENGTHEN_BUF1(strlen(entry->name)); + if (colptr) { + LENGTHEN_BUF1(strlen(entry->name)); - switch (entry->type) { - case SQL_CHAR: - case SQL_VARCHAR: - case SQL_LONGVARCHAR: - case SQL_BINARY: - case SQL_VARBINARY: - case SQL_LONGVARBINARY: - case SQL_GUID: - /* For these two field names, get the rendered form, instead of the raw - * form (but only when we're dealing with a character-based field). - */ - if (strcasecmp(entry->name, "disposition") == 0) - ast_cdr_getvar(cdr, entry->name, &colptr, colbuf, sizeof(colbuf), 0, 0); - else if (strcasecmp(entry->name, "amaflags") == 0) - ast_cdr_getvar(cdr, entry->name, &colptr, colbuf, sizeof(colbuf), 0, 0); + switch (entry->type) { + case SQL_CHAR: + case SQL_VARCHAR: + case SQL_LONGVARCHAR: + case SQL_BINARY: + case SQL_VARBINARY: + case SQL_LONGVARBINARY: + case SQL_GUID: + /* For these two field names, get the rendered form, instead of the raw + * form (but only when we're dealing with a character-based field). + */ + if (strcasecmp(entry->name, "disposition") == 0) + ast_cdr_getvar(cdr, entry->name, &colptr, colbuf, sizeof(colbuf), 0, 0); + else if (strcasecmp(entry->name, "amaflags") == 0) + ast_cdr_getvar(cdr, entry->name, &colptr, colbuf, sizeof(colbuf), 0, 0); - /* Truncate too-long fields */ - if (entry->type != SQL_GUID) { - if (strlen(colptr) > entry->octetlen) - colptr[entry->octetlen] = '\0'; - } + /* Truncate too-long fields */ + if (entry->type != SQL_GUID) { + if (strlen(colptr) > entry->octetlen) + colptr[entry->octetlen] = '\0'; + } - lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); - LENGTHEN_BUF2(strlen(colptr)); + lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); + LENGTHEN_BUF2(strlen(colptr)); - /* Encode value, with escaping */ - strcpy(sql2 + lensql2, "'"); - lensql2++; - for (tmp = colptr; *tmp; tmp++) { - if (*tmp == '\'') { - strcpy(sql2 + lensql2, "''"); - lensql2 += 2; - } else if (*tmp == '\\') { - strcpy(sql2 + lensql2, "\\\\"); - lensql2 += 2; - } else { - sql2[lensql2++] = *tmp; - sql2[lensql2] = '\0'; - } + /* Encode value, with escaping */ + strcpy(sql2 + lensql2, "'"); + lensql2++; + for (tmp = colptr; *tmp; tmp++) { + if (*tmp == '\'') { + strcpy(sql2 + lensql2, "''"); + lensql2 += 2; + } else if (*tmp == '\\') { + strcpy(sql2 + lensql2, "\\\\"); + lensql2 += 2; + } else { + sql2[lensql2++] = *tmp; + sql2[lensql2] = '\0'; } - strcpy(sql2 + lensql2, "',"); - lensql2 += 2; - break; - case SQL_TYPE_DATE: - { - int year = 0, month = 0, day = 0; - if (sscanf(colptr, "%d-%d-%d", &year, &month, &day) != 3 || year <= 0 || - month <= 0 || month > 12 || day < 0 || day > 31 || - ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) || - (month == 2 && year % 400 == 0 && day > 29) || - (month == 2 && year % 100 == 0 && day > 28) || - (month == 2 && year % 4 == 0 && day > 29) || - (month == 2 && year % 4 != 0 && day > 28)) { - ast_log(LOG_WARNING, "CDR variable %s is not a valid date ('%s').\n", entry->name, colptr); - break; - } + } + strcpy(sql2 + lensql2, "',"); + lensql2 += 2; + break; + case SQL_TYPE_DATE: + { + int year = 0, month = 0, day = 0; + if (sscanf(colptr, "%d-%d-%d", &year, &month, &day) != 3 || year <= 0 || + month <= 0 || month > 12 || day < 0 || day > 31 || + ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) || + (month == 2 && year % 400 == 0 && day > 29) || + (month == 2 && year % 100 == 0 && day > 28) || + (month == 2 && year % 4 == 0 && day > 29) || + (month == 2 && year % 4 != 0 && day > 28)) { + ast_log(LOG_WARNING, "CDR variable %s is not a valid date ('%s').\n", entry->name, colptr); + break; + } - if (year > 0 && year < 100) - year += 2000; + if (year > 0 && year < 100) + year += 2000; - lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); - LENGTHEN_BUF2(10); - lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "'%04d-%02d-%02d',", year, month, day); + lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); + LENGTHEN_BUF2(10); + lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "'%04d-%02d-%02d',", year, month, day); + } + break; + case SQL_TYPE_TIME: + { + int hour = 0, minute = 0, second = 0; + int count = sscanf(colptr, "%d:%d:%d", &hour, &minute, &second); + + if ((count != 2 && count != 3) || hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) { + ast_log(LOG_WARNING, "CDR variable %s is not a valid time ('%s').\n", entry->name, colptr); + break; } - break; - case SQL_TYPE_TIME: - { - int hour = 0, minute = 0, second = 0; - int count = sscanf(colptr, "%d:%d:%d", &hour, &minute, &second); - if ((count != 2 && count != 3) || hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) { - ast_log(LOG_WARNING, "CDR variable %s is not a valid time ('%s').\n", entry->name, colptr); - break; - } + lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); + LENGTHEN_BUF2(8); + lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "'%02d:%02d:%02d',", hour, minute, second); + } + break; + case SQL_TYPE_TIMESTAMP: + case SQL_TIMESTAMP: + { + int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0; + int count = sscanf(colptr, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second); - lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); - LENGTHEN_BUF2(8); - lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "'%02d:%02d:%02d',", hour, minute, second); + if ((count != 3 && count != 5 && count != 6) || year <= 0 || + month <= 0 || month > 12 || day < 0 || day > 31 || + ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) || + (month == 2 && year % 400 == 0 && day > 29) || + (month == 2 && year % 100 == 0 && day > 28) || + (month == 2 && year % 4 == 0 && day > 29) || + (month == 2 && year % 4 != 0 && day > 28) || + hour > 23 || minute > 59 || second > 59 || hour < 0 || minute < 0 || second < 0) { + ast_log(LOG_WARNING, "CDR variable %s is not a valid timestamp ('%s').\n", entry->name, colptr); + break; } - break; - case SQL_TYPE_TIMESTAMP: - case SQL_TIMESTAMP: - { - int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0; - int count = sscanf(colptr, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second); - if ((count != 3 && count != 5 && count != 6) || year <= 0 || - month <= 0 || month > 12 || day < 0 || day > 31 || - ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) || - (month == 2 && year % 400 == 0 && day > 29) || - (month == 2 && year % 100 == 0 && day > 28) || - (month == 2 && year % 4 == 0 && day > 29) || - (month == 2 && year % 4 != 0 && day > 28) || - hour > 23 || minute > 59 || second > 59 || hour < 0 || minute < 0 || second < 0) { - ast_log(LOG_WARNING, "CDR variable %s is not a valid timestamp ('%s').\n", entry->name, colptr); - break; - } + if (year > 0 && year < 100) + year += 2000; - if (year > 0 && year < 100) - year += 2000; - - lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); - LENGTHEN_BUF2(19); - lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "'%04d-%02d-%02d %02d:%02d:%02d',", year, month, day, hour, minute, second); + lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); + LENGTHEN_BUF2(19); + lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "'%04d-%02d-%02d %02d:%02d:%02d',", year, month, day, hour, minute, second); + } + break; + case SQL_INTEGER: + { + int integer = 0; + if (sscanf(colptr, "%d", &integer) != 1) { + ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); + break; } - break; - case SQL_INTEGER: - { - int integer = 0; - if (sscanf(colptr, "%d", &integer) != 1) { - ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); - break; - } - lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); - LENGTHEN_BUF2(12); - lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%d,", integer); + lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); + LENGTHEN_BUF2(12); + lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%d,", integer); + } + break; + case SQL_BIGINT: + { + long long integer = 0; + if (sscanf(colptr, "%lld", &integer) != 1) { + ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); + break; } - break; - case SQL_BIGINT: - { - long long integer = 0; - if (sscanf(colptr, "%lld", &integer) != 1) { - ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); - break; - } - lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); - LENGTHEN_BUF2(24); - lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%lld,", integer); + lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); + LENGTHEN_BUF2(24); + lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%lld,", integer); + } + break; + case SQL_SMALLINT: + { + short integer = 0; + if (sscanf(colptr, "%hd", &integer) != 1) { + ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); + break; } - break; - case SQL_SMALLINT: - { - short integer = 0; - if (sscanf(colptr, "%hd", &integer) != 1) { - ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); - break; - } - lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); - LENGTHEN_BUF2(6); - lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%d,", integer); + lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); + LENGTHEN_BUF2(6); + lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%d,", integer); + } + break; + case SQL_TINYINT: + { + char integer = 0; + if (sscanf(colptr, "%hhd", &integer) != 1) { + ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); + break; } - break; - case SQL_TINYINT: - { - char integer = 0; - if (sscanf(colptr, "%hhd", &integer) != 1) { - ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); - break; - } - lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); - LENGTHEN_BUF2(4); - lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%d,", integer); + lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); + LENGTHEN_BUF2(4); + lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%d,", integer); + } + break; + case SQL_BIT: + { + char integer = 0; + if (sscanf(colptr, "%hhd", &integer) != 1) { + ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); + break; } - break; - case SQL_BIT: - { - char integer = 0; - if (sscanf(colptr, "%hhd", &integer) != 1) { - ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); - break; - } - if (integer != 0) - integer = 1; + if (integer != 0) + integer = 1; - lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); - LENGTHEN_BUF2(2); - lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%d,", integer); + lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); + LENGTHEN_BUF2(2); + lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%d,", integer); + } + break; + case SQL_NUMERIC: + case SQL_DECIMAL: + { + double number = 0.0; + if (sscanf(colptr, "%lf", &number) != 1) { + ast_log(LOG_WARNING, "CDR variable %s is not an numeric type.\n", entry->name); + break; } - break; - case SQL_NUMERIC: - case SQL_DECIMAL: - { - double number = 0.0; - if (sscanf(colptr, "%lf", &number) != 1) { - ast_log(LOG_WARNING, "CDR variable %s is not an numeric type.\n", entry->name); - break; - } - lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); - LENGTHEN_BUF2(entry->decimals); - lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%*.*lf,", entry->decimals, entry->radix, number); + lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); + LENGTHEN_BUF2(entry->decimals); + lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%*.*lf,", entry->decimals, entry->radix, number); + } + break; + case SQL_FLOAT: + case SQL_REAL: + case SQL_DOUBLE: + { + double number = 0.0; + if (sscanf(colptr, "%lf", &number) != 1) { + ast_log(LOG_WARNING, "CDR variable %s is not an numeric type.\n", entry->name); + break; } - break; - case SQL_FLOAT: - case SQL_REAL: - case SQL_DOUBLE: - { - double number = 0.0; - if (sscanf(colptr, "%lf", &number) != 1) { - ast_log(LOG_WARNING, "CDR variable %s is not an numeric type.\n", entry->name); - break; - } - lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); - LENGTHEN_BUF2(entry->decimals); - lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%lf,", number); - } - break; - default: - ast_log(LOG_WARNING, "Column type %d (field '%s:%s:%s') is unsupported at this time.\n", entry->type, tableptr->connection, tableptr->table, entry->name); + lensql += snprintf(sql + lensql, sizesql - lensql, "%s,", entry->name); + LENGTHEN_BUF2(entry->decimals); + lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%lf,", number); } + break; + default: + ast_log(LOG_WARNING, "Column type %d (field '%s:%s:%s') is unsupported at this time.\n", entry->type, tableptr->connection, tableptr->table, entry->name); } } + } - /* Concatenate the two constructed buffers */ - LENGTHEN_BUF1(lensql2); - sql[lensql - 1] = ')'; - sql2[lensql2 - 1] = ')'; - strcat(sql + lensql, sql2); + /* Concatenate the two constructed buffers */ + LENGTHEN_BUF1(lensql2); + sql[lensql - 1] = ')'; + sql2[lensql2 - 1] = ')'; + strcat(sql + lensql, sql2); - ast_verb(11, "[%s]\n", sql); - /* No need to check the connection now; we'll handle any failure in prepare_and_execute */ - obj = ast_odbc_request_obj(tableptr->connection, 0); - if (obj) { - stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, sql); - if (stmt) { - SQLRowCount(stmt, &rows); - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - } - if (rows == 0) { - ast_log(LOG_WARNING, "cdr_adaptive_odbc: Insert failed on '%s:%s'. CDR failed: %s\n", tableptr->connection, tableptr->table, sql); - /* We have to assume SQL error here I think, so don't retry. */ - res = AST_CDR_POST_FATAL; - } - ast_odbc_release_obj(obj); - } else { - ast_log(LOG_WARNING, "cdr_adaptive_odbc: Unable to retrieve database handle for '%s:%s'. CDR failed: %s\n", tableptr->connection, tableptr->table, sql); - res = AST_CDR_POST_RETRY; + ast_verb(11, "[%s]\n", sql); + + /* No need to check the connection now; we'll handle any failure in prepare_and_execute */ + obj = ast_odbc_request_obj(tableptr->connection, 0); + if (obj) { + stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, sql); + if (stmt) { + SQLRowCount(stmt, &rows); + SQLFreeHandle(SQL_HANDLE_STMT, stmt); } + if (rows == 0) { + ast_log(LOG_WARNING, "Insert failed on '%s:%s'. CDR failed: %s\n", tableptr->connection, tableptr->table, sql); + /* We have to assume SQL error here I think, so don't retry. */ + res = AST_CDR_POST_FATAL; + } + ast_odbc_release_obj(obj); + } else { + ast_log(LOG_WARNING, "Unable to retrieve database handle for '%s:%s'. CDR failed: %s\n", tableptr->connection, tableptr->table, sql); + res = AST_CDR_POST_RETRY; + } /* Next time, just allocate buffers that are that big to start with. */ if (sizesql > maxsize) @@ -577,7 +579,7 @@ static int unload_module(void) { - ast_cdr_unregister_all(name); + ast_cdr_unregister(name, NULL); return 0; } @@ -591,16 +593,14 @@ static int reload(void) { - ast_cdr_unregister_all(name); + unload_module(); + load_module(); - load_config(); - return 0; } -AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Adaptive ODBC CDR backend", - .load = load_module, +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Adaptive ODBC CDR Backend", + .load = load_module, .unload = unload_module, .reload = reload, ); -