From 1282de797de2190f282b60308b093223f93cf89a Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Thu, 13 Sep 2007 15:26:40 +0000 Subject: Various code and documentation cleanups for res_config_sqlite (closes issue #10711, rbraun_proformatique) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@82321 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- res/res_config_sqlite.c | 496 ++++++++++++++++++++++++------------------------ 1 file changed, 252 insertions(+), 244 deletions(-) (limited to 'res') diff --git a/res/res_config_sqlite.c b/res/res_config_sqlite.c index 5797ba6f0..3cfb41648 100644 --- a/res/res_config_sqlite.c +++ b/res/res_config_sqlite.c @@ -5,7 +5,7 @@ * * Written by Richard Braun * - * Based on res_sqlite3 by Anthony Minessale II, + * Based on res_sqlite3 by Anthony Minessale II, * and res_config_mysql by Matthew Boehm * * See http://www.asterisk.org for more information about @@ -21,75 +21,60 @@ /*! * \page res_config_sqlite - * + * * \section intro_sec Presentation - * - * res_config_sqlite is a module for the Asterisk Open Source PBX to - * support SQLite 2 databases. It can be used to fetch configuration - * from a database (static configuration files and/or using the Asterisk + * + * res_config_sqlite is a module for the Asterisk Open Source PBX to + * support SQLite 2 databases. It can be used to fetch configuration + * from a database (static configuration files and/or using the Asterisk * RealTime Architecture - ARA). * It can also be used to log CDR entries. Finally, it can be used for simple * queries in the Dialplan. Note that Asterisk already comes with a module - * named cdr_sqlite. There are two reasons for including it in res_sqlite: + * named cdr_sqlite. There are two reasons for including it in res_config_sqlite: * the first is that rewriting it was a training to learn how to write a * simple module for Asterisk, the other is to have the same database open for * all kinds of operations, which improves reliability and performance. - * + * * There is already a module for SQLite 3 (named res_sqlite3) in the Asterisk - * addons. res_sqlite was developed because we, at Proformatique, are using + * addons. res_config_sqlite was developed because we, at Proformatique, are using * PHP 4 in our embedded systems, and PHP 4 has no stable support for SQLite 3 * at this time. We also needed RealTime support. - * + * * \section conf_sec Configuration - * + * * The main configuration file is res_config_sqlite.conf. It must be readable or - * res_sqlite will fail to start. It is suggested to use the sample file + * res_config_sqlite will fail to start. It is suggested to use the sample file * in this package as a starting point. The file has only one section * named general. Here are the supported parameters : - * + * *
*
dbfile
*
The absolute path to the SQLite database (the file can be non existent, - * res_sqlite will create it if is has the appropriate rights)
+ * res_config_sqlite will create it if it has the appropriate rights) *
config_table
*
The table used for static configuration
*
cdr_table
*
The table used to store CDR entries (if ommitted, CDR support is * disabled)
*
- * - * To use res_sqlite for static and/or RealTime configuration, refer to the + * + * To use res_config_sqlite for static and/or RealTime configuration, refer to the * Asterisk documentation. The file tables.sql can be used to create the * needed tables. - * - * The SQLITE() application is very similar to the MYSQL() application. You - * can find more details at - * http://voip-info.org/wiki/view/Asterisk+cmd+MYSQL. - * The main difference is that you cannot choose your database - it's the - * file set in the dbfile parameter. As a result, there is no - * Connect or Disconnect command, and there is no connid variable. - * + * * \section status_sec Driver status - * + * * The CLI command show sqlite status returns status information - * about the running driver. One information is more important than others: - * the number of registered virtual machines. A SQLite virtual machine is - * created each time a SQLITE() query command is used. If the number of - * registered virtual machines isn't 0 (or near 0, since one or more SQLITE() - * commands can be running when requesting the module status) and increases - * over time, this probably means that you're badly using the application - * and you're creating resource leaks. You should check your Dialplan and - * reload res_sqlite (by unloading and then loading again - reloading isn't - * supported) - * + * about the running driver. + * * \section credits_sec Credits - * + * * res_config_sqlite was developed by Richard Braun at the Proformatique company. */ /*! - * \file - * \brief res_sqlite module. + * \file + * \brief res_config_sqlite module. */ /*** MODULEINFO @@ -114,94 +99,85 @@ #include "asterisk/options.h" #include "asterisk/linkedlists.h" -#define RES_SQLITE_NAME "res_sqlite" -#define RES_SQLITE_DRIVER "sqlite" -#define RES_SQLITE_APP_DRIVER "SQLITE" -#define RES_SQLITE_DESCRIPTION "Resource Module for SQLite 2" -#define RES_SQLITE_CONF_FILE "res_config_sqlite.conf" -#define RES_SQLITE_APP_SYNOPSIS "Dialplan access to SQLite 2" -#define RES_SQLITE_APP_DESCRIPTION \ -"SQLITE(): " RES_SQLITE_APP_SYNOPSIS "\n" -#define RES_SQLITE_STATUS_SUMMARY \ -"Show status information about the SQLite 2 driver" -#define RES_SQLITE_STATUS_USAGE \ -"Usage: show sqlite status\n" \ -" " RES_SQLITE_STATUS_SUMMARY "\n" +#define MACRO_BEGIN do { +#define MACRO_END } while (0) + +#define RES_CONFIG_SQLITE_NAME "res_config_sqlite" +#define RES_CONFIG_SQLITE_DRIVER "sqlite" +#define RES_CONFIG_SQLITE_DESCRIPTION "Resource Module for SQLite 2" +#define RES_CONFIG_SQLITE_CONF_FILE "res_config_sqlite.conf" +#define RES_CONFIG_SQLITE_STATUS_SUMMARY "Show status information about the SQLite 2 driver" +#define RES_CONFIG_SQLITE_STATUS_USAGE \ + "Usage: show sqlite status\n" \ + " " RES_CONFIG_SQLITE_STATUS_SUMMARY "\n" enum { - RES_SQLITE_CONFIG_ID, - RES_SQLITE_CONFIG_COMMENTED, - RES_SQLITE_CONFIG_FILENAME, - RES_SQLITE_CONFIG_CATEGORY, - RES_SQLITE_CONFIG_VAR_NAME, - RES_SQLITE_CONFIG_VAR_VAL, - RES_SQLITE_CONFIG_COLUMNS, + RES_CONFIG_SQLITE_CONFIG_ID, + 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, }; -/*! - * Limit the number of maximum simultaneous registered SQLite VMs to avoid - * a denial of service attack. - */ -#define RES_SQLITE_VM_MAX 1024 - -#define SET_VAR(config, to, from) \ -do \ - { \ - int __error; \ - __error = set_var(&to, #to, from->value); \ - if (__error) \ - { \ - ast_config_destroy(config); \ - unload_config(); \ - return 1; \ - } \ - } \ -while (0) +#define SET_VAR(config, to, from) \ +MACRO_BEGIN \ + int __error; \ + \ + __error = set_var(&to, #to, from->value); \ + \ + if (__error) { \ + ast_config_destroy(config); \ + unload_config(); \ + return 1; \ + } \ +MACRO_END /*! * Maximum number of loops before giving up executing a query. Calls to * sqlite_xxx() functions which can return SQLITE_BUSY or SQLITE_LOCKED - * are enclosed by RES_SQLITE_BEGIN and RES_SQLITE_END, e.g. + * are enclosed by RES_CONFIG_SQLITE_BEGIN and RES_CONFIG_SQLITE_END, e.g. *
  * char *errormsg;
  * int error;
