res_config_sqlite3.c File Reference

SQLite 3 configuration engine. More...

#include "asterisk.h"
#include <sqlite3.h>
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/paths.h"
#include "asterisk/astobj2.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"

Include dependency graph for res_config_sqlite3.c:

Go to the source code of this file.

Data Structures

struct  cfg_entry_args
struct  realtime_sqlite3_db

Defines

#define DB_BUCKETS   7

Enumerations

enum  { REALTIME_SQLITE3_REQ_WARN, REALTIME_SQLITE3_REQ_CLOSE, REALTIME_SQLITE3_REQ_CHAR }
enum  { COL_CATEGORY, COL_VAR_NAME, COL_VAR_VAL, COL_COLUMNS }

Functions

static void __init_escape_column_buf (void)
static void __init_escape_table_buf (void)
static void __init_escape_value_buf (void)
static void __reg_module (void)
static void __unreg_module (void)
static int add_column_name (void *arg, int num_columns, char **values, char **columns)
 Callback for creating a hash of column names for comparison in realtime_sqlite3_require.
static int append_row_to_cfg (void *arg, int num_columns, char **values, char **columns)
 Callback for creating an ast_config from a successive sqlite3 result rows.
static int db_cmp_fn (void *obj, void *arg, int flags)
static void db_destructor (void *obj)
static int db_hash_fn (const void *obj, const int flags)
static int db_open (struct realtime_sqlite3_db *db)
 Open a database and appropriately set debugging on the db handle.
void db_start_batch (struct realtime_sqlite3_db *db)
void db_stop_batch (struct realtime_sqlite3_db *db)
static void db_sync (struct realtime_sqlite3_db *db)
static void * db_sync_thread (void *data)
 Wrap commands in transactions increased write performance.
static struct realtime_sqlite3_dbfind_database (const char *database)
static const char * get_sqlite_column_type (int type)
 Convert Asterisk realtime types to SQLite 3 types.
static int handle_missing_column (struct realtime_sqlite3_db *db, const char *table, const char *column, int type, size_t sz)
 If ast_realtime_require sends info about a column we don't have, create it.
static int handle_missing_table (struct realtime_sqlite3_db *db, const char *table, va_list ap)
 Create a table if ast_realtime_require shows that we are configured to handle the data.
static int is_dirty_cb (void *obj, void *arg, int flags)
static int load_module (void)
 Load the module.
static void mark_all_databases_dirty (void)
static int mark_dirty_cb (void *obj, void *arg, int flags)
static struct realtime_sqlite3_dbnew_realtime_sqlite3_db (struct ast_config *config, const char *cat)
 Create a db object based on a config category.
static int parse_config (int reload)
 Parse the res_config_sqlite3 config file.
static struct ast_variablerealtime_sqlite3 (const char *database, const char *table, const struct ast_variable *fields)
 Realtime callback for a single row query.
static int realtime_sqlite3_destroy (const char *database, const char *table, const char *keyfield, const char *entity, const struct ast_variable *fields)
 Realtime callback for deleting a row.
static int realtime_sqlite3_execute (const char *database, const char *sql, int(*callback)(void *, int, char **, char **), void *arg, int sync)
static int realtime_sqlite3_execute_handle (struct realtime_sqlite3_db *db, const char *sql, int(*callback)(void *, int, char **, char **), void *arg, int sync)
static int realtime_sqlite3_helper (const char *database, const char *table, const struct ast_variable *fields, int is_multi, void *arg)
 Helper function for single and multi-row realtime load functions.
static struct ast_configrealtime_sqlite3_load (const char *database, const char *table, const char *configfile, struct ast_config *config, struct ast_flags flags, const char *suggested_include_file, const char *who_asked)
 Realtime callback for static realtime.
static struct ast_configrealtime_sqlite3_multi (const char *database, const char *table, const struct ast_variable *fields)
 Realtime callback for a multi-row query.
static int realtime_sqlite3_require (const char *database, const char *table, va_list ap)
 Callback for ast_realtime_require.
static int realtime_sqlite3_store (const char *database, const char *table, const struct ast_variable *fields)
 Realtime callback for inserting a row.
static int realtime_sqlite3_unload (const char *database, const char *table)
 Callback for clearing any cached info.
static int realtime_sqlite3_update (const char *database, const char *table, const char *keyfield, const char *entity, const struct ast_variable *fields)
 Realtime callback for updating a row based on a single criteria.
static int realtime_sqlite3_update2 (const char *database, const char *table, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)
 Realtime callback for updating a row based on multiple criteria.
static int reload (void)
static int row_to_varlist (void *arg, int num_columns, char **values, char **columns)
 Create a varlist from a single sqlite3 result row.
static const char * sqlite3_escape_column (const char *param)
static const char * sqlite3_escape_column_op (const char *param)
static const char * sqlite3_escape_string_helper (struct ast_threadstorage *ts, const char *param)
static const char * sqlite3_escape_table (const char *param)
static const char * sqlite3_escape_value (const char *param)
static int static_realtime_cb (void *arg, int num_columns, char **values, char **columns)
static int stop_batch_cb (void *obj, void *arg, int flags)
static int str_cmp_fn (void *obj, void *arg, int flags)
static int str_hash_fn (const void *obj, const int flags)
static int str_to_requirements (const char *data)
static void trace_cb (void *arg, const char *sql)
static void unlink_dirty_databases (void)
static int unload_module (void)
static void unref_db (struct realtime_sqlite3_db **db)
static int update_realtime_sqlite3_db (struct realtime_sqlite3_db *db, struct ast_config *config, const char *cat)
 Update an existing db object based on config data.

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "SQLite 3 realtime config engine" , .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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_REALTIME_DRIVER, }
static struct ast_module_infoast_module_info = &__mod_info
static ast_mutex_t config_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
struct ao2_containerdatabases
static struct ast_threadstorage escape_column_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_escape_column_buf , .custom_init = NULL , }
static struct ast_threadstorage escape_table_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_escape_table_buf , .custom_init = NULL , }
static struct ast_threadstorage escape_value_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_escape_value_buf , .custom_init = NULL , }
struct ast_config_engine sqlite3_config_engine
static const char * static_sql = "SELECT category, var_name, var_val FROM \"%q\" WHERE filename = %Q AND commented = 0 ORDER BY cat_metric ASC, var_metric ASC"


Detailed Description

SQLite 3 configuration engine.

Author:
Terry Wilson <twilson@digium.com> 
This is a realtime configuration engine for the SQLite 3 Database

Definition in file res_config_sqlite3.c.


Define Documentation

#define DB_BUCKETS   7

Definition at line 109 of file res_config_sqlite3.c.

Referenced by load_module().


Enumeration Type Documentation

anonymous enum

Enumerator:
REALTIME_SQLITE3_REQ_WARN 
REALTIME_SQLITE3_REQ_CLOSE 
REALTIME_SQLITE3_REQ_CHAR 

Definition at line 86 of file res_config_sqlite3.c.

anonymous enum

Enumerator:
COL_CATEGORY 
COL_VAR_NAME 
COL_VAR_VAL 
COL_COLUMNS 

Definition at line 568 of file res_config_sqlite3.c.

00568      {
00569    COL_CATEGORY,
00570    COL_VAR_NAME,
00571    COL_VAR_VAL,
00572    COL_COLUMNS,
00573 };


Function Documentation

