Thu Jul 9 13:40:54 2009

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"

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 (void)
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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, }
static const 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 357 of file cdr_sqlite3_custom.c.

static void __unreg_module ( void   )  [static]

Definition at line 357 of file cdr_sqlite3_custom.c.

static void free_config ( void   )  [static]

Definition at line 211 of file cdr_sqlite3_custom.c.

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

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

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

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

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_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))) {
00162       if (reload)
00163          ast_log(LOG_WARNING, "Failed to reload configuration file.\n");
00164       else
00165          ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
00166       return -1;
00167    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
00168       return 0;
00169 
00170    if (reload)
00171       free_config();
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    tmp = ast_variable_retrieve(cfg, "master", "table");
00181    if (!ast_strlen_zero(tmp))
00182       ast_copy_string(table, tmp, sizeof(table));
00183    else {
00184       ast_log(LOG_WARNING, "Table name not specified.  Assuming cdr.\n");
00185       strcpy(table, "cdr");
00186    }
00187 
00188    /* Columns */
00189    tmp = ast_variable_retrieve(cfg, "master", "columns");
00190    if (load_column_config(tmp)) {
00191       ast_config_destroy(cfg);
00192       free_config();
00193       return -1;
00194    }
00195 
00196    /* Values */
00197    tmp = ast_variable_retrieve(cfg, "master", "values");
00198    if (load_values_config(tmp)) {
00199       ast_config_destroy(cfg);
00200       free_config();
00201       return -1;
00202    }
00203 
00204    ast_verb(3, "cdr_sqlite3_custom: Logging CDR records to table '%s' in 'master.db'\n", table);
00205 
00206    ast_config_destroy(cfg);
00207 
00208    return 0;
00209 }

static int load_module ( void   )  [static]

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

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

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

Definition at line 122 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::list, LOG_ERROR, LOG_WARNING, and strsep().

Referenced by load_config().

00123 {
00124    char *val = NULL;
00125    char *vals = NULL, *save = NULL;
00126    struct values *value = NULL;
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    while ((val = strsep(&vals, ","))) {
00137       /* Strip the single quotes off if they are there */
00138       val = ast_strip_quoted(val, "'", "'");
00139       value = ast_calloc(sizeof(char), sizeof(*value) + strlen(val) + 1);
00140       if (!value) {
00141          ast_log(LOG_ERROR, "Out of memory creating entry for value '%s'\n", val);
00142          ast_free(save);
00143          return -1;
00144       }
00145       value->expression = (char *) value + sizeof(*value);
00146       ast_copy_string(value->expression, val, strlen(val) + 1);
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 342 of file cdr_sqlite3_custom.c.

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

00343 {
00344    int res = 0;
00345 
00346    ast_mutex_lock(&lock);
00347    res = load_config(1);
00348    ast_mutex_unlock(&lock);
00349 
00350    return res;
00351 }

static int sqlite3_log ( struct ast_cdr cdr  )  [static]

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

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

static int unload_module ( void   )  [static]

Definition at line 286 of file cdr_sqlite3_custom.c.

References ast_cdr_unregister(), and free_config().

00287 {
00288    ast_cdr_unregister(name);
00289 
00290    free_config();
00291 
00292    return 0;
00293 }


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

Definition at line 357 of file cdr_sqlite3_custom.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

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

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 on Thu Jul 9 13:40:54 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7