2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief ASTdb Management
23 * \author Mark Spencer <markster@digium.com>
25 * \note DB3 is licensed under Sleepycat Public License and is thus incompatible
26 * with GPL. To avoid having to make another exception (and complicate
27 * licensing even further) we elect to use DB1 which is BSD licensed
31 <support_level>core</support_level>
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
38 #include "asterisk/_private.h"
39 #include "asterisk/paths.h" /* use ast_config_AST_DB */
41 #include <sys/types.h>
48 #include "asterisk/channel.h"
49 #include "asterisk/file.h"
50 #include "asterisk/app.h"
51 #include "asterisk/dsp.h"
52 #include "asterisk/astdb.h"
53 #include "asterisk/cli.h"
54 #include "asterisk/utils.h"
55 #include "asterisk/manager.h"
58 <manager name="DBGet" language="en_US">
63 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
64 <parameter name="Family" required="true" />
65 <parameter name="Key" required="true" />
70 <manager name="DBPut" language="en_US">
75 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
76 <parameter name="Family" required="true" />
77 <parameter name="Key" required="true" />
78 <parameter name="Val" />
83 <manager name="DBDel" language="en_US">
88 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
89 <parameter name="Family" required="true" />
90 <parameter name="Key" required="true" />
95 <manager name="DBDelTree" language="en_US">
100 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
101 <parameter name="Family" required="true" />
102 <parameter name="Key" />
109 #define MAX_DB_FIELD 256
110 AST_MUTEX_DEFINE_STATIC(dblock);
111 static ast_cond_t dbcond;
112 static sqlite3 *astdb;
113 static pthread_t syncthread;
116 static void db_sync(void);
118 #define DEFINE_SQL_STATEMENT(stmt,sql) static sqlite3_stmt *stmt; \
119 const char stmt##_sql[] = sql;
121 DEFINE_SQL_STATEMENT(put_stmt, "INSERT OR REPLACE INTO astdb (key, value) VALUES (?, ?)")
122 DEFINE_SQL_STATEMENT(get_stmt, "SELECT value FROM astdb WHERE key=?")
123 DEFINE_SQL_STATEMENT(del_stmt, "DELETE FROM astdb WHERE key=?")
124 DEFINE_SQL_STATEMENT(deltree_stmt, "DELETE FROM astdb WHERE key || '/' LIKE ? || '/' || '%'")
125 DEFINE_SQL_STATEMENT(deltree_all_stmt, "DELETE FROM astdb")
126 DEFINE_SQL_STATEMENT(gettree_stmt, "SELECT key, value FROM astdb WHERE key || '/' LIKE ? || '/' || '%' ORDER BY key")
127 DEFINE_SQL_STATEMENT(gettree_all_stmt, "SELECT key, value FROM astdb ORDER BY key")
128 DEFINE_SQL_STATEMENT(showkey_stmt, "SELECT key, value FROM astdb WHERE key LIKE '%' || '/' || ? ORDER BY key")
129 DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key VARCHAR(256), value VARCHAR(256), PRIMARY KEY(key))")
131 static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len)
133 ast_mutex_lock(&dblock);
134 if (sqlite3_prepare(astdb, sql, len, stmt, NULL) != SQLITE_OK) {
135 ast_log(LOG_WARNING, "Couldn't prepare statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
136 ast_mutex_unlock(&dblock);
139 ast_mutex_unlock(&dblock);
144 static int init_statements(void)
146 /* Don't initialize create_astdb_statment here as the astdb table needs to exist
147 * brefore these statments can be initialized */
148 return init_stmt(&get_stmt, get_stmt_sql, sizeof(get_stmt_sql))
149 || init_stmt(&del_stmt, del_stmt_sql, sizeof(del_stmt_sql))
150 || init_stmt(&deltree_stmt, deltree_stmt_sql, sizeof(deltree_stmt_sql))
151 || init_stmt(&deltree_all_stmt, deltree_all_stmt_sql, sizeof(deltree_all_stmt_sql))
152 || init_stmt(&gettree_stmt, gettree_stmt_sql, sizeof(gettree_stmt_sql))
153 || init_stmt(&gettree_all_stmt, gettree_all_stmt_sql, sizeof(gettree_all_stmt_sql))
154 || init_stmt(&showkey_stmt, showkey_stmt_sql, sizeof(showkey_stmt_sql))
155 || init_stmt(&put_stmt, put_stmt_sql, sizeof(put_stmt_sql));
158 static int convert_bdb_to_sqlite3(void)
163 ast_asprintf(&cmd, "%s/astdb2sqlite3 '%s'\n", ast_config_AST_SBIN_DIR, ast_config_AST_DB);
164 res = ast_safe_system(cmd);
170 static int db_create_astdb(void)
174 if (!create_astdb_stmt) {
175 init_stmt(&create_astdb_stmt, create_astdb_stmt_sql, sizeof(create_astdb_stmt_sql));
178 ast_mutex_lock(&dblock);
179 if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) {
180 ast_log(LOG_WARNING, "Couldn't create astdb table: %s\n", sqlite3_errmsg(astdb));
183 sqlite3_reset(create_astdb_stmt);
185 ast_mutex_unlock(&dblock);
190 static int db_open(void)
193 struct stat dont_care;
195 if (!(dbname = ast_alloca(strlen(ast_config_AST_DB) + sizeof(".sqlite3")))) {
198 strcpy(dbname, ast_config_AST_DB);
199 strcat(dbname, ".sqlite3");
201 if (stat(dbname, &dont_care) && !stat(ast_config_AST_DB, &dont_care)) {
202 if (convert_bdb_to_sqlite3()) {
203 ast_log(LOG_ERROR, "*** Database conversion failed!\n");
204 ast_log(LOG_ERROR, "*** Asterisk now uses SQLite3 for its internal\n");
205 ast_log(LOG_ERROR, "*** database. Conversion from the old astdb\n");
206 ast_log(LOG_ERROR, "*** failed. Most likely the astdb2sqlite3 utility\n");
207 ast_log(LOG_ERROR, "*** was not selected for build. To convert the\n");
208 ast_log(LOG_ERROR, "*** old astdb, please delete '%s'\n", dbname);
209 ast_log(LOG_ERROR, "*** and re-run 'make menuselect' and select astdb2sqlite3\n");
210 ast_log(LOG_ERROR, "*** in the Utilities section, then 'make && make install'.\n");
211 ast_log(LOG_ERROR, "*** It is also imperative that the user under which\n");
212 ast_log(LOG_ERROR, "*** Asterisk runs have write permission to the directory\n");
213 ast_log(LOG_ERROR, "*** where the database resides.\n");
216 ast_log(LOG_NOTICE, "Database conversion succeeded!\n");
220 ast_mutex_lock(&dblock);
221 if (sqlite3_open(dbname, &astdb) != SQLITE_OK) {
222 ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb));
223 sqlite3_close(astdb);
224 ast_mutex_unlock(&dblock);
227 ast_mutex_unlock(&dblock);
232 static int db_init(void)
238 if (db_open() || db_create_astdb() || init_statements()) {
245 /* We purposely don't lock around the sqlite3 call because the transaction
246 * calls will be called with the database lock held. For any other use, make
247 * sure to take the dblock yourself. */
248 static int db_execute_sql(const char *sql, int (*callback)(void *, int, char **, char **), void *arg)
253 sqlite3_exec(astdb, sql, callback, arg, &errmsg);
255 ast_log(LOG_WARNING, "Error executing SQL: %s\n", errmsg);
256 sqlite3_free(errmsg);
263 static int ast_db_begin_transaction(void)
265 return db_execute_sql("BEGIN TRANSACTION", NULL, NULL);
268 static int ast_db_commit_transaction(void)
270 return db_execute_sql("COMMIT", NULL, NULL);
273 static int ast_db_rollback_transaction(void)
275 return db_execute_sql("ROLLBACK", NULL, NULL);
278 int ast_db_put(const char *family, const char *key, const char *value)
280 char fullkey[MAX_DB_FIELD];
284 if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
285 ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
289 fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
291 ast_mutex_lock(&dblock);
292 if (sqlite3_bind_text(put_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
293 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
295 } else if (sqlite3_bind_text(put_stmt, 2, value, -1, SQLITE_STATIC) != SQLITE_OK) {
296 ast_log(LOG_WARNING, "Couldn't bind value to stmt: %s\n", sqlite3_errmsg(astdb));
298 } else if (sqlite3_step(put_stmt) != SQLITE_DONE) {
299 ast_log(LOG_WARNING, "Couldn't execute statment: %s\n", sqlite3_errmsg(astdb));
303 sqlite3_reset(put_stmt);
305 ast_mutex_unlock(&dblock);
312 * \brief Get key value specified by family/key.
314 * Gets the value associated with the specified \a family and \a key, and
315 * stores it, either into the fixed sized buffer specified by \a buffer
316 * and \a bufferlen, or as a heap allocated string if \a bufferlen is -1.
318 * \note If \a bufferlen is -1, \a buffer points to heap allocated memory
319 * and must be freed by calling ast_free().
321 * \retval -1 An error occurred
324 static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen)
326 const unsigned char *result;
327 char fullkey[MAX_DB_FIELD];
331 if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
332 ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
336 fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
338 ast_mutex_lock(&dblock);
339 if (sqlite3_bind_text(get_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
340 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
342 } else if (sqlite3_step(get_stmt) != SQLITE_ROW) {
343 ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
345 } else if (!(result = sqlite3_column_text(get_stmt, 0))) {
346 ast_log(LOG_WARNING, "Couldn't get value\n");
349 const char *value = (const char *) result;
351 if (bufferlen == -1) {
352 *buffer = ast_strdup(value);
354 ast_copy_string(*buffer, value, bufferlen);
357 sqlite3_reset(get_stmt);
358 ast_mutex_unlock(&dblock);
363 int ast_db_get(const char *family, const char *key, char *value, int valuelen)
365 ast_assert(value != NULL);
367 /* Make sure we initialize */
370 return db_get_common(family, key, &value, valuelen);
373 int ast_db_get_allocated(const char *family, const char *key, char **out)
377 return db_get_common(family, key, out, -1);
380 int ast_db_del(const char *family, const char *key)
382 char fullkey[MAX_DB_FIELD];
386 if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
387 ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
391 fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
393 ast_mutex_lock(&dblock);
394 if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
395 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
397 } else if (sqlite3_step(del_stmt) != SQLITE_DONE) {
398 ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
401 sqlite3_reset(del_stmt);
403 ast_mutex_unlock(&dblock);
408 int ast_db_deltree(const char *family, const char *keytree)
410 sqlite3_stmt *stmt = deltree_stmt;
411 char prefix[MAX_DB_FIELD];
414 if (!ast_strlen_zero(family)) {
415 if (!ast_strlen_zero(keytree)) {
416 /* Family and key tree */
417 snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
420 snprintf(prefix, sizeof(prefix), "/%s", family);
424 stmt = deltree_all_stmt;
427 ast_mutex_lock(&dblock);
428 if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
429 ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
431 } else if (sqlite3_step(stmt) != SQLITE_DONE) {
432 ast_log(LOG_WARNING, "Couldn't execute stmt: %s\n", sqlite3_errmsg(astdb));
435 res = sqlite3_changes(astdb);
438 ast_mutex_unlock(&dblock);
443 struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
445 char prefix[MAX_DB_FIELD];
446 sqlite3_stmt *stmt = gettree_stmt;
447 struct ast_db_entry *cur, *last = NULL, *ret = NULL;
449 if (!ast_strlen_zero(family)) {
450 if (!ast_strlen_zero(keytree)) {
451 /* Family and key tree */
452 snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
455 snprintf(prefix, sizeof(prefix), "/%s", family);
459 stmt = gettree_all_stmt;
462 ast_mutex_lock(&dblock);
463 if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
464 ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
466 ast_mutex_unlock(&dblock);
470 while (sqlite3_step(stmt) == SQLITE_ROW) {
471 const char *key_s, *value_s;
472 if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
475 if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
478 if (!(cur = ast_malloc(sizeof(*cur) + strlen(key_s) + strlen(value_s) + 2))) {
482 cur->key = cur->data + strlen(value_s) + 1;
483 strcpy(cur->data, value_s);
484 strcpy(cur->key, key_s);
493 ast_mutex_unlock(&dblock);
498 void ast_db_freetree(struct ast_db_entry *dbe)
500 struct ast_db_entry *last;
508 static char *handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
514 e->command = "database put";
516 "Usage: database put <family> <key> <value>\n"
517 " Adds or updates an entry in the Asterisk database for\n"
518 " a given family, key, and value.\n";
525 return CLI_SHOWUSAGE;
526 res = ast_db_put(a->argv[2], a->argv[3], a->argv[4]);
528 ast_cli(a->fd, "Failed to update entry\n");
530 ast_cli(a->fd, "Updated database successfully\n");
535 static char *handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
538 char tmp[MAX_DB_FIELD];
542 e->command = "database get";
544 "Usage: database get <family> <key>\n"
545 " Retrieves an entry in the Asterisk database for a given\n"
546 " family and key.\n";
553 return CLI_SHOWUSAGE;
554 res = ast_db_get(a->argv[2], a->argv[3], tmp, sizeof(tmp));
556 ast_cli(a->fd, "Database entry not found.\n");
558 ast_cli(a->fd, "Value: %s\n", tmp);
563 static char *handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
569 e->command = "database del";
571 "Usage: database del <family> <key>\n"
572 " Deletes an entry in the Asterisk database for a given\n"
573 " family and key.\n";
580 return CLI_SHOWUSAGE;
581 res = ast_db_del(a->argv[2], a->argv[3]);
583 ast_cli(a->fd, "Database entry does not exist.\n");
585 ast_cli(a->fd, "Database entry removed.\n");
590 static char *handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
596 e->command = "database deltree";
598 "Usage: database deltree <family> [keytree]\n"
599 " OR: database deltree <family>[/keytree]\n"
600 " Deletes a family or specific keytree within a family\n"
601 " in the Asterisk database. The two arguments may be\n"
602 " separated by either a space or a slash.\n";
608 if ((a->argc < 3) || (a->argc > 4))
609 return CLI_SHOWUSAGE;
611 res = ast_db_deltree(a->argv[2], a->argv[3]);
613 res = ast_db_deltree(a->argv[2], NULL);
616 ast_cli(a->fd, "Database entries do not exist.\n");
618 ast_cli(a->fd, "%d database entries removed.\n",res);
623 static char *handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
625 char prefix[MAX_DB_FIELD];
627 sqlite3_stmt *stmt = gettree_stmt;
631 e->command = "database show";
633 "Usage: database show [family [keytree]]\n"
634 " OR: database show [family[/keytree]]\n"
635 " Shows Asterisk database contents, optionally restricted\n"
636 " to a given family, or family and keytree. The two arguments\n"
637 " may be separated either by a space or by a slash.\n";
644 /* Family and key tree */
645 snprintf(prefix, sizeof(prefix), "/%s/%s", a->argv[2], a->argv[3]);
646 } else if (a->argc == 3) {
648 snprintf(prefix, sizeof(prefix), "/%s", a->argv[2]);
649 } else if (a->argc == 2) {
652 stmt = gettree_all_stmt;
655 return CLI_SHOWUSAGE;
658 ast_mutex_lock(&dblock);
659 if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
660 ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
662 ast_mutex_unlock(&dblock);
666 while (sqlite3_step(stmt) == SQLITE_ROW) {
667 const char *key_s, *value_s;
668 if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
669 ast_log(LOG_WARNING, "Skipping invalid key!\n");
672 if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
673 ast_log(LOG_WARNING, "Skipping invalid value!\n");
677 ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
681 ast_mutex_unlock(&dblock);
683 ast_cli(a->fd, "%d results found.\n", counter);
687 static char *handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
693 e->command = "database showkey";
695 "Usage: database showkey <keytree>\n"
696 " Shows Asterisk database contents, restricted to a given key.\n";
703 return CLI_SHOWUSAGE;
706 ast_mutex_lock(&dblock);
707 if (!ast_strlen_zero(a->argv[2]) && (sqlite3_bind_text(showkey_stmt, 1, a->argv[2], -1, SQLITE_STATIC) != SQLITE_OK)) {
708 ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", a->argv[2], sqlite3_errmsg(astdb));
709 sqlite3_reset(showkey_stmt);
710 ast_mutex_unlock(&dblock);
714 while (sqlite3_step(showkey_stmt) == SQLITE_ROW) {
715 const char *key_s, *value_s;
716 if (!(key_s = (const char *) sqlite3_column_text(showkey_stmt, 0))) {
719 if (!(value_s = (const char *) sqlite3_column_text(showkey_stmt, 1))) {
723 ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
725 sqlite3_reset(showkey_stmt);
726 ast_mutex_unlock(&dblock);
728 ast_cli(a->fd, "%d results found.\n", counter);
732 static int display_results(void *arg, int columns, char **values, char **colnames)
734 struct ast_cli_args *a = arg;
737 for (x = 0; x < columns; x++) {
738 ast_cli(a->fd, "%-5s: %-50s\n", colnames[x], values[x]);
740 ast_cli(a->fd, "\n");
745 static char *handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
750 e->command = "database query";
752 "Usage: database query \"<SQL Statement>\"\n"
753 " Run a user-specified SQL query on the database. Be careful.\n";
760 return CLI_SHOWUSAGE;
763 ast_mutex_lock(&dblock);
764 db_execute_sql(a->argv[2], display_results, a);
765 db_sync(); /* Go ahead and sync the db in case they write */
766 ast_mutex_unlock(&dblock);
771 static struct ast_cli_entry cli_database[] = {
772 AST_CLI_DEFINE(handle_cli_database_show, "Shows database contents"),
773 AST_CLI_DEFINE(handle_cli_database_showkey, "Shows database contents"),
774 AST_CLI_DEFINE(handle_cli_database_get, "Gets database value"),
775 AST_CLI_DEFINE(handle_cli_database_put, "Adds/updates database value"),
776 AST_CLI_DEFINE(handle_cli_database_del, "Removes database key/value"),
777 AST_CLI_DEFINE(handle_cli_database_deltree, "Removes database keytree/values"),
778 AST_CLI_DEFINE(handle_cli_database_query, "Run a user-specified query on the astdb"),
781 static int manager_dbput(struct mansession *s, const struct message *m)
783 const char *family = astman_get_header(m, "Family");
784 const char *key = astman_get_header(m, "Key");
785 const char *val = astman_get_header(m, "Val");
788 if (ast_strlen_zero(family)) {
789 astman_send_error(s, m, "No family specified");
792 if (ast_strlen_zero(key)) {
793 astman_send_error(s, m, "No key specified");
797 res = ast_db_put(family, key, S_OR(val, ""));
799 astman_send_error(s, m, "Failed to update entry");
801 astman_send_ack(s, m, "Updated database successfully");
806 static int manager_dbget(struct mansession *s, const struct message *m)
808 const char *id = astman_get_header(m,"ActionID");
809 char idText[256] = "";
810 const char *family = astman_get_header(m, "Family");
811 const char *key = astman_get_header(m, "Key");
812 char tmp[MAX_DB_FIELD];
815 if (ast_strlen_zero(family)) {
816 astman_send_error(s, m, "No family specified.");
819 if (ast_strlen_zero(key)) {
820 astman_send_error(s, m, "No key specified.");
824 if (!ast_strlen_zero(id))
825 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
827 res = ast_db_get(family, key, tmp, sizeof(tmp));
829 astman_send_error(s, m, "Database entry not found");
831 astman_send_ack(s, m, "Result will follow");
832 astman_append(s, "Event: DBGetResponse\r\n"
838 family, key, tmp, idText);
839 astman_append(s, "Event: DBGetComplete\r\n"
847 static int manager_dbdel(struct mansession *s, const struct message *m)
849 const char *family = astman_get_header(m, "Family");
850 const char *key = astman_get_header(m, "Key");
853 if (ast_strlen_zero(family)) {
854 astman_send_error(s, m, "No family specified.");
858 if (ast_strlen_zero(key)) {
859 astman_send_error(s, m, "No key specified.");
863 res = ast_db_del(family, key);
865 astman_send_error(s, m, "Database entry not found");
867 astman_send_ack(s, m, "Key deleted successfully");
872 static int manager_dbdeltree(struct mansession *s, const struct message *m)
874 const char *family = astman_get_header(m, "Family");
875 const char *key = astman_get_header(m, "Key");
878 if (ast_strlen_zero(family)) {
879 astman_send_error(s, m, "No family specified.");
883 if (!ast_strlen_zero(key))
884 res = ast_db_deltree(family, key);
886 res = ast_db_deltree(family, NULL);
889 astman_send_error(s, m, "Database entry not found");
891 astman_send_ack(s, m, "Key tree deleted successfully");
898 * \brief Signal the astdb sync thread to do its thing.
900 * \note dblock is assumed to be held when calling this function.
902 static void db_sync(void)
904 ast_cond_signal(&dbcond);
909 * \brief astdb sync thread
911 * This thread is in charge of syncing astdb to disk after a change.
912 * By pushing it off to this thread to take care of, this I/O bound operation
913 * will not block other threads from performing other critical processing.
914 * If changes happen rapidly, this thread will also ensure that the sync
915 * operations are rate limited.
917 static void *db_sync_thread(void *data)
919 ast_mutex_lock(&dblock);
920 ast_db_begin_transaction();
922 /* We're ok with spurious wakeups, so we don't worry about a predicate */
923 ast_cond_wait(&dbcond, &dblock);
924 if (ast_db_commit_transaction()) {
925 ast_db_rollback_transaction();
928 ast_mutex_unlock(&dblock);
931 ast_db_begin_transaction();
932 ast_mutex_unlock(&dblock);
934 ast_mutex_lock(&dblock);
935 /* Unfortunately, it is possible for signaling to happen
936 * when we're not waiting: in the bit when we're unlocked
937 * above. Do the do-exit check here again. (We could do
938 * it once, but that would impose a forced delay of 1
941 ast_mutex_unlock(&dblock);
949 static void astdb_atexit(void)
951 /* Set doexit to 1 to kill thread. db_sync must be called with
954 ast_mutex_lock(&dblock);
956 ast_mutex_unlock(&dblock);
958 pthread_join(syncthread, NULL);
959 ast_mutex_lock(&dblock);
960 sqlite3_close(astdb);
961 ast_mutex_unlock(&dblock);
970 ast_cond_init(&dbcond, NULL);
971 if (ast_pthread_create_background(&syncthread, NULL, db_sync_thread, NULL)) {
975 ast_register_atexit(astdb_atexit);
976 ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database));
977 ast_manager_register_xml_core("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget);
978 ast_manager_register_xml_core("DBPut", EVENT_FLAG_SYSTEM, manager_dbput);
979 ast_manager_register_xml_core("DBDel", EVENT_FLAG_SYSTEM, manager_dbdel);
980 ast_manager_register_xml_core("DBDelTree", EVENT_FLAG_SYSTEM, manager_dbdeltree);