static void __init_escape_column_buf ( void   )  [static]

Definition at line 115 of file res_config_sqlite3.c.

00123 {

static void __init_escape_table_buf ( void   )  [static]

Definition at line 114 of file res_config_sqlite3.c.

00123 {

static void __init_escape_value_buf ( void   )  [static]

Definition at line 116 of file res_config_sqlite3.c.

00123 {

static void __reg_module ( void   )  [static]

Definition at line 1211 of file res_config_sqlite3.c.

static void __unreg_module ( void   )  [static]

Definition at line 1211 of file res_config_sqlite3.c.

static int add_column_name ( void *  arg,
int  num_columns,
char **  values,
char **  columns 
) [static]

Callback for creating a hash of column names for comparison in realtime_sqlite3_require.

Definition at line 994 of file res_config_sqlite3.c.

References ao2_alloc, ao2_link, ao2_ref, and NULL.

Referenced by realtime_sqlite3_require().

00995 {
00996    char *column;
00997    struct ao2_container *cnames = arg;
00998 
00999 
01000    if (!(column = ao2_alloc(strlen(values[1]) + 1, NULL))) {
01001       return -1;
01002    }
01003 
01004    strcpy(column, values[1]);
01005 
01006    ao2_link(cnames, column);
01007    ao2_ref(column, -1);
01008 
01009    return 0;
01010 }

static int append_row_to_cfg ( void *  arg,
int  num_columns,
char **  values,
char **  columns 
) [static]

Callback for creating an ast_config from a successive sqlite3 result rows.

Definition at line 482 of file res_config_sqlite3.c.

References ast_category_append(), ast_category_new(), ast_log, ast_variable_append(), ast_variable_new(), LOG_ERROR, S_OR, and var.

Referenced by realtime_sqlite3_helper().

00483 {
00484    struct ast_config *cfg = arg;
00485    struct ast_category *cat;
00486    int i;
00487 
00488    if (!(cat = ast_category_new("", "", 99999))) {
00489       return SQLITE_ABORT;
00490    }
00491 
00492    for (i = 0; i < num_columns; i++) {
00493       struct ast_variable *var;
00494       if (!(var = ast_variable_new(columns[i], S_OR(values[i], ""), ""))) {
00495          ast_log(LOG_ERROR, "Could not create new variable for '%s: %s', throwing away list\n", columns[i], values[i]);
00496          continue;
00497       }
00498       ast_variable_append(cat, var);
00499    }
00500    ast_category_append(cfg, cat);
00501 
00502    return 0;
00503 }

static int db_cmp_fn ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 204 of file res_config_sqlite3.c.

References CMP_MATCH, CMP_STOP, realtime_sqlite3_db::name, name, and OBJ_KEY.

Referenced by load_module().

00204                                                       {
00205    struct realtime_sqlite3_db *db = obj, *other = arg;
00206    const char *name = arg;
00207 
00208    return !strcasecmp(db->name, flags & OBJ_KEY ? name : other->name) ? CMP_MATCH | CMP_STOP : 0;
00209 }

static void db_destructor ( void *  obj  )  [static]

Definition at line 211 of file res_config_sqlite3.c.

References ao2_lock, ao2_unlock, ast_debug, ast_string_field_free_memory, db_stop_batch(), realtime_sqlite3_db::handle, and realtime_sqlite3_db::name.

Referenced by new_realtime_sqlite3_db().

00212 {
00213    struct realtime_sqlite3_db *db = obj;
00214 
00215    ast_debug(1, "Destroying db: %s\n", db->name);
00216    ast_string_field_free_memory(db);
00217    db_stop_batch(db);
00218    if (db->handle) {
00219       ao2_lock(db);
00220       sqlite3_close(db->handle);
00221       ao2_unlock(db);
00222    }
00223 }

static int db_hash_fn ( const void *  obj,
const int  flags 
) [static]

Definition at line 197 of file res_config_sqlite3.c.

References ast_str_hash(), realtime_sqlite3_db::name, and OBJ_KEY.

Referenced by load_module().

00198 {
00199    const struct realtime_sqlite3_db *db = obj;
00200 
00201    return ast_str_hash(flags & OBJ_KEY ? (const char *) obj : db->name);
00202 }

static int db_open ( struct realtime_sqlite3_db db  )  [static]

Open a database and appropriately set debugging on the db handle.

Definition at line 319 of file res_config_sqlite3.c.

References ao2_lock, ao2_unlock, ast_log, realtime_sqlite3_db::debug, realtime_sqlite3_db::filename, realtime_sqlite3_db::handle, LOG_WARNING, NULL, and trace_cb().

00320 {
00321    ao2_lock(db);
00322    if (sqlite3_open(db->filename, &db->handle) != SQLITE_OK) {
00323       ast_log(LOG_WARNING, "Could not open %s: %s\n", db->filename, sqlite3_errmsg(db->handle));
00324       ao2_unlock(db);
00325       return -1;
00326    }
00327    sqlite3_busy_timeout(db->handle, 1000);
00328 
00329    if (db->debug) {
00330       sqlite3_trace(db->handle, trace_cb, db);
00331    } else {
00332       sqlite3_trace(db->handle, NULL, NULL);
00333    }
00334 
00335    ao2_unlock(db);
00336 
00337    return 0;
00338 }

void db_start_batch ( struct realtime_sqlite3_db db  ) 

void db_stop_batch ( struct realtime_sqlite3_db db  ) 

Definition at line 355 of file res_config_sqlite3.c.

References realtime_sqlite3_db::batch, db_sync(), realtime_sqlite3_db::exiting, NULL, and realtime_sqlite3_db::syncthread.

Referenced by db_destructor(), is_dirty_cb(), stop_batch_cb(), and update_realtime_sqlite3_db().

00356 {
00357    if (db->batch) {
00358       db->exiting = 1;
00359       db_sync(db);
00360       pthread_join(db->syncthread, NULL);
00361    }
00362 }

static void db_sync ( struct realtime_sqlite3_db db  )  [static]

Definition at line 340 of file res_config_sqlite3.c.

References ast_cond_signal, realtime_sqlite3_db::cond, and realtime_sqlite3_db::wakeup.

00341 {
00342    db->wakeup = 1;
00343    ast_cond_signal(&db->cond);
00344 }

static void* db_sync_thread ( void *  data  )  [static]

Wrap commands in transactions increased write performance.

Definition at line 290 of file res_config_sqlite3.c.

References ao2_lock, ao2_object_get_lockaddr(), ao2_unlock, ast_cond_wait, realtime_sqlite3_db::batch, realtime_sqlite3_db::cond, realtime_sqlite3_db::exiting, NULL, realtime_sqlite3_execute_handle(), unref_db(), and realtime_sqlite3_db::wakeup.

00291 {
00292    struct realtime_sqlite3_db *db = data;
00293    ao2_lock(db);
00294    realtime_sqlite3_execute_handle(db, "BEGIN TRANSACTION", NULL, NULL, 0);
00295    for (;;) {
00296       if (!db->wakeup) {
00297          ast_cond_wait(&db->cond, ao2_object_get_lockaddr(db));
00298       }
00299       db->wakeup = 0;
00300       if (realtime_sqlite3_execute_handle(db, "COMMIT", NULL, NULL, 0) < 0) {
00301          realtime_sqlite3_execute_handle(db, "ROLLBACK", NULL, NULL, 0);
00302       }
00303       if (db->exiting) {
00304          ao2_unlock(db);
00305          break;
00306       }
00307       realtime_sqlite3_execute_handle(db, "BEGIN TRANSACTION", NULL, NULL, 0);
00308       ao2_unlock(db);
00309       usleep(1000 * db->batch);
00310       ao2_lock(db);
00311    }
00312 
00313    unref_db(&db);
00314 
00315    return NULL;
00316 }

static struct realtime_sqlite3_db* find_database ( const char *  database  )  [static, read]

Definition at line 225 of file res_config_sqlite3.c.

References ao2_find, and OBJ_KEY.

00226 {
00227    return ao2_find(databases, database, OBJ_KEY);
00228 }

static const char* get_sqlite_column_type ( int  type  )  [static]

Convert Asterisk realtime types to SQLite 3 types.

Note:
SQLite 3 has NULL, INTEGER, REAL, TEXT, and BLOB types. Any column other than an INTEGER PRIMARY KEY will actually store any kind of data due to its dynamic typing. When we create columns, we'll go ahead and use these base types instead of messing with column widths, etc.

Definition at line 897 of file res_config_sqlite3.c.

References RQ_CHAR, RQ_DATE, RQ_DATETIME, RQ_FLOAT, RQ_INTEGER1, RQ_INTEGER2, RQ_INTEGER3, RQ_INTEGER4, RQ_INTEGER8, RQ_UINTEGER1, RQ_UINTEGER2, RQ_UINTEGER3, RQ_UINTEGER4, and RQ_UINTEGER8.

Referenced by handle_missing_column(), and handle_missing_table().

00898 {
00899    switch(type) {
00900    case RQ_INTEGER1 :
00901    case RQ_UINTEGER1 :
00902    case RQ_INTEGER2 :
00903    case RQ_UINTEGER2 :
00904    case RQ_INTEGER3 :
00905    case RQ_UINTEGER3 :
00906    case RQ_INTEGER4 :
00907    case RQ_UINTEGER4 :
00908    case RQ_INTEGER8 :
00909       return "INTEGER";
00910    case RQ_UINTEGER8 : /* SQLite3 stores INTEGER as signed 8-byte */
00911    case RQ_CHAR :
00912    case RQ_DATE :
00913    case RQ_DATETIME :
00914       return "TEXT";
00915    case RQ_FLOAT :
00916       return "REAL";
00917    default :
00918       return "TEXT";
00919    }
00920 
00921    return "TEXT";
00922 }

static int handle_missing_column ( struct realtime_sqlite3_db db,
const char *  table,
const char *  column,
int  type,
size_t  sz 
) [static]

If ast_realtime_require sends info about a column we don't have, create it.

Definition at line 957 of file res_config_sqlite3.c.

References ast_log, get_sqlite_column_type(), LOG_NOTICE, LOG_WARNING, realtime_sqlite3_db::name, NULL, realtime_sqlite3_execute_handle(), REALTIME_SQLITE3_REQ_CHAR, REALTIME_SQLITE3_REQ_WARN, and realtime_sqlite3_db::requirements.

Referenced by realtime_sqlite3_require().

00958 {
00959    char *sql;
00960    const char *sqltype = get_sqlite_column_type(type);
00961    int res;
00962 
00963    if (db->requirements == REALTIME_SQLITE3_REQ_WARN) {
00964       ast_log(LOG_WARNING, "Missing column '%s' of type '%s' in %s.%s\n", column, sqltype, db->name, table);
00965       return -1;
00966    } else if (db->requirements == REALTIME_SQLITE3_REQ_CHAR) {
00967       sqltype = "TEXT";
00968    }
00969 
00970    if (!(sql = sqlite3_mprintf("ALTER TABLE \"%q\" ADD COLUMN \"%q\" %s", table, column, sqltype))) {
00971       return -1;
00972    }
00973 
00974    if (!(res = (realtime_sqlite3_execute_handle(db, sql, NULL, NULL, 1) < 0 ? -1 : 0))) {
00975       ast_log(LOG_NOTICE, "Creating column '%s' type %s for table %s\n", column, sqltype, table);
00976    }
00977 
00978    sqlite3_free(sql);
00979 
00980    return res;
00981 }

static int handle_missing_table ( struct realtime_sqlite3_db db,
const char *  table,
va_list  ap 
) [static]

Create a table if ast_realtime_require shows that we are configured to handle the data.

Definition at line 926 of file res_config_sqlite3.c.

References ast_free, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), first, get_sqlite_column_type(), NULL, realtime_sqlite3_execute_handle(), sqlite3_escape_column(), sqlite3_escape_table(), type, and typeof().

Referenced by realtime_sqlite3_require().

00927 {
00928    const char *column;
00929    int type, first = 1, res;
00930    size_t sz;
00931    struct ast_str *sql;
00932 
00933    if (!(sql = ast_str_create(128))) {
00934       return -1;
00935    }
00936 
00937    while ((column = va_arg(ap, typeof(column))) && (type = va_arg(ap, typeof(type))) && (sz = va_arg(ap, typeof(sz)))) {
00938       if (first) {
00939          ast_str_set(&sql, 0, "CREATE TABLE IF NOT EXISTS %s (%s %s", sqlite3_escape_table(table),
00940                sqlite3_escape_column(column), get_sqlite_column_type(type));
00941          first = 0;
00942       } else {
00943          ast_str_append(&sql, 0, ", %s %s", sqlite3_escape_column(column), get_sqlite_column_type(type));
00944       }
00945    }
00946 
00947    ast_str_append(&sql, 0, ")");
00948 
00949    res = realtime_sqlite3_execute_handle(db, ast_str_buffer(sql), NULL, NULL, 1) < 0 ? -1 : 0;
00950    ast_free(sql);
00951 
00952    return res;
00953 }

static int is_dirty_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 256 of file res_config_sqlite3.c.

References CMP_MATCH, db_stop_batch(), and realtime_sqlite3_db::dirty.

Referenced by unlink_dirty_databases().

00257 {
00258    struct realtime_sqlite3_db *db = obj;
00259    if (db->dirty) {
00260       db_stop_batch(db);
00261       return CMP_MATCH;
00262    }
00263    return 0;
00264 }

static int load_module ( void   )  [static]

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 1185 of file res_config_sqlite3.c.

References ao2_container_alloc, ao2_ref, ast_config_engine_register(), ast_log, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, DB_BUCKETS, db_cmp_fn(), db_hash_fn(), LOG_ERROR, and parse_config().

01186 {
01187    if (!((databases = ao2_container_alloc(DB_BUCKETS, db_hash_fn, db_cmp_fn)))) {
01188       return AST_MODULE_LOAD_FAILURE;
01189    }
01190 
01191    if (parse_config(0)) {
01192       ao2_ref(databases, -1);
01193       return AST_MODULE_LOAD_FAILURE;
01194    }
01195 
01196    if (!(ast_config_engine_register(&sqlite3_config_engine))) {
01197       ast_log(LOG_ERROR, "The config API must have changed, this shouldn't happen.\n");
01198       ao2_ref(databases, -1);
01199       return AST_MODULE_LOAD_FAILURE;
01200    }
01201 
01202    return AST_MODULE_LOAD_SUCCESS;
01203 }

static void mark_all_databases_dirty ( void   )  [static]

Definition at line 251 of file res_config_sqlite3.c.

References ao2_callback, mark_dirty_cb(), NULL, OBJ_MULTIPLE, and OBJ_NODATA.

Referenced by parse_config().

static int mark_dirty_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 244 of file res_config_sqlite3.c.

References CMP_MATCH, and realtime_sqlite3_db::dirty.

Referenced by mark_all_databases_dirty().

00245 {
00246    struct realtime_sqlite3_db *db = obj;
00247    db->dirty = 1;
00248    return CMP_MATCH;
00249 }

static struct realtime_sqlite3_db* new_realtime_sqlite3_db ( struct ast_config config,
const char *  cat 
) [static, read]

Create a db object based on a config category.

Note:
Opening the db handle and linking to databases must be handled outside of this function

Definition at line 367 of file res_config_sqlite3.c.

References ao2_alloc, ast_app_parse_timelen(), ast_log, ast_string_field_init, ast_string_field_set, ast_strlen_zero, ast_true(), ast_variable_browse(), realtime_sqlite3_db::batch, db_destructor(), realtime_sqlite3_db::debug, realtime_sqlite3_db::filename, LOG_WARNING, ast_variable::name, name, ast_variable::next, NULL, REALTIME_SQLITE3_REQ_WARN, realtime_sqlite3_db::requirements, str_to_requirements(), TIMELEN_MILLISECONDS, unref_db(), ast_variable::value, and var.

Referenced by parse_config(), and update_realtime_sqlite3_db().

00368 {
00369    struct ast_variable *var;
00370    struct realtime_sqlite3_db *db;
00371 
00372    if (!(db = ao2_alloc(sizeof(*db), db_destructor))) {
00373       return NULL;
00374    }
00375 
00376    if (ast_string_field_init(db, 64)) {
00377       unref_db(&db);
00378       return NULL;
00379    }
00380 
00381    /* Set defaults */
00382    db->requirements = REALTIME_SQLITE3_REQ_WARN;
00383    db->batch = 100;
00384    ast_string_field_set(db, name, cat);
00385 
00386    for (var = ast_variable_browse(config, cat); var; var = var->next) {
00387       if (!strcasecmp(var->name, "dbfile")) {
00388          ast_string_field_set(db, filename, var->value);
00389       } else if (!strcasecmp(var->name, "requirements")) {
00390          db->requirements = str_to_requirements(var->value);
00391       } else if (!strcasecmp(var->name, "batch")) {
00392          ast_app_parse_timelen(var->value, (int *) &db->batch, TIMELEN_MILLISECONDS);
00393       } else if (!strcasecmp(var->name, "debug")) {
00394          db->debug = ast_true(var->value);
00395       }
00396    }
00397 
00398    if (ast_strlen_zero(db->filename)) {
00399       ast_log(LOG_WARNING, "Must specify dbfile in res_config_sqlite3.conf\n");
00400       unref_db(&db);
00401       return NULL;
00402    }
00403 
00404    return db;
00405 }

static int parse_config ( int  reload  )  [static]

Parse the res_config_sqlite3 config file.

Definition at line 1100 of file res_config_sqlite3.c.

References ao2_link, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, config, config_filename, CONFIG_FLAG_FILEUNCHANGED, CONFIG_FLAG_NOREALTIME, config_lock, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, db_open(), db_start_batch(), find_database(), LOG_ERROR, LOG_WARNING, mark_all_databases_dirty(), new_realtime_sqlite3_db(), NULL, unlink_dirty_databases(), unref_db(), and update_realtime_sqlite3_db().

01101 {
01102    struct ast_config *config;
01103    struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME | (reload ? CONFIG_FLAG_FILEUNCHANGED : 0) };
01104    static const char *config_filename = "res_config_sqlite3.conf";
01105 
01106    config = ast_config_load(config_filename, config_flags);
01107 
01108    if (config == CONFIG_STATUS_FILEUNCHANGED) {
01109       ast_debug(1, "%s was unchanged, skipping parsing\n", config_filename);
01110       return 0;
01111    }
01112 
01113    ast_mutex_lock(&config_lock);
01114 
01115    if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
01116       ast_log(LOG_ERROR, "%s config file '%s'\n",
01117          config == CONFIG_STATUS_FILEMISSING ? "Missing" : "Invalid", config_filename);
01118    } else {
01119       const char *cat;
01120       struct realtime_sqlite3_db *db;
01121 
01122       mark_all_databases_dirty();
01123       for (cat = ast_category_browse(config, NULL); cat; cat = ast_category_browse(config, cat)) {
01124          if (!strcasecmp(cat, "general")) {
01125             continue;
01126          }
01127          if (!(db = find_database(cat))) {
01128             if (!(db = new_realtime_sqlite3_db(config, cat))) {
01129                ast_log(LOG_WARNING, "Could not allocate new db for '%s' - skipping.\n", cat);
01130                continue;
01131             }
01132             if (db_open(db)) {
01133                unref_db(&db);
01134                continue;
01135             }
01136             db_start_batch(db);
01137             ao2_link(databases, db);
01138             unref_db(&db);
01139          } else  {
01140             if (update_realtime_sqlite3_db(db, config, cat)) {
01141                unref_db(&db);
01142                continue;
01143             }
01144             unref_db(&db);
01145          }
01146       }
01147       unlink_dirty_databases();
01148    }
01149 
01150    ast_mutex_unlock(&config_lock);
01151 
01152    ast_config_destroy(config);
01153 
01154    return 0;
01155 }

