Thu Apr 28 2011 17:14:01

Asterisk developer's documentation


res_config_sqlite.c File Reference

res_config_sqlite module. More...

#include "asterisk.h"
#include <sqlite.h>
#include "asterisk/logger.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/cdr.h"
#include "asterisk/cli.h"
#include "asterisk/lock.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/linkedlists.h"
Include dependency graph for res_config_sqlite.c:

Go to the source code of this file.

Data Structures

struct  sqlite_cache_tables::_columns
struct  cfg_entry_args
struct  rt_cfg_entry_args
struct  rt_multi_cfg_entry_args
struct  sqlite_cache_columns
struct  sqlite_cache_tables
struct  sqlite_tables

Defines

#define MACRO_BEGIN   do {
#define MACRO_END   } while (0)
#define release_table(a)   AST_RWLIST_UNLOCK(&((a)->columns))
#define RES_CONFIG_SQLITE_BEGIN
#define RES_CONFIG_SQLITE_CONF_FILE   "res_config_sqlite.conf"
#define RES_CONFIG_SQLITE_DESCRIPTION   "Resource Module for SQLite 2"
#define RES_CONFIG_SQLITE_DRIVER   "sqlite"
#define RES_CONFIG_SQLITE_END(error)
#define RES_CONFIG_SQLITE_MAX_LOOPS   10
#define RES_CONFIG_SQLITE_NAME   "res_config_sqlite"
#define SET_VAR(config, to, from)
#define sql_get_config_table
#define sql_table_structure   "SELECT sql FROM sqlite_master WHERE type='table' AND tbl_name='%s'"

Enumerations

enum  {
  RES_CONFIG_SQLITE_CONFIG_ID, RES_CONFIG_SQLITE_CONFIG_CAT_METRIC, RES_CONFIG_SQLITE_CONFIG_VAR_METRIC, RES_CONFIG_SQLITE_CONFIG_COMMENTED,
  RES_CONFIG_SQLITE_CONFIG_FILENAME, RES_CONFIG_SQLITE_CONFIG_CATEGORY, RES_CONFIG_SQLITE_CONFIG_VAR_NAME, RES_CONFIG_SQLITE_CONFIG_VAR_VAL,
  RES_CONFIG_SQLITE_CONFIG_COLUMNS
}

Functions

static void __fini_sqlite_tables (void)
static void __init_sqlite_tables (void)
static void __reg_module (void)
static void __unreg_module (void)
static int add_cfg_entry (void *arg, int argc, char **argv, char **columnNames)
 SQLite callback function for static configuration.
static int add_rt_cfg_entry (void *arg, int argc, char **argv, char **columnNames)
 SQLite callback function for RealTime configuration.
static int add_rt_multi_cfg_entry (void *arg, int argc, char **argv, char **columnNames)
 SQLite callback function for RealTime configuration.
 AST_THREADSTORAGE_CUSTOM_SCOPE (where_buf, NULL, ast_free_ptr, static)
 AST_THREADSTORAGE_CUSTOM_SCOPE (sql_buf, NULL, ast_free_ptr, static)
static int cdr_handler (struct ast_cdr *cdr)
 Asterisk callback function for CDR support.
static int check_vars (void)
static struct ast_configconfig_handler (const char *database, const char *table, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl, const char *who_asked)
 Asterisk callback function for static configuration.
static struct sqlite_cache_tablesfind_table (const char *tablename)
static int find_table_cb (void *vtblptr, int argc, char **argv, char **columnNames)
static void free_table (struct sqlite_cache_tables *tblptr)
static size_t get_params (va_list ap, const char ***params_ptr, const char ***vals_ptr, int warn)
 Helper function to parse a va_list object into 2 dynamic arrays of strings, parameters and values.
static char * handle_cli_show_sqlite_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Asterisk callback function for the CLI status command.
static char * handle_cli_sqlite_show_tables (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int load_config (void)
 Load the configuration file.
static int load_module (void)
static int realtime_destroy_handler (const char *database, const char *table, const char *keyfield, const char *entity, va_list ap)
 Asterisk callback function for RealTime configuration (destroys variable).
static struct ast_variablerealtime_handler (const char *database, const char *table, va_list ap)
 Asterisk callback function for RealTime configuration.
static struct ast_configrealtime_multi_handler (const char *database, const char *table, va_list ap)
 Asterisk callback function for RealTime configuration.
static int realtime_require_handler (const char *database, const char *table, va_list ap)
static int realtime_store_handler (const char *database, const char *table, va_list ap)
 Asterisk callback function for RealTime configuration (variable create/store).
static int realtime_unload_handler (const char *unused, const char *tablename)
static int realtime_update2_handler (const char *database, const char *table, va_list ap)
static int realtime_update_handler (const char *database, const char *table, const char *keyfield, const char *entity, va_list ap)
 Asterisk callback function for RealTime configuration (variable update).
static int set_var (char **var, const char *name, const char *value)
 Allocate a variable.
static void unload_config (void)
 Free resources related to configuration.
static int unload_module (void)

Variables

static struct ast_module_info
__MODULE_INFO_SECTION 
__mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Realtime SQLite configuration" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, }
static struct ast_module_infoast_module_info = &__mod_info
static int cdr_registered
static char * cdr_table
static struct ast_cli_entry cli_status []
static int cli_status_registered
static char * config_table
static sqlite * db
static char * dbfile
static ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
static char * sql_create_cdr_table = ");"
static struct ast_config_engine sqlite_engine
static struct sqlite_tables sqlite_tables
static int use_cdr

Detailed Description

res_config_sqlite module.

Definition in file res_config_sqlite.c.


Define Documentation

#define MACRO_BEGIN   do {

Definition at line 93 of file res_config_sqlite.c.

#define MACRO_END   } while (0)

Definition at line 94 of file res_config_sqlite.c.

#define release_table (   a)    AST_RWLIST_UNLOCK(&((a)->columns))

Definition at line 706 of file res_config_sqlite.c.

Referenced by cdr_handler().

#define RES_CONFIG_SQLITE_BEGIN
#define RES_CONFIG_SQLITE_CONF_FILE   "res_config_sqlite.conf"

Definition at line 99 of file res_config_sqlite.c.

Referenced by load_config().

#define RES_CONFIG_SQLITE_DESCRIPTION   "Resource Module for SQLite 2"

Definition at line 98 of file res_config_sqlite.c.

Referenced by load_module().

#define RES_CONFIG_SQLITE_DRIVER   "sqlite"

Definition at line 97 of file res_config_sqlite.c.

#define RES_CONFIG_SQLITE_END (   error)
Value:
if (error != SQLITE_BUSY)  \
         break;                  \
      usleep(1000);                 \
   }                       \
MACRO_END;

Macro used after executing a query.

See also:
RES_CONFIG_SQLITE_MAX_LOOPS.

Definition at line 163 of file res_config_sqlite.c.

Referenced by cdr_handler(), config_handler(), load_module(), realtime_destroy_handler(), realtime_handler(), realtime_multi_handler(), realtime_store_handler(), realtime_update2_handler(), and realtime_update_handler().

#define RES_CONFIG_SQLITE_MAX_LOOPS   10

Maximum number of loops before giving up executing a query. Calls to sqlite_xxx() functions which can return SQLITE_BUSY are enclosed by RES_CONFIG_SQLITE_BEGIN and RES_CONFIG_SQLITE_END, e.g.

 char *errormsg;
 int error;
 RES_CONFIG_SQLITE_BEGIN
	 error = sqlite_exec(db, query, NULL, NULL, &errormsg);
 RES_CONFIG_SQLITE_END(error)
 if (error)
	 ...;
 

