Mon Mar 12 2012 21:27:21

Asterisk developer's documentation


cdr_sqlite3_custom.c File Reference

Custom SQLite3 CDR records. More...

#include "asterisk.h"
#include <sqlite3.h>
#include "asterisk/paths.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
Include dependency graph for cdr_sqlite3_custom.c:

Go to the source code of this file.

Data Structures

struct  sql_values
struct  values

Functions

static void __reg_module (void)
static void __unreg_module (void)
static void free_config (int reload)
static int load_column_config (const char *tmp)
static int load_config (int reload)
static int load_module (void)
static int load_values_config (const char *tmp)
static int reload (void)
static int unload_module (void)
static int write_cdr (struct ast_cdr *cdr)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "SQLite3 Custom CDR Module" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, }
static struct ast_module_infoast_module_info = &__mod_info
static char * columns
static const char config_file [] = "cdr_sqlite3_custom.conf"
static sqlite3 * db = NULL
static const char desc [] = "Customizable SQLite3 CDR Backend"
static ast_mutex_t lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static const char name [] = "cdr_sqlite3_custom"
static struct sql_values sql_values
static char table [80]

Detailed Description

Custom SQLite3 CDR records.

Author:
Adapted by Alejandro Rios <alejandro.rios@avatar.com.co> and Russell Bryant <russell@digium.com> from cdr_mysql_custom by Edward Eastman <ed@dm3.co.uk>, and cdr_sqlite by Holger Schurig <hs4233@mail.mn-solutions.de>

Definition in file cdr_sqlite3_custom.c.


Function Documentation

static void __reg_module ( void  ) [static]

Definition at line 363 of file cdr_sqlite3_custom.c.

static void __unreg_module ( void  ) [static]

Definition at line 363 of file cdr_sqlite3_custom.c.

static void free_config ( int  reload) [static]

Definition at line 208 of file cdr_sqlite3_custom.c.

References ast_free, AST_LIST_REMOVE_HEAD, values::list, and value.

Referenced by load_config(), load_module(), and unload_module().

{
   struct values *value;

   if (!reload && db) {
      sqlite3_close(db);
      db = NULL;
   }

   if (columns) {
      ast_free(columns);
      columns = NULL;
   }

   while ((value = AST_LIST_REMOVE_HEAD(&sql_values, list))) {
      ast_free(value);
   }
}
static int load_column_config ( const char *  tmp) [static]

Definition at line 76 of file cdr_sqlite3_custom.c.

References ast_free, ast_log(), ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_strlen(), ast_strdup, ast_strip(), ast_strlen_zero(), LOG_ERROR, LOG_WARNING, and strsep().

Referenced by load_config().

{
   char *col = NULL;
   char *cols = NULL, *save = NULL;
   char *escaped = NULL;
   struct ast_str *column_string = NULL;

   if (ast_strlen_zero(tmp)) {
      ast_log(LOG_WARNING, "Column names not specified. Module not loaded.\n");
      return -1;
   }
   if (!(column_string = ast_str_create(1024))) {
      ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table);
      return -1;
   }
   if (!(save = cols = ast_strdup(tmp))) {
      ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table);
      ast_free(column_string);
      return -1;
   }
   while ((col = strsep(&cols, ","))) {
      col = ast_strip(col);
      escaped = sqlite3_mprintf("%q", col);
      if (!escaped) {
         ast_log(LOG_ERROR, "Out of memory creating entry for column '%s' in table '%s.'\n", col, table);
         ast_free(column_string);
         ast_free(save);
         return -1;
      }
      ast_str_append(&column_string, 0, "%s%s", ast_str_strlen(column_string) ? "," : "", escaped);
      sqlite3_free(escaped);
   }
   if (!(columns = ast_strdup(ast_str_buffer(column_string)))) {
      ast_log(LOG_ERROR, "Out of memory copying columns string for table '%s.'\n", table);
      ast_free(column_string);
      ast_free(save);
      return -1;
   }
   ast_free(column_string);
   ast_free(save);

   return 0;
}
static int load_config ( int  reload) [static]

Definition at line 155 of file cdr_sqlite3_custom.c.

References ast_config_destroy(), ast_config_load, ast_copy_string(), ast_log(), ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, free_config(), load_column_config(), load_values_config(), and LOG_WARNING.

Referenced by load_module(), and reload().

