Mon Jun 27 16:51:04 2011

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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 362 of file cdr_sqlite3_custom.c.

static void __unreg_module ( void   )  [static]

Definition at line 362 of file cdr_sqlite3_custom.c.

static void free_config ( int  reload  )  [static]

Definition at line 207 of file cdr_sqlite3_custom.c.

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

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

static int load_column_config ( const char *  tmp  )  [static]

Definition at line 75 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().

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

static int load_config ( int  reload  )  [static]

Definition at line 154 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.

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

static int load_module ( void   )  [static]

Definition at line 299 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().

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

static int load_values_config ( const char *  tmp  )  [static]

Definition at line 119 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().

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

static int reload ( void   )  [static]

Definition at line 346 of file cdr_sqlite3_custom.c.

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

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

static int unload_module ( void   )  [static]

Definition at line 290 of file cdr_sqlite3_custom.c.

References ast_cdr_unregister(), and free_config().

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

static int write_cdr ( struct ast_cdr cdr  )  [static]

Definition at line 226 of file cdr_sqlite3_custom.c.

References ast_cdr_dup(), ast_channel_release(), 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().

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


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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } [static]

Definition at line 362 of file cdr_sqlite3_custom.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 362 of file cdr_sqlite3_custom.c.

char* columns [static]

Definition at line 64 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 57 of file cdr_sqlite3_custom.c.

sqlite3* db = NULL [static]

Definition at line 61 of file cdr_sqlite3_custom.c.

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

Definition at line 59 of file cdr_sqlite3_custom.c.

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

Definition at line 55 of file cdr_sqlite3_custom.c.

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

Definition at line 60 of file cdr_sqlite3_custom.c.

char table[80] [static]

Definition at line 63 of file cdr_sqlite3_custom.c.


Generated on Mon Jun 27 16:51:04 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7