Wed Aug 18 22:34:05 2010

Asterisk developer's documentation


cdr_sqlite3_custom.c File Reference

Custom SQLite3 CDR records. More...

#include "asterisk.h"
#include <time.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_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
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 char * desc = "Customizable SQLite3 CDR Backend"
static ast_mutex_t lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static 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 361 of file cdr_sqlite3_custom.c.

static void __unreg_module ( void   )  [static]

Definition at line 361 of file cdr_sqlite3_custom.c.

static void free_config ( int  reload  )  [static]

Definition at line 215 of file cdr_sqlite3_custom.c.

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

00216 {
00217    struct values *value;
00218 
00219    if (!reload && db) {
00220       sqlite3_close(db);
00221       db = NULL;
00222    }
00223 
00224    if (columns) {
00225       ast_free(columns);
00226       columns = NULL;
00227    }
00228 
00229    while ((value = AST_LIST_REMOVE_HEAD(&sql_values, list)))
00230       ast_free(value);
00231 }

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_create(), ast_str_set(), ast_strdup, ast_strip(), ast_strlen_zero(), LOG_ERROR, LOG_WARNING, ast_str::str, strsep(), and ast_str::used.

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       if (!column_string->used)
00106          ast_str_set(&column_string, 0, "%s", escaped);
00107       else
00108          ast_str_append(&column_string, 0, ",%s", escaped);
00109       sqlite3_free(escaped);
00110    }
00111    if (!(columns = ast_strdup(column_string->str))) {
00112       ast_log(LOG_ERROR, "Out of memory copying columns string for table '%s.'\n", table);
00113       ast_free(column_string);
00114       ast_free(save);
00115       return -1;
00116    }
00117    ast_free(column_string);
00118    ast_free(save);
00119 
00120    return 0;
00121 }

static int load_config ( int  reload  )  [static]

Definition at line 158 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_FILEUNCHANGED, free_config(), load_column_config(), load_values_config(), and LOG_WARNING.

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

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 123 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, and LOG_WARNING.

Referenced by load_config().

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

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 233 of file cdr_sqlite3_custom.c.

References ast_debug, ast_free, AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_str_append(), ast_str_create(), dummy(), values::expression, values::list, lock, LOG_ERROR, pbx_substitute_variables_helper(), ast_str::str, and ast_str::used.

Referenced by load_module().

00234 {
00235    int res = 0;
00236    char *error = NULL;
00237    char *sql = NULL;
00238    struct ast_channel dummy = { 0, };
00239    int count = 0;
00240 
00241    if (db == NULL) {
00242       /* Should not have loaded, but be failsafe. */
00243       return 0;
00244    }
00245 
00246    ast_mutex_lock(&lock);
00247 
00248    { /* Make it obvious that only sql should be used outside of this block */
00249       char *escaped;
00250       char subst_buf[2048];
00251       struct values *value;
00252       struct ast_str *value_string = ast_str_create(1024);
00253       dummy.cdr = cdr;
00254       AST_LIST_TRAVERSE(&sql_values, value, list) {
00255          memset(subst_buf, 0, sizeof(subst_buf));
00256          pbx_substitute_variables_helper(&dummy, value->expression, subst_buf, sizeof(subst_buf) - 1);
00257          escaped = sqlite3_mprintf("%q", subst_buf);
00258          if (!value_string->used)
00259             ast_str_append(&value_string, 0, "'%s'", escaped);
00260          else
00261             ast_str_append(&value_string, 0, ",'%s'", escaped);
00262          sqlite3_free(escaped);
00263       }
00264       sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, value_string->str);
00265       ast_debug(1, "About to log: %s\n", sql);
00266       ast_free(value_string);
00267    }
00268 
00269    /* XXX This seems awful arbitrary... */
00270    for (count = 0; count < 5; count++) {
00271       res = sqlite3_exec(db, sql, NULL, NULL, &error);
00272       if (res != SQLITE_BUSY && res != SQLITE_LOCKED)
00273          break;
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    ast_mutex_unlock(&lock);
00286 
00287    return res;
00288 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 361 of file cdr_sqlite3_custom.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

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

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

Definition at line 60 of file cdr_sqlite3_custom.c.

ast_mutex_t lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 56 of file cdr_sqlite3_custom.c.

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 Wed Aug 18 22:34:05 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7