00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "asterisk.h"
00044
00045 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328446 $")
00046
00047 #include <sqlite.h>
00048
00049 #include "asterisk/channel.h"
00050 #include "asterisk/module.h"
00051 #include "asterisk/utils.h"
00052 #include "asterisk/paths.h"
00053
00054 #define LOG_UNIQUEID 0
00055 #define LOG_USERFIELD 0
00056 #define LOG_HRTIME 0
00057
00058
00059 #define DATE_FORMAT "%Y-%m-%d %T"
00060
00061 static const char name[] = "sqlite";
00062 static sqlite* db = NULL;
00063
00064 AST_MUTEX_DEFINE_STATIC(sqlite_lock);
00065
00066
00067 static const char sql_create_table[] = "CREATE TABLE cdr ("
00068 " AcctId INTEGER PRIMARY KEY,"
00069 " clid VARCHAR(80),"
00070 " src VARCHAR(80),"
00071 " dst VARCHAR(80),"
00072 " dcontext VARCHAR(80),"
00073 " channel VARCHAR(80),"
00074 " dstchannel VARCHAR(80),"
00075 " lastapp VARCHAR(80),"
00076 " lastdata VARCHAR(80),"
00077 " start CHAR(19),"
00078 " answer CHAR(19),"
00079 " end CHAR(19),"
00080 #if LOG_HRTIME
00081 " duration FLOAT,"
00082 " billsec FLOAT,"
00083 #else
00084 " duration INTEGER,"
00085 " billsec INTEGER,"
00086 #endif
00087 " disposition INTEGER,"
00088 " amaflags INTEGER,"
00089 " accountcode VARCHAR(20)"
00090 #if LOG_UNIQUEID
00091 " ,uniqueid VARCHAR(32)"
00092 #endif
00093 #if LOG_USERFIELD
00094 " ,userfield VARCHAR(255)"
00095 #endif
00096 ");";
00097
00098 static void format_date(char *buffer, size_t length, struct timeval *when)
00099 {
00100 struct ast_tm tm;
00101
00102 ast_localtime(when, &tm, NULL);
00103 ast_strftime(buffer, length, DATE_FORMAT, &tm);
00104 }
00105
00106 static int sqlite_log(struct ast_cdr *cdr)
00107 {
00108 int res = 0;
00109 char *zErr = 0;
00110 char startstr[80], answerstr[80], endstr[80];
00111 int count;
00112 #if LOG_HRTIME
00113 double hrbillsec = 0.0;
00114 double hrduration;
00115 #endif
00116
00117 ast_mutex_lock(&sqlite_lock);
00118
00119 format_date(startstr, sizeof(startstr), &cdr->start);
00120 format_date(answerstr, sizeof(answerstr), &cdr->answer);
00121 format_date(endstr, sizeof(endstr), &cdr->end);
00122
00123 #if LOG_HRTIME
00124 if (!ast_tvzero(cdr->answer)) {
00125 hrbillsec = (double) ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0;
00126 }
00127 hrduration = (double) ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0;
00128 #endif
00129
00130 for(count=0; count<5; count++) {
00131 res = sqlite_exec_printf(db,
00132 "INSERT INTO cdr ("
00133 "clid,src,dst,dcontext,"
00134 "channel,dstchannel,lastapp,lastdata, "
00135 "start,answer,end,"
00136 "duration,billsec,disposition,amaflags, "
00137 "accountcode"
00138 # if LOG_UNIQUEID
00139 ",uniqueid"
00140 # endif
00141 # if LOG_USERFIELD
00142 ",userfield"
00143 # endif
00144 ") VALUES ("
00145 "'%q', '%q', '%q', '%q', "
00146 "'%q', '%q', '%q', '%q', "
00147 "'%q', '%q', '%q', "
00148 #if LOG_HRTIME
00149 "%f, %f, %d, %d, "
00150 #else
00151 "%d, %d, %d, %d, "
00152 #endif
00153 "'%q'"
00154 # if LOG_UNIQUEID
00155 ",'%q'"
00156 # endif
00157 # if LOG_USERFIELD
00158 ",'%q'"
00159 # endif
00160 ")", NULL, NULL, &zErr,
00161 cdr->clid, cdr->src, cdr->dst, cdr->dcontext,
00162 cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata,
00163 startstr, answerstr, endstr,
00164 #if LOG_HRTIME
00165 hrduration, hrbillsec, cdr->disposition, cdr->amaflags,
00166 #else
00167 cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags,
00168 #endif
00169 cdr->accountcode
00170 # if LOG_UNIQUEID
00171 ,cdr->uniqueid
00172 # endif
00173 # if LOG_USERFIELD
00174 ,cdr->userfield
00175 # endif
00176 );
00177 if (res != SQLITE_BUSY && res != SQLITE_LOCKED)
00178 break;
00179 usleep(200);
00180 }
00181
00182 if (zErr) {
00183 ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
00184 ast_free(zErr);
00185 }
00186
00187 ast_mutex_unlock(&sqlite_lock);
00188 return res;
00189 }
00190
00191 static int unload_module(void)
00192 {
00193 ast_cdr_unregister(name);
00194 if (db) {
00195 sqlite_close(db);
00196 }
00197 return 0;
00198 }
00199
00200 static int load_module(void)
00201 {
00202 char *zErr;
00203 char fn[PATH_MAX];
00204 int res;
00205
00206 ast_log(LOG_NOTICE, "This module has been marked deprecated in favor of "
00207 "using cdr_sqlite3_custom.\n");
00208
00209
00210 snprintf(fn, sizeof(fn), "%s/cdr.db", ast_config_AST_LOG_DIR);
00211 db = sqlite_open(fn, AST_FILE_MODE, &zErr);
00212 if (!db) {
00213 ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
00214 ast_free(zErr);
00215 return AST_MODULE_LOAD_DECLINE;
00216 }
00217
00218
00219 res = sqlite_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL);
00220 if (res) {
00221 res = sqlite_exec(db, sql_create_table, NULL, NULL, &zErr);
00222 if (res) {
00223 ast_log(LOG_ERROR, "cdr_sqlite: Unable to create table 'cdr': %s\n", zErr);
00224 ast_free(zErr);
00225 goto err;
00226 }
00227
00228
00229 }
00230
00231 res = ast_cdr_register(name, ast_module_info->description, sqlite_log);
00232 if (res) {
00233 ast_log(LOG_ERROR, "Unable to register SQLite CDR handling\n");
00234 return AST_MODULE_LOAD_DECLINE;
00235 }
00236 return AST_MODULE_LOAD_SUCCESS;
00237
00238 err:
00239 if (db)
00240 sqlite_close(db);
00241 return AST_MODULE_LOAD_DECLINE;
00242 }
00243
00244 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SQLite CDR Backend",
00245 .load = load_module,
00246 .unload = unload_module,
00247 .load_pri = AST_MODPRI_CDR_DRIVER,
00248 );