[asterisk-commits] twilson: branch twilson/sqlite3_playground r341867 - in /team/twilson/sqlite3...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Oct 21 22:34:17 CDT 2011
Author: twilson
Date: Fri Oct 21 22:34:13 2011
New Revision: 341867
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=341867
Log:
Initial commit of astdb-as-a-realtime-module
Includes a fix to res_config_sqlite3's deltree function that I should fix in
the main tree. Still have some cleanup to do most likely.
The main idea is to eventually phase out the ast_db API and just use the realtime
API. I would like to see the realtime API beefed up a bit too. It is a bit...clunky.
All astdb tests pass. It is currently about 3 times slower than the non-realtime
implementation due to not being able to use SQL statement binding. That is one
of the improvements I'd like to do to realtime--the ability to register queries
so they can be cached.
Added:
team/twilson/sqlite3_playground/res/res_astdb.c (with props)
team/twilson/sqlite3_playground/res/res_astdb.exports.in (with props)
Modified:
team/twilson/sqlite3_playground/include/asterisk/_private.h
team/twilson/sqlite3_playground/include/asterisk/astdb.h
team/twilson/sqlite3_playground/main/asterisk.c
team/twilson/sqlite3_playground/main/db.c
team/twilson/sqlite3_playground/res/res_config_sqlite3.c
Modified: team/twilson/sqlite3_playground/include/asterisk/_private.h
URL: http://svnview.digium.com/svn/asterisk/team/twilson/sqlite3_playground/include/asterisk/_private.h?view=diff&rev=341867&r1=341866&r2=341867
==============================================================================
--- team/twilson/sqlite3_playground/include/asterisk/_private.h (original)
+++ team/twilson/sqlite3_playground/include/asterisk/_private.h Fri Oct 21 22:34:13 2011
@@ -21,7 +21,6 @@
void close_logger(void); /*!< Provided by logger.c */
int init_framer(void); /*!< Provided by frame.c */
int ast_term_init(void); /*!< Provided by term.c */
-int astdb_init(void); /*!< Provided by db.c */
void ast_channels_init(void); /*!< Provided by channel.c */
void ast_builtins_init(void); /*!< Provided by cli.c */
int ast_cli_perms_init(int reload); /*!< Provided by cli.c */
Modified: team/twilson/sqlite3_playground/include/asterisk/astdb.h
URL: http://svnview.digium.com/svn/asterisk/team/twilson/sqlite3_playground/include/asterisk/astdb.h?view=diff&rev=341867&r1=341866&r2=341867
==============================================================================
--- team/twilson/sqlite3_playground/include/asterisk/astdb.h (original)
+++ team/twilson/sqlite3_playground/include/asterisk/astdb.h Fri Oct 21 22:34:13 2011
@@ -26,6 +26,10 @@
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
+
+static const char * const ast_db_family = "astdb";
+static const char * const ast_db_key= "key";
+static const char * const ast_db_value = "value";
struct ast_db_entry {
struct ast_db_entry *next;
Modified: team/twilson/sqlite3_playground/main/asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/sqlite3_playground/main/asterisk.c?view=diff&rev=341867&r1=341866&r2=341867
==============================================================================
--- team/twilson/sqlite3_playground/main/asterisk.c (original)
+++ team/twilson/sqlite3_playground/main/asterisk.c Fri Oct 21 22:34:13 2011
@@ -3770,11 +3770,6 @@
ast_xmldoc_load_documentation();
#endif
- if (astdb_init()) {
- printf("%s", term_quit());
- exit(1);
- }
-
if (ast_msg_init()) {
printf("%s", term_quit());
exit(1);
Modified: team/twilson/sqlite3_playground/main/db.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/sqlite3_playground/main/db.c?view=diff&rev=341867&r1=341866&r2=341867
==============================================================================
--- team/twilson/sqlite3_playground/main/db.c (original)
+++ team/twilson/sqlite3_playground/main/db.c Fri Oct 21 22:34:13 2011
@@ -18,425 +18,180 @@
/*! \file
*
- * \brief ASTdb Management
- *
- * \author Mark Spencer <markster at digium.com>
- *
- * \note DB3 is licensed under Sleepycat Public License and is thus incompatible
- * with GPL. To avoid having to make another exception (and complicate
- * licensing even further) we elect to use DB1 which is BSD licensed
+ * \brief Asterisk Internal DB legacy API
+ *
+ * \author Terry Wilson
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-#include "asterisk/_private.h"
-#include "asterisk/paths.h" /* use ast_config_AST_DB */
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <signal.h>
-#include <dirent.h>
-#include <sqlite3.h>
-
-#include "asterisk/channel.h"
-#include "asterisk/file.h"
-#include "asterisk/app.h"
-#include "asterisk/dsp.h"
#include "asterisk/astdb.h"
-#include "asterisk/cli.h"
-#include "asterisk/utils.h"
-#include "asterisk/manager.h"
-
-/*** DOCUMENTATION
- <manager name="DBGet" language="en_US">
- <synopsis>
- Get DB Entry.
- </synopsis>
- <syntax>
- <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
- <parameter name="Family" required="true" />
- <parameter name="Key" required="true" />
- </syntax>
- <description>
- </description>
- </manager>
- <manager name="DBPut" language="en_US">
- <synopsis>
- Put DB entry.
- </synopsis>
- <syntax>
- <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
- <parameter name="Family" required="true" />
- <parameter name="Key" required="true" />
- <parameter name="Val" />
- </syntax>
- <description>
- </description>
- </manager>
- <manager name="DBDel" language="en_US">
- <synopsis>
- Delete DB entry.
- </synopsis>
- <syntax>
- <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
- <parameter name="Family" required="true" />
- <parameter name="Key" required="true" />
- </syntax>
- <description>
- </description>
- </manager>
- <manager name="DBDelTree" language="en_US">
- <synopsis>
- Delete DB Tree.
- </synopsis>
- <syntax>
- <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
- <parameter name="Family" required="true" />
- <parameter name="Key" />
- </syntax>
- <description>
- </description>
- </manager>
- ***/
-
-#define MAX_DB_FIELD 256
-AST_MUTEX_DEFINE_STATIC(dblock);
-static ast_cond_t dbcond;
-static sqlite3 *astdb;
-static pthread_t syncthread;
-static int doexit;
-
-static void db_sync(void);
-
-#define DEFINE_SQL_STATEMENT(stmt,sql) static sqlite3_stmt *stmt; \
- const char stmt##_sql[] = sql;
-
-DEFINE_SQL_STATEMENT(put_stmt, "INSERT OR REPLACE INTO astdb (key, value) VALUES (?, ?)")
-DEFINE_SQL_STATEMENT(get_stmt, "SELECT value FROM astdb WHERE key=?")
-DEFINE_SQL_STATEMENT(del_stmt, "DELETE FROM astdb WHERE key=?")
-DEFINE_SQL_STATEMENT(deltree_stmt, "DELETE FROM astdb WHERE key LIKE ? || '/' || '%'")
-DEFINE_SQL_STATEMENT(deltree_all_stmt, "DELETE FROM astdb")
-DEFINE_SQL_STATEMENT(gettree_stmt, "SELECT key, value FROM astdb WHERE key LIKE ? || '/' || '%'")
-DEFINE_SQL_STATEMENT(gettree_all_stmt, "SELECT key, value FROM astdb")
-DEFINE_SQL_STATEMENT(showkey_stmt, "SELECT key, value FROM astdb WHERE key LIKE '%' || '/' || ?")
-DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key VARCHAR(256), value VARCHAR(256), PRIMARY KEY(key))")
-
-static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len)
-{
- ast_mutex_lock(&dblock);
- if (sqlite3_prepare(astdb, sql, len, stmt, NULL) != SQLITE_OK) {
- ast_log(LOG_WARNING, "Couldn't prepare statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
- ast_mutex_unlock(&dblock);
- return -1;
- }
- ast_mutex_unlock(&dblock);
+#include "asterisk/config.h"
+#include "asterisk/strings.h"
+
+static struct ast_str *_fullkey(const char *family, const char *key)
+{
+ struct ast_str *fullkey;
+
+ if (!(fullkey = ast_str_create(256))) {
+ return NULL;
+ }
+
+ ast_str_set(&fullkey, 0, "/%s/%s", family, key);
+ return fullkey;
+}
+
+int ast_db_put(const char *family, const char *key, const char *value)
+{
+ struct ast_str *fullkey;
+
+ if (!(fullkey = _fullkey(family, key))) {
+ return -1;
+ }
+
+ if (!ast_update_realtime(ast_db_family, ast_db_key, ast_str_buffer(fullkey), ast_db_value, value, SENTINEL)) {
+ /* Updated 0 records so we must store a new value */
+ ast_store_realtime(ast_db_family, ast_db_key, ast_str_buffer(fullkey), ast_db_value, value, SENTINEL);
+ }
+
+ ast_free(fullkey);
return 0;
}
-static int init_statements(void)
-{
- /* Don't initialize create_astdb_statment here as the astdb table needs to exist
- * brefore these statments can be initialized */
- return init_stmt(&get_stmt, get_stmt_sql, sizeof(get_stmt_sql))
- || init_stmt(&del_stmt, del_stmt_sql, sizeof(del_stmt_sql))
- || init_stmt(&deltree_stmt, deltree_stmt_sql, sizeof(deltree_stmt_sql))
- || init_stmt(&deltree_all_stmt, deltree_all_stmt_sql, sizeof(deltree_all_stmt_sql))
- || init_stmt(&gettree_stmt, gettree_stmt_sql, sizeof(gettree_stmt_sql))
- || init_stmt(&gettree_all_stmt, gettree_all_stmt_sql, sizeof(gettree_all_stmt_sql))
- || init_stmt(&showkey_stmt, showkey_stmt_sql, sizeof(showkey_stmt_sql))
- || init_stmt(&put_stmt, put_stmt_sql, sizeof(put_stmt_sql));
-}
-
-static int convert_bdb_to_sqlite3(void)
-{
- char *cmd;
+int ast_db_get(const char *family, const char *key, char *value, int valuelen)
+{
+ struct ast_str *fullkey;
+ struct ast_variable *vars, *tmp;
+
+ if (!(fullkey = _fullkey(family, key))) {
+ return -1;
+ }
+
+ if (!(vars = ast_load_realtime(ast_db_family, ast_db_key, ast_str_buffer(fullkey), SENTINEL))) {
+ ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
+ ast_free(fullkey);
+ return -1;
+ }
+
+ ast_free(fullkey);
+
+ for (tmp = vars; tmp; tmp = tmp->next) {
+ if (!strcasecmp(tmp->name, ast_db_value)) {
+ break;
+ }
+ }
+
+ if (!tmp) {
+ return -1;
+ }
+
+ ast_copy_string(value, tmp->value, valuelen);
+ ast_variables_destroy(vars);
+
+ return 0;
+}
+
+int ast_db_del(const char *family, const char *key)
+{
+ struct ast_str *fullkey;
int res;
- ast_asprintf(&cmd, "astdb2sqlite3 '%s'\n", ast_config_AST_DB);
- res = ast_safe_system(cmd);
- ast_free(cmd);
+ if (!(fullkey = _fullkey(family, key))) {
+ return -1;
+ }
+
+ res = ast_destroy_realtime(ast_db_family, ast_db_key, ast_str_buffer(fullkey), SENTINEL) < 0 ? -1 : 0;
+ ast_free(fullkey);
return res;
}
-static int db_create_astdb(void)
-{
- int res = 0;
-
- if (!create_astdb_stmt) {
- init_stmt(&create_astdb_stmt, create_astdb_stmt_sql, sizeof(create_astdb_stmt_sql));
- }
-
- ast_mutex_lock(&dblock);
- if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) {
- ast_log(LOG_WARNING, "Couldn't create astdb table: %s\n", sqlite3_errmsg(astdb));
- res = -1;
- }
- sqlite3_reset(create_astdb_stmt);
- db_sync();
- ast_mutex_unlock(&dblock);
+int ast_db_deltree(const char *family, const char *subfamily)
+{
+ struct ast_str *fullkey;
+ int res;
+
+ if (ast_strlen_zero(family)) {
+ ast_destroy_realtime(ast_db_family, "key LIKE", "%", SENTINEL);
+ return 0;
+ }
+
+ if (!(fullkey = ast_str_create(256))) {
+ return -1;
+ }
+
+ if (!ast_strlen_zero(subfamily)) {
+ /* Family and key tree */
+ ast_str_set(&fullkey, 0, "/%s/%s/%%", family, subfamily);
+ } else {
+ /* Family only */
+ ast_str_set(&fullkey, 0, "/%s/%%", family);
+ }
+
+ res = ast_destroy_realtime(ast_db_family, "key LIKE", ast_str_buffer(fullkey), SENTINEL);
+ ast_free(fullkey);
return res;
}
-static int db_open(void)
-{
- char *dbname;
- struct stat dont_care;
-
- if (!(dbname = alloca(strlen(ast_config_AST_DB) + sizeof(".sqlite3")))) {
- return -1;
- }
- strcpy(dbname, ast_config_AST_DB);
- strcat(dbname, ".sqlite3");
-
- if (stat(dbname, &dont_care) && !stat(ast_config_AST_DB, &dont_care)) {
- if (convert_bdb_to_sqlite3()) {
- ast_log(LOG_ERROR, "*** Database conversion failed!\n");
- ast_log(LOG_ERROR, "*** Asterisk now uses SQLite3 for its internal\n");
- ast_log(LOG_ERROR, "*** database. Conversion from the old astdb\n");
- ast_log(LOG_ERROR, "*** failed. Most likely the astdb2sqlite3 utility\n");
- ast_log(LOG_ERROR, "*** was not selected for build. To convert the\n");
- ast_log(LOG_ERROR, "*** old astdb, please delete '%s'\n", dbname);
- ast_log(LOG_ERROR, "*** and re-run 'make menuselect' and select astdb2sqlite3\n");
- ast_log(LOG_ERROR, "*** in the Utilities section, then 'make && make install'.\n");
- ast_log(LOG_ERROR, "*** It is also imperative that the user under which\n");
- ast_log(LOG_ERROR, "*** Asterisk runs have write permission to the directory\n");
- ast_log(LOG_ERROR, "*** where the database resides.\n");
- sleep(5);
- } else {
- ast_log(LOG_NOTICE, "Database conversion succeeded!\n");
- }
- }
-
- ast_mutex_lock(&dblock);
- if (sqlite3_open(dbname, &astdb) != SQLITE_OK) {
- ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb));
- sqlite3_close(astdb);
- ast_mutex_unlock(&dblock);
- return -1;
- }
- ast_mutex_unlock(&dblock);
-
- return 0;
-}
-
-static int db_init(void)
-{
- if (astdb) {
- return 0;
- }
-
- if (db_open() || db_create_astdb() || init_statements()) {
- return -1;
- }
-
- return 0;
-}
-
-/* We purposely don't lock around the sqlite3 call because the transaction
- * calls will be called with the database lock held. For any other use, make
- * sure to take the dblock yourself. */
-static int db_execute_sql(const char *sql, int (*callback)(void *, int, char **, char **), void *arg)
-{
- char *errmsg = NULL;
- int res =0;
-
- sqlite3_exec(astdb, sql, callback, arg, &errmsg);
- if (errmsg) {
- ast_log(LOG_WARNING, "Error executing SQL: %s\n", errmsg);
- sqlite3_free(errmsg);
- res = -1;
- }
-
- return res;
-}
-
-static int ast_db_begin_transaction(void)
-{
- return db_execute_sql("BEGIN TRANSACTION", NULL, NULL);
-}
-
-static int ast_db_commit_transaction(void)
-{
- return db_execute_sql("COMMIT", NULL, NULL);
-}
-
-static int ast_db_rollback_transaction(void)
-{
- return db_execute_sql("ROLLBACK", NULL, NULL);
-}
-
-int ast_db_put(const char *family, const char *key, const char *value)
-{
- char fullkey[MAX_DB_FIELD];
- size_t fullkey_len;
- int res = 0;
-
- if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
- ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
- return -1;
- }
-
- fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
-
- ast_mutex_lock(&dblock);
- if (sqlite3_bind_text(put_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
- ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
- res = -1;
- } else if (sqlite3_bind_text(put_stmt, 2, value, -1, SQLITE_STATIC) != SQLITE_OK) {
- ast_log(LOG_WARNING, "Couldn't bind value to stmt: %s\n", sqlite3_errmsg(astdb));
- res = -1;
- } else if (sqlite3_step(put_stmt) != SQLITE_DONE) {
- ast_log(LOG_WARNING, "Couldn't execute statment: %s\n", sqlite3_errmsg(astdb));
- res = -1;
- }
-
- sqlite3_reset(put_stmt);
- db_sync();
- ast_mutex_unlock(&dblock);
-
- return res;
-}
-
-int ast_db_get(const char *family, const char *key, char *value, int valuelen)
-{
- const unsigned char *result;
- char fullkey[MAX_DB_FIELD];
- size_t fullkey_len;
- int res = 0;
-
- if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
- ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
- return -1;
- }
-
- fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
-
- ast_mutex_lock(&dblock);
- if (sqlite3_bind_text(get_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
- ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
- res = -1;
- } else if (sqlite3_step(get_stmt) != SQLITE_ROW) {
- ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
- res = -1;
- } else if (!(result = sqlite3_column_text(get_stmt, 0))) {
- ast_log(LOG_WARNING, "Couldn't get value\n");
- res = -1;
- } else {
- strncpy(value, (const char *) result, valuelen);
- }
- sqlite3_reset(get_stmt);
- ast_mutex_unlock(&dblock);
-
- return res;
-}
-
-int ast_db_del(const char *family, const char *key)
-{
- char fullkey[MAX_DB_FIELD];
- size_t fullkey_len;
- int res = 0;
-
- if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
- ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
- return -1;
- }
-
- fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
-
- ast_mutex_lock(&dblock);
- if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
- ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
- res = -1;
- } else if (sqlite3_step(del_stmt) != SQLITE_DONE) {
- ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
- res = -1;
- }
- sqlite3_reset(del_stmt);
- db_sync();
- ast_mutex_unlock(&dblock);
-
- return res;
-}
-
-int ast_db_deltree(const char *family, const char *subfamily)
-{
- sqlite3_stmt *stmt = deltree_stmt;
- char prefix[MAX_DB_FIELD];
- int res = 0;
+struct ast_db_entry *ast_db_gettree(const char *family, const char *subfamily)
+{
+ struct ast_str *fullkey;
+ struct ast_config *results = NULL;
+ struct ast_db_entry *cur, *ret = NULL, *last = NULL;
+ const char *cat;
+
+ if (!(fullkey = ast_str_create(256))) {
+ return NULL;
+ }
if (!ast_strlen_zero(family)) {
if (!ast_strlen_zero(subfamily)) {
/* Family and key tree */
- snprintf(prefix, sizeof(prefix), "/%s/%s", family, subfamily);
+ ast_str_set(&fullkey, 0, "/%s/%s/%%", family, subfamily);
} else {
/* Family only */
- snprintf(prefix, sizeof(prefix), "/%s", family);
- }
+ ast_str_set(&fullkey, 0, "/%s/%%", family);
+ }
+ results = ast_load_realtime_multientry(ast_db_family, "key LIKE", ast_str_buffer(fullkey), SENTINEL);
} else {
- prefix[0] = '\0';
- stmt = deltree_all_stmt;
- }
-
- ast_mutex_lock(&dblock);
- if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
- ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
- res = -1;
- } else if (sqlite3_step(stmt) != SQLITE_DONE) {
- ast_log(LOG_WARNING, "Couldn't execute stmt: %s\n", sqlite3_errmsg(astdb));
- res = -1;
- }
- res = sqlite3_changes(astdb);
- sqlite3_reset(stmt);
- db_sync();
- ast_mutex_unlock(&dblock);
-
- return res;
-}
-
-struct ast_db_entry *ast_db_gettree(const char *family, const char *subfamily)
-{
- char prefix[MAX_DB_FIELD];
- sqlite3_stmt *stmt = gettree_stmt;
- struct ast_db_entry *cur, *last = NULL, *ret = NULL;
-
- if (!ast_strlen_zero(family)) {
- if (!ast_strlen_zero(subfamily)) {
- /* Family and key tree */
- snprintf(prefix, sizeof(prefix), "/%s/%s", family, subfamily);
- } else {
- /* Family only */
- snprintf(prefix, sizeof(prefix), "/%s", family);
- }
- } else {
- prefix[0] = '\0';
- stmt = gettree_all_stmt;
- }
-
- ast_mutex_lock(&dblock);
- if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
- ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
- sqlite3_reset(stmt);
- ast_mutex_unlock(&dblock);
+ results = ast_load_realtime_multientry(ast_db_family, "key LIKE", "%", SENTINEL);
+ }
+
+ ast_free(fullkey);
+
+ if (!results) {
return NULL;
}
- while (sqlite3_step(stmt) == SQLITE_ROW) {
- const char *key_s, *value_s;
- if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
+ for (cat = ast_category_browse(results, NULL); cat; cat = ast_category_browse(results, cat)) {
+ struct ast_variable *var;
+ const char *key_s = NULL, *value_s = NULL;
+
+ for (var = ast_variable_browse(results, cat); var; var = var->next) {
+ if (!strcasecmp(var->name, ast_db_key)) {
+ key_s = var->value;
+ } else if (!strcasecmp(var->name, ast_db_value)) {
+ value_s = var->value;
+ }
+ }
+
+ if (!(key_s && value_s)) {
+ ast_log(LOG_WARNING, "Didn't have both a key and value. Skipping\n");
+ ast_config_destroy(results);
+ results = NULL;
break;
}
- if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
+
+ if (!(cur = ast_malloc(sizeof(*cur) + strlen(key_s) + strlen(value_s) + 2))) {
+ ast_config_destroy(results);
+ results = NULL;
break;
}
- if (!(cur = ast_malloc(sizeof(*cur) + strlen(key_s) + strlen(value_s) + 2))) {
- break;
- }
+
cur->next = NULL;
cur->key = cur->data + strlen(value_s) + 1;
strcpy(cur->data, value_s);
@@ -448,8 +203,8 @@
}
last = cur;
}
- sqlite3_reset(stmt);
- ast_mutex_unlock(&dblock);
+
+ ast_config_destroy(results);
return ret;
}
@@ -463,461 +218,3 @@
ast_free(last);
}
}
-
-static char *handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
- int res;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "database put";
- e->usage =
- "Usage: database put <family> <key> <value>\n"
- " Adds or updates an entry in the Asterisk database for\n"
- " a given family, key, and value.\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if (a->argc != 5)
- return CLI_SHOWUSAGE;
- res = ast_db_put(a->argv[2], a->argv[3], a->argv[4]);
- if (res) {
- ast_cli(a->fd, "Failed to update entry\n");
- } else {
- ast_cli(a->fd, "Updated database successfully\n");
- }
- return CLI_SUCCESS;
-}
-
-static char *handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
- int res;
- char tmp[MAX_DB_FIELD];
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "database get";
- e->usage =
- "Usage: database get <family> <key>\n"
- " Retrieves an entry in the Asterisk database for a given\n"
- " family and key.\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if (a->argc != 4)
- return CLI_SHOWUSAGE;
- res = ast_db_get(a->argv[2], a->argv[3], tmp, sizeof(tmp));
- if (res) {
- ast_cli(a->fd, "Database entry not found.\n");
- } else {
- ast_cli(a->fd, "Value: %s\n", tmp);
- }
- return CLI_SUCCESS;
-}
-
-static char *handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
- int res;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "database del";
- e->usage =
- "Usage: database del <family> <key>\n"
- " Deletes an entry in the Asterisk database for a given\n"
- " family and key.\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if (a->argc != 4)
- return CLI_SHOWUSAGE;
- res = ast_db_del(a->argv[2], a->argv[3]);
- if (res) {
- ast_cli(a->fd, "Database entry does not exist.\n");
- } else {
- ast_cli(a->fd, "Database entry removed.\n");
- }
- return CLI_SUCCESS;
-}
-
-static char *handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
- int res;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "database deltree";
- e->usage =
- "Usage: database deltree <family> [subfamily]\n"
- " Deletes a family or specific subfamily within a family\n"
- " in the Asterisk database.\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if ((a->argc < 3) || (a->argc > 4))
- return CLI_SHOWUSAGE;
- if (a->argc == 4) {
- res = ast_db_deltree(a->argv[2], a->argv[3]);
- } else {
- res = ast_db_deltree(a->argv[2], NULL);
- }
- if (res < 0) {
- ast_cli(a->fd, "Database entries do not exist.\n");
- } else {
- ast_cli(a->fd, "%d database entries removed.\n",res);
- }
- return CLI_SUCCESS;
-}
-
-static char *handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
- char prefix[MAX_DB_FIELD];
- int counter = 0;
- sqlite3_stmt *stmt = gettree_stmt;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "database show";
- e->usage =
- "Usage: database show [family [subfamily]]\n"
- " Shows Asterisk database contents, optionally restricted\n"
- " to a given family, or family and subfamily.\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if (a->argc == 4) {
- /* Family and key tree */
- snprintf(prefix, sizeof(prefix), "/%s/%s", a->argv[2], a->argv[3]);
- } else if (a->argc == 3) {
- /* Family only */
- snprintf(prefix, sizeof(prefix), "/%s", a->argv[2]);
- } else if (a->argc == 2) {
- /* Neither */
- prefix[0] = '\0';
- stmt = gettree_all_stmt;
-
- } else {
- return CLI_SHOWUSAGE;
- }
-
- ast_mutex_lock(&dblock);
- if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
- ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
- sqlite3_reset(stmt);
- ast_mutex_unlock(&dblock);
- return NULL;
- }
-
- while (sqlite3_step(stmt) == SQLITE_ROW) {
- const char *key_s, *value_s;
- if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
- ast_log(LOG_WARNING, "Skipping invalid key!\n");
- continue;
- }
- if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
- ast_log(LOG_WARNING, "Skipping invalid value!\n");
- continue;
- }
- ++counter;
- ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
- }
-
- sqlite3_reset(stmt);
- ast_mutex_unlock(&dblock);
-
- ast_cli(a->fd, "%d results found.\n", counter);
- return CLI_SUCCESS;
-}
-
-static char *handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
- int counter = 0;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "database showkey";
- e->usage =
- "Usage: database showkey <subfamily>\n"
- " Shows Asterisk database contents, restricted to a given key.\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if (a->argc != 3) {
- return CLI_SHOWUSAGE;
- }
-
- ast_mutex_lock(&dblock);
- if (!ast_strlen_zero(a->argv[2]) && (sqlite3_bind_text(showkey_stmt, 1, a->argv[2], -1, SQLITE_STATIC) != SQLITE_OK)) {
- ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", a->argv[2], sqlite3_errmsg(astdb));
- sqlite3_reset(showkey_stmt);
- ast_mutex_unlock(&dblock);
- return NULL;
- }
-
- while (sqlite3_step(showkey_stmt) == SQLITE_ROW) {
- const char *key_s, *value_s;
- if (!(key_s = (const char *) sqlite3_column_text(showkey_stmt, 0))) {
- break;
- }
- if (!(value_s = (const char *) sqlite3_column_text(showkey_stmt, 1))) {
- break;
- }
- ++counter;
- ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
- }
- sqlite3_reset(showkey_stmt);
- ast_mutex_unlock(&dblock);
-
- ast_cli(a->fd, "%d results found.\n", counter);
- return CLI_SUCCESS;
-}
-
-static int display_results(void *arg, int columns, char **values, char **colnames)
-{
- struct ast_cli_args *a = arg;
- size_t x;
-
- for (x = 0; x < columns; x++) {
- ast_cli(a->fd, "%-5s: %-50s\n", colnames[x], values[x]);
- }
- ast_cli(a->fd, "\n");
-
- return 0;
-}
-
-static char *handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "database query";
- e->usage =
- "Usage: database query \"<SQL Statement>\"\n"
- " Run a user-specified SQL query on the database. Be careful.\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if (a->argc != 3) {
- return CLI_SHOWUSAGE;
- }
-
- ast_mutex_lock(&dblock);
- db_execute_sql(a->argv[2], display_results, a);
- db_sync(); /* Go ahead and sync the db in case they write */
- ast_mutex_unlock(&dblock);
-
- return CLI_SUCCESS;
-}
-
-static struct ast_cli_entry cli_database[] = {
- AST_CLI_DEFINE(handle_cli_database_show, "Shows database contents"),
- AST_CLI_DEFINE(handle_cli_database_showkey, "Shows database contents"),
- AST_CLI_DEFINE(handle_cli_database_get, "Gets database value"),
- AST_CLI_DEFINE(handle_cli_database_put, "Adds/updates database value"),
- AST_CLI_DEFINE(handle_cli_database_del, "Removes database key/value"),
- AST_CLI_DEFINE(handle_cli_database_deltree, "Removes database subfamily/values"),
- AST_CLI_DEFINE(handle_cli_database_query, "Run a user-specified query on the astdb"),
-};
-
-static int manager_dbput(struct mansession *s, const struct message *m)
-{
- const char *family = astman_get_header(m, "Family");
- const char *key = astman_get_header(m, "Key");
- const char *val = astman_get_header(m, "Val");
- int res;
-
- if (ast_strlen_zero(family)) {
- astman_send_error(s, m, "No family specified");
- return 0;
- }
- if (ast_strlen_zero(key)) {
- astman_send_error(s, m, "No key specified");
- return 0;
- }
-
- res = ast_db_put(family, key, S_OR(val, ""));
- if (res) {
- astman_send_error(s, m, "Failed to update entry");
- } else {
- astman_send_ack(s, m, "Updated database successfully");
- }
- return 0;
-}
-
-static int manager_dbget(struct mansession *s, const struct message *m)
-{
- const char *id = astman_get_header(m,"ActionID");
- char idText[256] = "";
- const char *family = astman_get_header(m, "Family");
- const char *key = astman_get_header(m, "Key");
- char tmp[MAX_DB_FIELD];
- int res;
-
- if (ast_strlen_zero(family)) {
- astman_send_error(s, m, "No family specified.");
- return 0;
- }
- if (ast_strlen_zero(key)) {
- astman_send_error(s, m, "No key specified.");
- return 0;
- }
-
- if (!ast_strlen_zero(id))
- snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
-
- res = ast_db_get(family, key, tmp, sizeof(tmp));
- if (res) {
- astman_send_error(s, m, "Database entry not found");
- } else {
- astman_send_ack(s, m, "Result will follow");
- astman_append(s, "Event: DBGetResponse\r\n"
- "Family: %s\r\n"
- "Key: %s\r\n"
- "Val: %s\r\n"
- "%s"
- "\r\n",
- family, key, tmp, idText);
- astman_append(s, "Event: DBGetComplete\r\n"
- "%s"
- "\r\n",
- idText);
- }
- return 0;
-}
-
-static int manager_dbdel(struct mansession *s, const struct message *m)
-{
- const char *family = astman_get_header(m, "Family");
- const char *key = astman_get_header(m, "Key");
- int res;
-
- if (ast_strlen_zero(family)) {
- astman_send_error(s, m, "No family specified.");
- return 0;
- }
-
- if (ast_strlen_zero(key)) {
- astman_send_error(s, m, "No key specified.");
- return 0;
- }
-
- res = ast_db_del(family, key);
- if (res)
- astman_send_error(s, m, "Database entry not found");
- else
- astman_send_ack(s, m, "Key deleted successfully");
-
- return 0;
-}
-
-static int manager_dbdeltree(struct mansession *s, const struct message *m)
-{
- const char *family = astman_get_header(m, "Family");
- const char *key = astman_get_header(m, "Key");
- int res;
-
- if (ast_strlen_zero(family)) {
- astman_send_error(s, m, "No family specified.");
- return 0;
- }
-
- if (!ast_strlen_zero(key))
- res = ast_db_deltree(family, key);
- else
- res = ast_db_deltree(family, NULL);
-
- if (res <= 0)
- astman_send_error(s, m, "Database entry not found");
- else
- astman_send_ack(s, m, "Key tree deleted successfully");
-
- return 0;
-}
-
-/*!
- * \internal
- * \brief Signal the astdb sync thread to do its thing.
- *
- * \note dblock is assumed to be held when calling this function.
- */
-static void db_sync(void)
-{
- ast_cond_signal(&dbcond);
-}
-
-/*!
- * \internal
- * \brief astdb sync thread
- *
- * This thread is in charge of syncing astdb to disk after a change.
- * By pushing it off to this thread to take care of, this I/O bound operation
- * will not block other threads from performing other critical processing.
- * If changes happen rapidly, this thread will also ensure that the sync
- * operations are rate limited.
- */
-static void *db_sync_thread(void *data)
-{
- ast_mutex_lock(&dblock);
- ast_db_begin_transaction();
- for (;;) {
- /* We're ok with spurious wakeups, so we don't worry about a predicate */
- ast_cond_wait(&dbcond, &dblock);
- if (ast_db_commit_transaction()) {
- ast_db_rollback_transaction();
- }
- if (doexit) {
- ast_mutex_unlock(&dblock);
- break;
- }
- ast_db_begin_transaction();
- ast_mutex_unlock(&dblock);
- sleep(1);
- ast_mutex_lock(&dblock);
- }
-
- return NULL;
-}
-
-static void astdb_atexit(void)
-{
- doexit = 1;
- db_sync();
- pthread_join(syncthread, NULL);
- ast_mutex_lock(&dblock);
- sqlite3_close(astdb);
- ast_mutex_unlock(&dblock);
-}
-
-int astdb_init(void)
-{
- if (db_init()) {
- return -1;
- }
-
- ast_cond_init(&dbcond, NULL);
- if (ast_pthread_create_background(&syncthread, NULL, db_sync_thread, NULL)) {
- return -1;
- }
-
- ast_register_atexit(astdb_atexit);
- ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database));
- ast_manager_register_xml("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget);
- ast_manager_register_xml("DBPut", EVENT_FLAG_SYSTEM, manager_dbput);
- ast_manager_register_xml("DBDel", EVENT_FLAG_SYSTEM, manager_dbdel);
- ast_manager_register_xml("DBDelTree", EVENT_FLAG_SYSTEM, manager_dbdeltree);
- return 0;
-}
Added: team/twilson/sqlite3_playground/res/res_astdb.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/sqlite3_playground/res/res_astdb.c?view=auto&rev=341867
==============================================================================
--- team/twilson/sqlite3_playground/res/res_astdb.c (added)
+++ team/twilson/sqlite3_playground/res/res_astdb.c Fri Oct 21 22:34:13 2011
@@ -1,0 +1,456 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2005, Digium, Inc.
+ *
+ * Mark Spencer <markster at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Asterisk Internal Realtime Database
+ *
+ * \author Terry Wilson
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/module.h"
+#include "asterisk/astdb.h"
+#include "asterisk/cli.h"
+#include "asterisk/strings.h"
+#include "asterisk/utils.h"
+#include "asterisk/manager.h"
+#include "asterisk/config.h"
+
+/*** DOCUMENTATION
+ <manager name="DBGet" language="en_US">
+ <synopsis>
+ Get DB Entry.
+ </synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+ <parameter name="Family" required="true" />
+ <parameter name="Key" required="true" />
+ </syntax>
+ <description>
+ </description>
+ </manager>
+ <manager name="DBPut" language="en_US">
+ <synopsis>
+ Put DB entry.
+ </synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+ <parameter name="Family" required="true" />
+ <parameter name="Key" required="true" />
+ <parameter name="Val" />
+ </syntax>
+ <description>
+ </description>
+ </manager>
+ <manager name="DBDel" language="en_US">
+ <synopsis>
+ Delete DB entry.
+ </synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+ <parameter name="Family" required="true" />
+ <parameter name="Key" required="true" />
+ </syntax>
+ <description>
+ </description>
+ </manager>
+ <manager name="DBDelTree" language="en_US">
+ <synopsis>
+ Delete DB Tree.
+ </synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+ <parameter name="Family" required="true" />
+ <parameter name="Key" />
+ </syntax>
+ <description>
+ </description>
+ </manager>
+ ***/
+
+#define MAX_DB_FIELD 256
+
+static char *handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ int res;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "database put";
+ e->usage =
+ "Usage: database put <family> <key> <value>\n"
+ " Adds or updates an entry in the Asterisk database for\n"
+ " a given family, key, and value.\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc != 5)
+ return CLI_SHOWUSAGE;
+ res = ast_db_put(a->argv[2], a->argv[3], a->argv[4]);
+ if (res) {
+ ast_cli(a->fd, "Failed to update entry\n");
+ } else {
+ ast_cli(a->fd, "Updated database successfully\n");
+ }
+ return CLI_SUCCESS;
+}
+
+static char *handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ int res;
+ char tmp[MAX_DB_FIELD];
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "database get";
+ e->usage =
+ "Usage: database get <family> <key>\n"
+ " Retrieves an entry in the Asterisk database for a given\n"
+ " family and key.\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc != 4)
+ return CLI_SHOWUSAGE;
+ res = ast_db_get(a->argv[2], a->argv[3], tmp, sizeof(tmp));
+ if (res) {
+ ast_cli(a->fd, "Database entry not found.\n");
+ } else {
+ ast_cli(a->fd, "Value: %s\n", tmp);
+ }
+ return CLI_SUCCESS;
+}
+
+static char *handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ int res;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "database del";
+ e->usage =
+ "Usage: database del <family> <key>\n"
+ " Deletes an entry in the Asterisk database for a given\n"
+ " family and key.\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc != 4)
+ return CLI_SHOWUSAGE;
+ res = ast_db_del(a->argv[2], a->argv[3]);
+ if (res) {
+ ast_cli(a->fd, "Database entry does not exist.\n");
+ } else {
+ ast_cli(a->fd, "Database entry removed.\n");
+ }
+ return CLI_SUCCESS;
+}
+
+static char *handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ int res;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "database deltree";
+ e->usage =
+ "Usage: database deltree <family> [subfamily]\n"
+ " Deletes a family or specific subfamily within a family\n"
+ " in the Asterisk database.\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if ((a->argc < 3) || (a->argc > 4))
+ return CLI_SHOWUSAGE;
+ if (a->argc == 4) {
+ res = ast_db_deltree(a->argv[2], a->argv[3]);
+ } else {
+ res = ast_db_deltree(a->argv[2], NULL);
+ }
+ if (res < 0) {
+ ast_cli(a->fd, "Database entries do not exist.\n");
+ } else {
+ ast_cli(a->fd, "%d database entries removed.\n",res);
+ }
+ return CLI_SUCCESS;
+}
+
+static char *handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ int counter = 0;
+ struct ast_db_entry *results = NULL, *iter;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "database show";
+ e->usage =
+ "Usage: database show [family [subfamily]]\n"
+ " Shows Asterisk database contents, optionally restricted\n"
+ " to a given family, or family and subfamily.\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc == 4) {
+ /* Family and key tree */
+ results = ast_db_gettree(a->argv[2], a->argv[3]);
+ } else if (a->argc == 3) {
+ /* Family only */
+ results = ast_db_gettree(a->argv[2], NULL);
+ } else if (a->argc == 2) {
+ results = ast_db_gettree(NULL, NULL);
+ } else {
+ return CLI_SHOWUSAGE;
+ }
+
+ for (iter = results; iter; iter = iter->next) {
+ const char *key_s = iter->key, *value_s = iter->data;
+
+ if (!(key_s && value_s)) {
+ ast_log(LOG_WARNING, "Invalid key or value. Skipping.\n");
+ continue;
+ }
+
+ ++counter;
+ ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
+ }
+
+ ast_db_freetree(results);
+
+ ast_cli(a->fd, "%d results found.\n", counter);
+ return CLI_SUCCESS;
+}
+
+static char *handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ int counter = 0;
+ struct ast_str *lookup;
+ struct ast_config *results;
+ const char *cat;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "database showkey";
+ e->usage =
+ "Usage: database showkey <subfamily>\n"
[... 270 lines stripped ...]
More information about the asterisk-commits
mailing list