cdr_odbc.c File Reference

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"

Include dependency graph for cdr_odbc.c:

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, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, }
static struct ast_module_infoast_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


Detailed Description

ODBC CDR Backend.

Author:
Brian K. West <brian@bkw.org>
See also:

Definition in file cdr_odbc.c.


Define Documentation

#define DATE_FORMAT   "%Y-%m-%d %T"

Definition at line 55 of file cdr_odbc.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
CONFIG_LOGUNIQUEID 
CONFIG_USEGMTIME 
CONFIG_DISPOSITIONSTRING 
CONFIG_HRTIME 
CONFIG_REGISTERED 

Definition at line 61 of file cdr_odbc.c.

00061      {
00062    CONFIG_LOGUNIQUEID =       1 << 0,
00063    CONFIG_USEGMTIME =         1 << 1,
00064    CONFIG_DISPOSITIONSTRING = 1 << 2,
00065    CONFIG_HRTIME =            1 << 3,
00066    CONFIG_REGISTERED =        1 << 4,
00067 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 310 of file cdr_odbc.c.

static void __unreg_module ( void   )  [static]

Definition at line 310 of file cdr_odbc.c.

static SQLHSTMT execute_cb ( struct odbc_obj obj,
void *  data 
) [static]

Definition at line 71 of file cdr_odbc.c.

References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, ast_cdr_disp2str(), ast_localtime(), ast_log, ast_strdupa, ast_strftime(), ast_test_flag, ast_tvdiff_us(), ast_tvzero(), 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, LOG_WARNING, NULL, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.

Referenced by odbc_log().

00072 {
00073    struct ast_cdr *cdr = data;
00074    SQLRETURN ODBC_res;
00075    char sqlcmd[2048] = "", timestr[128];
00076    struct ast_tm tm;
00077    SQLHSTMT stmt;
00078 
00079    ast_localtime(&cdr->start, &tm, ast_test_flag(&config, CONFIG_USEGMTIME) ? "GMT" : NULL);
00080    ast_strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
00081 
00082    if (ast_test_flag(&config, CONFIG_LOGUNIQUEID)) {
00083       snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO %s "
00084       "(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,"
00085       "lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) "
00086       "VALUES ({ts '%s'},?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", table, timestr);
00087    } else {
00088       snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO %s "
00089       "(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,"
00090       "duration,billsec,disposition,amaflags,accountcode) "
00091       "VALUES ({ts '%s'},?,?,?,?,?,?,?,?,?,?,?,?,?)", table, timestr);
00092    }
00093 
00094    ODBC_res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
00095 
00096    if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
00097       ast_log(LOG_WARNING, "cdr_odbc: Failure in AllocStatement %d\n", ODBC_res);
00098       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00099       return NULL;
00100    }
00101 
00102    SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->clid), 0, cdr->clid, 0, NULL);
00103    SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->src), 0, cdr->src, 0, NULL);
00104    SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dst), 0, cdr->dst, 0, NULL);
00105    SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dcontext), 0, cdr->dcontext, 0, NULL);
00106    SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->channel), 0, cdr->channel, 0, NULL);
00107    SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dstchannel), 0, cdr->dstchannel, 0, NULL);
00108    SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastapp), 0, cdr->lastapp, 0, NULL);
00109    SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastdata), 0, cdr->lastdata, 0, NULL);
00110 
00111    if (ast_test_flag(&config, CONFIG_HRTIME)) {
00112       double hrbillsec = 0.0;
00113       double hrduration;
00114 
00115       if (!ast_tvzero(cdr->answer)) {
00116          hrbillsec = (double) ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0;
00117       }
00118       hrduration = (double) ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0;
00119 
00120       SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_FLOAT, 0, 0, &hrduration, 0, NULL);
00121       SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_FLOAT, 0, 0, &hrbillsec, 0, NULL);
00122    } else {
00123       SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->duration, 0, NULL);
00124       SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL);
00125    }
00126 
00127    if (ast_test_flag(&config, CONFIG_DISPOSITIONSTRING)) {
00128       char *disposition;
00129       disposition = ast_strdupa(ast_cdr_disp2str(cdr->disposition));
00130       SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(disposition) + 1, 0, disposition, 0, NULL);
00131    } else {
00132       SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->disposition, 0, NULL);
00133    }
00134    SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->amaflags, 0, NULL);
00135    SQLBindParameter(stmt, 13, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->accountcode), 0, cdr->accountcode, 0, NULL);
00136 
00137    if (ast_test_flag(&config, CONFIG_LOGUNIQUEID)) {
00138       SQLBindParameter(stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->uniqueid), 0, cdr->uniqueid, 0, NULL);
00139       SQLBindParameter(stmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->userfield), 0, cdr->userfield, 0, NULL);
00140    }
00141 
00142    ODBC_res = SQLExecDirect(stmt, (unsigned char *)sqlcmd, SQL_NTS);
00143 
00144    if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
00145       ast_log(LOG_WARNING, "cdr_odbc: Error in ExecDirect: %d, query is: %s\n", ODBC_res, sqlcmd);
00146       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00147       return NULL;
00148    }
00149 
00150    return stmt;
00151 }

