cdr_sqlite.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  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. * \file
  21. * \brief Store CDR records in a SQLite database.
  22. *
  23. * \author Holger Schurig <hs4233@mail.mn-solutions.de>
  24. * SQLite http://www.sqlite.org/
  25. *
  26. * See also
  27. * \arg \ref Config_cdr
  28. * \arg http://www.sqlite.org/
  29. *
  30. * Creates the database and table on-the-fly
  31. * \ingroup cdr_drivers
  32. *
  33. * \note This module has been marked deprecated in favor for cdr_sqlite3_custom
  34. */
  35. /*** MODULEINFO
  36. <depend>sqlite</depend>
  37. <defaultenabled>no</defaultenabled>
  38. <support_level>deprecated</support_level>
  39. <replacement>sqlite3_custom</replacement>
  40. ***/
  41. #include "asterisk.h"
  42. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  43. #include <sqlite.h>
  44. #include "asterisk/channel.h"
  45. #include "asterisk/module.h"
  46. #include "asterisk/utils.h"
  47. #include "asterisk/paths.h"
  48. #define LOG_UNIQUEID 0
  49. #define LOG_USERFIELD 0
  50. #define LOG_HRTIME 0
  51. /* When you change the DATE_FORMAT, be sure to change the CHAR(19) below to something else */
  52. #define DATE_FORMAT "%Y-%m-%d %T"
  53. static const char name[] = "sqlite";
  54. static sqlite* db = NULL;
  55. AST_MUTEX_DEFINE_STATIC(sqlite_lock);
  56. /*! \brief SQL table format */
  57. static const char sql_create_table[] = "CREATE TABLE cdr ("
  58. " AcctId INTEGER PRIMARY KEY,"
  59. " clid VARCHAR(80),"
  60. " src VARCHAR(80),"
  61. " dst VARCHAR(80),"
  62. " dcontext VARCHAR(80),"
  63. " channel VARCHAR(80),"
  64. " dstchannel VARCHAR(80),"
  65. " lastapp VARCHAR(80),"
  66. " lastdata VARCHAR(80),"
  67. " start CHAR(19),"
  68. " answer CHAR(19),"
  69. " end CHAR(19),"
  70. #if LOG_HRTIME
  71. " duration FLOAT,"
  72. " billsec FLOAT,"
  73. #else
  74. " duration INTEGER,"
  75. " billsec INTEGER,"
  76. #endif
  77. " disposition INTEGER,"
  78. " amaflags INTEGER,"
  79. " accountcode VARCHAR(20)"
  80. #if LOG_UNIQUEID
  81. " ,uniqueid VARCHAR(32)"
  82. #endif
  83. #if LOG_USERFIELD
  84. " ,userfield VARCHAR(255)"
  85. #endif
  86. ");";
  87. static void format_date(char *buffer, size_t length, struct timeval *when)
  88. {
  89. struct ast_tm tm;
  90. ast_localtime(when, &tm, NULL);
  91. ast_strftime(buffer, length, DATE_FORMAT, &tm);
  92. }
  93. static int sqlite_log(struct ast_cdr *cdr)
  94. {
  95. int res = 0;
  96. char *zErr = 0;
  97. char startstr[80], answerstr[80], endstr[80];
  98. int count;
  99. #if LOG_HRTIME
  100. double hrbillsec = 0.0;
  101. double hrduration;
  102. #endif
  103. ast_mutex_lock(&sqlite_lock);
  104. format_date(startstr, sizeof(startstr), &cdr->start);
  105. format_date(answerstr, sizeof(answerstr), &cdr->answer);
  106. format_date(endstr, sizeof(endstr), &cdr->end);
  107. #if LOG_HRTIME
  108. if (!ast_tvzero(cdr->answer)) {
  109. hrbillsec = (double) ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0;
  110. }
  111. hrduration = (double) ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0;
  112. #endif
  113. for(count=0; count<5; count++) {
  114. res = sqlite_exec_printf(db,
  115. "INSERT INTO cdr ("
  116. "clid,src,dst,dcontext,"
  117. "channel,dstchannel,lastapp,lastdata, "
  118. "start,answer,end,"
  119. "duration,billsec,disposition,amaflags, "
  120. "accountcode"
  121. # if LOG_UNIQUEID
  122. ",uniqueid"
  123. # endif
  124. # if LOG_USERFIELD
  125. ",userfield"
  126. # endif
  127. ") VALUES ("
  128. "'%q', '%q', '%q', '%q', "
  129. "'%q', '%q', '%q', '%q', "
  130. "'%q', '%q', '%q', "
  131. #if LOG_HRTIME
  132. "%f, %f, %d, %d, "
  133. #else
  134. "%d, %d, %d, %d, "
  135. #endif
  136. "'%q'"
  137. # if LOG_UNIQUEID
  138. ",'%q'"
  139. # endif
  140. # if LOG_USERFIELD
  141. ",'%q'"
  142. # endif
  143. ")", NULL, NULL, &zErr,
  144. cdr->clid, cdr->src, cdr->dst, cdr->dcontext,
  145. cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata,
  146. startstr, answerstr, endstr,
  147. #if LOG_HRTIME
  148. hrduration, hrbillsec, cdr->disposition, cdr->amaflags,
  149. #else
  150. cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags,
  151. #endif
  152. cdr->accountcode
  153. # if LOG_UNIQUEID
  154. ,cdr->uniqueid
  155. # endif
  156. # if LOG_USERFIELD
  157. ,cdr->userfield
  158. # endif
  159. );
  160. if (res != SQLITE_BUSY && res != SQLITE_LOCKED)
  161. break;
  162. usleep(200);
  163. }
  164. if (zErr) {
  165. ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
  166. ast_free(zErr);
  167. }
  168. ast_mutex_unlock(&sqlite_lock);
  169. return res;
  170. }
  171. static int unload_module(void)
  172. {
  173. if (ast_cdr_unregister(name)) {
  174. return -1;
  175. }
  176. if (db) {
  177. sqlite_close(db);
  178. }
  179. return 0;
  180. }
  181. static int load_module(void)
  182. {
  183. char *zErr;
  184. char fn[PATH_MAX];
  185. int res;
  186. ast_log(LOG_NOTICE, "This module has been marked deprecated in favor of "
  187. "using cdr_sqlite3_custom.\n");
  188. /* is the database there? */
  189. snprintf(fn, sizeof(fn), "%s/cdr.db", ast_config_AST_LOG_DIR);
  190. db = sqlite_open(fn, AST_FILE_MODE, &zErr);
  191. if (!db) {
  192. ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
  193. ast_free(zErr);
  194. return AST_MODULE_LOAD_DECLINE;
  195. }
  196. /* is the table there? */
  197. res = sqlite_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL);
  198. if (res) {
  199. res = sqlite_exec(db, sql_create_table, NULL, NULL, &zErr);
  200. if (res) {
  201. ast_log(LOG_ERROR, "cdr_sqlite: Unable to create table 'cdr': %s\n", zErr);
  202. ast_free(zErr);
  203. goto err;
  204. }
  205. /* TODO: here we should probably create an index */
  206. }
  207. res = ast_cdr_register(name, ast_module_info->description, sqlite_log);
  208. if (res) {
  209. ast_log(LOG_ERROR, "Unable to register SQLite CDR handling\n");
  210. return AST_MODULE_LOAD_DECLINE;
  211. }
  212. return AST_MODULE_LOAD_SUCCESS;
  213. err:
  214. if (db)
  215. sqlite_close(db);
  216. return AST_MODULE_LOAD_DECLINE;
  217. }
  218. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SQLite CDR Backend",
  219. .support_level = AST_MODULE_SUPPORT_DEPRECATED,
  220. .load = load_module,
  221. .unload = unload_module,
  222. .load_pri = AST_MODPRI_CDR_DRIVER,
  223. );