static struct ast_variable * realtime_sqlite3 ( const char *  database,
const char *  table,
const struct ast_variable fields 
) [static, read]

Realtime callback for a single row query.

Returns:
ast_variable list for single result on success, NULL on empty/failure

Definition at line 695 of file res_config_sqlite3.c.

References NULL, and realtime_sqlite3_helper().

00696 {
00697    struct ast_variable *result_row = NULL;
00698 
00699    realtime_sqlite3_helper(database, table, fields, 0, &result_row);
00700 
00701    return result_row;
00702 }

static int realtime_sqlite3_destroy ( const char *  database,
const char *  table,
const char *  keyfield,
const char *  entity,
const struct ast_variable fields 
) [static]

Realtime callback for deleting a row.

Returns:
Number of rows affected or -1 on error

Definition at line 859 of file res_config_sqlite3.c.

References ast_free, ast_log, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strlen_zero, first, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, realtime_sqlite3_execute(), sqlite3_escape_column_op(), sqlite3_escape_table(), sqlite3_escape_value(), and ast_variable::value.

00860 {
00861    struct ast_str *sql;
00862    const struct ast_variable *field;
00863    int first = 1, res;
00864 
00865    if (ast_strlen_zero(table)) {
00866       ast_log(LOG_WARNING, "Must have a table to query!\n");
00867       return -1;
00868    }
00869 
00870    if (!(sql = ast_str_create(128))) {
00871       return -1;
00872    }
00873 
00874    for (field = fields; field; field = field->next) {
00875       if (first) {
00876          ast_str_set(&sql, 0, "DELETE FROM %s WHERE %s %s", sqlite3_escape_table(table),
00877                sqlite3_escape_column_op(field->name), sqlite3_escape_value(field->value));
00878          first = 0;
00879       } else {
00880          ast_str_append(&sql, 0, " AND %s %s", sqlite3_escape_column_op(field->name), sqlite3_escape_value(field->value));
00881       }
00882    }
00883 
00884    res = realtime_sqlite3_execute(database, ast_str_buffer(sql), NULL, NULL, 1);
00885 
00886    ast_free(sql);
00887 
00888    return res;
00889 }

