cdr_sqlite.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2004 - 2005, Holger Schurig
00005  *
00006  *
00007  * Ideas taken from other cdr_*.c files
00008  *
00009  * See http://www.asterisk.org for more information about
00010  * the Asterisk project. Please do not directly contact
00011  * any of the maintainers of this project for assistance;
00012  * the project provides a web site, mailing lists and IRC
00013  * channels for your use.
00014  *
00015  * This program is free software, distributed under the terms of
00016  * the GNU General Public License Version 2. See the LICENSE file
00017  * at the top of the source tree.
00018  */
00019 
00020 /*!
00021  * \file
00022  * \brief Store CDR records in a SQLite database.
00023  *
00024  * \author Holger Schurig <hs4233@mail.mn-solutions.de>
00025  * SQLite http://www.sqlite.org/
00026  *
00027  * See also
00028  * \arg \ref Config_cdr
00029  * \arg http://www.sqlite.org/
00030  *
00031  * Creates the database and table on-the-fly
00032  * \ingroup cdr_drivers
00033  *
00034  * \note This module has been marked deprecated in favor for cdr_sqlite3_custom
00035  */
00036 
00037 /*** MODULEINFO
00038    <depend>sqlite</depend>
00039    <defaultenabled>no</defaultenabled>
00040    <support_level>deprecated</support_level>
00041    <replacement>sqlite3_custom</replacement>
00042  ***/
00043 
00044 #include "asterisk.h"
00045 
00046 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 419592 $")
00047 
00048 #include <sqlite.h>
00049 
00050 #include "asterisk/channel.h"
00051 #include "asterisk/module.h"
00052 #include "asterisk/utils.h"
00053 #include "asterisk/paths.h"
00054 
00055 #define LOG_UNIQUEID    0
00056 #define LOG_USERFIELD   0
00057 #define LOG_HRTIME      0
00058 
00059 /* When you change the DATE_FORMAT, be sure to change the CHAR(19) below to something else */
00060 #define DATE_FORMAT "%Y-%m-%d %T"
00061 
00062 static const char name[] = "sqlite";
00063 static sqlite* db = NULL;
00064 
00065 AST_MUTEX_DEFINE_STATIC(sqlite_lock);
00066 
00067 /*! \brief SQL table format */
00068 static const char sql_create_table[] = "CREATE TABLE cdr ("
00069 "  AcctId      INTEGER PRIMARY KEY,"
00070 "  clid     VARCHAR(80),"
00071 "  src      VARCHAR(80),"
00072 "  dst      VARCHAR(80),"
00073 "  dcontext VARCHAR(80),"
00074 "  channel     VARCHAR(80),"
00075 "  dstchannel  VARCHAR(80),"
00076 "  lastapp     VARCHAR(80),"
00077 "  lastdata VARCHAR(80),"
00078 "  start    CHAR(19),"
00079 "  answer      CHAR(19),"
00080 "  end      CHAR(19),"
00081 #if LOG_HRTIME
00082 "  duration FLOAT,"
00083 "  billsec     FLOAT,"
00084 #else
00085 "  duration INTEGER,"
00086 "  billsec     INTEGER,"
00087 #endif
00088 "  disposition INTEGER,"
00089 "  amaflags INTEGER,"
00090 "  accountcode VARCHAR(20)"
00091 #if LOG_UNIQUEID
00092 "  ,uniqueid   VARCHAR(32)"
00093 #endif
00094 #if LOG_USERFIELD
00095 "  ,userfield  VARCHAR(255)"
00096 #endif
00097 ");";
00098 
00099 static void format_date(char *buffer, size_t length, struct timeval *when)
00100 {
00101    struct ast_tm tm;
00102 
00103    ast_localtime(when, &tm, NULL);
00104    ast_strftime(buffer, length, DATE_FORMAT, &tm);
00105 }
00106 
00107 static int sqlite_log(struct ast_cdr *cdr)
00108 {
00109    int res = 0;
00110    char *zErr = 0;
00111    char startstr[80], answerstr[80], endstr[80];
00112    int count;
00113 #if LOG_HRTIME
00114    double hrbillsec = 0.0;
00115    double hrduration;
00116 #endif
00117 
00118    ast_mutex_lock(&sqlite_lock);
00119 
00120    format_date(startstr, sizeof(startstr), &cdr->start);
00121    format_date(answerstr, sizeof(answerstr), &cdr->answer);
00122    format_date(endstr, sizeof(endstr), &cdr->end);
00123 
00124 #if LOG_HRTIME
00125    if (!ast_tvzero(cdr->answer)) {
00126       hrbillsec = (double) ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0;
00127    }
00128    hrduration = (double) ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0;
00129 #endif
00130 
00131    for(count=0; count<5; count++) {
00132       res = sqlite_exec_printf(db,
00133          "INSERT INTO cdr ("
00134             "clid,src,dst,dcontext,"
00135             "channel,dstchannel,lastapp,lastdata, "
00136             "start,answer,end,"
00137             "duration,billsec,disposition,amaflags, "
00138             "accountcode"
00139 #           if LOG_UNIQUEID
00140             ",uniqueid"
00141 #           endif
00142 #           if LOG_USERFIELD
00143             ",userfield"
00144 #           endif
00145          ") VALUES ("
00146             "'%q', '%q', '%q', '%q', "
00147             "'%q', '%q', '%q', '%q', "
00148             "'%q', '%q', '%q', "
00149 #if LOG_HRTIME
00150             "%f, %f, %d, %d, "
00151 #else
00152             "%d, %d, %d, %d, "
00153 #endif
00154             "'%q'"
00155 #           if LOG_UNIQUEID
00156             ",'%q'"
00157 #           endif
00158 #           if LOG_USERFIELD
00159             ",'%q'"
00160 #           endif
00161          ")", NULL, NULL, &zErr,
00162             cdr->clid, cdr->src, cdr->dst, cdr->dcontext,
00163             cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata,
00164             startstr, answerstr, endstr,
00165 #if LOG_HRTIME
00166             hrduration, hrbillsec, cdr->disposition, cdr->amaflags,
00167 #else
00168             cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags,
00169 #endif
00170             cdr->accountcode
00171 #           if LOG_UNIQUEID
00172             ,cdr->uniqueid
00173 #           endif
00174 #           if LOG_USERFIELD
00175             ,cdr->userfield
00176 #           endif
00177          );
00178       if (res != SQLITE_BUSY && res != SQLITE_LOCKED)
00179          break;
00180       usleep(200);
00181    }
00182 
00183    if (zErr) {
00184       ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
00185       ast_free(zErr);
00186    }
00187 
00188    ast_mutex_unlock(&sqlite_lock);
00189    return res;
00190 }
00191 
00192 static int unload_module(void)
00193 {
00194    if (ast_cdr_unregister(name)) {
00195       return -1;
00196    }
00197 
00198    if (db) {
00199       sqlite_close(db);
00200    }
00201    return 0;
00202 }
00203 
00204 static int load_module(void)
00205 {
00206    char *zErr;
00207    char fn[PATH_MAX];
00208    int res;
00209 
00210    ast_log(LOG_NOTICE, "This module has been marked deprecated in favor of "
00211       "using cdr_sqlite3_custom.\n");
00212 
00213    /* is the database there? */
00214    snprintf(fn, sizeof(fn), "%s/cdr.db", ast_config_AST_LOG_DIR);
00215    db = sqlite_open(fn, AST_FILE_MODE, &zErr);
00216    if (!db) {
00217       ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
00218       ast_free(zErr);
00219       return AST_MODULE_LOAD_DECLINE;
00220    }
00221 
00222    /* is the table there? */
00223    res = sqlite_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL);
00224    if (res) {
00225       res = sqlite_exec(db, sql_create_table, NULL, NULL, &zErr);
00226       if (res) {
00227          ast_log(LOG_ERROR, "cdr_sqlite: Unable to create table 'cdr': %s\n", zErr);
00228          ast_free(zErr);
00229          goto err;
00230       }
00231 
00232       /* TODO: here we should probably create an index */
00233    }
00234 
00235    res = ast_cdr_register(name, ast_module_info->description, sqlite_log);
00236    if (res) {
00237       ast_log(LOG_ERROR, "Unable to register SQLite CDR handling\n");
00238       return AST_MODULE_LOAD_DECLINE;
00239    }
00240    return AST_MODULE_LOAD_SUCCESS;
00241 
00242 err:
00243    if (db)
00244       sqlite_close(db);
00245    return AST_MODULE_LOAD_DECLINE;
00246 }
00247 
00248 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SQLite CDR Backend",
00249    .support_level = AST_MODULE_SUPPORT_DEPRECATED,
00250    .load = load_module,
00251    .unload = unload_module,
00252    .load_pri = AST_MODPRI_CDR_DRIVER,
00253 );

Generated on Thu Apr 16 06:27:18 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6