Definition at line 145 of file res_config_sqlite.c.

#define RES_CONFIG_SQLITE_NAME   "res_config_sqlite"

Definition at line 96 of file res_config_sqlite.c.

Referenced by load_module(), and unload_module().

#define SET_VAR (   config,
  to,
  from 
)

Definition at line 113 of file res_config_sqlite.c.

Referenced by load_config().

#define sql_get_config_table
Value:
"SELECT *" \
   "  FROM '%q'" \
   "  WHERE filename = '%q' AND commented = 0" \
   "  ORDER BY cat_metric ASC, var_metric ASC;"

SQL query format to fetch the static configuration of a file. Rows must be sorted by category.

See also:
add_cfg_entry()

Definition at line 566 of file res_config_sqlite.c.

Referenced by config_handler().

#define sql_table_structure   "SELECT sql FROM sqlite_master WHERE type='table' AND tbl_name='%s'"

SQL query format to describe the table structure

Definition at line 558 of file res_config_sqlite.c.

Referenced by find_table().


Enumeration Type Documentation

anonymous enum
Enumerator:
RES_CONFIG_SQLITE_CONFIG_ID 
RES_CONFIG_SQLITE_CONFIG_CAT_METRIC 
RES_CONFIG_SQLITE_CONFIG_VAR_METRIC 
RES_CONFIG_SQLITE_CONFIG_COMMENTED 
RES_CONFIG_SQLITE_CONFIG_FILENAME 
RES_CONFIG_SQLITE_CONFIG_CATEGORY 
RES_CONFIG_SQLITE_CONFIG_VAR_NAME 
RES_CONFIG_SQLITE_CONFIG_VAR_VAL 
RES_CONFIG_SQLITE_CONFIG_COLUMNS 

Definition at line 101 of file res_config_sqlite.c.


Function Documentation

static void __fini_sqlite_tables ( void  ) [static]

Definition at line 524 of file res_config_sqlite.c.

:00:00',\n"
static void __init_sqlite_tables ( void  ) [static]

Definition at line 524 of file res_config_sqlite.c.

:00:00',\n"
static void __reg_module ( void  ) [static]

Definition at line 1870 of file res_config_sqlite.c.

static void __unreg_module ( void  ) [static]

Definition at line 1870 of file res_config_sqlite.c.

static int add_cfg_entry ( void *  arg,
int  argc,
char **  argv,
char **  columnNames 
) [static]

SQLite callback function for static configuration.

This function is passed to the SQLite engine as a callback function to parse a row and store it in a struct ast_config object. It relies on resulting rows being sorted by category.

Parameters:
arga pointer to a struct cfg_entry_args object
argcnumber of columns
argvvalues in the row
columnNamesnames and types of the columns
Return values:
0on success
1if an error occurred
See also:
cfg_entry_args
sql_get_config_table
config_handler()

Definition at line 853 of file res_config_sqlite.c.

References 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, cfg_entry_args::flags, LOG_WARNING, RES_CONFIG_SQLITE_CONFIG_CATEGORY, RES_CONFIG_SQLITE_CONFIG_COLUMNS, RES_CONFIG_SQLITE_CONFIG_VAR_NAME, RES_CONFIG_SQLITE_CONFIG_VAR_VAL, val, var, and cfg_entry_args::who_asked.

Referenced by config_handler().

{
   struct cfg_entry_args *args;
   struct ast_variable *var;

   if (argc != RES_CONFIG_SQLITE_CONFIG_COLUMNS) {
      ast_log(LOG_WARNING, "Corrupt table\n");
      return 1;
   }

   args = arg;

   if (!strcmp(argv[RES_CONFIG_SQLITE_CONFIG_VAR_NAME], "#include")) {
      struct ast_config *cfg;
      char *val;

      val = argv[RES_CONFIG_SQLITE_CONFIG_VAR_VAL];
      cfg = ast_config_internal_load(val, args->cfg, args->flags, "", args->who_asked);

      if (!cfg) {
         ast_log(LOG_WARNING, "Unable to include %s\n", val);
         return 1;
      } else {
         args->cfg = cfg;
         return 0;
      }
   }

   if (!args->cat_name || strcmp(args->cat_name, argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY])) {
      args->cat = ast_category_new(argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY], "", 99999);

      if (!args->cat) {
         ast_log(LOG_WARNING, "Unable to allocate category\n");
         return 1;
      }

      ast_free(args->cat_name);
      args->cat_name = ast_strdup(argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY]);

      if (!args->cat_name) {
         ast_category_destroy(args->cat);
         return 1;
      }

      ast_category_append(args->cfg, args->cat);
   }

   var = ast_variable_new(argv[RES_CONFIG_SQLITE_CONFIG_VAR_NAME], argv[RES_CONFIG_SQLITE_CONFIG_VAR_VAL], "");

   if (!var) {
      ast_log(LOG_WARNING, "Unable to allocate variable");
      return 1;
   }

   ast_variable_append(args->cat, var);

   return 0;
}
static int add_rt_cfg_entry ( void *  arg,
int  argc,
char **  argv,
char **  columnNames 
) [static]

SQLite callback function for RealTime configuration.

This function is passed to the SQLite engine as a callback function to parse a row and store it in a linked list of struct ast_variable objects.

Parameters:
arga pointer to a struct rt_cfg_entry_args object
argcnumber of columns
argvvalues in the row
columnNamesnames and types of the columns
Return values:
0on success.
1if an error occurred.
See also:
rt_cfg_entry_args
realtime_handler()

Definition at line 1001 of file res_config_sqlite.c.

References ast_variable_new(), rt_cfg_entry_args::last, ast_variable::next, rt_cfg_entry_args::var, and var.

Referenced by realtime_handler().

{
   struct rt_cfg_entry_args *args;
   struct ast_variable *var;
   int i;

   args = arg;

   for (i = 0; i < argc; i++) {
      if (!argv[i])
         continue;

      if (!(var = ast_variable_new(columnNames[i], argv[i], "")))
         return 1;

      if (!args->var)
         args->var = var;

      if (!args->last)
         args->last = var;
      else {
         args->last->next = var;
         args->last = var;
      }
   }

   return 0;
}
static int add_rt_multi_cfg_entry ( void *  arg,
int  argc,
char **  argv,
char **  columnNames 
) [static]

SQLite callback function for RealTime configuration.

This function performs the same actions as add_rt_cfg_entry() except that the rt_multi_cfg_entry_args structure is designed to store categories in addition to variables.

Parameters:
arga pointer to a struct rt_multi_cfg_entry_args object
argcnumber of columns
argvvalues in the row
columnNamesnames and types of the columns
Return values:
0on success.
1if an error occurred.
See also:
rt_multi_cfg_entry_args
realtime_multi_handler()

Definition at line 1120 of file res_config_sqlite.c.

References ast_category_append(), ast_category_new(), ast_log(), ast_variable_append(), ast_variable_new(), rt_multi_cfg_entry_args::cfg, rt_multi_cfg_entry_args::initfield, LOG_ERROR, LOG_WARNING, and var.

Referenced by realtime_multi_handler().