static int realtime_sqlite3_execute ( const char *  database,
const char *  sql,
int(*)(void *, int, char **, char **)  callback,
void *  arg,
int  sync 
) [static]

Exeute an SQL statement give the database name

Return values:
-1 ERROR
> -1 Number of rows changed

Definition at line 550 of file res_config_sqlite3.c.

References ao2_ref, ast_log, find_database(), LOG_WARNING, and realtime_sqlite3_execute_handle().

Referenced by realtime_sqlite3_destroy(), realtime_sqlite3_helper(), realtime_sqlite3_load(), realtime_sqlite3_store(), realtime_sqlite3_update(), and realtime_sqlite3_update2().

00551 {
00552    struct realtime_sqlite3_db *db;
00553    int res;
00554 
00555    if (!(db = find_database(database))) {
00556       ast_log(LOG_WARNING, "Could not find database: %s\n", database);
00557       return -1;
00558    }
00559 
00560    res = realtime_sqlite3_execute_handle(db, sql, callback, arg, sync);
00561    ao2_ref(db, -1);
00562 
00563    return res;
00564 }

static int realtime_sqlite3_execute_handle ( struct realtime_sqlite3_db db,
const char *  sql,
int(*)(void *, int, char **, char **)  callback,
void *  arg,
int  sync 
) [static]

