2004-07-08 08:29:26 +00:00
|
|
|
/*
|
2005-09-14 20:46:50 +00:00
|
|
|
* Asterisk -- An open source telephony toolkit.
|
2004-07-08 08:29:26 +00:00
|
|
|
*
|
2005-01-21 07:06:25 +00:00
|
|
|
* Copyright (C) 2004 - 2005, Holger Schurig
|
2004-07-08 08:29:26 +00:00
|
|
|
*
|
|
|
|
*
|
2005-09-14 20:46:50 +00:00
|
|
|
* Ideas taken from other cdr_*.c files
|
|
|
|
*
|
|
|
|
* See http://www.asterisk.org for more information about
|
|
|
|
* the Asterisk project. Please do not directly contact
|
|
|
|
* any of the maintainers of this project for assistance;
|
|
|
|
* the project provides a web site, mailing lists and IRC
|
|
|
|
* channels for your use.
|
|
|
|
*
|
2004-07-08 08:29:26 +00:00
|
|
|
* This program is free software, distributed under the terms of
|
2005-09-14 20:46:50 +00:00
|
|
|
* the GNU General Public License Version 2. See the LICENSE file
|
|
|
|
* at the top of the source tree.
|
|
|
|
*/
|
|
|
|
|
2010-02-26 08:08:38 +00:00
|
|
|
/*!
|
|
|
|
* \file
|
2005-10-26 13:03:17 +00:00
|
|
|
* \brief Store CDR records in a SQLite database.
|
2008-11-20 17:48:58 +00:00
|
|
|
*
|
2005-10-26 13:03:17 +00:00
|
|
|
* \author Holger Schurig <hs4233@mail.mn-solutions.de>
|
2012-09-21 17:14:59 +00:00
|
|
|
* SQLite http://www.sqlite.org/
|
2004-07-08 08:29:26 +00:00
|
|
|
*
|
2005-10-26 13:03:17 +00:00
|
|
|
* See also
|
|
|
|
* \arg \ref Config_cdr
|
|
|
|
* \arg http://www.sqlite.org/
|
2008-11-20 17:48:58 +00:00
|
|
|
*
|
2005-10-26 13:03:17 +00:00
|
|
|
* Creates the database and table on-the-fly
|
2005-11-06 15:09:47 +00:00
|
|
|
* \ingroup cdr_drivers
|
2007-03-13 21:22:33 +00:00
|
|
|
*
|
|
|
|
* \note This module has been marked deprecated in favor for cdr_sqlite3_custom
|
2004-07-08 08:29:26 +00:00
|
|
|
*/
|
|
|
|
|
2006-04-24 17:11:45 +00:00
|
|
|
/*** MODULEINFO
|
|
|
|
<depend>sqlite</depend>
|
2011-07-14 20:28:54 +00:00
|
|
|
<defaultenabled>no</defaultenabled>
|
|
|
|
<support_level>deprecated</support_level>
|
|
|
|
<replacement>sqlite3_custom</replacement>
|
2006-04-24 17:11:45 +00:00
|
|
|
***/
|
|
|
|
|
2006-06-07 18:54:56 +00:00
|
|
|
#include "asterisk.h"
|
2004-07-08 08:29:26 +00:00
|
|
|
|
2006-06-07 18:54:56 +00:00
|
|
|
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|
|
|
|
2004-07-08 08:29:26 +00:00
|
|
|
#include <sqlite.h>
|
|
|
|
|
2005-06-06 21:09:59 +00:00
|
|
|
#include "asterisk/channel.h"
|
|
|
|
#include "asterisk/module.h"
|
|
|
|
#include "asterisk/utils.h"
|
2007-11-20 23:29:33 +00:00
|
|
|
#include "asterisk/paths.h"
|
2004-07-08 08:29:26 +00:00
|
|
|
|
2010-06-08 23:48:17 +00:00
|
|
|
#define LOG_UNIQUEID 0
|
|
|
|
#define LOG_USERFIELD 0
|
|
|
|
#define LOG_HRTIME 0
|
2004-07-08 08:29:26 +00:00
|
|
|
|
|
|
|
/* When you change the DATE_FORMAT, be sure to change the CHAR(19) below to something else */
|
|
|
|
#define DATE_FORMAT "%Y-%m-%d %T"
|
|
|
|
|
2010-02-26 08:45:11 +00:00
|
|
|
static const char name[] = "sqlite";
|
2004-07-08 08:29:26 +00:00
|
|
|
static sqlite* db = NULL;
|
|
|
|
|
|
|
|
AST_MUTEX_DEFINE_STATIC(sqlite_lock);
|
|
|
|
|
2005-10-26 13:03:17 +00:00
|
|
|
/*! \brief SQL table format */
|
2009-05-21 21:13:09 +00:00
|
|
|
static const char sql_create_table[] = "CREATE TABLE cdr ("
|
2004-07-08 08:29:26 +00:00
|
|
|
" AcctId INTEGER PRIMARY KEY,"
|
|
|
|
" clid VARCHAR(80),"
|
|
|
|
" src VARCHAR(80),"
|
|
|
|
" dst VARCHAR(80),"
|
|
|
|
" dcontext VARCHAR(80),"
|
|
|
|
" channel VARCHAR(80),"
|
|
|
|
" dstchannel VARCHAR(80),"
|
|
|
|
" lastapp VARCHAR(80),"
|
|
|
|
" lastdata VARCHAR(80),"
|
|
|
|
" start CHAR(19),"
|
|
|
|
" answer CHAR(19),"
|
|
|
|
" end CHAR(19),"
|
2010-06-08 23:48:17 +00:00
|
|
|
#if LOG_HRTIME
|
|
|
|
" duration FLOAT,"
|
|
|
|
" billsec FLOAT,"
|
|
|
|
#else
|
2004-07-08 08:29:26 +00:00
|
|
|
" duration INTEGER,"
|
|
|
|
" billsec INTEGER,"
|
2010-06-08 23:48:17 +00:00
|
|
|
#endif
|
2004-07-08 08:29:26 +00:00
|
|
|
" disposition INTEGER,"
|
|
|
|
" amaflags INTEGER,"
|
|
|
|
" accountcode VARCHAR(20)"
|
|
|
|
#if LOG_UNIQUEID
|
2004-08-01 18:28:10 +00:00
|
|
|
" ,uniqueid VARCHAR(32)"
|
2004-07-08 08:29:26 +00:00
|
|
|
#endif
|
|
|
|
#if LOG_USERFIELD
|
|
|
|
" ,userfield VARCHAR(255)"
|
|
|
|
#endif
|
|
|
|
");";
|
|
|
|
|
2008-09-03 13:48:12 +00:00
|
|
|
static void format_date(char *buffer, size_t length, struct timeval *when)
|
|
|
|
{
|
|
|
|
struct ast_tm tm;
|
|
|
|
|
|
|
|
ast_localtime(when, &tm, NULL);
|
|
|
|
ast_strftime(buffer, length, DATE_FORMAT, &tm);
|
|
|
|
}
|
|
|
|
|
2004-07-08 08:29:26 +00:00
|
|
|
static int sqlite_log(struct ast_cdr *cdr)
|
|
|
|
{
|
|
|
|
int res = 0;
|
|
|
|
char *zErr = 0;
|
|
|
|
char startstr[80], answerstr[80], endstr[80];
|
|
|
|
int count;
|
2010-06-08 23:48:17 +00:00
|
|
|
#if LOG_HRTIME
|
|
|
|
double hrbillsec = 0.0;
|
|
|
|
double hrduration;
|
|
|
|
#endif
|
2004-07-08 08:29:26 +00:00
|
|
|
|
|
|
|
ast_mutex_lock(&sqlite_lock);
|
|
|
|
|
2008-09-03 13:48:12 +00:00
|
|
|
format_date(startstr, sizeof(startstr), &cdr->start);
|
|
|
|
format_date(answerstr, sizeof(answerstr), &cdr->answer);
|
|
|
|
format_date(endstr, sizeof(endstr), &cdr->end);
|
2004-07-08 08:29:26 +00:00
|
|
|
|
2010-06-08 23:48:17 +00:00
|
|
|
#if LOG_HRTIME
|
|
|
|
if (!ast_tvzero(cdr->answer)) {
|
|
|
|
hrbillsec = (double) ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0;
|
|
|
|
}
|
|
|
|
hrduration = (double) ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0;
|
|
|
|
#endif
|
|
|
|
|
2004-07-08 08:29:26 +00:00
|
|
|
for(count=0; count<5; count++) {
|
|
|
|
res = sqlite_exec_printf(db,
|
|
|
|
"INSERT INTO cdr ("
|
|
|
|
"clid,src,dst,dcontext,"
|
|
|
|
"channel,dstchannel,lastapp,lastdata, "
|
|
|
|
"start,answer,end,"
|
|
|
|
"duration,billsec,disposition,amaflags, "
|
|
|
|
"accountcode"
|
|
|
|
# if LOG_UNIQUEID
|
|
|
|
",uniqueid"
|
|
|
|
# endif
|
|
|
|
# if LOG_USERFIELD
|
|
|
|
",userfield"
|
|
|
|
# endif
|
|
|
|
") VALUES ("
|
|
|
|
"'%q', '%q', '%q', '%q', "
|
|
|
|
"'%q', '%q', '%q', '%q', "
|
|
|
|
"'%q', '%q', '%q', "
|
2010-06-08 23:48:17 +00:00
|
|
|
#if LOG_HRTIME
|
|
|
|
"%f, %f, %d, %d, "
|
|
|
|
#else
|
2004-07-08 08:29:26 +00:00
|
|
|
"%d, %d, %d, %d, "
|
2010-06-08 23:48:17 +00:00
|
|
|
#endif
|
2004-07-08 08:29:26 +00:00
|
|
|
"'%q'"
|
|
|
|
# if LOG_UNIQUEID
|
|
|
|
",'%q'"
|
|
|
|
# endif
|
|
|
|
# if LOG_USERFIELD
|
|
|
|
",'%q'"
|
|
|
|
# endif
|
|
|
|
")", NULL, NULL, &zErr,
|
|
|
|
cdr->clid, cdr->src, cdr->dst, cdr->dcontext,
|
|
|
|
cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata,
|
|
|
|
startstr, answerstr, endstr,
|
2010-06-08 23:48:17 +00:00
|
|
|
#if LOG_HRTIME
|
|
|
|
hrduration, hrbillsec, cdr->disposition, cdr->amaflags,
|
|
|
|
#else
|
2004-07-08 08:29:26 +00:00
|
|
|
cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags,
|
2010-06-08 23:48:17 +00:00
|
|
|
#endif
|
2004-07-08 08:29:26 +00:00
|
|
|
cdr->accountcode
|
|
|
|
# if LOG_UNIQUEID
|
|
|
|
,cdr->uniqueid
|
|
|
|
# endif
|
|
|
|
# if LOG_USERFIELD
|
|
|
|
,cdr->userfield
|
|
|
|
# endif
|
|
|
|
);
|
|
|
|
if (res != SQLITE_BUSY && res != SQLITE_LOCKED)
|
|
|
|
break;
|
|
|
|
usleep(200);
|
|
|
|
}
|
2008-11-20 17:48:58 +00:00
|
|
|
|
2004-07-08 08:29:26 +00:00
|
|
|
if (zErr) {
|
|
|
|
ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
|
2007-06-06 21:20:11 +00:00
|
|
|
ast_free(zErr);
|
2004-07-08 08:29:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ast_mutex_unlock(&sqlite_lock);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2006-08-21 02:11:39 +00:00
|
|
|
static int unload_module(void)
|
2004-07-08 08:29:26 +00:00
|
|
|
{
|
2013-10-27 20:04:17 +00:00
|
|
|
if (ast_cdr_unregister(name)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-12-16 06:51:51 +00:00
|
|
|
if (db) {
|
|
|
|
sqlite_close(db);
|
|
|
|
}
|
2004-07-08 08:29:26 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-08-21 02:11:39 +00:00
|
|
|
static int load_module(void)
|
2004-07-08 08:29:26 +00:00
|
|
|
{
|
|
|
|
char *zErr;
|
|
|
|
char fn[PATH_MAX];
|
|
|
|
int res;
|
|
|
|
|
2011-01-05 16:30:56 +00:00
|
|
|
ast_log(LOG_NOTICE, "This module has been marked deprecated in favor of "
|
|
|
|
"using cdr_sqlite3_custom.\n");
|
2007-03-13 21:22:33 +00:00
|
|
|
|
2004-07-08 08:29:26 +00:00
|
|
|
/* is the database there? */
|
2004-07-14 13:57:15 +00:00
|
|
|
snprintf(fn, sizeof(fn), "%s/cdr.db", ast_config_AST_LOG_DIR);
|
2006-12-21 19:44:20 +00:00
|
|
|
db = sqlite_open(fn, AST_FILE_MODE, &zErr);
|
2004-07-08 08:29:26 +00:00
|
|
|
if (!db) {
|
|
|
|
ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
|
2007-06-06 21:20:11 +00:00
|
|
|
ast_free(zErr);
|
2009-06-26 15:28:53 +00:00
|
|
|
return AST_MODULE_LOAD_DECLINE;
|
2004-07-08 08:29:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* is the table there? */
|
|
|
|
res = sqlite_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL);
|
|
|
|
if (res) {
|
|
|
|
res = sqlite_exec(db, sql_create_table, NULL, NULL, &zErr);
|
|
|
|
if (res) {
|
|
|
|
ast_log(LOG_ERROR, "cdr_sqlite: Unable to create table 'cdr': %s\n", zErr);
|
2007-06-06 21:20:11 +00:00
|
|
|
ast_free(zErr);
|
2004-07-08 08:29:26 +00:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: here we should probably create an index */
|
|
|
|
}
|
2008-11-20 17:48:58 +00:00
|
|
|
|
2006-08-21 02:11:39 +00:00
|
|
|
res = ast_cdr_register(name, ast_module_info->description, sqlite_log);
|
2004-07-08 08:29:26 +00:00
|
|
|
if (res) {
|
|
|
|
ast_log(LOG_ERROR, "Unable to register SQLite CDR handling\n");
|
2009-06-26 15:28:53 +00:00
|
|
|
return AST_MODULE_LOAD_DECLINE;
|
2004-07-08 08:29:26 +00:00
|
|
|
}
|
2009-06-26 15:28:53 +00:00
|
|
|
return AST_MODULE_LOAD_SUCCESS;
|
2004-07-08 08:29:26 +00:00
|
|
|
|
|
|
|
err:
|
|
|
|
if (db)
|
|
|
|
sqlite_close(db);
|
2009-06-26 15:28:53 +00:00
|
|
|
return AST_MODULE_LOAD_DECLINE;
|
2004-07-08 08:29:26 +00:00
|
|
|
}
|
|
|
|
|
2010-07-20 19:35:02 +00:00
|
|
|
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SQLite CDR Backend",
|
|
|
|
.load = load_module,
|
|
|
|
.unload = unload_module,
|
|
|
|
.load_pri = AST_MODPRI_CDR_DRIVER,
|
|
|
|
);
|