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 | |
AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,"ODBC CDR Backend",.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CDR_DRIVER,) | |
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_flags | config = { 0 } |
static const char | config_file [] = "cdr_odbc.conf" |
static char * | dsn = NULL |
static const char | name [] = "ODBC" |
static char * | table = NULL |
ODBC CDR Backend.
See also:
Definition in file cdr_odbc.c.
#define DATE_FORMAT "%Y-%m-%d %T" |
Definition at line 46 of file cdr_odbc.c.
anonymous enum |
CONFIG_LOGUNIQUEID | |
CONFIG_USEGMTIME | |
CONFIG_DISPOSITIONSTRING | |
CONFIG_HRTIME | |
CONFIG_REGISTERED |
Definition at line 52 of file cdr_odbc.c.
00052 { 00053 CONFIG_LOGUNIQUEID = 1 << 0, 00054 CONFIG_USEGMTIME = 1 << 1, 00055 CONFIG_DISPOSITIONSTRING = 1 << 2, 00056 CONFIG_HRTIME = 1 << 3, 00057 CONFIG_REGISTERED = 1 << 4, 00058 };
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_LOAD_ORDER | , | |||
"ODBC CDR Backend" | , | |||
. | load = load_module , |
|||
. | unload = unload_module , |
|||
. | reload = reload , |
|||
. | load_pri = AST_MODPRI_CDR_DRIVER | |||
) |
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().
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 00102 if (ast_test_flag(&config, CONFIG_HRTIME)) { 00103 double hrbillsec = 0.0; 00104 double hrduration; 00105 00106 if (!ast_tvzero(cdr->answer)) { 00107 hrbillsec = (double) ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0; 00108 } 00109 hrduration = (double) ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0; 00110 00111 SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_FLOAT, 0, 0, &hrduration, 0, NULL); 00112 SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_FLOAT, 0, 0, &hrbillsec, 0, NULL); 00113 } else { 00114 SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->duration, 0, NULL); 00115 SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL); 00116 } 00117 00118 if (ast_test_flag(&config, CONFIG_DISPOSITIONSTRING)) 00119 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); 00120 else 00121 SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->disposition, 0, NULL); 00122 SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->amaflags, 0, NULL); 00123 SQLBindParameter(stmt, 13, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->accountcode), 0, cdr->accountcode, 0, NULL); 00124 00125 if (ast_test_flag(&config, CONFIG_LOGUNIQUEID)) { 00126 SQLBindParameter(stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->uniqueid), 0, cdr->uniqueid, 0, NULL); 00127 SQLBindParameter(stmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->userfield), 0, cdr->userfield, 0, NULL); 00128 } 00129 00130 ODBC_res = SQLExecDirect(stmt, (unsigned char *)sqlcmd, SQL_NTS); 00131 00132 if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) { 00133 ast_verb(11, "cdr_odbc: Error in ExecDirect: %d\n", ODBC_res); 00134 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00135 return NULL; 00136 } 00137 00138 return stmt; 00139 }
static int load_module | ( | void | ) | [static] |
Definition at line 267 of file cdr_odbc.c.
References odbc_load_module().
00268 { 00269 return odbc_load_module(0); 00270 }
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, LOG_ERROR, LOG_WARNING, odbc_log(), and var.
Referenced by load_module(), and reload().
00168 { 00169 int res = 0; 00170 struct ast_config *cfg; 00171 struct ast_variable *var; 00172 const char *tmp; 00173 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 00174 00175 do { 00176 cfg = ast_config_load(config_file, config_flags); 00177 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) { 00178 ast_log(LOG_WARNING, "cdr_odbc: Unable to load config for ODBC CDR's: %s\n", config_file); 00179 res = AST_MODULE_LOAD_DECLINE; 00180 break; 00181 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) 00182 break; 00183 00184 var = ast_variable_browse(cfg, "global"); 00185 if (!var) { 00186 /* nothing configured */ 00187 break; 00188 } 00189 00190 if ((tmp = ast_variable_retrieve(cfg, "global", "dsn")) == NULL) { 00191 ast_log(LOG_WARNING, "cdr_odbc: dsn not specified. Assuming asteriskdb\n"); 00192 tmp = "asteriskdb"; 00193 } 00194 if (dsn) 00195 ast_free(dsn); 00196 dsn = ast_strdup(tmp); 00197 if (dsn == NULL) { 00198 res = -1; 00199 break; 00200 } 00201 00202 if (((tmp = ast_variable_retrieve(cfg, "global", "dispositionstring"))) && ast_true(tmp)) 00203 ast_set_flag(&config, CONFIG_DISPOSITIONSTRING); 00204 else 00205 ast_clear_flag(&config, CONFIG_DISPOSITIONSTRING); 00206 00207 if (((tmp = ast_variable_retrieve(cfg, "global", "loguniqueid"))) && ast_true(tmp)) { 00208 ast_set_flag(&config, CONFIG_LOGUNIQUEID); 00209 ast_debug(1, "cdr_odbc: Logging uniqueid\n"); 00210 } else { 00211 ast_clear_flag(&config, CONFIG_LOGUNIQUEID); 00212 ast_debug(1, "cdr_odbc: Not logging uniqueid\n"); 00213 } 00214 00215 if (((tmp = ast_variable_retrieve(cfg, "global", "usegmtime"))) && ast_true(tmp)) { 00216 ast_set_flag(&config, CONFIG_USEGMTIME); 00217 ast_debug(1, "cdr_odbc: Logging in GMT\n"); 00218 } else { 00219 ast_clear_flag(&config, CONFIG_USEGMTIME); 00220 ast_debug(1, "cdr_odbc: Logging in local time\n"); 00221 } 00222 00223 if (((tmp = ast_variable_retrieve(cfg, "global", "hrtime"))) && ast_true(tmp)) { 00224 ast_set_flag(&config, CONFIG_HRTIME); 00225 ast_debug(1, "cdr_odbc: Logging billsec and duration fields as floats\n"); 00226 } else { 00227 ast_clear_flag(&config, CONFIG_HRTIME); 00228 ast_debug(1, "cdr_odbc: Logging billsec and duration fields as integers\n"); 00229 } 00230 00231 if ((tmp = ast_variable_retrieve(cfg, "global", "table")) == NULL) { 00232 ast_log(LOG_WARNING, "cdr_odbc: table not specified. Assuming cdr\n"); 00233 tmp = "cdr"; 00234 } 00235 if (table) 00236 ast_free(table); 00237 table = ast_strdup(tmp); 00238 if (table == NULL) { 00239 res = -1; 00240 break; 00241 } 00242 00243 ast_verb(3, "cdr_odbc: dsn is %s\n", dsn); 00244 ast_verb(3, "cdr_odbc: table is %s\n", table); 00245 00246 if (!ast_test_flag(&config, CONFIG_REGISTERED)) { 00247 res = ast_cdr_register(name, ast_module_info->description, odbc_log); 00248 if (res) { 00249 ast_log(LOG_ERROR, "cdr_odbc: Unable to register ODBC CDR handling\n"); 00250 } else { 00251 ast_set_flag(&config, CONFIG_REGISTERED); 00252 } 00253 } 00254 } while (0); 00255 00256 if (ast_test_flag(&config, CONFIG_REGISTERED) && (!cfg || dsn == NULL || table == NULL)) { 00257 ast_cdr_unregister(name); 00258 ast_clear_flag(&config, CONFIG_REGISTERED); 00259 } 00260 00261 if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED && cfg != CONFIG_STATUS_FILEINVALID) { 00262 ast_config_destroy(cfg); 00263 } 00264 return res; 00265 }
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().
00143 { 00144 struct odbc_obj *obj = ast_odbc_request_obj(dsn, 0); 00145 SQLHSTMT stmt; 00146 00147 if (!obj) { 00148 ast_log(LOG_ERROR, "Unable to retrieve database handle. CDR failed.\n"); 00149 return -1; 00150 } 00151 00152 stmt = ast_odbc_direct_execute(obj, execute_cb, cdr); 00153 if (stmt) { 00154 SQLLEN rows = 0; 00155 00156 SQLRowCount(stmt, &rows); 00157 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00158 00159 if (rows == 0) 00160 ast_log(LOG_WARNING, "CDR successfully ran, but inserted 0 rows?\n"); 00161 } else 00162 ast_log(LOG_ERROR, "CDR direct execute failed\n"); 00163 ast_odbc_release_obj(obj); 00164 return 0; 00165 }
static int reload | ( | void | ) | [static] |
Definition at line 288 of file cdr_odbc.c.
References odbc_load_module().
00289 { 00290 return odbc_load_module(1); 00291 }
static int unload_module | ( | void | ) | [static] |
Definition at line 272 of file cdr_odbc.c.
References ast_cdr_unregister(), ast_free, and ast_verb.
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 [static] |
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(), find_table(), read_config_maps(), realtime_common(), reload(), require_pgsql(), tds_load_module(), unload_module(), update2_pgsql(), and update_pgsql().