Exeute an SQL statement given the database object

Return values:
-1 ERROR
> -1 Number of rows changed

Definition at line 523 of file res_config_sqlite3.c.

References ao2_lock, ao2_unlock, ast_log, db_sync(), realtime_sqlite3_db::handle, and LOG_WARNING.

Referenced by db_sync_thread(), handle_missing_column(), handle_missing_table(), realtime_sqlite3_execute(), and realtime_sqlite3_require().

00524 {
00525    int res = 0;
00526    char *errmsg;
00527 
00528    ao2_lock(db);
00529    if (sqlite3_exec(db->handle, sql, callback, arg, &errmsg) != SQLITE_OK) {
00530       ast_log(LOG_WARNING, "Could not execute '%s': %s\n", sql, errmsg);
00531       sqlite3_free(errmsg);
00532       res = -1;
00533    } else {
00534       res = sqlite3_changes(db->handle);
00535    }
00536    ao2_unlock(db);
00537 
00538    if (sync) {
00539       db_sync(db);
00540    }
00541 
00542    return res;
00543 }

static int realtime_sqlite3_helper ( const char *  database,
const char *  table,
const struct ast_variable fields,
int  is_multi,
void *  arg 
) [static]

Helper function for single and multi-row realtime load functions.

Definition at line 652 of file res_config_sqlite3.c.

References append_row_to_cfg(), ast_free, ast_log, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strlen_zero, first, LOG_WARNING, ast_variable::name, ast_variable::next, realtime_sqlite3_execute(), row_to_varlist(), sqlite3_escape_column_op(), sqlite3_escape_table(), sqlite3_escape_value(), and ast_variable::value.

Referenced by realtime_sqlite3(), and realtime_sqlite3_multi().

00653 {
00654    struct ast_str *sql;
00655    const struct ast_variable *field;
00656    int first = 1;
00657 
00658    if (ast_strlen_zero(table)) {
00659       ast_log(LOG_WARNING, "Must have a table to query!\n");
00660       return -1;
00661    }
00662 
00663    if (!(sql = ast_str_create(128))) {
00664       return -1;
00665    }
00666 
00667    for (field = fields; field; field = field->next) {
00668       if (first) {
00669          ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s %s", sqlite3_escape_table(table),
00670                 sqlite3_escape_column_op(field->name), sqlite3_escape_value(field->value));
00671          first = 0;
00672       } else {
00673          ast_str_append(&sql, 0, " AND %s %s", sqlite3_escape_column_op(field->name),
00674                sqlite3_escape_value(field->value));
00675       }
00676    }
00677 
00678    if (!is_multi) {
00679       ast_str_append(&sql, 0, "%s", " LIMIT 1");
00680    }
00681 
00682    if (realtime_sqlite3_execute(database, ast_str_buffer(sql), is_multi ? append_row_to_cfg : row_to_varlist, arg, 0) < 0) {
00683       ast_free(sql);
00684       return -1;
00685    }
00686 
00687    ast_free(sql);
00688 
00689    return 0;
00690 }

static struct ast_config * realtime_sqlite3_load ( const char *  database,
const char *  table,
const char *  configfile,
struct ast_config config,
struct ast_flags  flags,
const char *  suggested_include_file,
const char *  who_asked 
) [static, read]

Realtime callback for static realtime.

Returns:
ast_config on success, NULL on failure

Definition at line 623 of file res_config_sqlite3.c.

References ast_log, ast_strlen_zero, cfg_entry_args::cat, cfg_entry_args::cat_name, cfg_entry_args::cfg, cfg_entry_args::flags, LOG_WARNING, NULL, realtime_sqlite3_execute(), static_realtime_cb(), and cfg_entry_args::who_asked.

00624 {
00625    char *sql;
00626    struct cfg_entry_args args;
00627 
00628    if (ast_strlen_zero(table)) {
00629       ast_log(LOG_WARNING, "Must have a table to query!\n");
00630       return NULL;
00631    }
00632 
00633    if (!(sql = sqlite3_mprintf(static_sql, table, configfile))) {
00634       ast_log(LOG_WARNING, "Couldn't allocate query\n");
00635       return NULL;
00636    };
00637 
00638    args.cfg = config;
00639    args.cat = NULL;
00640    args.cat_name = NULL;
00641    args.flags = flags;
00642    args.who_asked = who_asked;
00643 
00644    realtime_sqlite3_execute(database, sql, static_realtime_cb, &args, 0);
00645 
00646    sqlite3_free(sql);
00647 
00648    return config;
00649 }

static struct ast_config * realtime_sqlite3_multi ( const char *  database,
const char *  table,
const struct ast_variable fields 
) [static, read]

Realtime callback for a multi-row query.

Returns:
ast_config containing possibly many results on success, NULL on empty/failure

Definition at line 707 of file res_config_sqlite3.c.

References ast_config_destroy(), ast_config_new(), NULL, and realtime_sqlite3_helper().

00708 {
00709    struct ast_config *cfg;
00710 
00711    if (!(cfg = ast_config_new())) {
00712       return NULL;
00713    }
00714 
00715    if (realtime_sqlite3_helper(database, table, fields, 1, cfg)) {
00716       ast_config_destroy(cfg);
00717       return NULL;
00718    }
00719 
00720    return cfg;
00721 }

static int realtime_sqlite3_require ( const char *  database,
const char *  table,
va_list  ap 
) [static]

Callback for ast_realtime_require.

Return values:
0 Required fields met specified standards
-1 One or more fields was missing or insufficient

Definition at line 1016 of file res_config_sqlite3.c.

References add_column_name(), ao2_container_alloc, ao2_find, ao2_ref, ast_log, ast_strlen_zero, find_database(), handle_missing_column(), handle_missing_table(), LOG_WARNING, OBJ_POINTER, OBJ_UNLINK, realtime_sqlite3_execute_handle(), str_cmp_fn(), str_hash_fn(), type, typeof(), and unref_db().