{
   struct rt_multi_cfg_entry_args *args;
   struct ast_category *cat;
   struct ast_variable *var;
   char *cat_name;
   size_t i;

   args = arg;
   cat_name = NULL;

   /*
    * cat_name should always be set here, since initfield is forged from
    * params[0] in realtime_multi_handler(), which is a search parameter
    * of the SQL query.
    */
   for (i = 0; i < argc; i++) {
      if (!strcmp(args->initfield, columnNames[i]))
         cat_name = argv[i];
   }

   if (!cat_name) {
      ast_log(LOG_ERROR, "Bogus SQL results, cat_name is NULL !\n");
      return 1;
   }

   if (!(cat = ast_category_new(cat_name, "", 99999))) {
      ast_log(LOG_WARNING, "Unable to allocate category\n");
      return 1;
   }

   ast_category_append(args->cfg, cat);

   for (i = 0; i < argc; i++) {
      if (!argv[i] || !strcmp(args->initfield, columnNames[i]))
         continue;

      if (!(var = ast_variable_new(columnNames[i], argv[i], ""))) {
         ast_log(LOG_WARNING, "Unable to allocate variable\n");
         return 1;
      }

      ast_variable_append(cat, var);
   }

   return 0;
}
AST_THREADSTORAGE_CUSTOM_SCOPE ( where_buf  ,
NULL  ,
ast_free_ptr  ,
static   
)
AST_THREADSTORAGE_CUSTOM_SCOPE ( sql_buf  ,
NULL  ,
ast_free_ptr  ,
static   
)
static int cdr_handler ( struct ast_cdr cdr) [static]

Asterisk callback function for CDR support.

Parameters:
cdrthe CDR entry Asterisk sends us.

Asterisk will call this function each time a CDR entry must be logged if CDR support is enabled.

Return values:
0on success
1if an error occurred

Definition at line 787 of file res_config_sqlite.c.

References ast_cdr_getvar(), ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_RWLIST_TRAVERSE, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), sqlite_cache_tables::columns, find_table(), first, sqlite_cache_columns::isint, LOG_ERROR, LOG_WARNING, mutex, sqlite_cache_columns::name, release_table, RES_CONFIG_SQLITE_BEGIN, RES_CONFIG_SQLITE_END, and S_OR.

Referenced by load_module().

{
   char *errormsg = NULL, *tmp, workspace[500];
   int error, scannum;
   struct sqlite_cache_tables *tbl = find_table(cdr_table);
   struct sqlite_cache_columns *col;
   struct ast_str *sql1 = ast_str_create(160), *sql2 = ast_str_create(16);
   int first = 1;

   if (!tbl) {
      ast_log(LOG_WARNING, "No such table: %s\n", cdr_table);
      return -1;
   }

   ast_str_set(&sql1, 0, "INSERT INTO %s (", cdr_table);
   ast_str_set(&sql2, 0, ") VALUES (");

   AST_RWLIST_TRAVERSE(&(tbl->columns), col, list) {
      if (col->isint) {
         ast_cdr_getvar(cdr, col->name, &tmp, workspace, sizeof(workspace), 0, 1);
         if (!tmp) {
            continue;
         }
         if (sscanf(tmp, "%30d", &scannum) == 1) {
            ast_str_append(&sql1, 0, "%s%s", first ? "" : ",", col->name);
            ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", scannum);
         }
      } else {
         ast_cdr_getvar(cdr, col->name, &tmp, workspace, sizeof(workspace), 0, 0);
         if (!tmp) {
            continue;
         }
         ast_str_append(&sql1, 0, "%s%s", first ? "" : ",", col->name);
         tmp = sqlite_mprintf("%Q", tmp);
         ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", tmp);
         sqlite_freemem(tmp);
      }
      first = 0;
   }
   release_table(tbl);

   ast_str_append(&sql1, 0, "%s)", ast_str_buffer(sql2));
   ast_free(sql2);

   ast_debug(1, "SQL query: %s\n", ast_str_buffer(sql1));

   ast_mutex_lock(&mutex);

   RES_CONFIG_SQLITE_BEGIN
      error = sqlite_exec(db, ast_str_buffer(sql1), NULL, NULL, &errormsg);
   RES_CONFIG_SQLITE_END(error)

   ast_mutex_unlock(&mutex);

   ast_free(sql1);

   if (error) {
      ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
      sqlite_freemem(errormsg);
      return 1;
   }
   sqlite_freemem(errormsg);

   return 0;
}
static int check_vars ( void  ) [static]

Definition at line 723 of file res_config_sqlite.c.

References ast_log(), and LOG_ERROR.

Referenced by load_config().

{
   if (!dbfile) {
      ast_log(LOG_ERROR, "Required parameter undefined: dbfile\n");
      return 1;
   }

   use_cdr = (cdr_table != NULL);

   return 0;
}
static struct ast_config * config_handler ( const char *  database,
const char *  table,
const char *  file,
struct ast_config cfg,
struct ast_flags  flags,
const char *  suggested_incl,
const char *  who_asked 
) [static, read]

Asterisk callback function for static configuration.

Asterisk will call this function when it loads its static configuration, which usually happens at startup and reload.

Parameters:
databasethe database to use (ignored)
tablethe table to use
filethe file to load from the database
cfgthe struct ast_config object to use when storing variables
flagsOptional flags. Not used.
suggested_inclsuggest include.
Return values:
cfgobject
NULLif an error occurred
See also:
add_cfg_entry()

Definition at line 912 of file res_config_sqlite.c.

References add_cfg_entry(), ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), cfg_entry_args::cat, cfg_entry_args::cat_name, cfg_entry_args::cfg, config_table, cfg_entry_args::flags, LOG_ERROR, LOG_WARNING, mutex, RES_CONFIG_SQLITE_BEGIN, RES_CONFIG_SQLITE_END, S_OR, sql_get_config_table, and cfg_entry_args::who_asked.

{
   struct cfg_entry_args args;
   char *query, *errormsg = NULL;
   int error;

   if (!config_table) {
      if (!table) {
         ast_log(LOG_ERROR, "Table name unspecified\n");
         return NULL;
      }
   } else
      table = config_table;

   query = sqlite_mprintf(sql_get_config_table, table, file);

   if (!query) {
      ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
      return NULL;
   }

   ast_debug(1, "SQL query: %s\n", query);
   args.cfg = cfg;
   args.cat = NULL;
   args.cat_name = NULL;
   args.flags = flags;
   args.who_asked = who_asked;

   ast_mutex_lock(&mutex);

   RES_CONFIG_SQLITE_BEGIN
      error = sqlite_exec(db, query, add_cfg_entry, &args, &errormsg);
   RES_CONFIG_SQLITE_END(error)

   ast_mutex_unlock(&mutex);

   ast_free(args.cat_name);
   sqlite_freemem(query);

   if (error) {
      ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
      sqlite_freemem(errormsg);
      return NULL;
   }
   sqlite_freemem(errormsg);

   return cfg;
}
static struct sqlite_cache_tables* find_table ( const char *  tablename) [static, read]

Definition at line 641 of file res_config_sqlite.c.

References asprintf, ast_calloc, ast_debug, ast_free, AST_LIST_EMPTY, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_RWLIST_HEAD_INIT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, sqlite_cache_tables::columns, errno, find_table_cb(), free_table(), LOG_ERROR, LOG_WARNING, mutex, sqlite_cache_tables::name, and sql_table_structure.

Referenced by cdr_handler(), and realtime_require_handler().

