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