Wed Jan 8 2020 09:49:42

Asterisk developer's documentation


cdr_sqlite.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2004 - 2005, Holger Schurig
5  *
6  *
7  * Ideas taken from other cdr_*.c files
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19 
20 /*!
21  * \file
22  * \brief Store CDR records in a SQLite database.
23  *
24  * \author Holger Schurig <hs4233@mail.mn-solutions.de>
25  * \extref SQLite http://www.sqlite.org/
26  *
27  * See also
28  * \arg \ref Config_cdr
29  * \arg http://www.sqlite.org/
30  *
31  * Creates the database and table on-the-fly
32  * \ingroup cdr_drivers
33  *
34  * \note This module has been marked deprecated in favor for cdr_sqlite3_custom
35  */
36 
37 /*** MODULEINFO
38  <depend>sqlite</depend>
39  <support_level>deprecated</support_level>
40  <replacement>sqlite3_custom</replacement>
41  ***/
42 
43 #include "asterisk.h"
44 
45 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328446 $")
46 
47 #include <sqlite.h>
48 
49 #include "asterisk/channel.h"
50 #include "asterisk/module.h"
51 #include "asterisk/utils.h"
52 #include "asterisk/paths.h"
53 
54 #define LOG_UNIQUEID 0
55 #define LOG_USERFIELD 0
56 #define LOG_HRTIME 0
57 
58 /* When you change the DATE_FORMAT, be sure to change the CHAR(19) below to something else */
59 #define DATE_FORMAT "%Y-%m-%d %T"
60 
61 static const char name[] = "sqlite";
62 static sqlite* db = NULL;
63 
65 
66 /*! \brief SQL table format */
67 static const char sql_create_table[] = "CREATE TABLE cdr ("
68 " AcctId INTEGER PRIMARY KEY,"
69 " clid VARCHAR(80),"
70 " src VARCHAR(80),"
71 " dst VARCHAR(80),"
72 " dcontext VARCHAR(80),"
73 " channel VARCHAR(80),"
74 " dstchannel VARCHAR(80),"
75 " lastapp VARCHAR(80),"
76 " lastdata VARCHAR(80),"
77 " start CHAR(19),"
78 " answer CHAR(19),"
79 " end CHAR(19),"
80 #if LOG_HRTIME
81 " duration FLOAT,"
82 " billsec FLOAT,"
83 #else
84 " duration INTEGER,"
85 " billsec INTEGER,"
86 #endif
87 " disposition INTEGER,"
88 " amaflags INTEGER,"
89 " accountcode VARCHAR(20)"
90 #if LOG_UNIQUEID
91 " ,uniqueid VARCHAR(32)"
92 #endif
93 #if LOG_USERFIELD
94 " ,userfield VARCHAR(255)"
95 #endif
96 ");";
97 
98 static void format_date(char *buffer, size_t length, struct timeval *when)
99 {
100  struct ast_tm tm;
101 
102  ast_localtime(when, &tm, NULL);
103  ast_strftime(buffer, length, DATE_FORMAT, &tm);
104 }
105 
106 static int sqlite_log(struct ast_cdr *cdr)
107 {
108  int res = 0;
109  char *zErr = 0;
110  char startstr[80], answerstr[80], endstr[80];
111  int count;
112 #if LOG_HRTIME
113  double hrbillsec = 0.0;
114  double hrduration;
115 #endif
116 
118 
119  format_date(startstr, sizeof(startstr), &cdr->start);
120  format_date(answerstr, sizeof(answerstr), &cdr->answer);
121  format_date(endstr, sizeof(endstr), &cdr->end);
122 
123 #if LOG_HRTIME
124  if (!ast_tvzero(cdr->answer)) {
125  hrbillsec = (double) ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0;
126  }
127  hrduration = (double) ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0;
128 #endif
129 
130  for(count=0; count<5; count++) {
131  res = sqlite_exec_printf(db,
132  "INSERT INTO cdr ("
133  "clid,src,dst,dcontext,"
134  "channel,dstchannel,lastapp,lastdata, "
135  "start,answer,end,"
136  "duration,billsec,disposition,amaflags, "
137  "accountcode"
138 # if LOG_UNIQUEID
139  ",uniqueid"
140 # endif
141 # if LOG_USERFIELD
142  ",userfield"
143 # endif
144  ") VALUES ("
145  "'%q', '%q', '%q', '%q', "
146  "'%q', '%q', '%q', '%q', "
147  "'%q', '%q', '%q', "
148 #if LOG_HRTIME
149  "%f, %f, %d, %d, "
150 #else
151  "%d, %d, %d, %d, "
152 #endif
153  "'%q'"
154 # if LOG_UNIQUEID
155  ",'%q'"
156 # endif
157 # if LOG_USERFIELD
158  ",'%q'"
159 # endif
160  ")", NULL, NULL, &zErr,
161  cdr->clid, cdr->src, cdr->dst, cdr->dcontext,
162  cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata,
163  startstr, answerstr, endstr,
164 #if LOG_HRTIME
165  hrduration, hrbillsec, cdr->disposition, cdr->amaflags,
166 #else
167  cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags,
168 #endif
169  cdr->accountcode
170 # if LOG_UNIQUEID
171  ,cdr->uniqueid
172 # endif
173 # if LOG_USERFIELD
174  ,cdr->userfield
175 # endif
176  );
177  if (res != SQLITE_BUSY && res != SQLITE_LOCKED)
178  break;
179  usleep(200);
180  }
181 
182  if (zErr) {
183  ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
184  ast_free(zErr);
185  }
186 
188  return res;
189 }
190 
191 static int unload_module(void)
192 {
193  ast_cdr_unregister(name);
194  if (db) {
195  sqlite_close(db);
196  }
197  return 0;
198 }
199 
200 static int load_module(void)
201 {
202  char *zErr;
203  char fn[PATH_MAX];
204  int res;
205 
206  ast_log(LOG_NOTICE, "This module has been marked deprecated in favor of "
207  "using cdr_sqlite3_custom.\n");
208 
209  /* is the database there? */
210  snprintf(fn, sizeof(fn), "%s/cdr.db", ast_config_AST_LOG_DIR);
211  db = sqlite_open(fn, AST_FILE_MODE, &zErr);
212  if (!db) {
213  ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
214  ast_free(zErr);
216  }
217 
218  /* is the table there? */
219  res = sqlite_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL);
220  if (res) {
221  res = sqlite_exec(db, sql_create_table, NULL, NULL, &zErr);
222  if (res) {
223  ast_log(LOG_ERROR, "cdr_sqlite: Unable to create table 'cdr': %s\n", zErr);
224  ast_free(zErr);
225  goto err;
226  }
227 
228  /* TODO: here we should probably create an index */
229  }
230 
232  if (res) {
233  ast_log(LOG_ERROR, "Unable to register SQLite CDR handling\n");
235  }
237 
238 err:
239  if (db)
240  sqlite_close(db);
242 }
243 
245  .load = load_module,
246  .unload = unload_module,
247  .load_pri = AST_MODPRI_CDR_DRIVER,
248 );
const char * description
Definition: module.h:234
static int unload_module(void)
Definition: cdr_sqlite.c:191
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:114
Asterisk main include file. File version handling, generic pbx functions.
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:94
long int billsec
Definition: cdr.h:108
char dcontext[AST_MAX_EXTENSION]
Definition: cdr.h:90
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:100
char uniqueid[150]
Definition: cdr.h:121
#define ast_mutex_lock(a)
Definition: lock.h:155
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:374
#define AST_FILE_MODE
Definition: asterisk.h:36
Utility functions.
#define DATE_FORMAT
Definition: cdr_sqlite.c:59
static ast_mutex_t sqlite_lock
Definition: cdr_sqlite.c:64
char lastdata[AST_MAX_EXTENSION]
Definition: cdr.h:98
long int amaflags
Definition: cdr.h:112
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
Definition: cdr.c:130
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
char dst[AST_MAX_EXTENSION]
Definition: cdr.h:88
#define LOG_USERFIELD
Definition: cdr_sqlite.c:55
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:92
struct timeval answer
Definition: cdr.h:102
Responsible for call detail data.
Definition: cdr.h:82
char lastapp[AST_MAX_EXTENSION]
Definition: cdr.h:96
#define LOG_ERROR
Definition: logger.h:155
#define LOG_UNIQUEID
Definition: cdr_sqlite.c:54
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
const char * ast_config_AST_LOG_DIR
Definition: asterisk.c:263
#define LOG_HRTIME
Definition: cdr_sqlite.c:56
struct timeval start
Definition: cdr.h:100
static const char name[]
#define ast_free(a)
Definition: astmm.h:97
static sqlite * db
Definition: cdr_sqlite.c:62
long int duration
Definition: cdr.h:106
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2351
static void format_date(char *buffer, size_t length, struct timeval *when)
Definition: cdr_sqlite.c:98
static int sqlite_log(struct ast_cdr *cdr)
Definition: cdr_sqlite.c:106
char src[AST_MAX_EXTENSION]
Definition: cdr.h:86
struct timeval end
Definition: cdr.h:104
static int load_module(void)
Definition: cdr_sqlite.c:200
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:70
long int disposition
Definition: cdr.h:110
char clid[AST_MAX_EXTENSION]
Definition: cdr.h:84
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Asterisk module definitions.
static const char sql_create_table[]
SQL table format.
Definition: cdr_sqlite.c:67
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:526
void ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition: cdr.c:165
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.h:125
#define ast_mutex_unlock(a)
Definition: lock.h:156