{
   struct sqlite_cache_tables *tblptr;
   int i, err;
   char *sql, *errstr = NULL;

   AST_RWLIST_RDLOCK(&sqlite_tables);

   for (i = 0; i < 2; i++) {
      AST_RWLIST_TRAVERSE(&sqlite_tables, tblptr, list) {
         if (strcmp(tblptr->name, tablename) == 0) {
            break;
         }
      }
      if (tblptr) {
         AST_RWLIST_RDLOCK(&(tblptr->columns));
         AST_RWLIST_UNLOCK(&sqlite_tables);
         return tblptr;
      }

      if (i == 0) {
         AST_RWLIST_UNLOCK(&sqlite_tables);
         AST_RWLIST_WRLOCK(&sqlite_tables);
      }
   }

   /* Table structure not cached; build the structure now */
   if (asprintf(&sql, sql_table_structure, tablename) < 0) {
      ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
      sql = NULL;
   }
   if (!(tblptr = ast_calloc(1, sizeof(*tblptr) + strlen(tablename) + 1))) {
      AST_RWLIST_UNLOCK(&sqlite_tables);
      ast_log(LOG_ERROR, "Memory error.  Cannot cache table '%s'\n", tablename);
      return NULL;
   }
   tblptr->name = (char *)tblptr + sizeof(*tblptr);
   strcpy(tblptr->name, tablename); /* SAFE */
   AST_RWLIST_HEAD_INIT(&(tblptr->columns));

   ast_debug(1, "About to query table structure: %s\n", sql);

   ast_mutex_lock(&mutex);
   if ((err = sqlite_exec(db, sql, find_table_cb, tblptr, &errstr))) {
      ast_mutex_unlock(&mutex);
      ast_log(LOG_WARNING, "SQLite error %d: %s\n", err, errstr);
      ast_free(errstr);
      free_table(tblptr);
      AST_RWLIST_UNLOCK(&sqlite_tables);
      return NULL;
   }
   ast_mutex_unlock(&mutex);

   if (AST_LIST_EMPTY(&(tblptr->columns))) {
      free_table(tblptr);
      AST_RWLIST_UNLOCK(&sqlite_tables);
      return NULL;
   }

   AST_RWLIST_INSERT_TAIL(&sqlite_tables, tblptr, list);
   AST_RWLIST_RDLOCK(&(tblptr->columns));
   AST_RWLIST_UNLOCK(&sqlite_tables);
   return tblptr;
}
static int find_table_cb ( void *  vtblptr,
int  argc,
char **  argv,
char **  columnNames 
) [static]

Definition at line 586 of file res_config_sqlite.c.

References AST_APP_ARG, ast_calloc, ast_debug, AST_DECLARE_APP_ARGS, AST_LIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, ast_skip_blanks(), AST_STANDARD_APP_ARGS, ast_strdupa, sqlite_cache_tables::columns, sqlite_cache_columns::isint, sqlite_cache_columns::name, strcasestr(), and sqlite_cache_columns::type.

Referenced by find_table().

{
   struct sqlite_cache_tables *tblptr = vtblptr;
   char *sql = ast_strdupa(argv[0]), *start, *end, *type, *remainder;
   int i;
   AST_DECLARE_APP_ARGS(fie,
      AST_APP_ARG(ld)[100]; /* This means we support up to 100 columns per table */
   );
   struct sqlite_cache_columns *col;

   /* This is really fun.  We get to parse an SQL statement to figure out
    * what columns are in the table.
    */
   if ((start = strchr(sql, '(')) && (end = strrchr(sql, ')'))) {
      start++;
      *end = '\0';
   } else {
      /* Abort */
      return -1;
   }

   AST_STANDARD_APP_ARGS(fie, start);
   for (i = 0; i < fie.argc; i++) {
      fie.ld[i] = ast_skip_blanks(fie.ld[i]);
      ast_debug(5, "Found field: %s\n", fie.ld[i]);
      if (strncasecmp(fie.ld[i], "PRIMARY KEY", 11) == 0 && (start = strchr(fie.ld[i], '(')) && (end = strchr(fie.ld[i], ')'))) {
         *end = '\0';
         AST_RWLIST_TRAVERSE(&(tblptr->columns), col, list) {
            if (strcasecmp(start + 1, col->name) == 0 && strcasestr(col->type, "INTEGER")) {
               col->isint = 1;
            }
         }
         continue;
      }
      /* type delimiter could be any space character */
      for (type = fie.ld[i]; *type > 32; type++);
      *type++ = '\0';
      type = ast_skip_blanks(type);
      for (remainder = type; *remainder > 32; remainder++);
      *remainder = '\0';
      if (!(col = ast_calloc(1, sizeof(*col) + strlen(fie.ld[i]) + strlen(type) + 2))) {
         return -1;
      }
      col->name = (char *)col + sizeof(*col);
      col->type = (char *)col + sizeof(*col) + strlen(fie.ld[i]) + 1;
      strcpy(col->name, fie.ld[i]); /* SAFE */
      strcpy(col->type, type); /* SAFE */
      if (strcasestr(col->type, "INTEGER") && strcasestr(col->type, "PRIMARY KEY")) {
         col->isint = 1;
      }
      AST_LIST_INSERT_TAIL(&(tblptr->columns), col, list);
   }
   return 0;
}
static void free_table ( struct sqlite_cache_tables tblptr) [static]

Definition at line 572 of file res_config_sqlite.c.

References ast_free, AST_RWLIST_HEAD_DESTROY, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and sqlite_cache_tables::columns.

Referenced by find_table(), realtime_unload_handler(), and unload_config().

{
   struct sqlite_cache_columns *col;

   /* Obtain a write lock to ensure there are no read locks outstanding */
   AST_RWLIST_WRLOCK(&(tblptr->columns));
   while ((col = AST_RWLIST_REMOVE_HEAD(&(tblptr->columns), list))) {
      ast_free(col);
   }
   AST_RWLIST_UNLOCK(&(tblptr->columns));
   AST_RWLIST_HEAD_DESTROY(&(tblptr->columns));
   ast_free(tblptr);
}
static size_t get_params ( va_list  ap,
const char ***  params_ptr,
const char ***  vals_ptr,
int  warn 
) [static]

Helper function to parse a va_list object into 2 dynamic arrays of strings, parameters and values.

ap must have the following format : param1 val1 param2 val2 param3 val3 ... arguments will be extracted to create 2 arrays:

  • params : param1 param2 param3 ...
  • vals : val1 val2 val3 ...

The address of these arrays are stored in params_ptr and vals_ptr. It is the responsibility of the caller to release the memory of these arrays. It is considered an error that va_list has a null or odd number of strings.

Parameters:
apthe va_list object to parse
params_ptrwhere the address of the params array is stored
vals_ptrwhere the address of the vals array is stored
Return values:
thenumber of elements in the arrays (which have the same size).
0if an error occurred.

Definition at line 962 of file res_config_sqlite.c.

References ast_free, ast_log(), ast_realloc, LOG_WARNING, and val.

Referenced by realtime_destroy_handler(), realtime_handler(), realtime_multi_handler(), realtime_store_handler(), and realtime_update_handler().

{
   const char **tmp, *param, *val, **params, **vals;
   size_t params_count;

   params = NULL;
   vals = NULL;
   params_count = 0;

   while ((param = va_arg(ap, const char *)) && (val = va_arg(ap, const char *))) {
      if (!(tmp = ast_realloc(params, (params_count + 1) * sizeof(char *)))) {
         ast_free(params);
         ast_free(vals);
         return 0;
      }
      params = tmp;

      if (!(tmp = ast_realloc(vals, (params_count + 1) * sizeof(char *)))) {
         ast_free(params);
         ast_free(vals);
         return 0;
      }
      vals = tmp;

      params[params_count] = param;
      vals[params_count] = val;
      params_count++;
   }

   if (params_count > 0) {
      *params_ptr = params;
      *vals_ptr = vals;
   } else if (warn) {
      ast_log(LOG_WARNING, "1 parameter and 1 value at least required\n");
   }

   return params_count;
}
static char * handle_cli_show_sqlite_status ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Asterisk callback function for the CLI status command.