01017 {
01018    const char *column;
01019    char *sql;
01020    int type;
01021    int res;
01022    size_t sz;
01023    struct ao2_container *columns;
01024    struct realtime_sqlite3_db *db;
01025 
01026    /* SQLite3 columns are dynamically typed, with type affinity. Built-in functions will
01027     * return the results as char * anyway. The only field that that cannot contain text
01028     * data is an INTEGER PRIMARY KEY, which must be a 64-bit signed integer. So, for
01029     * the purposes here we really only care whether the column exists and not what its
01030     * type or length is. */
01031 
01032    if (ast_strlen_zero(table)) {
01033       ast_log(LOG_WARNING, "Must have a table to query!\n");
01034       return -1;
01035    }
01036 
01037    if (!(db = find_database(database))) {
01038       return -1;
01039    }
01040 
01041    if (!(columns = ao2_container_alloc(31, str_hash_fn, str_cmp_fn))) {
01042       unref_db(&db);
01043       return -1;
01044    }
01045 
01046    if (!(sql = sqlite3_mprintf("PRAGMA table_info(\"%q\")", table))) {
01047       unref_db(&db);
01048       ao2_ref(columns, -1);
01049       return -1;
01050    }
01051 
01052    if ((res = realtime_sqlite3_execute_handle(db, sql, add_column_name, columns, 0)) < 0) {
01053       unref_db(&db);
01054       ao2_ref(columns, -1);
01055       sqlite3_free(sql);
01056       return -1;
01057    } else if (res == 0) {
01058       /* Table does not exist */
01059       sqlite3_free(sql);
01060       res = handle_missing_table(db, table, ap);
01061       ao2_ref(columns, -1);
01062       unref_db(&db);
01063       return res;
01064    }
01065 
01066    sqlite3_free(sql);
01067 
01068    while ((column = va_arg(ap, typeof(column))) && (type = va_arg(ap, typeof(type))) && (sz = va_arg(ap, typeof(sz)))) {
01069       char *found;
01070       if (!(found = ao2_find(columns, column, OBJ_POINTER | OBJ_UNLINK))) {
01071          if (handle_missing_column(db, table, column, type, sz)) {
01072             unref_db(&db);
01073             ao2_ref(columns, -1);
01074             return -1;
01075          }
01076       } else {
01077          ao2_ref(found, -1);
01078       }
01079    }
01080 
01081    ao2_ref(columns, -1);
01082    unref_db(&db);
01083 
01084    return 0;
01085 }

static int realtime_sqlite3_store ( const char *  database,
const char *  table,
const struct ast_variable fields 
) [static]

Realtime callback for inserting a row.

Returns:
Number of rows affected or -1 on error

Definition at line 815 of file res_config_sqlite3.c.

References ast_free, ast_log, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strlen_zero, first, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, realtime_sqlite3_execute(), sqlite3_escape_column(), sqlite3_escape_table(), sqlite3_escape_value(), and ast_variable::value.

00816 {
00817    struct ast_str *sql, *values;
00818    const struct ast_variable *field;
00819    int first = 1, res;
00820 
00821    if (ast_strlen_zero(table)) {
00822       ast_log(LOG_WARNING, "Must have a table to query!\n");
00823       return -1;
00824    }
00825 
00826    if (!(sql = ast_str_create(128))) {
00827       return -1;
00828    }
00829 
00830    if (!(values = ast_str_create(128))) {
00831       ast_free(sql);
00832       return -1;
00833    }
00834 
00835    for (field = fields; field; field = field->next) {
00836       if (first) {
00837          ast_str_set(&sql, 0, "INSERT INTO %s (%s", sqlite3_escape_table(table), sqlite3_escape_column(field->name));
00838          ast_str_set(&values, 0, ") VALUES (%s", sqlite3_escape_value(field->value));
00839          first = 0;
00840       } else {
00841          ast_str_append(&sql, 0, ", %s", sqlite3_escape_column(field->name));
00842          ast_str_append(&values, 0, ", %s", sqlite3_escape_value(field->value));
00843       }
00844    }
00845 
00846    ast_str_append(&sql, 0, "%s)", ast_str_buffer(values));
00847 
00848    res = realtime_sqlite3_execute(database, ast_str_buffer(sql), NULL, NULL, 1);
00849 
00850    ast_free(sql);
00851    ast_free(values);
00852 
00853    return res;
00854 }

static int realtime_sqlite3_unload ( const char *  database,
const char *  table 
) [static]

Callback for clearing any cached info.

Note:
We don't currently cache anything
Return values:
0 If any cache was purged
-1 If no cache was found

Definition at line 1092 of file res_config_sqlite3.c.

01093 {
01094    /* We currently do no caching */
01095    return -1;
01096 }

static int realtime_sqlite3_update ( const char *  database,
const char *  table,
const char *  keyfield,
const char *  entity,
const struct ast_variable fields 
) [static]

Realtime callback for updating a row based on a single criteria.

Returns:
Number of rows affected or -1 on error

Definition at line 726 of file res_config_sqlite3.c.

References ast_free, ast_log, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strlen_zero, first, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, realtime_sqlite3_execute(), sqlite3_escape_column(), sqlite3_escape_column_op(), sqlite3_escape_table(), sqlite3_escape_value(), and ast_variable::value.

00727 {
00728    struct ast_str *sql;
00729    const struct ast_variable *field;
00730    int first = 1, res;
00731 
00732    if (ast_strlen_zero(table)) {
00733       ast_log(LOG_WARNING, "Must have a table to query!\n");
00734       return -1;
00735    }
00736 
00737    if (!(sql = ast_str_create(128))) {
00738       return -1;
00739    }
00740 
00741    for (field = fields; field; field = field->next) {
00742       if (first) {
00743          ast_str_set(&sql, 0, "UPDATE %s SET %s = %s",
00744                sqlite3_escape_table(table), sqlite3_escape_column(field->name), sqlite3_escape_value(field->value));
00745          first = 0;
00746       } else {
00747          ast_str_append(&sql, 0, ", %s = %s", sqlite3_escape_column(field->name), sqlite3_escape_value(field->value));
00748       }
00749    }
00750 
00751    ast_str_append(&sql, 0, " WHERE %s %s", sqlite3_escape_column_op(keyfield), sqlite3_escape_value(entity));
00752 
00753    res = realtime_sqlite3_execute(database, ast_str_buffer(sql), NULL, NULL, 1);
00754    ast_free(sql);
00755 
00756    return res;
00757 }

static int realtime_sqlite3_update2 ( const char *  database,
const char *  table,
const struct ast_variable lookup_fields,
const struct ast_variable update_fields 
) [static]

Realtime callback for updating a row based on multiple criteria.

Returns:
Number of rows affected or -1 on error

Definition at line 762 of file res_config_sqlite3.c.

References ast_free, ast_log, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strlen_zero, first, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, realtime_sqlite3_execute(), sqlite3_escape_column(), sqlite3_escape_column_op(), sqlite3_escape_table(), sqlite3_escape_value(), and ast_variable::value.

