cdr_sqlite.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * Asterisk -- A telephony toolkit for Linux.
  3. *
  4. * Store CDR records in a SQLite database.
  5. *
  6. * Copyright (C) 2004, Holger Schurig
  7. *
  8. * Holger Schurig <hs4233@mail.mn-solutions.de>
  9. *
  10. * This program is free software, distributed under the terms of
  11. * the GNU General Public License.
  12. *
  13. * Ideas taken from other cdr_*.c files
  14. */
  15. #include <sys/types.h>
  16. #include <asterisk/cdr.h>
  17. #include <asterisk/module.h>
  18. #include <asterisk/logger.h>
  19. #include <asterisk/utils.h>
  20. #include "../asterisk.h"
  21. #include "../astconf.h"
  22. #include <unistd.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <sqlite.h>
  26. #define LOG_UNIQUEID 0
  27. #define LOG_USERFIELD 0
  28. /* When you change the DATE_FORMAT, be sure to change the CHAR(19) below to something else */
  29. #define DATE_FORMAT "%Y-%m-%d %T"
  30. static char *desc = "SQLite CDR Backend";
  31. static char *name = "sqlite";
  32. static sqlite* db = NULL;
  33. AST_MUTEX_DEFINE_STATIC(sqlite_lock);
  34. static char sql_create_table[] = "CREATE TABLE cdr ("
  35. " AcctId INTEGER PRIMARY KEY,"
  36. " clid VARCHAR(80),"
  37. " src VARCHAR(80),"
  38. " dst VARCHAR(80),"
  39. " dcontext VARCHAR(80),"
  40. " channel VARCHAR(80),"
  41. " dstchannel VARCHAR(80),"
  42. " lastapp VARCHAR(80),"
  43. " lastdata VARCHAR(80),"
  44. " start CHAR(19),"
  45. " answer CHAR(19),"
  46. " end CHAR(19),"
  47. " duration INTEGER,"
  48. " billsec INTEGER,"
  49. " disposition INTEGER,"
  50. " amaflags INTEGER,"
  51. " accountcode VARCHAR(20)"
  52. #if LOG_UNIQUEID
  53. " ,uniqueid VARCHAR(32)"
  54. #endif
  55. #if LOG_USERFIELD
  56. " ,userfield VARCHAR(255)"
  57. #endif
  58. ");";
  59. static int sqlite_log(struct ast_cdr *cdr)
  60. {
  61. int res = 0;
  62. char *zErr = 0;
  63. struct tm tm;
  64. time_t t;
  65. char startstr[80], answerstr[80], endstr[80];
  66. int count;
  67. ast_mutex_lock(&sqlite_lock);
  68. t = cdr->start.tv_sec;
  69. localtime_r(&t, &tm);
  70. strftime(startstr, sizeof(startstr), DATE_FORMAT, &tm);
  71. t = cdr->answer.tv_sec;
  72. localtime_r(&t, &tm);
  73. strftime(answerstr, sizeof(answerstr), DATE_FORMAT, &tm);
  74. t = cdr->end.tv_sec;
  75. localtime_r(&t, &tm);
  76. strftime(endstr, sizeof(endstr), DATE_FORMAT, &tm);
  77. for(count=0; count<5; count++) {
  78. res = sqlite_exec_printf(db,
  79. "INSERT INTO cdr ("
  80. "clid,src,dst,dcontext,"
  81. "channel,dstchannel,lastapp,lastdata, "
  82. "start,answer,end,"
  83. "duration,billsec,disposition,amaflags, "
  84. "accountcode"
  85. # if LOG_UNIQUEID
  86. ",uniqueid"
  87. # endif
  88. # if LOG_USERFIELD
  89. ",userfield"
  90. # endif
  91. ") VALUES ("
  92. "'%q', '%q', '%q', '%q', "
  93. "'%q', '%q', '%q', '%q', "
  94. "'%q', '%q', '%q', "
  95. "%d, %d, %d, %d, "
  96. "'%q'"
  97. # if LOG_UNIQUEID
  98. ",'%q'"
  99. # endif
  100. # if LOG_USERFIELD
  101. ",'%q'"
  102. # endif
  103. ")", NULL, NULL, &zErr,
  104. cdr->clid, cdr->src, cdr->dst, cdr->dcontext,
  105. cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata,
  106. startstr, answerstr, endstr,
  107. cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags,
  108. cdr->accountcode
  109. # if LOG_UNIQUEID
  110. ,cdr->uniqueid
  111. # endif
  112. # if LOG_USERFIELD
  113. ,cdr->userfield
  114. # endif
  115. );
  116. if (res != SQLITE_BUSY && res != SQLITE_LOCKED)
  117. break;
  118. usleep(200);
  119. }
  120. if (zErr) {
  121. ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
  122. free(zErr);
  123. }
  124. ast_mutex_unlock(&sqlite_lock);
  125. return res;
  126. }
  127. char *description(void)
  128. {
  129. return desc;
  130. }
  131. int unload_module(void)
  132. {
  133. if (db)
  134. sqlite_close(db);
  135. ast_cdr_unregister(name);
  136. return 0;
  137. }
  138. int load_module(void)
  139. {
  140. char *zErr;
  141. char fn[PATH_MAX];
  142. int res;
  143. /* is the database there? */
  144. snprintf(fn, sizeof(fn), "%s/cdr.db", ast_config_AST_LOG_DIR);
  145. db = sqlite_open(fn, 0660, &zErr);
  146. if (!db) {
  147. ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
  148. free(zErr);
  149. return -1;
  150. }
  151. /* is the table there? */
  152. res = sqlite_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL);
  153. if (res) {
  154. res = sqlite_exec(db, sql_create_table, NULL, NULL, &zErr);
  155. if (res) {
  156. ast_log(LOG_ERROR, "cdr_sqlite: Unable to create table 'cdr': %s\n", zErr);
  157. free(zErr);
  158. goto err;
  159. }
  160. /* TODO: here we should probably create an index */
  161. }
  162. res = ast_cdr_register(name, desc, sqlite_log);
  163. if (res) {
  164. ast_log(LOG_ERROR, "Unable to register SQLite CDR handling\n");
  165. return -1;
  166. }
  167. return 0;
  168. err:
  169. if (db)
  170. sqlite_close(db);
  171. return -1;
  172. }
  173. int reload(void)
  174. {
  175. return 0;
  176. }
  177. int usecount(void)
  178. {
  179. return 0;
  180. }
  181. char *key()
  182. {
  183. return ASTERISK_GPL_KEY;
  184. }