Mon Mar 19 11:30:37 2012

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"

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 = "88eaa8f5c1bd988bedd71113385e0886" , .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 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, columns, values::list, and value.

00209 {
00210    struct values *value;
00211 
00212    if (!reload && db) {
00213       sqlite3_close(db);
00214       db = NULL;
00215    }
00216 
00217    if (columns) {
00218       ast_free(columns);
00219       columns = NULL;
00220    }
00221 
00222    while ((value = AST_LIST_REMOVE_HEAD(&sql_values, list))) {
00223       ast_free(value);
00224    }
00225 }

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().

00077 {
00078    char *col = NULL;
00079    char *cols = NULL, *save = NULL;
00080    char *escaped = NULL;
00081    struct ast_str *column_string = NULL;
00082 
00083    if (ast_strlen_zero(tmp)) {
00084       ast_log(LOG_WARNING, "Column names not specified. Module not loaded.\n");
00085       return -1;
00086    }
00087    if (!(column_string = ast_str_create(1024))) {
00088       ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table);
00089       return -1;
00090    }
00091    if (!(save = cols = ast_strdup(tmp))) {
00092       ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table);
00093       ast_free(column_string);
00094       return -1;
00095    }
00096    while ((col = strsep(&cols, ","))) {
00097       col = ast_strip(col);
00098       escaped = sqlite3_mprintf("%q", col);
00099       if (!escaped) {
00100          ast_log(LOG_ERROR, "Out of memory creating entry for column '%s' in table '%s.'\n", col, table);
00101          ast_free(column_string);
00102          ast_free(save);
00103          return -1;
00104       }
00105       ast_str_append(&column_string, 0, "%s%s", ast_str_strlen(column_string) ? "," : "", escaped);
00106       sqlite3_free(escaped);
00107    }
00108    if (!(columns = ast_strdup(ast_str_buffer(column_string)))) {
00109       ast_log(LOG_ERROR, "Out of memory copying columns string for table '%s.'\n", table);
00110       ast_free(column_string);
00111       ast_free(save);
00112       return -1;
00113    }
00114    ast_free(column_string);
00115    ast_free(save);
00116 
00117    return 0;
00118 }

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_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, free_config(), load_column_config(), load_values_config(), and LOG_WARNING.

00156 {
00157    struct ast_config *cfg;
00158    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00159    struct ast_variable *mappingvar;
00160    const char *tmp;
00161 
00162    if ((cfg = ast_config_load(config_file, config_flags)) == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
00163       ast_log(LOG_WARNING, "Failed to %sload configuration file. %s\n", reload ? "re" : "", reload ? "" : "Module not activated.");
00164       return -1;
00165    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
00166       return 0;
00167    }
00168 
00169    if (reload) {
00170       free_config(1);
00171    }
00172 
00173    if (!(mappingvar = ast_variable_browse(cfg, "master"))) {
00174       /* Nothing configured */
00175       ast_config_destroy(cfg);
00176       return -1;
00177    }
00178 
00179    /* Mapping must have a table name */
00180    if (!ast_strlen_zero(tmp = ast_variable_retrieve(cfg, "master", "table"))) {
00181       ast_copy_string(table, tmp, sizeof(table));
00182    } else {
00183       ast_log(LOG_WARNING, "Table name not specified.  Assuming cdr.\n");
00184       strcpy(table, "cdr");
00185    }
00186 
00187    /* Columns */
00188    if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) {
00189       ast_config_destroy(cfg);
00190       free_config(0);
00191       return -1;
00192    }
00193 
00194    /* Values */
00195    if (load_values_config(ast_variable_retrieve(cfg, "master", "values"))) {
00196       ast_config_destroy(cfg);
00197       free_config(0);
00198       return -1;
00199    }
00200 
00201    ast_verb(3, "cdr_sqlite3_custom: Logging CDR records to table '%s' in 'master.db'\n", table);
00202 
00203    ast_config_destroy(cfg);
00204 
00205    return 0;
00206 }

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().

00301 {
00302    char *error;
00303    char filename[PATH_MAX];
00304    int res;
00305    char *sql;
00306 
00307    if (load_config(0)) {
00308       return AST_MODULE_LOAD_DECLINE;
00309    }
00310 
00311    /* is the database there? */
00312    snprintf(filename, sizeof(filename), "%s/master.db", ast_config_AST_LOG_DIR);
00313    res = sqlite3_open(filename, &db);
00314    if (res != SQLITE_OK) {
00315       ast_log(LOG_ERROR, "Could not open database %s.\n", filename);
00316       free_config(0);
00317       return AST_MODULE_LOAD_DECLINE;
00318    }
00319 
00320    /* is the table there? */
00321    sql = sqlite3_mprintf("SELECT COUNT(AcctId) FROM %q;", table);
00322    res = sqlite3_exec(db, sql, NULL, NULL, NULL);
00323    sqlite3_free(sql);
00324    if (res != SQLITE_OK) {
00325       /* We don't use %q for the column list here since we already escaped when building it */
00326       sql = sqlite3_mprintf("CREATE TABLE %q (AcctId INTEGER PRIMARY KEY, %s)", table, columns);
00327       res = sqlite3_exec(db, sql, NULL, NULL, &error);
00328       sqlite3_free(sql);
00329       if (res != SQLITE_OK) {
00330          ast_log(LOG_WARNING, "Unable to create table '%s': %s.\n", table, error);
00331          sqlite3_free(error);
00332          free_config(0);
00333          return AST_MODULE_LOAD_DECLINE;
00334       }
00335    }
00336 
00337    res = ast_cdr_register(name, desc, write_cdr);
00338    if (res) {
00339       ast_log(LOG_ERROR, "Unable to register custom SQLite3 CDR handling\n");
00340       free_config(0);
00341       return AST_MODULE_LOAD_DECLINE;
00342    }
00343 
00344    return AST_MODULE_LOAD_SUCCESS;
00345 }

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::list, LOG_ERROR, LOG_WARNING, and value.