Parameters:
eCLI command
cmd
aCLI argument list
Returns:
RESULT_SUCCESS

Definition at line 1665 of file res_config_sqlite.c.

References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

{
   switch (cmd) {
   case CLI_INIT:
      e->command = "sqlite show status";
      e->usage =
         "Usage: sqlite show status\n"
         "       Show status information about the SQLite 2 driver\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }

   if (a->argc != 3)
      return CLI_SHOWUSAGE;

   ast_cli(a->fd, "SQLite database path: %s\n", dbfile);
   ast_cli(a->fd, "config_table: ");

   if (!config_table)
      ast_cli(a->fd, "unspecified, must be present in extconfig.conf\n");
   else
      ast_cli(a->fd, "%s\n", config_table);

   ast_cli(a->fd, "cdr_table: ");

   if (!cdr_table)
      ast_cli(a->fd, "unspecified, CDR support disabled\n");
   else
      ast_cli(a->fd, "%s\n", cdr_table);

   return CLI_SUCCESS;
}
static char * handle_cli_sqlite_show_tables ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1699 of file res_config_sqlite.c.

References ast_cli_args::argc, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, sqlite_cache_tables::columns, ast_cli_entry::command, ast_cli_args::fd, sqlite_cache_columns::name, sqlite_cache_tables::name, sqlite_cache_columns::type, and ast_cli_entry::usage.

{
   struct sqlite_cache_tables *tbl;
   struct sqlite_cache_columns *col;
   int found = 0;

   switch (cmd) {
   case CLI_INIT:
      e->command = "sqlite show tables";
      e->usage =
         "Usage: sqlite show tables\n"
         "       Show table information about the SQLite 2 driver\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }

   if (a->argc != 3)
      return CLI_SHOWUSAGE;

   AST_RWLIST_RDLOCK(&sqlite_tables);
   AST_RWLIST_TRAVERSE(&sqlite_tables, tbl, list) {
      found++;
      ast_cli(a->fd, "Table %s:\n", tbl->name);
      AST_RWLIST_TRAVERSE(&(tbl->columns), col, list) {
         fprintf(stderr, "%s\n", col->name);
         ast_cli(a->fd, "  %20.20s  %-30.30s\n", col->name, col->type);
      }
   }
   AST_RWLIST_UNLOCK(&sqlite_tables);

   if (!found) {
      ast_cli(a->fd, "No tables currently in cache\n");
   }

   return CLI_SUCCESS;
}
static int load_config ( void  ) [static]

Load the configuration file.

See also:
unload_config()

This function sets dbfile, config_table, and cdr_table. It calls check_vars() before returning, and unload_config() if an error occurred.

Return values:
0on success
1if an error occurred

Definition at line 735 of file res_config_sqlite.c.

References ast_config_destroy(), ast_config_load, ast_log(), ast_variable_browse(), check_vars(), config, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, RES_CONFIG_SQLITE_CONF_FILE, SET_VAR, unload_config(), and var.

Referenced by load_module().

{
   struct ast_config *config;
   struct ast_variable *var;
   int error;
   struct ast_flags config_flags = { 0 };

   config = ast_config_load(RES_CONFIG_SQLITE_CONF_FILE, config_flags);

   if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
      ast_log(LOG_ERROR, "Unable to load " RES_CONFIG_SQLITE_CONF_FILE "\n");
      return 1;
   }

   for (var = ast_variable_browse(config, "general"); var; var = var->next) {
      if (!strcasecmp(var->name, "dbfile"))
         SET_VAR(config, dbfile, var);
      else if (!strcasecmp(var->name, "config_table"))
         SET_VAR(config, config_table, var);
      else if (!strcasecmp(var->name, "cdr_table")) {
         SET_VAR(config, cdr_table, var);
      } else
         ast_log(LOG_WARNING, "Unknown parameter : %s\n", var->name);
   }

   ast_config_destroy(config);
   error = check_vars();

   if (error) {
      unload_config();
      return 1;
   }

   return 0;
}
static int load_module ( void  ) [static]

Definition at line 1755 of file res_config_sqlite.c.

References ARRAY_LEN, ast_cdr_register(), ast_cli_register_multiple(), ast_config_engine_register(), ast_debug, ast_log(), AST_MODULE_LOAD_DECLINE, cdr_handler(), load_config(), LOG_ERROR, RES_CONFIG_SQLITE_BEGIN, RES_CONFIG_SQLITE_DESCRIPTION, RES_CONFIG_SQLITE_END, RES_CONFIG_SQLITE_NAME, S_OR, sql_create_cdr_table, and unload_module().

{
   char *errormsg = NULL;
   int error;

   db = NULL;
   cdr_registered = 0;
   cli_status_registered = 0;
   dbfile = NULL;
   config_table = NULL;
   cdr_table = NULL;
   error = load_config();

   if (error)
      return AST_MODULE_LOAD_DECLINE;

   if (!(db = sqlite_open(dbfile, 0660, &errormsg))) {
      ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
      sqlite_freemem(errormsg);
      unload_module();
      return 1;
   }

   sqlite_freemem(errormsg);
   errormsg = NULL;
   ast_config_engine_register(&sqlite_engine);

   if (use_cdr) {
      char *query;

/* \cond DOXYGEN_CAN_PARSE_THIS */
#undef QUERY
#define QUERY "SELECT COUNT(id) FROM %Q;"
/* \endcond */

      query = sqlite_mprintf(QUERY, cdr_table);

      if (!query) {
         ast_log(LOG_ERROR, "Unable to allocate SQL query\n");
         unload_module();
         return 1;
      }

      ast_debug(1, "SQL query: %s\n", query);

      RES_CONFIG_SQLITE_BEGIN
         error = sqlite_exec(db, query, NULL, NULL, &errormsg);
      RES_CONFIG_SQLITE_END(error)

      sqlite_freemem(query);

      if (error) {
         /*
          * Unexpected error.
          */
         if (error != SQLITE_ERROR) {
            ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
            sqlite_freemem(errormsg);
            unload_module();
            return 1;
         }

         sqlite_freemem(errormsg);
         errormsg = NULL;
         query = sqlite_mprintf(sql_create_cdr_table, cdr_table);

         if (!query) {
            ast_log(LOG_ERROR, "Unable to allocate SQL query\n");
            unload_module();
            return 1;
         }

         ast_debug(1, "SQL query: %s\n", query);

         RES_CONFIG_SQLITE_BEGIN
            error = sqlite_exec(db, query, NULL, NULL, &errormsg);
         RES_CONFIG_SQLITE_END(error)

         sqlite_freemem(query);

         if (error) {
            ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
            sqlite_freemem(errormsg);
            unload_module();
            return 1;
         }
      }
      sqlite_freemem(errormsg);
      errormsg = NULL;

      error = ast_cdr_register(RES_CONFIG_SQLITE_NAME, RES_CONFIG_SQLITE_DESCRIPTION, cdr_handler);

      if (error) {
         unload_module();
         return 1;
      }

      cdr_registered = 1;
   }

   error = ast_cli_register_multiple(cli_status, ARRAY_LEN(cli_status));

   if (error) {
      unload_module();
      return 1;
   }

   cli_status_registered = 1;

   return 0;
}
static int realtime_destroy_handler ( const char *  database,
const char *  table,
const char *  keyfield,
const char *  entity,
va_list  ap 
) [static]

Asterisk callback function for RealTime configuration (destroys variable).

Asterisk will call this function each time a variable has been destroyed internally and must be removed from the backend engine. keyfield and entity are used to find the row to delete, e.g. DELETE FROM table WHERE keyfield = 'entity';. ap is a list of parameters and values with the same format as the other realtime functions.

Parameters:
databasethe database to use (ignored)
tablethe table to use
keyfieldthe column of the matching cell
entitythe value of the matching cell
aplist of additional parameters for cell matching
Return values:
thenumber of affected rows.
-1if an error occurred.

Definition at line 1537 of file res_config_sqlite.c.

References ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), get_params(), LOG_WARNING, mutex, RES_CONFIG_SQLITE_BEGIN, RES_CONFIG_SQLITE_END, and S_OR.

