ODBC CDR Backend. More...
#include "asterisk.h"#include "asterisk/config.h"#include "asterisk/channel.h"#include "asterisk/cdr.h"#include "asterisk/module.h"#include "asterisk/res_odbc.h"
Go to the source code of this file.
Defines | |
| #define | DATE_FORMAT "%Y-%m-%d %T" |
Enumerations | |
| enum | { CONFIG_LOGUNIQUEID = 1 << 0, CONFIG_USEGMTIME = 1 << 1, CONFIG_DISPOSITIONSTRING = 1 << 2, CONFIG_HRTIME = 1 << 3, CONFIG_REGISTERED = 1 << 4 } |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static SQLHSTMT | execute_cb (struct odbc_obj *obj, void *data) |
| static int | load_module (void) |
| static int | odbc_load_module (int reload) |
| static int | odbc_log (struct ast_cdr *cdr) |
| static int | reload (void) |
| static int | unload_module (void) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "ODBC CDR Backend" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct ast_flags | config = { 0 } |
| static const char | config_file [] = "cdr_odbc.conf" |
| static char * | dsn = NULL |
| static const char | name [] = "ODBC" |
| static char * | table = NULL |
| #define DATE_FORMAT "%Y-%m-%d %T" |
Definition at line 46 of file cdr_odbc.c.
Referenced by execute_cb().
| anonymous enum |
| CONFIG_LOGUNIQUEID | |
| CONFIG_USEGMTIME | |
| CONFIG_DISPOSITIONSTRING | |
| CONFIG_HRTIME | |
| CONFIG_REGISTERED |
Definition at line 52 of file cdr_odbc.c.
{
CONFIG_LOGUNIQUEID = 1 << 0,
CONFIG_USEGMTIME = 1 << 1,
CONFIG_DISPOSITIONSTRING = 1 << 2,
CONFIG_HRTIME = 1 << 3,
CONFIG_REGISTERED = 1 << 4,
};
| static void __reg_module | ( | void | ) | [static] |
Definition at line 298 of file cdr_odbc.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 298 of file cdr_odbc.c.
| static SQLHSTMT execute_cb | ( | struct odbc_obj * | obj, |
| void * | data | ||
| ) | [static] |
Definition at line 62 of file cdr_odbc.c.
References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, ast_cdr_disp2str(), ast_localtime(), ast_strftime(), ast_test_flag, ast_tvdiff_us(), ast_tvzero(), ast_verb, ast_cdr::billsec, ast_cdr::channel, ast_cdr::clid, odbc_obj::con, CONFIG_DISPOSITIONSTRING, CONFIG_HRTIME, CONFIG_LOGUNIQUEID, CONFIG_USEGMTIME, DATE_FORMAT, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::end, ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.
Referenced by odbc_log().
{
struct ast_cdr *cdr = data;
SQLRETURN ODBC_res;
char sqlcmd[2048] = "", timestr[128];
struct ast_tm tm;
SQLHSTMT stmt;
ast_localtime(&cdr->start, &tm, ast_test_flag(&config, CONFIG_USEGMTIME) ? "GMT" : NULL);
ast_strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
if (ast_test_flag(&config, CONFIG_LOGUNIQUEID)) {
snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO %s "
"(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,"
"lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) "
"VALUES ({ts '%s'},?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", table, timestr);
} else {
snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO %s "
"(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,"
"duration,billsec,disposition,amaflags,accountcode) "
"VALUES ({ts '%s'},?,?,?,?,?,?,?,?,?,?,?,?,?)", table, timestr);
}
ODBC_res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
ast_verb(11, "cdr_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(cdr->clid), 0, cdr->clid, 0, NULL);
SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->src), 0, cdr->src, 0, NULL);
SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dst), 0, cdr->dst, 0, NULL);
SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dcontext), 0, cdr->dcontext, 0, NULL);
SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->channel), 0, cdr->channel, 0, NULL);
SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dstchannel), 0, cdr->dstchannel, 0, NULL);
SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastapp), 0, cdr->lastapp, 0, NULL);
SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastdata), 0, cdr->lastdata, 0, NULL);
if (ast_test_flag(&config, CONFIG_HRTIME)) {
double hrbillsec = 0.0;
double hrduration;
if (!ast_tvzero(cdr->answer)) {
hrbillsec = (double) ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0;
}
hrduration = (double) ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0;
SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_FLOAT, 0, 0, &hrduration, 0, NULL);
SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_FLOAT, 0, 0, &hrbillsec, 0, NULL);
} else {
SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->duration, 0, NULL);
SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL);
}
if (ast_test_flag(&config, CONFIG_DISPOSITIONSTRING))
SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(ast_cdr_disp2str(cdr->disposition)) + 1, 0, ast_cdr_disp2str(cdr->disposition), 0, NULL);
else
SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->disposition, 0, NULL);
SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->amaflags, 0, NULL);
SQLBindParameter(stmt, 13, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->accountcode), 0, cdr->accountcode, 0, NULL);
if (ast_test_flag(&config, CONFIG_LOGUNIQUEID)) {
SQLBindParameter(stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->uniqueid), 0, cdr->uniqueid, 0, NULL);
SQLBindParameter(stmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->userfield), 0, cdr->userfield, 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 int load_module | ( | void | ) | [static] |
Definition at line 267 of file cdr_odbc.c.
References odbc_load_module().
{
return odbc_load_module(0);
}
| static int odbc_load_module | ( | int | reload | ) | [static] |
Definition at line 167 of file cdr_odbc.c.
References ast_cdr_register(), ast_cdr_unregister(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_debug, ast_free, ast_log(), AST_MODULE_LOAD_DECLINE, ast_set_flag, ast_strdup, ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_DISPOSITIONSTRING, CONFIG_FLAG_FILEUNCHANGED, CONFIG_HRTIME, CONFIG_LOGUNIQUEID, CONFIG_REGISTERED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, CONFIG_USEGMTIME, ast_module_info::description, LOG_ERROR, LOG_WARNING, odbc_log(), and var.
Referenced by load_module(), and reload().
{
int res = 0;
struct ast_config *cfg;
struct ast_variable *var;
const char *tmp;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
do {
cfg = ast_config_load(config_file, config_flags);
if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_WARNING, "cdr_odbc: Unable to load config for ODBC CDR'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;
}
if ((tmp = ast_variable_retrieve(cfg, "global", "dsn")) == NULL) {
ast_log(LOG_WARNING, "cdr_odbc: dsn not specified. Assuming asteriskdb\n");
tmp = "asteriskdb";
}
if (dsn)
ast_free(dsn);
dsn = ast_strdup(tmp);
if (dsn == NULL) {
res = -1;
break;
}
if (((tmp = ast_variable_retrieve(cfg, "global", "dispositionstring"))) && ast_true(tmp))
ast_set_flag(&config, CONFIG_DISPOSITIONSTRING);
else
ast_clear_flag(&config, CONFIG_DISPOSITIONSTRING);
if (((tmp = ast_variable_retrieve(cfg, "global", "loguniqueid"))) && ast_true(tmp)) {
ast_set_flag(&config, CONFIG_LOGUNIQUEID);
ast_debug(1, "cdr_odbc: Logging uniqueid\n");
} else {
ast_clear_flag(&config, CONFIG_LOGUNIQUEID);
ast_debug(1, "cdr_odbc: Not logging uniqueid\n");
}
if (((tmp = ast_variable_retrieve(cfg, "global", "usegmtime"))) && ast_true(tmp)) {
ast_set_flag(&config, CONFIG_USEGMTIME);
ast_debug(1, "cdr_odbc: Logging in GMT\n");
} else {
ast_clear_flag(&config, CONFIG_USEGMTIME);
ast_debug(1, "cdr_odbc: Logging in local time\n");
}
if (((tmp = ast_variable_retrieve(cfg, "global", "hrtime"))) && ast_true(tmp)) {
ast_set_flag(&config, CONFIG_HRTIME);
ast_debug(1, "cdr_odbc: Logging billsec and duration fields as floats\n");
} else {
ast_clear_flag(&config, CONFIG_HRTIME);
ast_debug(1, "cdr_odbc: Logging billsec and duration fields as integers\n");
}
if ((tmp = ast_variable_retrieve(cfg, "global", "table")) == NULL) {
ast_log(LOG_WARNING, "cdr_odbc: table not specified. Assuming cdr\n");
tmp = "cdr";
}
if (table)
ast_free(table);
table = ast_strdup(tmp);
if (table == NULL) {
res = -1;
break;
}
ast_verb(3, "cdr_odbc: dsn is %s\n", dsn);
ast_verb(3, "cdr_odbc: table is %s\n", table);
if (!ast_test_flag(&config, CONFIG_REGISTERED)) {
res = ast_cdr_register(name, ast_module_info->description, odbc_log);
if (res) {
ast_log(LOG_ERROR, "cdr_odbc: Unable to register ODBC CDR handling\n");
} else {
ast_set_flag(&config, CONFIG_REGISTERED);
}
}
} while (0);
if (ast_test_flag(&config, CONFIG_REGISTERED) && (!cfg || dsn == NULL || table == NULL)) {
ast_cdr_unregister(name);
ast_clear_flag(&config, CONFIG_REGISTERED);
}
if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED && cfg != CONFIG_STATUS_FILEINVALID) {
ast_config_destroy(cfg);
}
return res;
}
| static int odbc_log | ( | struct ast_cdr * | cdr | ) | [static] |
Definition at line 142 of file cdr_odbc.c.
References ast_log(), ast_odbc_direct_execute(), ast_odbc_release_obj(), ast_odbc_request_obj, execute_cb(), LOG_ERROR, and LOG_WARNING.
Referenced by odbc_load_module().
{
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 -1;
}
stmt = ast_odbc_direct_execute(obj, execute_cb, cdr);
if (stmt) {
SQLLEN rows = 0;
SQLRowCount(stmt, &rows);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
if (rows == 0)
ast_log(LOG_WARNING, "CDR successfully ran, but inserted 0 rows?\n");
} else
ast_log(LOG_ERROR, "CDR direct execute failed\n");
ast_odbc_release_obj(obj);
return 0;
}
| static int reload | ( | void | ) | [static] |
Definition at line 288 of file cdr_odbc.c.
References odbc_load_module().
{
return odbc_load_module(1);
}
| static int unload_module | ( | void | ) | [static] |
Definition at line 272 of file cdr_odbc.c.
References ast_cdr_unregister(), ast_free, and ast_verb.
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "ODBC CDR Backend" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } [static] |
Definition at line 298 of file cdr_odbc.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 298 of file cdr_odbc.c.
Definition at line 60 of file cdr_odbc.c.
const char config_file[] = "cdr_odbc.conf" [static] |
Definition at line 49 of file cdr_odbc.c.
char* dsn = NULL [static] |
Definition at line 50 of file cdr_odbc.c.
Referenced by acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), and init_acf_query().
const char name[] = "ODBC" [static] |
Definition at line 48 of file cdr_odbc.c.
| char * table = NULL |
Definition at line 50 of file cdr_odbc.c.
Referenced by ast_config_internal_load(), ast_destroy_realtime(), ast_load_realtime_helper(), ast_load_realtime_multientry(), ast_realtime_require_field(), ast_store_realtime(), ast_unload_realtime(), ast_update2_realtime(), ast_update_realtime(), config_module(), free_config(), quan(), read_config_maps(), realtime_common(), reload(), tds_load_module(), and update2_odbc().