Wed Oct 28 11:51:46 2009

Asterisk developer's documentation


cdr_odbc.c File Reference

ODBC CDR Backend. More...

#include "asterisk.h"
#include <time.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 }

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_DEFAULT , .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, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_flags config = { 0 }
static char * config_file = "cdr_odbc.conf"
static char * dsn = NULL
static 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 48 of file cdr_odbc.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
CONFIG_LOGUNIQUEID 
CONFIG_USEGMTIME 
CONFIG_DISPOSITIONSTRING 

Definition at line 54 of file cdr_odbc.c.

00054      {
00055    CONFIG_LOGUNIQUEID =       1 << 0,
00056    CONFIG_USEGMTIME =         1 << 1,
00057    CONFIG_DISPOSITIONSTRING = 1 << 2,
00058 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 264 of file cdr_odbc.c.

static void __unreg_module ( void   )  [static]

Definition at line 264 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_disp2str(), ast_localtime(), ast_strftime(), ast_test_flag, ast_verb, ast_cdr::billsec, ast_cdr::channel, ast_cdr::clid, odbc_obj::con, CONFIG_DISPOSITIONSTRING, CONFIG_LOGUNIQUEID, CONFIG_USEGMTIME, DATE_FORMAT, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.

Referenced by odbc_log().

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

static int load_module ( void   )  [static]

Definition at line 234 of file cdr_odbc.c.

References odbc_load_module().

00235 {
00236    return odbc_load_module(0);
00237 }

static int odbc_load_module ( int  reload  )  [static]

Definition at line 152 of file cdr_odbc.c.

References 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_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_DISPOSITIONSTRING, CONFIG_FLAG_FILEUNCHANGED, CONFIG_LOGUNIQUEID, CONFIG_STATUS_FILEUNCHANGED, CONFIG_USEGMTIME, LOG_ERROR, LOG_WARNING, odbc_log(), and var.

Referenced by load_module(), and reload().

00153 {
00154    int res = 0;
00155    struct ast_config *cfg;
00156    struct ast_variable *var;
00157    const char *tmp;
00158    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00159 
00160    do {
00161       cfg = ast_config_load(config_file, config_flags);
00162       if (!cfg) {
00163          ast_log(LOG_WARNING, "cdr_odbc: Unable to load config for ODBC CDR's: %s\n", config_file);
00164          res = AST_MODULE_LOAD_DECLINE;
00165          break;
00166       } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
00167          break;
00168 
00169       var = ast_variable_browse(cfg, "global");
00170       if (!var) {
00171          /* nothing configured */
00172          break;
00173       }
00174 
00175       if ((tmp = ast_variable_retrieve(cfg, "global", "dsn")) == NULL) {
00176          ast_log(LOG_WARNING, "cdr_odbc: dsn not specified.  Assuming asteriskdb\n");
00177          tmp = "asteriskdb";
00178       }
00179       if (dsn)
00180          ast_free(dsn);
00181       dsn = ast_strdup(tmp);
00182       if (dsn == NULL) {
00183          res = -1;
00184          break;
00185       }
00186 
00187       if (((tmp = ast_variable_retrieve(cfg, "global", "dispositionstring"))) && ast_true(tmp))
00188          ast_set_flag(&config, CONFIG_DISPOSITIONSTRING);
00189       else
00190          ast_clear_flag(&config, CONFIG_DISPOSITIONSTRING);
00191 
00192       if (((tmp = ast_variable_retrieve(cfg, "global", "loguniqueid"))) && ast_true(tmp)) {
00193          ast_set_flag(&config, CONFIG_LOGUNIQUEID);
00194          ast_debug(1, "cdr_odbc: Logging uniqueid\n");
00195       } else {
00196          ast_clear_flag(&config, CONFIG_LOGUNIQUEID);
00197          ast_debug(1, "cdr_odbc: Not logging uniqueid\n");
00198       }
00199 
00200       if (((tmp = ast_variable_retrieve(cfg, "global", "usegmtime"))) && ast_true(tmp)) {
00201          ast_set_flag(&config, CONFIG_USEGMTIME);
00202          ast_debug(1, "cdr_odbc: Logging in GMT\n");
00203       } else {
00204          ast_clear_flag(&config, CONFIG_USEGMTIME);
00205          ast_debug(1, "cdr_odbc: Logging in local time\n");
00206       }
00207 
00208       if ((tmp = ast_variable_retrieve(cfg, "global", "table")) == NULL) {
00209          ast_log(LOG_WARNING, "cdr_odbc: table not specified.  Assuming cdr\n");
00210          tmp = "cdr";
00211       }
00212       if (table)
00213          ast_free(table);
00214       table = ast_strdup(tmp);
00215       if (table == NULL) {
00216          res = -1;
00217          break;
00218       }
00219 
00220       ast_verb(3, "cdr_odbc: dsn is %s\n", dsn);
00221       ast_verb(3, "cdr_odbc: table is %s\n", table);
00222 
00223       res = ast_cdr_register(name, ast_module_info->description, odbc_log);
00224       if (res) {
00225          ast_log(LOG_ERROR, "cdr_odbc: Unable to register ODBC CDR handling\n");
00226       }
00227    } while (0);
00228 
00229    if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED)
00230       ast_config_destroy(cfg);
00231    return res;
00232 }

static int odbc_log ( struct ast_cdr cdr  )  [static]

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

00128 {
00129    struct odbc_obj *obj = ast_odbc_request_obj(dsn, 0);
00130    SQLHSTMT stmt;
00131 
00132    if (!obj) {
00133       ast_log(LOG_ERROR, "Unable to retrieve database handle.  CDR failed.\n");
00134       return -1;
00135    }
00136 
00137    stmt = ast_odbc_direct_execute(obj, execute_cb, cdr);
00138    if (stmt) {
00139       SQLLEN rows = 0;
00140 
00141       SQLRowCount(stmt, &rows);
00142       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00143 
00144       if (rows == 0)
00145          ast_log(LOG_WARNING, "CDR successfully ran, but inserted 0 rows?\n");
00146    } else
00147       ast_log(LOG_ERROR, "CDR direct execute failed\n");
00148    ast_odbc_release_obj(obj);
00149    return 0;
00150 }

static int reload ( void   )  [static]

Definition at line 255 of file cdr_odbc.c.

References odbc_load_module().

00256 {
00257    return odbc_load_module(1);
00258 }

static int unload_module ( void   )  [static]

Definition at line 239 of file cdr_odbc.c.

References ast_cdr_unregister(), ast_free, and ast_verb.

00240 {
00241    ast_cdr_unregister(name);
00242 
00243    if (dsn) {
00244       ast_verb(11, "cdr_odbc: free dsn\n");
00245       ast_free(dsn);
00246    }
00247    if (table) {
00248       ast_verb(11, "cdr_odbc: free table\n");
00249       ast_free(table);
00250    }
00251 
00252    return 0;
00253 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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, } [static]

Definition at line 264 of file cdr_odbc.c.

Definition at line 264 of file cdr_odbc.c.

struct ast_flags config = { 0 } [static]

Definition at line 60 of file cdr_odbc.c.

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

Definition at line 51 of file cdr_odbc.c.

char* dsn = NULL [static]

Definition at line 52 of file cdr_odbc.c.

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

char* name = "ODBC" [static]

Definition at line 50 of file cdr_odbc.c.

char * table = NULL [static]


Generated on Wed Oct 28 11:51:47 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6