{
   char *query, *errormsg = NULL, *tmp_str;
   const char **params = NULL, **vals = NULL;
   size_t params_count;
   int error, rows_num;
   size_t i;

   if (!table) {
      ast_log(LOG_WARNING, "Table name unspecified\n");
      return -1;
   }

   params_count = get_params(ap, &params, &vals, 0);

/* \cond DOXYGEN_CAN_PARSE_THIS */
#undef QUERY
#define QUERY "DELETE FROM '%q' WHERE"
/* \endcond */

   if (!(query = sqlite_mprintf(QUERY, table))) {
      ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
      ast_free(params);
      ast_free(vals);
      return -1;
   }

   for (i = 0; i < params_count; i++) {
      tmp_str = sqlite_mprintf("%s %q = '%q' AND", query, params[i], vals[i]);
      sqlite_freemem(query);

      if (!tmp_str) {
         ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
         ast_free(params);
         ast_free(vals);
         return -1;
      }

      query = tmp_str;
   }

   ast_free(params);
   ast_free(vals);
   if (!(tmp_str = sqlite_mprintf("%s %q = '%q';", query, keyfield, entity))) {
      ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
      sqlite_freemem(query);
      return -1;
   }
   sqlite_freemem(query);
   query = tmp_str;
   ast_debug(1, "SQL query: %s\n", query);

   ast_mutex_lock(&mutex);

   RES_CONFIG_SQLITE_BEGIN
      error = sqlite_exec(db, query, NULL, NULL, &errormsg);
   RES_CONFIG_SQLITE_END(error)

   if (!error) {
      rows_num = sqlite_changes(db);
   } else {
      rows_num = -1;
   }

   ast_mutex_unlock(&mutex);

   sqlite_freemem(query);

   if (error) {
      ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
   }
   sqlite_freemem(errormsg);

   return rows_num;
}
static struct ast_variable * realtime_handler ( const char *  database,
const char *  table,
va_list  ap 
) [static, read]

Asterisk callback function for RealTime configuration.

Asterisk will call this function each time it requires a variable through the RealTime architecture. ap is a list of parameters and values used to find a specific row, e.g one parameter "name" and one value "123" so that the SQL query becomes SELECT * FROM table WHERE name = '123';.

Parameters:
databasethe database to use (ignored)
tablethe table to use
aplist of parameters and values to match
Return values:
alinked list of struct ast_variable objects
NULLif an error occurred
See also:
add_rt_cfg_entry()

Definition at line 1030 of file res_config_sqlite.c.

References add_rt_cfg_entry(), ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_variables_destroy(), get_params(), rt_cfg_entry_args::last, LOG_WARNING, mutex, RES_CONFIG_SQLITE_BEGIN, RES_CONFIG_SQLITE_END, S_OR, and rt_cfg_entry_args::var.

{
   char *query, *errormsg = NULL, *op, *tmp_str;
   struct rt_cfg_entry_args args;
   const char **params, **vals;
   size_t params_count;
   int error;

   if (!table) {
      ast_log(LOG_WARNING, "Table name unspecified\n");
      return NULL;
   }

   params_count = get_params(ap, &params, &vals, 1);

   if (params_count == 0)
      return NULL;

   op = (strchr(params[0], ' ') == NULL) ? " =" : "";

/* \cond DOXYGEN_CAN_PARSE_THIS */
#undef QUERY
#define QUERY "SELECT * FROM '%q' WHERE%s %q%s '%q'"
/* \endcond */

   query = sqlite_mprintf(QUERY, table, !strcmp(config_table, table) ? " commented = 0 AND" : "", params[0], op, vals[0]);

   if (!query) {
      ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
      ast_free(params);
      ast_free(vals);
      return NULL;
   }

   if (params_count > 1) {
      size_t i;

      for (i = 1; i < params_count; i++) {
         op = (strchr(params[i], ' ') == NULL) ? " =" : "";
         tmp_str = sqlite_mprintf("%s AND %q%s '%q'", query, params[i], op, vals[i]);
         sqlite_freemem(query);

         if (!tmp_str) {
            ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
            ast_free(params);
            ast_free(vals);
            return NULL;
         }

         query = tmp_str;
      }
   }

   ast_free(params);
   ast_free(vals);

   tmp_str = sqlite_mprintf("%s LIMIT 1;", query);
   sqlite_freemem(query);

   if (!tmp_str) {
      ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
      return NULL;
   }

   query = tmp_str;
   ast_debug(1, "SQL query: %s\n", query);
   args.var = NULL;
   args.last = NULL;

   ast_mutex_lock(&mutex);

   RES_CONFIG_SQLITE_BEGIN
      error = sqlite_exec(db, query, add_rt_cfg_entry, &args, &errormsg);
   RES_CONFIG_SQLITE_END(error)

   ast_mutex_unlock(&mutex);

   sqlite_freemem(query);

   if (error) {
      ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
      sqlite_freemem(errormsg);
      ast_variables_destroy(args.var);
      return NULL;
   }
   sqlite_freemem(errormsg);

   return args.var;
}
static struct ast_config * realtime_multi_handler ( const char *  database,
const char *  table,
va_list  ap 
) [static, read]

Asterisk callback function for RealTime configuration.

This function performs the same actions as realtime_handler() except that it can store variables per category, and can return several categories.

Parameters:
databasethe database to use (ignored)
tablethe table to use
aplist of parameters and values to match
Return values:
astruct ast_config object storing categories and variables.
NULLif an error occurred.
See also:
add_rt_multi_cfg_entry()

Definition at line 1168 of file res_config_sqlite.c.

References add_rt_multi_cfg_entry(), ast_config_destroy(), ast_config_new(), ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdup, rt_multi_cfg_entry_args::cfg, get_params(), rt_multi_cfg_entry_args::initfield, LOG_WARNING, mutex, RES_CONFIG_SQLITE_BEGIN, RES_CONFIG_SQLITE_END, and S_OR.