static int load_module ( void   )  [static]

Definition at line 278 of file cdr_odbc.c.

References odbc_load_module().

00279 {
00280    return odbc_load_module(0);
00281 }

static int odbc_load_module ( int  reload  )  [static]

Definition at line 179 of file cdr_odbc.c.

References ast_cdr_backend_suspend(), ast_cdr_backend_unsuspend(), ast_cdr_register(), 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(), CONFIG_DISPOSITIONSTRING, CONFIG_FLAG_FILEUNCHANGED, CONFIG_HRTIME, CONFIG_LOGUNIQUEID, CONFIG_REGISTERED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, CONFIG_USEGMTIME, LOG_ERROR, LOG_WARNING, NULL, odbc_log(), tmp(), and var.

Referenced by load_module(), and reload().

00180 {
00181    int res = 0;
00182    struct ast_config *cfg;
00183    struct ast_variable *var;
00184    const char *tmp;
00185    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00186 
00187    do {
00188       cfg = ast_config_load(config_file, config_flags);
00189       if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
00190          ast_log(LOG_WARNING, "cdr_odbc: Unable to load config for ODBC CDR's: %s\n", config_file);
00191          res = AST_MODULE_LOAD_DECLINE;
00192          break;
00193       } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
00194          break;
00195 
00196       var = ast_variable_browse(cfg, "global");
00197       if (!var) {
00198          /* nothing configured */
00199          break;
00200       }
00201 
00202       if ((tmp = ast_variable_retrieve(cfg, "global", "dsn")) == NULL) {
00203          ast_log(LOG_WARNING, "cdr_odbc: dsn not specified.  Assuming asteriskdb\n");
00204          tmp = "asteriskdb";
00205       }
00206       if (dsn)
00207          ast_free(dsn);
00208       dsn = ast_strdup(tmp);
00209       if (dsn == NULL) {
00210          res = -1;
00211          break;
00212       }
00213 
00214       if (((tmp = ast_variable_retrieve(cfg, "global", "dispositionstring"))) && ast_true(tmp))
00215          ast_set_flag(&config, CONFIG_DISPOSITIONSTRING);
00216       else
00217          ast_clear_flag(&config, CONFIG_DISPOSITIONSTRING);
00218 
00219       if (((tmp = ast_variable_retrieve(cfg, "global", "loguniqueid"))) && ast_true(tmp)) {
00220          ast_set_flag(&config, CONFIG_LOGUNIQUEID);
00221          ast_debug(1, "cdr_odbc: Logging uniqueid\n");
00222       } else {
00223          ast_clear_flag(&config, CONFIG_LOGUNIQUEID);
00224          ast_debug(1, "cdr_odbc: Not logging uniqueid\n");
00225       }
00226 
00227       if (((tmp = ast_variable_retrieve(cfg, "global", "usegmtime"))) && ast_true(tmp)) {
00228          ast_set_flag(&config, CONFIG_USEGMTIME);
00229          ast_debug(1, "cdr_odbc: Logging in GMT\n");
00230       } else {
00231          ast_clear_flag(&config, CONFIG_USEGMTIME);
00232          ast_debug(1, "cdr_odbc: Logging in local time\n");
00233       }
00234 
00235       if (((tmp = ast_variable_retrieve(cfg, "global", "hrtime"))) && ast_true(tmp)) {
00236          ast_set_flag(&config, CONFIG_HRTIME);
00237          ast_debug(1, "cdr_odbc: Logging billsec and duration fields as floats\n");
00238       } else {
00239          ast_clear_flag(&config, CONFIG_HRTIME);
00240          ast_debug(1, "cdr_odbc: Logging billsec and duration fields as integers\n");
00241       }
00242 
00243       if ((tmp = ast_variable_retrieve(cfg, "global", "table")) == NULL) {
00244          ast_log(LOG_WARNING, "cdr_odbc: table not specified.  Assuming cdr\n");
00245          tmp = "cdr";
00246       }
00247       if (table)
00248          ast_free(table);
00249       table = ast_strdup(tmp);
00250       if (table == NULL) {
00251          res = -1;
00252          break;
00253       }
00254 
00255       if (!ast_test_flag(&config, CONFIG_REGISTERED)) {
00256          res = ast_cdr_register(name, ast_module_info->description, odbc_log);
00257          if (res) {
00258             ast_log(LOG_ERROR, "cdr_odbc: Unable to register ODBC CDR handling\n");
00259          } else {
00260             ast_set_flag(&config, CONFIG_REGISTERED);
00261          }
00262       }
00263    } while (0);
00264 
00265    if (ast_test_flag(&config, CONFIG_REGISTERED) && (!cfg || dsn == NULL || table == NULL)) {
00266       ast_cdr_backend_suspend(name);
00267       ast_clear_flag(&config, CONFIG_REGISTERED);
00268    } else {
00269       ast_cdr_backend_unsuspend(name);
00270    }
00271 
00272    if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED && cfg != CONFIG_STATUS_FILEINVALID) {
00273       ast_config_destroy(cfg);
00274    }
00275    return res;
00276 }