Referenced by load_config().

00121 {
00122    char *vals = NULL, *save = NULL;
00123    struct values *value = NULL;
00124    int i;
00125    AST_DECLARE_APP_ARGS(val,
00126       AST_APP_ARG(ues)[200]; /* More than 200 columns in this CDR?  Yeah, right... */
00127    );
00128 
00129    if (ast_strlen_zero(tmp)) {
00130       ast_log(LOG_WARNING, "Values not specified. Module not loaded.\n");
00131       return -1;
00132    }
00133    if (!(save = vals = ast_strdup(tmp))) {
00134       ast_log(LOG_ERROR, "Out of memory creating temporary buffer for value '%s'\n", tmp);
00135       return -1;
00136    }
00137    AST_STANDARD_RAW_ARGS(val, vals);
00138    for (i = 0; i < val.argc; i++) {
00139       /* Strip the single quotes off if they are there */
00140       char *v = ast_strip_quoted(val.ues[i], "'", "'");
00141       value = ast_calloc(sizeof(char), sizeof(*value) + strlen(v));
00142       if (!value) {
00143          ast_log(LOG_ERROR, "Out of memory creating entry for value '%s'\n", v);
00144          ast_free(save);
00145          return -1;
00146       }
00147       strcpy(value->expression, v); /* SAFE */
00148       AST_LIST_INSERT_TAIL(&sql_values, value, list);
00149    }
00150    ast_free(save);
00151 
00152    return 0;
00153 }

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.

00348 {
00349    int res = 0;
00350 
00351    ast_mutex_lock(&lock);
00352    res = load_config(1);
00353    ast_mutex_unlock(&lock);
00354 
00355    return res;
00356 }

static int unload_module ( void   )  [static]

Definition at line 291 of file cdr_sqlite3_custom.c.

References ast_cdr_unregister(), and free_config().

00292 {
00293    ast_cdr_unregister(name);
00294 
00295    free_config(0);
00296 
00297    return 0;
00298 }

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(), dummy(), values::list, lock, LOG_ERROR, pbx_substitute_variables_helper(), and value.

Referenced by load_module().

00228 {
00229    int res = 0;
00230    char *error = NULL;
00231    char *sql = NULL;
00232    int count = 0;
00233 
00234    if (db == NULL) {
00235       /* Should not have loaded, but be failsafe. */
00236       return 0;
00237    }
00238 
00239    ast_mutex_lock(&lock);
00240 
00241    { /* Make it obvious that only sql should be used outside of this block */
00242       char *escaped;
00243       char subst_buf[2048];
00244       struct values *value;
00245       struct ast_channel *dummy;
00246       struct ast_str *value_string = ast_str_create(1024);
00247 
00248       dummy = ast_dummy_channel_alloc();
00249       if (!dummy) {
00250          ast_log(LOG_ERROR, "Unable to allocate channel for variable subsitution.\n");
00251          ast_free(value_string);
00252          ast_mutex_unlock(&lock);
00253          return 0;
00254       }
00255       dummy->cdr = ast_cdr_dup(cdr);
00256       AST_LIST_TRAVERSE(&sql_values, value, list) {
00257          pbx_substitute_variables_helper(dummy, value->expression, subst_buf, sizeof(subst_buf) - 1);
00258          escaped = sqlite3_mprintf("%q", subst_buf);
00259          ast_str_append(&value_string, 0, "%s'%s'", ast_str_strlen(value_string) ? "," : "", escaped);
00260          sqlite3_free(escaped);
00261       }
00262       sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, ast_str_buffer(value_string));
00263       ast_debug(1, "About to log: %s\n", sql);
00264       ast_channel_unref(dummy);
00265       ast_free(value_string);
00266    }
00267 
00268    /* XXX This seems awful arbitrary... */
00269    for (count = 0; count < 5; count++) {
00270       res = sqlite3_exec(db, sql, NULL, NULL, &error);
00271       if (res != SQLITE_BUSY && res != SQLITE_LOCKED) {
00272          break;
00273       }
00274       usleep(200);
00275    }
00276 
00277    if (error) {
00278       ast_log(LOG_ERROR, "%s. SQL: %s.\n", error, sql);
00279       sqlite3_free(error);
00280    }
00281 
00282    if (sql) {
00283       sqlite3_free(sql);
00284    }
00285 
00286    ast_mutex_unlock(&lock);
00287 
00288    return res;
00289 }


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 = "88eaa8f5c1bd988bedd71113385e0886" , .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.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 363 of file cdr_sqlite3_custom.c.

char* columns [static]

Definition at line 65 of file cdr_sqlite3_custom.c.

Referenced by free_config(), and load_config().

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.

char table[80] [static]

Definition at line 64 of file cdr_sqlite3_custom.c.


Generated on Mon Mar 19 11:30:37 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7