Mon Jun 27 16:51:04 2011

Asterisk developer's documentation


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"

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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 45 of file cdr_odbc.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
CONFIG_LOGUNIQUEID 
CONFIG_USEGMTIME 
CONFIG_DISPOSITIONSTRING 
CONFIG_HRTIME 
CONFIG_REGISTERED 

Definition at line 51 of file cdr_odbc.c.

00051      {
00052    CONFIG_LOGUNIQUEID =       1 << 0,
00053    CONFIG_USEGMTIME =         1 << 1,
00054    CONFIG_DISPOSITIONSTRING = 1 << 2,
00055    CONFIG_HRTIME =            1 << 3,
00056    CONFIG_REGISTERED =        1 << 4,
00057 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 297 of file cdr_odbc.c.

static void __unreg_module ( void   )  [static]

Definition at line 297 of file cdr_odbc.c.

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

Definition at line 61 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, 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().

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

static int load_module ( void   )  [static]

Definition at line 266 of file cdr_odbc.c.

References odbc_load_module().

00267 {
00268    return odbc_load_module(0);
00269 }

static int odbc_load_module ( int  reload  )  [static]

Definition at line 166 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, CONFIG_DISPOSITIONSTRING, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_HRTIME, CONFIG_LOGUNIQUEID, CONFIG_REGISTERED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, CONFIG_USEGMTIME, LOG_ERROR, LOG_WARNING, odbc_log(), and var.

Referenced by load_module(), and reload().

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

static int odbc_log ( struct ast_cdr cdr  )  [static]

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

00142 {
00143    struct odbc_obj *obj = ast_odbc_request_obj(dsn, 0);
00144    SQLHSTMT stmt;
00145 
00146    if (!obj) {
00147       ast_log(LOG_ERROR, "Unable to retrieve database handle.  CDR failed.\n");
00148       return -1;
00149    }
00150 
00151    stmt = ast_odbc_direct_execute(obj, execute_cb, cdr);
00152    if (stmt) {
00153       SQLLEN rows = 0;
00154 
00155       SQLRowCount(stmt, &rows);
00156       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00157 
00158       if (rows == 0)
00159          ast_log(LOG_WARNING, "CDR successfully ran, but inserted 0 rows?\n");
00160    } else
00161       ast_log(LOG_ERROR, "CDR direct execute failed\n");
00162    ast_odbc_release_obj(obj);
00163    return 0;
00164 }

static int reload ( void   )  [static]

Definition at line 287 of file cdr_odbc.c.

References odbc_load_module().

00288 {
00289    return odbc_load_module(1);
00290 }

static int unload_module ( void   )  [static]

Definition at line 271 of file cdr_odbc.c.

References ast_cdr_unregister(), ast_free, and ast_verb.

00272 {
00273    ast_cdr_unregister(name);
00274 
00275    if (dsn) {
00276       ast_verb(11, "cdr_odbc: free dsn\n");
00277       ast_free(dsn);
00278    }
00279    if (table) {
00280       ast_verb(11, "cdr_odbc: free table\n");
00281       ast_free(table);
00282    }
00283 
00284    return 0;
00285 }


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

Definition at line 297 of file cdr_odbc.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 297 of file cdr_odbc.c.

struct ast_flags config = { 0 } [static]

Definition at line 59 of file cdr_odbc.c.

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

Definition at line 48 of file cdr_odbc.c.

char* dsn = NULL [static]

Definition at line 49 of file cdr_odbc.c.

Referenced by acf_odbc_read(), acf_odbc_write(), and init_acf_query().

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

Definition at line 47 of file cdr_odbc.c.

char * table = NULL [static]

Definition at line 49 of file cdr_odbc.c.

Referenced by ast_config_internal_load(), ast_destroy_realtime(), ast_load_realtime_helper(), ast_load_realtime_multientry(), ast_odbc_find_column(), ast_realtime_require_field(), ast_store_realtime(), ast_unload_realtime(), ast_update2_realtime(), ast_update_realtime(), destroy_table(), destroy_table_cache(), find_table(), free_config(), map_s_x(), map_x_s(), read_config_maps(), realtime_common(), reload(), require_pgsql(), tds_load_module(), unload_module(), update2_pgsql(), and update_pgsql().


Generated on Mon Jun 27 16:51:04 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7