{
   struct ast_config *cfg;
   struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
   struct ast_variable *mappingvar;
   const char *tmp;

   if ((cfg = ast_config_load(config_file, config_flags)) == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
      ast_log(LOG_WARNING, "Failed to %sload configuration file. %s\n", reload ? "re" : "", reload ? "" : "Module not activated.");
      return -1;
   } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
      return 0;
   }

   if (reload) {
      free_config(1);
   }

   if (!(mappingvar = ast_variable_browse(cfg, "master"))) {
      /* Nothing configured */
      ast_config_destroy(cfg);
      return -1;
   }

   /* Mapping must have a table name */
   if (!ast_strlen_zero(tmp = ast_variable_retrieve(cfg, "master", "table"))) {
      ast_copy_string(table, tmp, sizeof(table));
   } else {
      ast_log(LOG_WARNING, "Table name not specified.  Assuming cdr.\n");
      strcpy(table, "cdr");
   }

   /* Columns */
   if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) {
      ast_config_destroy(cfg);
      free_config(0);
      return -1;
   }

   /* Values */
   if (load_values_config(ast_variable_retrieve(cfg, "master", "values"))) {
      ast_config_destroy(cfg);
      free_config(0);
      return -1;
   }

   ast_verb(3, "cdr_sqlite3_custom: Logging CDR records to table '%s' in 'master.db'\n", table);

   ast_config_destroy(cfg);

   return 0;
}
static int load_module ( void  ) [static]

Definition at line 300 of file cdr_sqlite3_custom.c.

References ast_cdr_register(), ast_config_AST_LOG_DIR, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, free_config(), load_config(), LOG_ERROR, LOG_WARNING, and write_cdr().

{
   char *error;
   char filename[PATH_MAX];
   int res;
   char *sql;

   if (load_config(0)) {
      return AST_MODULE_LOAD_DECLINE;
   }

   /* is the database there? */
   snprintf(filename, sizeof(filename), "%s/master.db", ast_config_AST_LOG_DIR);
   res = sqlite3_open(filename, &db);
   if (res != SQLITE_OK) {
      ast_log(LOG_ERROR, "Could not open database %s.\n", filename);
      free_config(0);
      return AST_MODULE_LOAD_DECLINE;
   }

   /* is the table there? */
   sql = sqlite3_mprintf("SELECT COUNT(AcctId) FROM %q;", table);
   res = sqlite3_exec(db, sql, NULL, NULL, NULL);
   sqlite3_free(sql);
   if (res != SQLITE_OK) {
      /* We don't use %q for the column list here since we already escaped when building it */
      sql = sqlite3_mprintf("CREATE TABLE %q (AcctId INTEGER PRIMARY KEY, %s)", table, columns);
      res = sqlite3_exec(db, sql, NULL, NULL, &error);
      sqlite3_free(sql);
      if (res != SQLITE_OK) {
         ast_log(LOG_WARNING, "Unable to create table '%s': %s.\n", table, error);
         sqlite3_free(error);
         free_config(0);
         return AST_MODULE_LOAD_DECLINE;
      }
   }

   res = ast_cdr_register(name, desc, write_cdr);
   if (res) {
      ast_log(LOG_ERROR, "Unable to register custom SQLite3 CDR handling\n");
      free_config(0);
      return AST_MODULE_LOAD_DECLINE;
   }

   return AST_MODULE_LOAD_SUCCESS;
}
static int load_values_config ( const char *  tmp) [static]

Definition at line 120 of file cdr_sqlite3_custom.c.

References AST_APP_ARG, ast_calloc, AST_DECLARE_APP_ARGS, ast_free, AST_LIST_INSERT_TAIL, ast_log(), AST_STANDARD_RAW_ARGS, ast_strdup, ast_strip_quoted(), ast_strlen_zero(), values::expression, values::list, LOG_ERROR, LOG_WARNING, and value.

Referenced by load_config().

{
   char *vals = NULL, *save = NULL;
   struct values *value = NULL;
   int i;
   AST_DECLARE_APP_ARGS(val,
      AST_APP_ARG(ues)[200]; /* More than 200 columns in this CDR?  Yeah, right... */
   );

   if (ast_strlen_zero(tmp)) {
      ast_log(LOG_WARNING, "Values not specified. Module not loaded.\n");
      return -1;
   }
   if (!(save = vals = ast_strdup(tmp))) {
      ast_log(LOG_ERROR, "Out of memory creating temporary buffer for value '%s'\n", tmp);
      return -1;
   }
   AST_STANDARD_RAW_ARGS(val, vals);
   for (i = 0; i < val.argc; i++) {
      /* Strip the single quotes off if they are there */
      char *v = ast_strip_quoted(val.ues[i], "'", "'");
      value = ast_calloc(sizeof(char), sizeof(*value) + strlen(v));
      if (!value) {
         ast_log(LOG_ERROR, "Out of memory creating entry for value '%s'\n", v);
         ast_free(save);
         return -1;
      }
      strcpy(value->expression, v); /* SAFE */
      AST_LIST_INSERT_TAIL(&sql_values, value, list);
   }
   ast_free(save);

   return 0;
}
static int reload ( void  ) [static]

