Fri Nov 12 11:54:48 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 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 sqlite3_log (struct ast_cdr *cdr)
static int unload_module (void)

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 = "0901e4e500243c855563a2d78b0c03e4" , .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 349 of file cdr_sqlite3_custom.c.

static void __unreg_module ( void   )  [static]

Definition at line 349 of file cdr_sqlite3_custom.c.

static void free_config ( int  reload  )  [static]

Definition at line 204 of file cdr_sqlite3_custom.c.

References ast_free, AST_LIST_REMOVE_HEAD, and values::list.

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

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

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

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

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

static int load_module ( void   )  [static]

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

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

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

Definition at line 119 of file cdr_sqlite3_custom.c.

References ast_calloc, ast_copy_string(), ast_free, AST_LIST_INSERT_TAIL, ast_log(), ast_strdup, ast_strip_quoted(), ast_strlen_zero(), values::expression, values::list, LOG_ERROR, and LOG_WARNING.

Referenced by load_config().

00120 {
00121    char *val = NULL;
00122    char *vals = NULL, *save = NULL;
00123    struct values *value = NULL;
00124 
00125    if (ast_strlen_zero(tmp)) {
00126       ast_log(LOG_WARNING, "Values not specified. Module not loaded.\n");
00127       return -1;
00128    }
00129    if (!(save = vals = ast_strdup(tmp))) {
00130       ast_log(LOG_ERROR, "Out of memory creating temporary buffer for value '%s'\n", tmp);
00131       return -1;
00132    }
00133    while ((val = strsep(&vals, ","))) {
00134       /* Strip the single quotes off if they are there */
00135       val = ast_strip_quoted(val, "'", "'");
00136       value = ast_calloc(sizeof(char), sizeof(*value) + strlen(val) + 1);
00137       if (!value) {
00138          ast_log(LOG_ERROR, "Out of memory creating entry for value '%s'\n", val);
00139          ast_free(save);
00140          return -1;
00141       }
00142       value->expression = (char *) value + sizeof(*value);
00143       ast_copy_string(value->expression, val, strlen(val) + 1);
00144       AST_LIST_INSERT_TAIL(&sql_values, value, list);
00145    }
00146    ast_free(save);
00147 
00148    return 0;
00149 }

static int reload ( void   )  [static]

Definition at line 334 of file cdr_sqlite3_custom.c.

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

00335 {
00336    int res = 0;
00337 
00338    ast_mutex_lock(&lock);
00339    res = load_config(1);
00340    ast_mutex_unlock(&lock);
00341 
00342    return res;
00343 }

static int sqlite3_log ( struct ast_cdr cdr  )  [static]

Definition at line 223 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_buffer(), ast_str_create(), ast_str_strlen(), ast_channel::cdr, values::expression, values::list, lock, LOG_ERROR, and pbx_substitute_variables_helper().

Referenced by load_module().

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

static int unload_module ( void   )  [static]

Definition at line 278 of file cdr_sqlite3_custom.c.

References ast_cdr_unregister(), and free_config().

00279 {
00280    ast_cdr_unregister(name);
00281 
00282    free_config(0);
00283 
00284    return 0;
00285 }


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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 349 of file cdr_sqlite3_custom.c.

Definition at line 349 of file cdr_sqlite3_custom.c.

char* columns [static]

Definition at line 64 of file cdr_sqlite3_custom.c.

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.

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

Definition at line 59 of file cdr_sqlite3_custom.c.

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

Definition at line 55 of file cdr_sqlite3_custom.c.

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 by  doxygen 1.6.2