- * 
- * RES_SQLITE_BEGIN
+ *
+ * RES_CONFIG_SQLITE_BEGIN
  *	 error = sqlite_exec(db, query, NULL, NULL, &errormsg);
- * RES_SQLITE_END(error)
- * 
+ * RES_CONFIG_SQLITE_END(error)
+ *
  * if (error)
  *	 ...;
  * 
*/ -#define RES_SQLITE_MAX_LOOPS 10 +#define RES_CONFIG_SQLITE_MAX_LOOPS 10 /*! * Macro used before executing a query. - * - * \see RES_SQLITE_MAX_LOOPS. + * + * \see RES_CONFIG_SQLITE_MAX_LOOPS. */ -#define RES_SQLITE_BEGIN \ -{ \ - int __i; \ - for (__i = 0; __i < RES_SQLITE_MAX_LOOPS; __i++) \ - { +#define RES_CONFIG_SQLITE_BEGIN \ +MACRO_BEGIN \ + int __i; \ + \ + for (__i = 0; __i < RES_CONFIG_SQLITE_MAX_LOOPS; __i++) { /*! * Macro used after executing a query. - * - * \see RES_SQLITE_MAX_LOOPS. + * + * \see RES_CONFIG_SQLITE_MAX_LOOPS. */ -#define RES_SQLITE_END(error) \ - if (error != SQLITE_BUSY && error != SQLITE_LOCKED) \ - break; \ - usleep(1000); \ - } \ -} +#define RES_CONFIG_SQLITE_END(error) \ + if (error != SQLITE_BUSY && error != SQLITE_LOCKED) \ + break; \ + usleep(1000); \ + } \ +MACRO_END; /*! * Structure sent to the SQLite callback function for static configuration. - * + * * \see add_cfg_entry() */ struct cfg_entry_args { @@ -212,7 +188,7 @@ struct cfg_entry_args { /*! * Structure sent to the SQLite callback function for RealTime configuration. - * + * * \see add_rt_cfg_entry() */ struct rt_cfg_entry_args { @@ -223,7 +199,7 @@ struct rt_cfg_entry_args { /*! * Structure sent to the SQLite callback function for RealTime configuration * (realtime_multi_handler()). - * + * * \see add_rt_multi_cfg_entry() */ struct rt_multi_cfg_entry_args { @@ -244,10 +220,10 @@ static int set_var(char **var, char *name, char *value); /*! * \brief Load the configuration file. * \see unload_config() - * + * * This function sets dbfile, config_table, and cdr_table. It calls * check_vars() before returning, and unload_config() if an error occurred. - * + * * \retval 0 on success * \retval 1 if an error occurred */ @@ -262,10 +238,10 @@ static void unload_config(void); /*! * \brief Asterisk callback function for CDR support. * \param cdr the CDR entry Asterisk sends us. - * + * * Asterisk will call this function each time a CDR entry must be logged if * CDR support is enabled. - * + * * \retval 0 on success * \retval 1 if an error occurred */ @@ -273,11 +249,11 @@ static int cdr_handler(struct ast_cdr *cdr); /*! * \brief 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. - * + * resulting rows being sorted by category. + * * \param arg a pointer to a struct cfg_entry_args object * \param argc number of columns * \param argv values in the row @@ -292,10 +268,10 @@ static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames); /*! * \brief Asterisk callback function for static configuration. - * + * * Asterisk will call this function when it loads its static configuration, * which usually happens at startup and reload. - * + * * \param database the database to use (ignored) * \param table the table to use * \param file the file to load from the database @@ -307,24 +283,24 @@ static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames); * \see add_cfg_entry() */ 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); + struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl); /*! * \brief 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: - * + * * - * + * * 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. - * + * * \param ap the va_list object to parse * \param params_ptr where the address of the params array is stored * \param vals_ptr where the address of the vals array is stored @@ -336,10 +312,10 @@ static size_t get_params(va_list ap, const char ***params_ptr, /*! * \brief 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. - * + * * \param arg a pointer to a struct rt_cfg_entry_args object * \param argc number of columns * \param argv values in the row @@ -354,16 +330,16 @@ static int add_rt_cfg_entry(void *arg, int argc, char **argv, /*! * 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';. - * + * * \param database the database to use (ignored) - * \param table the table to use - * \param ap list of parameters and values to match + * \param table the table to use + * \param ap list of parameters and values to match * * \retval a linked list of struct ast_variable objects * \retval NULL if an error occurred @@ -374,11 +350,11 @@ static struct ast_variable * realtime_handler(const char *database, /*! * \brief 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 of variables. - * + * categories in addition to variables. + * * \param arg a pointer to a struct rt_multi_cfg_entry_args object * \param argc number of columns * \param argv values in the row @@ -393,11 +369,11 @@ static int add_rt_multi_cfg_entry(void *arg, int argc, char **argv, /*! * \brief 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. - * + * * \param database the database to use (ignored) * \param table the table to use * \param ap list of parameters and values to match @@ -407,19 +383,18 @@ static int add_rt_multi_cfg_entry(void *arg, int argc, char **argv, * \see add_rt_multi_cfg_entry() */ static struct ast_config * realtime_multi_handler(const char *database, - const char *table, - va_list ap); + const char *table, va_list ap); /*! * \brief 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. - * + * * \param database the database to use (ignored) * \param table the table to use * \param keyfield the column of the matching cell @@ -429,18 +404,17 @@ static struct ast_config * realtime_multi_handler(const char *database, * \retval -1 if an error occurred. */ static int realtime_update_handler(const char *database, const char *table, - const char *keyfield, const char *entity, - va_list ap); + const char *keyfield, const char *entity, va_list ap); /*! * \brief 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 + * 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. - * + * * \param database the database to use (ignored) * \param table the table to use * \param ap list of parameters and new values to insert into the database @@ -451,15 +425,15 @@ static int realtime_store_handler(const char *database, const char *table, va_list ap); /*! - * \brief Asterisk callback function for RealTime configuration (destroys + * \brief 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. - * + * * \param database the database to use (ignored) * \param table the table to use * \param keyfield the column of the matching cell @@ -469,12 +443,11 @@ static int realtime_store_handler(const char *database, const char *table, * \retval -1 if an error occurred. */ static int realtime_destroy_handler(const char *database, const char *table, - const char *keyfield, const char *entity, - va_list ap); + const char *keyfield, const char *entity, va_list ap); /*! * \brief Asterisk callback function for the CLI status command. - * + * * \param fd file descriptor provided by Asterisk to use with ast_cli() * \param argc number of arguments * \param argv arguments list @@ -503,16 +476,13 @@ static char *config_table; /*! The name of the table used to store CDR entries. */ static char *cdr_table; -/*! The number of registered virtual machines. */ -static int vm_count; - /*! * The structure specifying all callback functions used by Asterisk for static * and RealTime configuration. */ static struct ast_config_engine sqlite_engine = { - .name = RES_SQLITE_DRIVER, + .name = RES_CONFIG_SQLITE_DRIVER, .load_func = config_handler, .realtime_func = realtime_handler, .realtime_multi_func = realtime_multi_handler, @@ -523,7 +493,6 @@ static struct ast_config_engine sqlite_engine = /*! * The mutex used to prevent simultaneous access to the SQLite database. - * SQLite isn't always compiled with thread safety. */ AST_MUTEX_DEFINE_STATIC(mutex); @@ -535,8 +504,8 @@ static struct ast_cli_entry cli_status_cmd = { .cmda = {"show", "sqlite", "status", NULL}, .handler = cli_status, - .summary = RES_SQLITE_STATUS_SUMMARY, - .usage = RES_SQLITE_STATUS_USAGE + .summary = RES_CONFIG_SQLITE_STATUS_SUMMARY, + .usage = RES_CONFIG_SQLITE_STATUS_USAGE }; /* @@ -545,32 +514,33 @@ static struct ast_cli_entry cli_status_cmd = /*! SQL query format to create the CDR table if non existent. */ static char *sql_create_cdr_table = -"CREATE TABLE '%q' (" -" id INTEGER PRIMARY KEY," -" clid VARCHAR(80) NOT NULL DEFAULT ''," -" src VARCHAR(80) NOT NULL DEFAULT ''," -" dst VARCHAR(80) NOT NULL DEFAULT ''," -" dcontext VARCHAR(80) NOT NULL DEFAULT ''," -" channel VARCHAR(80) NOT NULL DEFAULT ''," -" dstchannel VARCHAR(80) NOT NULL DEFAULT ''," -" lastapp VARCHAR(80) NOT NULL DEFAULT ''," -" lastdata VARCHAR(80) NOT NULL DEFAULT ''," -" start CHAR(19) NOT NULL DEFAULT '0000-00-00 00:00:00'," -" answer CHAR(19) NOT NULL DEFAULT '0000-00-00 00:00:00'," -" end CHAR(19) NOT NULL DEFAULT '0000-00-00 00:00:00'," -" duration INT(11) NOT NULL DEFAULT '0'," -" billsec INT(11) NOT NULL DEFAULT '0'," -" disposition INT(11) NOT NULL DEFAULT '0'," -" amaflags INT(11) NOT NULL DEFAULT '0'," -" accountcode VARCHAR(20) NOT NULL DEFAULT ''," -" uniqueid VARCHAR(32) NOT NULL DEFAULT ''," -" userfield VARCHAR(255) NOT NULL DEFAULT ''" +"CREATE TABLE '%q' (\n" +" id INTEGER,\n" +" clid VARCHAR(80) NOT NULL DEFAULT '',\n" +" src VARCHAR(80) NOT NULL DEFAULT '',\n" +" dst VARCHAR(80) NOT NULL DEFAULT '',\n" +" dcontext VARCHAR(80) NOT NULL DEFAULT '',\n" +" channel VARCHAR(80) NOT NULL DEFAULT '',\n" +" dstchannel VARCHAR(80) NOT NULL DEFAULT '',\n" +" lastapp VARCHAR(80) NOT NULL DEFAULT '',\n" +" lastdata VARCHAR(80) NOT NULL DEFAULT '',\n" +" start DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',\n" +" answer DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',\n" +" end DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',\n" +" duration INT(11) NOT NULL DEFAULT 0,\n" +" billsec INT(11) NOT NULL DEFAULT 0,\n" +" disposition VARCHAR(45) NOT NULL DEFAULT '',\n" +" amaflags INT(11) NOT NULL DEFAULT 0,\n" +" accountcode VARCHAR(20) NOT NULL DEFAULT '',\n" +" uniqueid VARCHAR(32) NOT NULL DEFAULT '',\n" +" userfield VARCHAR(255) NOT NULL DEFAULT '',\n" +" PRIMARY KEY (id)\n" ");"; /*! SQL query format to insert a CDR entry. */ static char *sql_add_cdr_entry = "INSERT INTO '%q' (" -" clid," +" clid," " src," " dst," " dcontext," @@ -612,7 +582,7 @@ static char *sql_add_cdr_entry = /*! * SQL query format to fetch the static configuration of a file. * Rows must be sorted by category. - * + * * \see add_cfg_entry() */ static char *sql_get_config_table = @@ -655,10 +625,10 @@ static int load_config(void) int error; struct ast_flags config_flags = { 0 }; - config = ast_config_load(RES_SQLITE_CONF_FILE, config_flags); + config = ast_config_load(RES_CONFIG_SQLITE_CONF_FILE, config_flags); if (!config) { - ast_log(LOG_ERROR, "Unable to load " RES_SQLITE_CONF_FILE "\n"); + ast_log(LOG_ERROR, "Unable to load " RES_CONFIG_SQLITE_CONF_FILE "\n"); return 1; } @@ -696,27 +666,37 @@ static void unload_config(void) static int cdr_handler(struct ast_cdr *cdr) { - char *errormsg; + char *query, *errormsg; int error; + query = sqlite_mprintf(sql_add_cdr_entry, cdr_table, cdr->clid, + cdr->src, cdr->dst, cdr->dcontext, cdr->channel, + cdr->dstchannel, cdr->lastapp, cdr->lastdata, + cdr->start.tv_sec, cdr->answer.tv_sec, + cdr->end.tv_sec, cdr->duration, cdr->billsec, + cdr->disposition, cdr->amaflags, cdr->accountcode, + cdr->uniqueid, cdr->userfield); + + if (!query) { + ast_log(LOG_WARNING, "Unable to allocate SQL query\n"); + return 1; + } + + ast_debug(1, "SQL query: %s\n", query); + ast_mutex_lock(&mutex); - RES_SQLITE_BEGIN - error = sqlite_exec_printf(db, sql_add_cdr_entry, NULL, NULL, &errormsg, - cdr_table, cdr->clid, cdr->src, cdr->dst, - cdr->dcontext, cdr->channel, cdr->dstchannel, - cdr->lastapp, cdr->lastdata, cdr->start.tv_sec, - cdr->answer.tv_sec, cdr->end.tv_sec, - cdr->duration, cdr->billsec, cdr->disposition, - cdr->amaflags, cdr->accountcode, cdr->uniqueid, - cdr->userfield); - RES_SQLITE_END(error) + RES_CONFIG_SQLITE_BEGIN + error = sqlite_exec(db, query, NULL, NULL, &errormsg); + RES_CONFIG_SQLITE_END(error) ast_mutex_unlock(&mutex); + sqlite_freemem(query); + if (error) { ast_log(LOG_ERROR, "%s\n", errormsg); - ast_free(errormsg); + sqlite_freemem(errormsg); return 1; } @@ -728,15 +708,15 @@ static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames) struct cfg_entry_args *args; struct ast_variable *var; - if (argc != RES_SQLITE_CONFIG_COLUMNS) { + if (argc != RES_CONFIG_SQLITE_CONFIG_COLUMNS) { ast_log(LOG_WARNING, "Corrupt table\n"); return 1; } args = arg; - if (!args->cat_name || strcmp(args->cat_name, argv[RES_SQLITE_CONFIG_CATEGORY])) { - args->cat = ast_category_new(argv[RES_SQLITE_CONFIG_CATEGORY], "", 99999); + 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"); @@ -744,7 +724,7 @@ static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames) } ast_free(args->cat_name); - args->cat_name = ast_strdup(argv[RES_SQLITE_CONFIG_CATEGORY]); + args->cat_name = ast_strdup(argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY]); if (!args->cat_name) { ast_category_destroy(args->cat); @@ -754,8 +734,7 @@ static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames) ast_category_append(args->cfg, args->cat); } - var = ast_variable_new(argv[RES_SQLITE_CONFIG_VAR_NAME], - argv[RES_SQLITE_CONFIG_VAR_VAL], ""); + 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"); @@ -763,15 +742,15 @@ static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames) } ast_variable_append(args->cat, var); - + 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) + struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl) { struct cfg_entry_args args; - char *errormsg; + char *query, *errormsg; int error; if (!config_table) { @@ -782,24 +761,32 @@ struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl) } 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; ast_mutex_lock(&mutex); - RES_SQLITE_BEGIN - error = sqlite_exec_printf(db, sql_get_config_table, add_cfg_entry, - &args, &errormsg, table, file); - RES_SQLITE_END(error) + 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", errormsg); - ast_free(errormsg); + sqlite_freemem(errormsg); return NULL; } @@ -873,8 +860,7 @@ static int add_rt_cfg_entry(void *arg, int argc, char **argv, char **columnNames return 0; } -static struct ast_variable * -realtime_handler(const char *database, const char *table, va_list ap) +static struct ast_variable * realtime_handler(const char *database, const char *table, va_list ap) { char *query, *errormsg, *op, *tmp_str; struct rt_cfg_entry_args args; @@ -913,8 +899,7 @@ realtime_handler(const char *database, const char *table, va_list ap) 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]); + tmp_str = sqlite_mprintf("%s AND %q%s '%q'", query, params[i], op, vals[i]); sqlite_freemem(query); if (!tmp_str) { @@ -946,9 +931,9 @@ realtime_handler(const char *database, const char *table, va_list ap) ast_mutex_lock(&mutex); - RES_SQLITE_BEGIN + RES_CONFIG_SQLITE_BEGIN error = sqlite_exec(db, query, add_rt_cfg_entry, &args, &errormsg); - RES_SQLITE_END(error) + RES_CONFIG_SQLITE_END(error) ast_mutex_unlock(&mutex); @@ -956,7 +941,7 @@ realtime_handler(const char *database, const char *table, va_list ap) if (error) { ast_log(LOG_WARNING, "%s\n", errormsg); - ast_free(errormsg); + sqlite_freemem(errormsg); ast_variables_destroy(args.var); return NULL; } @@ -972,7 +957,7 @@ static int add_rt_multi_cfg_entry(void *arg, int argc, char **argv, char **colum char *cat_name; size_t i; - args = (struct rt_multi_cfg_entry_args *)arg; + args = arg; cat_name = NULL; /* @@ -1012,7 +997,7 @@ static int add_rt_multi_cfg_entry(void *arg, int argc, char **argv, char **colum return 0; } -static struct ast_config *realtime_multi_handler(const char *database, +static struct ast_config *realtime_multi_handler(const char *database, const char *table, va_list ap) { char *query, *errormsg, *op, *tmp_str, *initfield; @@ -1076,8 +1061,7 @@ static struct ast_config *realtime_multi_handler(const char *database, 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]); + tmp_str = sqlite_mprintf("%s AND %q%s '%q'", query, params[i], op, vals[i]); sqlite_freemem(query); if (!tmp_str) { @@ -1111,9 +1095,9 @@ static struct ast_config *realtime_multi_handler(const char *database, ast_mutex_lock(&mutex); - RES_SQLITE_BEGIN + RES_CONFIG_SQLITE_BEGIN error = sqlite_exec(db, query, add_rt_multi_cfg_entry, &args, &errormsg); - RES_SQLITE_END(error) + RES_CONFIG_SQLITE_END(error) ast_mutex_unlock(&mutex); @@ -1122,7 +1106,7 @@ static struct ast_config *realtime_multi_handler(const char *database, if (error) { ast_log(LOG_WARNING, "%s\n", errormsg); - ast_free(errormsg); + sqlite_freemem(errormsg); ast_config_destroy(cfg); return NULL; } @@ -1131,8 +1115,7 @@ static struct ast_config *realtime_multi_handler(const char *database, } static int realtime_update_handler(const char *database, const char *table, - const char *keyfield, const char *entity, - va_list ap) + const char *keyfield, const char *entity, va_list ap) { char *query, *errormsg, *tmp_str; const char **params, **vals; @@ -1163,8 +1146,7 @@ static int realtime_update_handler(const char *database, const char *table, size_t i; for (i = 1; i < params_count; i++) { - tmp_str = sqlite_mprintf("%s, %q = '%q'", query, params[i], - vals[i]); + tmp_str = sqlite_mprintf("%s, %q = '%q'", query, params[i], vals[i]); sqlite_freemem(query); if (!tmp_str) { @@ -1192,9 +1174,9 @@ static int realtime_update_handler(const char *database, const char *table, ast_mutex_lock(&mutex); - RES_SQLITE_BEGIN + RES_CONFIG_SQLITE_BEGIN error = sqlite_exec(db, query, NULL, NULL, &errormsg); - RES_SQLITE_END(error) + RES_CONFIG_SQLITE_END(error) if (!error) rows_num = sqlite_changes(db); @@ -1207,7 +1189,7 @@ static int realtime_update_handler(const char *database, const char *table, if (error) { ast_log(LOG_WARNING, "%s\n", errormsg); - ast_free(errormsg); + sqlite_freemem(errormsg); } return rows_num; @@ -1282,9 +1264,9 @@ static int realtime_store_handler(const char *database, const char *table, va_li ast_mutex_lock(&mutex); - RES_SQLITE_BEGIN + RES_CONFIG_SQLITE_BEGIN error = sqlite_exec(db, tmp_str, NULL, NULL, &errormsg); - RES_SQLITE_END(error) + RES_CONFIG_SQLITE_END(error) if (!error) { rows_id = sqlite_last_insert_rowid(db); @@ -1298,15 +1280,14 @@ static int realtime_store_handler(const char *database, const char *table, va_li if (error) { ast_log(LOG_WARNING, "%s\n", errormsg); - ast_free(errormsg); + sqlite_freemem(errormsg); } return rows_id; } static int realtime_destroy_handler(const char *database, const char *table, - const char *keyfield, const char *entity, - va_list ap) + const char *keyfield, const char *entity, va_list ap) { char *query, *errormsg, *tmp_str; const char **params, **vals; @@ -1356,14 +1337,13 @@ static int realtime_destroy_handler(const char *database, const char *table, } sqlite_freemem(query); query = tmp_str; - ast_debug(1, "SQL query: %s\n", query); ast_mutex_lock(&mutex); - RES_SQLITE_BEGIN + RES_CONFIG_SQLITE_BEGIN error = sqlite_exec(db, query, NULL, NULL, &errormsg); - RES_SQLITE_END(error) + RES_CONFIG_SQLITE_END(error) if (!error) rows_num = sqlite_changes(db); @@ -1376,7 +1356,7 @@ static int realtime_destroy_handler(const char *database, const char *table, if (error) { ast_log(LOG_WARNING, "%s\n", errormsg); - ast_free(errormsg); + sqlite_freemem(errormsg); } return rows_num; @@ -1409,7 +1389,7 @@ static int unload_module(void) ast_cli_unregister(&cli_status_cmd); if (cdr_registered) - ast_cdr_unregister(RES_SQLITE_NAME); + ast_cdr_unregister(RES_CONFIG_SQLITE_NAME); ast_config_engine_deregister(&sqlite_engine); @@ -1432,7 +1412,6 @@ static int load_module(void) dbfile = NULL; config_table = NULL; cdr_table = NULL; - vm_count = 0; error = load_config(); if (error) @@ -1440,7 +1419,7 @@ static int load_module(void) if (!(db = sqlite_open(dbfile, 0660, &errormsg))) { ast_log(LOG_ERROR, "%s\n", errormsg); - ast_free(errormsg); + sqlite_freemem(errormsg); unload_module(); return 1; } @@ -1448,10 +1427,28 @@ static int load_module(void) ast_config_engine_register(&sqlite_engine); if (use_cdr) { - RES_SQLITE_BEGIN - error = sqlite_exec_printf(db, "SELECT COUNT(id) FROM %Q;", NULL, NULL, - &errormsg, cdr_table); - RES_SQLITE_END(error) + 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) { /* @@ -1459,26 +1456,37 @@ static int load_module(void) */ if (error != SQLITE_ERROR) { ast_log(LOG_ERROR, "%s\n", errormsg); - ast_free(errormsg); + sqlite_freemem(errormsg); + unload_module(); + return 1; + } + + sqlite_freemem(errormsg); + 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; } - RES_SQLITE_BEGIN - error = sqlite_exec_printf(db, sql_create_cdr_table, NULL, NULL, - &errormsg, cdr_table); - RES_SQLITE_END(error) + 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", errormsg); - ast_free(errormsg); + sqlite_freemem(errormsg); unload_module(); return 1; } } - error = ast_cdr_register(RES_SQLITE_NAME, RES_SQLITE_DESCRIPTION, - cdr_handler); + error = ast_cdr_register(RES_CONFIG_SQLITE_NAME, RES_CONFIG_SQLITE_DESCRIPTION, cdr_handler); if (error) { unload_module(); -- cgit v1.2.3