Fri Jul 24 00:41:19 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 int 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 = "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 362 of file cdr_sqlite3_custom.c.

static void __unreg_module ( void   )  [static]

Definition at line 362 of file cdr_sqlite3_custom.c.

static int free_config ( void   )  [static]

Definition at line 217 of file cdr_sqlite3_custom.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), columns, values::list, and lock.

00218 {
00219    struct values *value;
00220 
00221    ast_mutex_lock(&lock);
00222 
00223    if (db) {
00224       sqlite3_close(db);
00225       db = NULL;
00226    }
00227 
00228    if (columns) {
00229       ast_free(columns);
00230       columns = NULL;
00231    }
00232 
00233    while ((value = AST_LIST_REMOVE_HEAD(&sql_values, list)))
00234       ast_free(value);
00235 
00236    ast_mutex_unlock(&lock);
00237 
00238    return 0;
00239 }

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_mutex_lock(), ast_mutex_unlock(), 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(), lock, 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    ast_mutex_lock(&lock);
00174 
00175    if (!(mappingvar = ast_variable_browse(cfg, "master"))) {
00176       /* Nothing configured */
00177       ast_mutex_unlock(&lock);
00178       ast_config_destroy(cfg);
00179       return -1;
00180    }
00181 
00182    /* Mapping must have a table name */
00183    tmp = ast_variable_retrieve(cfg, "master", "table");
00184    if (!ast_strlen_zero(tmp))
00185       ast_copy_string(table, tmp, sizeof(table));
00186    else {
00187       ast_log(LOG_WARNING, "Table name not specified.  Assuming cdr.\n");
00188       strcpy(table, "cdr");
00189    }
00190 
00191    /* Columns */
00192    tmp = ast_variable_retrieve(cfg, "master", "columns");
00193    if (load_column_config(tmp)) {
00194       ast_mutex_unlock(&lock);
00195       ast_config_destroy(cfg);
00196       free_config();
00197       return -1;
00198    }
00199 
00200    /* Values */
00201    tmp = ast_variable_retrieve(cfg, "master", "values");
00202    if (load_values_config(tmp)) {
00203       ast_mutex_unlock(&lock);
00204       ast_config_destroy(cfg);
00205       free_config();
00206       return -1;
00207    }
00208 
00209    ast_verb(3, "cdr_sqlite3_custom: Logging CDR records to table '%s' in 'master.db'\n", table);
00210 
00211    ast_mutex_unlock(&lock);
00212    ast_config_destroy(cfg);
00213 
00214    return 0;
00215 }

static int load_module ( void   )  [static]

Definition at line 307 of file cdr_sqlite3_custom.c.

References ast_cdr_register(), ast_config_AST_LOG_DIR, ast_log(), AST_MODULE_LOAD_DECLINE, free_config(), load_config(), LOG_ERROR, LOG_WARNING, and sqlite3_log().

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

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

References load_config().

00354 {
00355    return load_config(1);
00356 }

static int sqlite3_log ( struct ast_cdr cdr  )  [static]

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

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

static int unload_module ( void   )  [static]

Definition at line 298 of file cdr_sqlite3_custom.c.

References ast_cdr_unregister(), and free_config().

00299 {
00300    free_config();
00301 
00302    ast_cdr_unregister(name);
00303 
00304    return 0;
00305 }


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

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 Fri Jul 24 00:41:19 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7