00763 {
00764    struct ast_str *sql;
00765    struct ast_str *where_clause;
00766    const struct ast_variable *field;
00767    int first = 1, res;
00768 
00769    if (ast_strlen_zero(table)) {
00770       ast_log(LOG_WARNING, "Must have a table to query!\n");
00771       return -1;
00772    }
00773 
00774    if (!(sql = ast_str_create(128))) {
00775       return -1;
00776    }
00777 
00778    if (!(where_clause = ast_str_create(128))) {
00779       ast_free(sql);
00780       return -1;
00781    }
00782 
00783    for (field = lookup_fields; field; field = field->next) {
00784       if (first) {
00785          ast_str_set(&where_clause, 0, " WHERE %s %s", sqlite3_escape_column_op(field->name), sqlite3_escape_value(field->value));
00786          first = 0;
00787       } else {
00788          ast_str_append(&where_clause, 0, " AND %s %s", sqlite3_escape_column_op(field->name), sqlite3_escape_value(field->value));
00789       }
00790    }
00791 
00792    first = 1;
00793    for (field = update_fields; field; field = field->next) {
00794       if (first) {
00795          ast_str_set(&sql, 0, "UPDATE %s SET %s = %s", sqlite3_escape_table(table), sqlite3_escape_column(field->name), sqlite3_escape_value(field->value));
00796          first = 0;
00797       } else {
00798          ast_str_append(&sql, 0, ", %s = %s", sqlite3_escape_column(field->name), sqlite3_escape_value(field->value));
00799       }
00800    }
00801 
00802    ast_str_append(&sql, 0, "%s", ast_str_buffer(where_clause));
00803 
00804    res = realtime_sqlite3_execute(database, ast_str_buffer(sql), NULL, NULL, 1);
00805 
00806    ast_free(sql);
00807    ast_free(where_clause);
00808 
00809    return res;
00810 }

static int reload ( void   )  [static]

Definition at line 1157 of file res_config_sqlite3.c.

References parse_config().

01158 {
01159    parse_config(1);
01160    return 0;
01161 }

static int row_to_varlist ( void *  arg,
int  num_columns,
char **  values,
char **  columns 
) [static]

Create a varlist from a single sqlite3 result row.

Definition at line 457 of file res_config_sqlite3.c.

References ast_variable_new(), ast_variables_destroy(), NULL, and S_OR.

Referenced by realtime_sqlite3_helper().

00458 {
00459    struct ast_variable **head = arg, *tail;
00460    int i;
00461    struct ast_variable *new;
00462 
00463    if (!(new = ast_variable_new(columns[0], S_OR(values[0], ""), ""))) {
00464       return SQLITE_ABORT;
00465    }
00466    *head = tail = new;
00467 
00468    for (i = 1; i < num_columns; i++) {
00469       if (!(new = ast_variable_new(columns[i], S_OR(values[i], ""), ""))) {
00470          ast_variables_destroy(*head);
00471          *head = NULL;
00472          return SQLITE_ABORT;
00473       }
00474       tail->next = new;
00475       tail = new;
00476    }
00477 
00478    return 0;
00479 }

static const char* sqlite3_escape_column ( const char *  param  )  [inline, static]

static const char* sqlite3_escape_column_op ( const char *  param  )  [static]

Definition at line 159 of file res_config_sqlite3.c.

References ast_str_buffer(), ast_str_reset(), ast_str_thread_get(), ast_str_update(), buf, escape_column_buf, and tmp().

Referenced by realtime_sqlite3_destroy(), realtime_sqlite3_helper(), realtime_sqlite3_update(), and realtime_sqlite3_update2().

00160 {
00161    size_t maxlen = strlen(param) * 2 + sizeof("\"\" =");
00162    struct ast_str *buf = ast_str_thread_get(&escape_column_buf, maxlen);
00163    char *tmp = ast_str_buffer(buf);
00164    int space = 0;
00165 
00166    ast_str_reset(buf);
00167    *tmp++ = '"';
00168    while ((*tmp++ = *param++)) {
00169       /* If we have seen a space, don't double quotes. XXX If we ever make the column/op field
00170        * available to users via an API, we will definitely need to avoid allowing special
00171        * characters like ';' in the data past the space as it will be unquoted data */
00172       if (space) {
00173          continue;
00174       }
00175       if (*(tmp - 1) == ' ') {
00176          *(tmp - 1) = '"';
00177          *tmp++ = ' ';
00178          space = 1;
00179       } else if (*(tmp - 1) == '"') {
00180          *tmp++ = '"';
00181       }
00182    }
00183    if (!space) {
00184       strcpy(tmp - 1, "\" =");
00185    }
00186 
00187    ast_str_update(buf);
00188 
00189    return ast_str_buffer(buf);
00190 }

static const char* sqlite3_escape_string_helper ( struct ast_threadstorage ts,
const char *  param 
) [inline, static]

Definition at line 122 of file res_config_sqlite3.c.

References ast_str_buffer(), ast_str_reset(), ast_str_thread_get(), ast_str_update(), buf, escape_value_buf, and tmp().

Referenced by sqlite3_escape_column(), sqlite3_escape_table(), and sqlite3_escape_value().

00123 {
00124    size_t maxlen = strlen(param) * 2 + sizeof("\"\"");
00125    /* It doesn't appear that sqlite3_snprintf will do more than double the
00126     * length of a string with %q as an option. %Q could double and possibly
00127     * add two quotes, and convert NULL pointers to the word "NULL", but we
00128     * don't allow those anyway. Just going to use %q for now. */
00129    struct ast_str *buf = ast_str_thread_get(ts, maxlen);
00130    char *tmp = ast_str_buffer(buf);
00131    char q = ts == &escape_value_buf ? '\'' : '"';
00132 
00133    ast_str_reset(buf);
00134    *tmp++ = q; /* Initial quote */
00135    while ((*tmp++ = *param++)) {
00136       /* Did we just copy a quote? Then double it. */
00137       if (*(tmp - 1) == q) {
00138          *tmp++ = q;
00139       }
00140    }
00141    *tmp = '\0'; /* Terminate past NULL from copy */
00142    *(tmp - 1) = q; /* Replace original NULL with the quote */
00143    ast_str_update(buf);
00144 
00145    return ast_str_buffer(buf);
00146 }

static const char* sqlite3_escape_table ( const char *  param  )  [inline, static]

static const char* sqlite3_escape_value ( const char *  param  )  [inline, static]

static int static_realtime_cb ( void *  arg,
int  num_columns,
char **  values,
char **  columns 
) [static]

Definition at line 575 of file res_config_sqlite3.c.

References args, ast_category_append(), ast_category_destroy(), ast_category_new(), ast_config_internal_load(), ast_free, ast_log, ast_strdup, ast_variable_append(), ast_variable_new(), cfg_entry_args::cat, cfg_entry_args::cat_name, cfg_entry_args::cfg, COL_CATEGORY, COL_VAR_NAME, COL_VAR_VAL, cfg_entry_args::flags, LOG_WARNING, var, and cfg_entry_args::who_asked.

Referenced by realtime_sqlite3_load().