Definition at line 347 of file cdr_sqlite3_custom.c.

References ast_mutex_lock, ast_mutex_unlock, load_config(), and lock.

{
   int res = 0;

   ast_mutex_lock(&lock);
   res = load_config(1);
   ast_mutex_unlock(&lock);

   return res;
}
static int unload_module ( void  ) [static]

Definition at line 291 of file cdr_sqlite3_custom.c.

References ast_cdr_unregister(), and free_config().

{
   ast_cdr_unregister(name);

   free_config(0);

   return 0;
}
static int write_cdr ( struct ast_cdr cdr) [static]

Definition at line 227 of file cdr_sqlite3_custom.c.

References ast_cdr_dup(), ast_channel_unref, ast_debug, ast_dummy_channel_alloc(), ast_free, AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_strlen(), ast_channel::cdr, dummy(), values::expression, values::list, lock, LOG_ERROR, pbx_substitute_variables_helper(), and value.

Referenced by load_module().

{
   int res = 0;
   char *error = NULL;
   char *sql = NULL;
   int count = 0;

   if (db == NULL) {
      /* Should not have loaded, but be failsafe. */
      return 0;
   }

   ast_mutex_lock(&lock);

   { /* Make it obvious that only sql should be used outside of this block */
      char *escaped;
      char subst_buf[2048];
      struct values *value;
      struct ast_channel *dummy;
      struct ast_str *value_string = ast_str_create(1024);

      dummy = ast_dummy_channel_alloc();
      if (!dummy) {
         ast_log(LOG_ERROR, "Unable to allocate channel for variable subsitution.\n");
         ast_free(value_string);
         ast_mutex_unlock(&lock);
         return 0;
      }
      dummy->cdr = ast_cdr_dup(cdr);
      AST_LIST_TRAVERSE(&sql_values, value, list) {
         pbx_substitute_variables_helper(dummy, value->expression, subst_buf, sizeof(subst_buf) - 1);
         escaped = sqlite3_mprintf("%q", subst_buf);
         ast_str_append(&value_string, 0, "%s'%s'", ast_str_strlen(value_string) ? "," : "", escaped);
         sqlite3_free(escaped);
      }
      sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, ast_str_buffer(value_string));
      ast_debug(1, "About to log: %s\n", sql);
      ast_channel_unref(dummy);
      ast_free(value_string);
   }

   /* XXX This seems awful arbitrary... */
   for (count = 0; count < 5; count++) {
      res = sqlite3_exec(db, sql, NULL, NULL, &error);
      if (res != SQLITE_BUSY && res != SQLITE_LOCKED) {
         break;
      }
      usleep(200);
   }

   if (error) {
      ast_log(LOG_ERROR, "%s. SQL: %s.\n", error, sql);
      sqlite3_free(error);
   }

   if (sql) {
      sqlite3_free(sql);
   }

   ast_mutex_unlock(&lock);

   return res;
}

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "SQLite3 Custom CDR Module" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } [static]

Definition at line 363 of file cdr_sqlite3_custom.c.

Definition at line 363 of file cdr_sqlite3_custom.c.

char* columns [static]

Definition at line 65 of file cdr_sqlite3_custom.c.

const char config_file[] = "cdr_sqlite3_custom.conf" [static]

Definition at line 58 of file cdr_sqlite3_custom.c.

sqlite3* db = NULL [static]

Definition at line 62 of file cdr_sqlite3_custom.c.

const char desc[] = "Customizable SQLite3 CDR Backend" [static]

Definition at line 60 of file cdr_sqlite3_custom.c.

ast_mutex_t lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 56 of file cdr_sqlite3_custom.c.

const char name[] = "cdr_sqlite3_custom" [static]

Definition at line 61 of file cdr_sqlite3_custom.c.

struct sql_values sql_values [static]
char table[80] [static]

Definition at line 64 of file cdr_sqlite3_custom.c.