{
   char *query, *errormsg = NULL, *op, *tmp_str, *initfield;
   struct rt_multi_cfg_entry_args args;
   const char **params, **vals;
   struct ast_config *cfg;
   size_t params_count;
   int error;

   if (!table) {
      ast_log(LOG_WARNING, "Table name unspecified\n");
      return NULL;
   }

   if (!(cfg = ast_config_new())) {
      ast_log(LOG_WARNING, "Unable to allocate configuration structure\n");
      return NULL;
   }

   if (!(params_count = get_params(ap, &params, &vals, 1))) {
      ast_config_destroy(cfg);
      return NULL;
   }

   if (!(initfield = ast_strdup(params[0]))) {
      ast_config_destroy(cfg);
      ast_free(params);
      ast_free(vals);
      return NULL;
   }

   tmp_str = strchr(initfield, ' ');

   if (tmp_str)
      *tmp_str = '\0';

   op = (!strchr(params[0], ' ')) ? " =" : "";

   /*
    * Asterisk sends us an already escaped string when searching for
    * "exten LIKE" (uh!). Handle it separately.
    */
   tmp_str = (!strcmp(vals[0], "\\_%")) ? "_%" : (char *)vals[0];

/* \cond DOXYGEN_CAN_PARSE_THIS */
#undef QUERY
#define QUERY "SELECT * FROM '%q' WHERE commented = 0 AND %q%s '%q'"
/* \endcond */

   if (!(query = sqlite_mprintf(QUERY, table, params[0], op, tmp_str))) {
      ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
      ast_config_destroy(cfg);
      ast_free(params);
      ast_free(vals);
      ast_free(initfield);
      return NULL;
   }

   if (params_count > 1) {
      size_t i;

      for (i = 1; i < params_count; i++) {
         op = (!strchr(params[i], ' ')) ? " =" : "";
         tmp_str = sqlite_mprintf("%s AND %q%s '%q'", query, params[i], op, vals[i]);
         sqlite_freemem(query);

         if (!tmp_str) {
            ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
            ast_config_destroy(cfg);
            ast_free(params);
            ast_free(vals);
            ast_free(initfield);
            return NULL;
         }

         query = tmp_str;
      }
   }

   ast_free(params);
   ast_free(vals);

   if (!(tmp_str = sqlite_mprintf("%s ORDER BY %q;", query, initfield))) {
      ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
      sqlite_freemem(query);
      ast_config_destroy(cfg);
      ast_free(initfield);
      return NULL;
   }

   sqlite_freemem(query);
   query = tmp_str;
   ast_debug(1, "SQL query: %s\n", query);
   args.cfg = cfg;
   args.initfield = initfield;

   ast_mutex_lock(&mutex);

   RES_CONFIG_SQLITE_BEGIN
      error = sqlite_exec(db, query, add_rt_multi_cfg_entry, &args, &errormsg);
   RES_CONFIG_SQLITE_END(error)

   ast_mutex_unlock(&mutex);

   sqlite_freemem(query);
   ast_free(initfield);

   if (error) {
      ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
      sqlite_freemem(errormsg);
      ast_config_destroy(cfg);
      return NULL;
   }
   sqlite_freemem(errormsg);

   return cfg;
}
static int realtime_require_handler ( const char *  database,
const char *  table,
va_list  ap 
) [static]

Definition at line 1614 of file res_config_sqlite.c.

References ast_log(), ast_rq_is_int(), AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, sqlite_cache_tables::columns, find_table(), sqlite_cache_columns::isint, LOG_WARNING, sqlite_cache_columns::name, and sqlite_cache_columns::type.

{
   struct sqlite_cache_tables *tbl = find_table(tablename);
   struct sqlite_cache_columns *col;
   char *elm;
   int type, size, res = 0;

   if (!tbl) {
      return -1;
   }

   while ((elm = va_arg(ap, char *))) {
      type = va_arg(ap, require_type);
      size = va_arg(ap, int);
      /* Check if the field matches the criteria */
      AST_RWLIST_TRAVERSE(&tbl->columns, col, list) {
         if (strcmp(col->name, elm) == 0) {
            /* SQLite only has two types - the 32-bit integer field that
             * is the key column, and everything else (everything else
             * being a string).
             */
            if (col->isint && !ast_rq_is_int(type)) {
               ast_log(LOG_WARNING, "Realtime table %s: column '%s' is an integer field, but Asterisk requires that it not be!\n", tablename, col->name);
               res = -1;
            }
            break;
         }
      }
      if (!col) {
         ast_log(LOG_WARNING, "Realtime table %s requires column '%s', but that column does not exist!\n", tablename, elm);
      }
   }
   AST_RWLIST_UNLOCK(&(tbl->columns));
   return res;
}
static int realtime_store_handler ( const char *  database,
const char *  table,
va_list  ap 
) [static]

Asterisk callback function for RealTime configuration (variable create/store).

Asterisk will call this function each time a variable has been created internally and must be stored in the backend engine. are used to find the row to update, e.g. ap is a list of parameters and values with the same format as the other realtime functions.

Parameters:
databasethe database to use (ignored)
tablethe table to use
aplist of parameters and new values to insert into the database
Return values:
therowid of inserted row.
-1if an error occurred.

Definition at line 1443 of file res_config_sqlite.c.

References ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), get_params(), LOG_WARNING, mutex, RES_CONFIG_SQLITE_BEGIN, RES_CONFIG_SQLITE_END, and S_OR.

{
   char *errormsg = NULL, *tmp_str, *tmp_keys = NULL, *tmp_keys2 = NULL, *tmp_vals = NULL, *tmp_vals2 = NULL;
   const char **params, **vals;
   size_t params_count;
   int error, rows_id;
   size_t i;

   if (!table) {
      ast_log(LOG_WARNING, "Table name unspecified\n");
      return -1;
   }

   if (!(params_count = get_params(ap, &params, &vals, 1)))
      return -1;

/* \cond DOXYGEN_CAN_PARSE_THIS */
#undef QUERY
#define QUERY "INSERT into '%q' (%s) VALUES (%s);"
/* \endcond */

   for (i = 0; i < params_count; i++) {
      if ( tmp_keys2 ) {
         tmp_keys = sqlite_mprintf("%s, %q", tmp_keys2, params[i]);
         sqlite_freemem(tmp_keys2);
      } else {
         tmp_keys = sqlite_mprintf("%q", params[i]);
      }
      if (!tmp_keys) {
         ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
         sqlite_freemem(tmp_vals);
         ast_free(params);
         ast_free(vals);
         return -1;
      }

      if ( tmp_vals2 ) {
         tmp_vals = sqlite_mprintf("%s, '%q'", tmp_vals2, vals[i]);
         sqlite_freemem(tmp_vals2);
      } else {
         tmp_vals = sqlite_mprintf("'%q'", vals[i]);
      }
      if (!tmp_vals) {
         ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
         sqlite_freemem(tmp_keys);
         ast_free(params);
         ast_free(vals);
         return -1;
      }


      tmp_keys2 = tmp_keys;
      tmp_vals2 = tmp_vals;
   }

   ast_free(params);
   ast_free(vals);

   if (!(tmp_str = sqlite_mprintf(QUERY, table, tmp_keys, tmp_vals))) {
      ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
      sqlite_freemem(tmp_keys);
      sqlite_freemem(tmp_vals);
      return -1;
   }

   sqlite_freemem(tmp_keys);
   sqlite_freemem(tmp_vals);

   ast_debug(1, "SQL query: %s\n", tmp_str);

   ast_mutex_lock(&mutex);

   RES_CONFIG_SQLITE_BEGIN
      error = sqlite_exec(db, tmp_str, NULL, NULL, &errormsg);
   RES_CONFIG_SQLITE_END(error)

   if (!error) {
      rows_id = sqlite_last_insert_rowid(db);
   } else {
      rows_id = -1;
   }

   ast_mutex_unlock(&mutex);

   sqlite_freemem(tmp_str);

   if (error) {
      ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
   }
   sqlite_freemem(errormsg);

   return rows_id;
}
static int realtime_unload_handler ( const char *  unused,
const char *  tablename 
) [static]
static int realtime_update2_handler ( const char *  database,
const char *  table,
va_list  ap 
) [static]

Definition at line 1369 of file res_config_sqlite.c.

References ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), first, LOG_ERROR, LOG_WARNING, mutex, RES_CONFIG_SQLITE_BEGIN, RES_CONFIG_SQLITE_END, and S_OR.