00576 {
00577    struct cfg_entry_args *args = arg;
00578    struct ast_variable *var;
00579 
00580    if (!strcmp(values[COL_VAR_NAME], "#include")) {
00581       struct ast_config *cfg;
00582       char *val;
00583 
00584       val = values[COL_VAR_VAL];
00585       if (!(cfg = ast_config_internal_load(val, args->cfg, args->flags, "", args->who_asked))) {
00586          ast_log(LOG_WARNING, "Unable to include %s\n", val);
00587          return SQLITE_ABORT;
00588       } else {
00589          args->cfg = cfg;
00590          return 0;
00591       }
00592    }
00593 
00594    if (!args->cat_name || strcmp(args->cat_name, values[COL_CATEGORY])) {
00595       if (!(args->cat = ast_category_new(values[COL_CATEGORY], "", 99999))) {
00596          ast_log(LOG_WARNING, "Unable to allocate category\n");
00597          return SQLITE_ABORT;
00598       }
00599 
00600       ast_free(args->cat_name);
00601 
00602       if (!(args->cat_name = ast_strdup(values[COL_CATEGORY]))) {
00603          ast_category_destroy(args->cat);
00604          return SQLITE_ABORT;
00605       }
00606 
00607       ast_category_append(args->cfg, args->cat);
00608    }
00609 
00610    if (!(var = ast_variable_new(values[COL_VAR_NAME], values[COL_VAR_VAL], ""))) {
00611       ast_log(LOG_WARNING, "Unable to allocate variable\n");
00612       return SQLITE_ABORT;
00613    }
00614 
00615    ast_variable_append(args->cat, var);
00616 
00617    return 0;
00618 }

static int stop_batch_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 236 of file res_config_sqlite3.c.

References CMP_MATCH, and db_stop_batch().

Referenced by unload_module().

00237 {
00238    struct realtime_sqlite3_db *db = obj;
00239 
00240    db_stop_batch(db);
00241    return CMP_MATCH;
00242 }

static int str_cmp_fn ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 988 of file res_config_sqlite3.c.

Referenced by realtime_sqlite3_require().

00988                                                        {
00989    return !strcasecmp((const char *) obj, (const char *) arg);
00990 }

static int str_hash_fn ( const void *  obj,
const int  flags 
) [static]

Definition at line 983 of file res_config_sqlite3.c.

References ast_str_hash().

Referenced by realtime_sqlite3_require().

00984 {
00985    return ast_str_hash((const char *) obj);
00986 }

static int str_to_requirements ( const char *  data  )  [static]

Definition at line 271 of file res_config_sqlite3.c.

References REALTIME_SQLITE3_REQ_CHAR, REALTIME_SQLITE3_REQ_CLOSE, and REALTIME_SQLITE3_REQ_WARN.

Referenced by new_realtime_sqlite3_db().

00272 {
00273    if (!strcasecmp(data, "createclose")) {
00274       return REALTIME_SQLITE3_REQ_CLOSE;
00275    } else if (!strcasecmp(data, "createchar")) {
00276       return REALTIME_SQLITE3_REQ_CHAR;
00277    }
00278    /* default */
00279    return REALTIME_SQLITE3_REQ_WARN;
00280 }

static void trace_cb ( void *  arg,
const char *  sql 
) [static]

Note:
Since this is called while a query is executing, we should already hold the db lock

Definition at line 283 of file res_config_sqlite3.c.

References ast_debug, and realtime_sqlite3_db::name.

Referenced by db_open(), and update_realtime_sqlite3_db().

00284 {
00285    struct realtime_sqlite3_db *db = arg;
00286    ast_debug(3, "DB: %s SQL: %s\n", db->name, sql);
00287 }

static void unlink_dirty_databases ( void   )  [static]

Definition at line 266 of file res_config_sqlite3.c.

References ao2_callback, is_dirty_cb(), NULL, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

Referenced by parse_config().

static int unload_module ( void   )  [static]

static void unref_db ( struct realtime_sqlite3_db **  db  )  [static]

Definition at line 230 of file res_config_sqlite3.c.

References ao2_ref, and NULL.

Referenced by db_sync_thread(), new_realtime_sqlite3_db(), parse_config(), realtime_sqlite3_require(), and update_realtime_sqlite3_db().

00231 {
00232    ao2_ref(*db, -1);
00233    *db = NULL;
00234 }

static int update_realtime_sqlite3_db ( struct realtime_sqlite3_db db,
struct ast_config config,
const char *  cat 
) [static]

Update an existing db object based on config data.

Parameters:
db The database object to update
config The configuration data with which to update the db
cat The config category (which becomes db->name)

Definition at line 412 of file res_config_sqlite3.c.

References ast_string_field_set, realtime_sqlite3_db::batch, db_open(), db_start_batch(), db_stop_batch(), realtime_sqlite3_db::debug, realtime_sqlite3_db::dirty, realtime_sqlite3_db::filename, realtime_sqlite3_db::handle, new_realtime_sqlite3_db(), NULL, realtime_sqlite3_db::requirements, trace_cb(), and unref_db().

Referenced by parse_config().

00413 {
00414    struct realtime_sqlite3_db *new;
00415 
00416    if (!(new = new_realtime_sqlite3_db(config, cat))) {
00417       return -1;
00418    }
00419 
00420    /* Copy fields that don't need anything special done on change */
00421    db->requirements = new->requirements;
00422 
00423    /* Handle changes that require immediate behavior modification */
00424    if (db->debug != new->debug) {
00425       if (db->debug) {
00426          sqlite3_trace(db->handle, NULL, NULL);
00427       } else {
00428          sqlite3_trace(db->handle, trace_cb, db);
00429       }
00430       db->debug = new->debug;
00431    }
00432 
00433    if (strcmp(db->filename, new->filename)) {
00434       sqlite3_close(db->handle);
00435       ast_string_field_set(db, filename, new->filename);
00436       db_open(db); /* Also handles setting appropriate debug on new handle */
00437    }
00438 
00439    if (db->batch != new->batch) {
00440       if (db->batch == 0) {
00441          db->batch = new->batch;
00442          db_start_batch(db);
00443       } else if (new->batch == 0) {
00444          db->batch = new->batch;
00445          db_stop_batch(db);
00446       }
00447       db->batch = new->batch;
00448    }
00449 
00450    db->dirty = 0;
00451    unref_db(&new);
00452 
00453    return 0;
00454 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "SQLite 3 realtime config engine" , .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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_REALTIME_DRIVER, } [static]

Definition at line 1211 of file res_config_sqlite3.c.

Definition at line 1211 of file res_config_sqlite3.c.

ast_mutex_t config_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

Definition at line 111 of file res_config_sqlite3.c.

Definition at line 108 of file res_config_sqlite3.c.

struct ast_threadstorage escape_column_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_escape_column_buf , .custom_init = NULL , } [static]

Definition at line 115 of file res_config_sqlite3.c.

Referenced by sqlite3_escape_column(), and sqlite3_escape_column_op().

struct ast_threadstorage escape_table_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_escape_table_buf , .custom_init = NULL , } [static]

Definition at line 114 of file res_config_sqlite3.c.

Referenced by sqlite3_escape_table().

struct ast_threadstorage escape_value_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_escape_value_buf , .custom_init = NULL , } [static]

Definition at line 116 of file res_config_sqlite3.c.

Referenced by sqlite3_escape_string_helper(), and sqlite3_escape_value().

Definition at line 73 of file res_config_sqlite3.c.

const char* static_sql = "SELECT category, var_name, var_val FROM \"%q\" WHERE filename = %Q AND commented = 0 ORDER BY cat_metric ASC, var_metric ASC" [static]

Note:
It is important that the COL_* enum matches the order of the columns selected in static_sql

Definition at line 567 of file res_config_sqlite3.c.


Generated on Thu Apr 16 06:32:47 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6