static int odbc_log ( struct ast_cdr cdr  )  [static]

Definition at line 154 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.

00155 {
00156    struct odbc_obj *obj = ast_odbc_request_obj(dsn, 0);
00157    SQLHSTMT stmt;
00158 
00159    if (!obj) {
00160       ast_log(LOG_ERROR, "Unable to retrieve database handle.  CDR failed.\n");
00161       return -1;
00162    }
00163 
00164    stmt = ast_odbc_direct_execute(obj, execute_cb, cdr);
00165    if (stmt) {
00166       SQLLEN rows = 0;
00167 
00168       SQLRowCount(stmt, &rows);
00169       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00170 
00171       if (rows == 0)
00172          ast_log(LOG_WARNING, "CDR successfully ran, but inserted 0 rows?\n");
00173    } else
00174       ast_log(LOG_ERROR, "CDR direct execute failed\n");
00175    ast_odbc_release_obj(obj);
00176    return 0;
00177 }

static int reload ( void   )  [static]

Definition at line 299 of file cdr_odbc.c.

References odbc_load_module().

00300 {
00301    return odbc_load_module(1);
00302 }

static int unload_module ( void   )  [static]

Definition at line 283 of file cdr_odbc.c.

References ast_cdr_unregister(), and ast_free.

00284 {
00285    if (ast_cdr_unregister(name)) {
00286       return -1;
00287    }
00288 
00289    if (dsn) {
00290       ast_free(dsn);
00291    }
00292    if (table) {
00293       ast_free(table);
00294    }
00295 
00296    return 0;
00297 }


Variable Documentation

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, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } [static]

Definition at line 310 of file cdr_odbc.c.

Definition at line 310 of file cdr_odbc.c.

struct ast_flags config = { 0 } [static]

Definition at line 69 of file cdr_odbc.c.

const char config_file[] = "cdr_odbc.conf" [static]

Definition at line 58 of file cdr_odbc.c.

Referenced by AST_TEST_DEFINE(), and write_config_file().

char* dsn = NULL [static]

const char name[] = "ODBC" [static]

Definition at line 57 of file cdr_odbc.c.

char * table = NULL [static]


Generated on Thu Apr 16 06:29:25 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6