{
   char *errormsg = NULL, *tmp1, *tmp2;
   int error, rows_num, first = 1;
   struct ast_str *sql = ast_str_thread_get(&sql_buf, 100);
   struct ast_str *where = ast_str_thread_get(&where_buf, 100);
   const char *param, *value;

   if (!table) {
      ast_log(LOG_WARNING, "Table name unspecified\n");
      return -1;
   }

   if (!sql) {
      return -1;
   }

   ast_str_set(&sql, 0, "UPDATE %s SET", table);
   ast_str_set(&where, 0, " WHERE");

   while ((param = va_arg(ap, const char *))) {
      value = va_arg(ap, const char *);
      ast_str_append(&where, 0, "%s %s = %s",
         first ? "" : " AND",
         tmp1 = sqlite_mprintf("%q", param),
         tmp2 = sqlite_mprintf("%Q", value));
      sqlite_freemem(tmp1);
      sqlite_freemem(tmp2);
      first = 0;
   }

   if (first) {
      ast_log(LOG_ERROR, "No criteria specified on update to '%s@%s'!\n", table, database);
      return -1;
   }

   first = 1;
   while ((param = va_arg(ap, const char *))) {
      value = va_arg(ap, const char *);
      ast_str_append(&sql, 0, "%s %s = %s",
         first ? "" : ",",
         tmp1 = sqlite_mprintf("%q", param),
         tmp2 = sqlite_mprintf("%Q", value));
      sqlite_freemem(tmp1);
      sqlite_freemem(tmp2);
      first = 0;
   }

   ast_str_append(&sql, 0, " %s", ast_str_buffer(where));
   ast_debug(1, "SQL query: %s\n", ast_str_buffer(sql));

   ast_mutex_lock(&mutex);

   RES_CONFIG_SQLITE_BEGIN
      error = sqlite_exec(db, ast_str_buffer(sql), NULL, NULL, &errormsg);
   RES_CONFIG_SQLITE_END(error)

   if (!error) {
      rows_num = sqlite_changes(db);
   } else {
      rows_num = -1;
   }

   ast_mutex_unlock(&mutex);

   if (error) {
      ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
   }
   sqlite_freemem(errormsg);

   return rows_num;
}
static int realtime_update_handler ( const char *  database,
const char *  table,
const char *  keyfield,
const char *  entity,
va_list  ap 
) [static]

Asterisk callback function for RealTime configuration (variable update).

Asterisk will call this function each time a variable has been modified internally and must be updated in the backend engine. keyfield and entity are used to find the row to update, e.g. UPDATE table SET ... WHERE keyfield = 'entity';. ap is a list of parameters and values with the same format as the other realtime functions.

Parameters:
databasethe database to use (ignored)
tablethe table to use
keyfieldthe column of the matching cell
entitythe value of the matching cell
aplist of parameters and new values to update in the database
Return values:
thenumber of affected rows.
-1if an error occurred.

Definition at line 1287 of file res_config_sqlite.c.

References ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), get_params(), LOG_WARNING, mutex, RES_CONFIG_SQLITE_BEGIN, RES_CONFIG_SQLITE_END, and S_OR.

{
   char *query, *errormsg = NULL, *tmp_str;
   const char **params, **vals;
   size_t params_count;
   int error, rows_num;

   if (!table) {
      ast_log(LOG_WARNING, "Table name unspecified\n");
      return -1;
   }

   if (!(params_count = get_params(ap, &params, &vals, 1)))
      return -1;

/* \cond DOXYGEN_CAN_PARSE_THIS */
#undef QUERY
#define QUERY "UPDATE '%q' SET %q = '%q'"
/* \endcond */

   if (!(query = sqlite_mprintf(QUERY, table, params[0], vals[0]))) {
      ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
      ast_free(params);
      ast_free(vals);
      return -1;
   }

   if (params_count > 1) {
      size_t i;

      for (i = 1; i < params_count; i++) {
         tmp_str = sqlite_mprintf("%s, %q = '%q'", query, params[i], vals[i]);
         sqlite_freemem(query);

         if (!tmp_str) {
            ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
            ast_free(params);
            ast_free(vals);
            return -1;
         }

         query = tmp_str;
      }
   }

   ast_free(params);
   ast_free(vals);

   if (!(tmp_str = sqlite_mprintf("%s WHERE %q = '%q';", query, keyfield, entity))) {
      ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
      sqlite_freemem(query);
      return -1;
   }

   sqlite_freemem(query);
   query = tmp_str;
   ast_debug(1, "SQL query: %s\n", query);

   ast_mutex_lock(&mutex);

   RES_CONFIG_SQLITE_BEGIN
      error = sqlite_exec(db, query, NULL, NULL, &errormsg);
   RES_CONFIG_SQLITE_END(error)

   if (!error)
      rows_num = sqlite_changes(db);
   else
      rows_num = -1;

   ast_mutex_unlock(&mutex);

   sqlite_freemem(query);

   if (error) {
      ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
   }
   sqlite_freemem(errormsg);

   return rows_num;
}
static int set_var ( char **  var,
const char *  name,
const char *  value 
) [static]

Allocate a variable.

Parameters:
varthe address of the variable to set (it will be allocated)
namethe name of the variable (for error handling)
valuethe value to store in var
Return values:
0on success
1if an allocation error occurred

Definition at line 708 of file res_config_sqlite.c.

References ast_free, ast_log(), ast_strdup, and LOG_WARNING.

{
   if (*var)
      ast_free(*var);

   *var = ast_strdup(value);

   if (!*var) {
      ast_log(LOG_WARNING, "Unable to allocate variable %s\n", name);
      return 1;
   }

   return 0;
}
static void unload_config ( void  ) [static]

Free resources related to configuration.

See also:
load_config()

Definition at line 771 of file res_config_sqlite.c.

References ast_free, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and free_table().

Referenced by load_config(), and unload_module().


Variable Documentation

struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Realtime SQLite configuration" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static]

Definition at line 1870 of file res_config_sqlite.c.

Definition at line 1870 of file res_config_sqlite.c.

int cdr_registered [static]

Set to 1 if the CDR callback function was registered.

Definition at line 465 of file res_config_sqlite.c.

char* cdr_table [static]

The name of the table used to store CDR entries.

Definition at line 477 of file res_config_sqlite.c.

struct ast_cli_entry cli_status[] [static]
Initial value:
 {
   AST_CLI_DEFINE(handle_cli_show_sqlite_status, "Show status information about the SQLite 2 driver"),
   AST_CLI_DEFINE(handle_cli_sqlite_show_tables, "Cached table information about the SQLite 2 driver"),
}

Structure containing details and callback functions for the CLI status command.

Definition at line 506 of file res_config_sqlite.c.

int cli_status_registered [static]

Set to 1 if the CLI status command callback function was registered.

Definition at line 468 of file res_config_sqlite.c.

char* config_table [static]

The name of the static configuration table.

Definition at line 474 of file res_config_sqlite.c.

Referenced by config_handler().

sqlite* db [static]

The SQLite database object.

Definition at line 459 of file res_config_sqlite.c.

char* dbfile [static]

The path of the database file.

Definition at line 471 of file res_config_sqlite.c.

ast_mutex_t mutex = AST_MUTEX_INIT_VALUE [static]
char* sql_create_cdr_table = ");" [static]

SQL query format to create the CDR table if non existent.

Definition at line 531 of file res_config_sqlite.c.

Referenced by load_module().

The structure specifying all callback functions used by Asterisk for static and RealTime configuration.

Definition at line 483 of file res_config_sqlite.c.

struct sqlite_tables sqlite_tables [static]
int use_cdr [static]

Set to 1 if CDR support is enabled.

Definition at line 462 of file res_config_sqlite.c.