39 #include <sys/types.h>
119 #define MAX_DB_FIELD 256
120 AST_MUTEX_DEFINE_STATIC(dblock);
121 static ast_cond_t dbcond;
122 static sqlite3 *astdb;
123 static pthread_t syncthread;
127 static void db_sync(
void);
129 #define DEFINE_SQL_STATEMENT(stmt,sql) static sqlite3_stmt *stmt; \
130 const char stmt##_sql[] = sql;
132 DEFINE_SQL_STATEMENT(put_stmt,
"INSERT OR REPLACE INTO astdb (key, value) VALUES (?, ?)")
133 DEFINE_SQL_STATEMENT(get_stmt, "SELECT value FROM astdb WHERE key=?")
134 DEFINE_SQL_STATEMENT(exists_stmt, "SELECT CAST(COUNT(1) AS INTEGER) AS 'exists' FROM astdb WHERE key=?")
135 DEFINE_SQL_STATEMENT(del_stmt, "DELETE FROM astdb WHERE key=?")
136 DEFINE_SQL_STATEMENT(deltree_stmt, "DELETE FROM astdb WHERE key || '/' LIKE ? || '/' || '%'")
137 DEFINE_SQL_STATEMENT(deltree_all_stmt, "DELETE FROM astdb")
138 DEFINE_SQL_STATEMENT(gettree_stmt, "SELECT key, value FROM astdb WHERE key || '/' LIKE ? || '/' || '%' ORDER BY key")
139 DEFINE_SQL_STATEMENT(gettree_all_stmt, "SELECT key, value FROM astdb ORDER BY key")
140 DEFINE_SQL_STATEMENT(showkey_stmt, "SELECT key, value FROM astdb WHERE key LIKE '%' || '/' || ? ORDER BY key")
141 DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key VARCHAR(256), value VARCHAR(256), PRIMARY KEY(key))")
155 DEFINE_SQL_STATEMENT(gettree_prefix_stmt, "SELECT key, value FROM astdb WHERE key > ?1 AND key <= ?1 || X'ffff'")
157 static
int init_stmt(sqlite3_stmt **stmt, const
char *sql,
size_t len)
159 ast_mutex_lock(&dblock);
160 if (sqlite3_prepare(astdb, sql, len, stmt, NULL) != SQLITE_OK) {
161 ast_log(LOG_WARNING,
"Couldn't prepare statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
162 ast_mutex_unlock(&dblock);
165 ast_mutex_unlock(&dblock);
174 static int clean_stmt(sqlite3_stmt **stmt,
const char *sql)
176 if (sqlite3_finalize(*stmt) != SQLITE_OK) {
177 ast_log(LOG_WARNING,
"Couldn't finalize statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
189 static void clean_statements(
void)
191 clean_stmt(&get_stmt, get_stmt_sql);
192 clean_stmt(&exists_stmt, exists_stmt_sql);
193 clean_stmt(&del_stmt, del_stmt_sql);
194 clean_stmt(&deltree_stmt, deltree_stmt_sql);
195 clean_stmt(&deltree_all_stmt, deltree_all_stmt_sql);
196 clean_stmt(&gettree_stmt, gettree_stmt_sql);
197 clean_stmt(&gettree_all_stmt, gettree_all_stmt_sql);
198 clean_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql);
199 clean_stmt(&showkey_stmt, showkey_stmt_sql);
200 clean_stmt(&put_stmt, put_stmt_sql);
201 clean_stmt(&create_astdb_stmt, create_astdb_stmt_sql);
204 static int init_statements(
void)
208 return init_stmt(&get_stmt, get_stmt_sql,
sizeof(get_stmt_sql))
209 || init_stmt(&exists_stmt, exists_stmt_sql,
sizeof(exists_stmt_sql))
210 || init_stmt(&del_stmt, del_stmt_sql,
sizeof(del_stmt_sql))
211 || init_stmt(&deltree_stmt, deltree_stmt_sql,
sizeof(deltree_stmt_sql))
212 || init_stmt(&deltree_all_stmt, deltree_all_stmt_sql,
sizeof(deltree_all_stmt_sql))
213 || init_stmt(&gettree_stmt, gettree_stmt_sql,
sizeof(gettree_stmt_sql))
214 || init_stmt(&gettree_all_stmt, gettree_all_stmt_sql,
sizeof(gettree_all_stmt_sql))
215 || init_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql,
sizeof(gettree_prefix_stmt_sql))
216 || init_stmt(&showkey_stmt, showkey_stmt_sql,
sizeof(showkey_stmt_sql))
217 || init_stmt(&put_stmt, put_stmt_sql,
sizeof(put_stmt_sql));
220 static int convert_bdb_to_sqlite3(
void)
225 res =
ast_asprintf(&cmd,
"%s/astdb2sqlite3 '%s'\n", ast_config_AST_SBIN_DIR, ast_config_AST_DB);
234 static int db_create_astdb(
void)
238 if (!create_astdb_stmt) {
239 init_stmt(&create_astdb_stmt, create_astdb_stmt_sql,
sizeof(create_astdb_stmt_sql));
242 ast_mutex_lock(&dblock);
243 if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) {
244 ast_log(LOG_WARNING,
"Couldn't create astdb table: %s\n", sqlite3_errmsg(astdb));
247 sqlite3_reset(create_astdb_stmt);
249 ast_mutex_unlock(&dblock);
257 struct stat dont_care;
259 if (!(dbname =
ast_alloca(strlen(ast_config_AST_DB) +
sizeof(
".sqlite3")))) {
262 strcpy(dbname, ast_config_AST_DB);
263 strcat(dbname,
".sqlite3");
265 if (stat(dbname, &dont_care) && !stat(ast_config_AST_DB, &dont_care)) {
266 if (convert_bdb_to_sqlite3()) {
267 ast_log(LOG_ERROR,
"*** Database conversion failed!\n");
268 ast_log(LOG_ERROR,
"*** Asterisk now uses SQLite3 for its internal\n");
269 ast_log(LOG_ERROR,
"*** database. Conversion from the old astdb\n");
270 ast_log(LOG_ERROR,
"*** failed. Most likely the astdb2sqlite3 utility\n");
271 ast_log(LOG_ERROR,
"*** was not selected for build. To convert the\n");
272 ast_log(LOG_ERROR,
"*** old astdb, please delete '%s'\n", dbname);
273 ast_log(LOG_ERROR,
"*** and re-run 'make menuselect' and select astdb2sqlite3\n");
274 ast_log(LOG_ERROR,
"*** in the Utilities section, then 'make && make install'.\n");
275 ast_log(LOG_ERROR,
"*** It is also imperative that the user under which\n");
276 ast_log(LOG_ERROR,
"*** Asterisk runs have write permission to the directory\n");
277 ast_log(LOG_ERROR,
"*** where the database resides.\n");
280 ast_log(LOG_NOTICE,
"Database conversion succeeded!\n");
284 ast_mutex_lock(&dblock);
285 if (sqlite3_open(dbname, &astdb) != SQLITE_OK) {
286 ast_log(LOG_WARNING,
"Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb));
287 sqlite3_close(astdb);
288 ast_mutex_unlock(&dblock);
292 ast_mutex_unlock(&dblock);
297 static int db_init(
void)
303 if (
db_open() || db_create_astdb() || init_statements()) {
313 static int db_execute_sql(
const char *sql,
int (*callback)(
void *,
int,
char **,
char **),
void *arg)
318 if (sqlite3_exec(astdb, sql, callback, arg, &errmsg) != SQLITE_OK) {
319 ast_log(LOG_WARNING,
"Error executing SQL (%s): %s\n", sql, errmsg);
320 sqlite3_free(errmsg);
327 static int ast_db_begin_transaction(
void)
329 return db_execute_sql(
"BEGIN TRANSACTION", NULL, NULL);
332 static int ast_db_commit_transaction(
void)
334 return db_execute_sql(
"COMMIT", NULL, NULL);
337 static int ast_db_rollback_transaction(
void)
339 return db_execute_sql(
"ROLLBACK", NULL, NULL);
342 int ast_db_put(
const char *family,
const char *key,
const char *value)
344 char fullkey[MAX_DB_FIELD];
348 if (strlen(family) + strlen(key) + 2 >
sizeof(fullkey) - 1) {
349 ast_log(LOG_WARNING,
"Family and key length must be less than %zu bytes\n",
sizeof(fullkey) - 3);
353 fullkey_len = snprintf(fullkey,
sizeof(fullkey),
"/%s/%s", family, key);
355 ast_mutex_lock(&dblock);
356 if (sqlite3_bind_text(put_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
357 ast_log(LOG_WARNING,
"Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
359 }
else if (sqlite3_bind_text(put_stmt, 2, value, -1, SQLITE_STATIC) != SQLITE_OK) {
360 ast_log(LOG_WARNING,
"Couldn't bind value to stmt: %s\n", sqlite3_errmsg(astdb));
362 }
else if (sqlite3_step(put_stmt) != SQLITE_DONE) {
363 ast_log(LOG_WARNING,
"Couldn't execute statement: %s\n", sqlite3_errmsg(astdb));
367 sqlite3_reset(put_stmt);
369 ast_mutex_unlock(&dblock);
388 static int db_get_common(
const char *family,
const char *key,
char **buffer,
int bufferlen)
390 const unsigned char *result;
391 char fullkey[MAX_DB_FIELD];
395 if (strlen(family) + strlen(key) + 2 >
sizeof(fullkey) - 1) {
396 ast_log(LOG_WARNING,
"Family and key length must be less than %zu bytes\n",
sizeof(fullkey) - 3);
400 fullkey_len = snprintf(fullkey,
sizeof(fullkey),
"/%s/%s", family, key);
402 ast_mutex_lock(&dblock);
403 if (sqlite3_bind_text(get_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
404 ast_log(LOG_WARNING,
"Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
406 }
else if (sqlite3_step(get_stmt) != SQLITE_ROW) {
407 ast_debug(1,
"Unable to find key '%s' in family '%s'\n", key, family);
409 }
else if (!(result = sqlite3_column_text(get_stmt, 0))) {
410 ast_log(LOG_WARNING,
"Couldn't get value\n");
413 const char *value = (
const char *) result;
415 if (bufferlen == -1) {
421 sqlite3_reset(get_stmt);
422 ast_mutex_unlock(&dblock);
427 int ast_db_get(
const char *family,
const char *key,
char *value,
int valuelen)
429 ast_assert(value != NULL);
434 return db_get_common(family, key, &value, valuelen);
441 return db_get_common(family, key, out, -1);
447 char fullkey[MAX_DB_FIELD];
451 fullkey_len = snprintf(fullkey,
sizeof(fullkey),
"/%s/%s", family, key);
452 if (fullkey_len >=
sizeof(fullkey)) {
453 ast_log(LOG_WARNING,
"Family and key length must be less than %zu bytes\n",
sizeof(fullkey) - 3);
457 ast_mutex_lock(&dblock);
458 res = sqlite3_bind_text(exists_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC);
459 if (res != SQLITE_OK) {
460 ast_log(LOG_WARNING,
"Couldn't bind key to stmt: %d:%s\n", res, sqlite3_errmsg(astdb));
462 }
else if (sqlite3_step(exists_stmt) != SQLITE_ROW) {
464 }
else if (!(result = sqlite3_column_int(exists_stmt, 0))) {
469 sqlite3_reset(exists_stmt);
470 ast_mutex_unlock(&dblock);
478 char fullkey[MAX_DB_FIELD];
482 if (strlen(family) + strlen(key) + 2 >
sizeof(fullkey) - 1) {
483 ast_log(LOG_WARNING,
"Family and key length must be less than %zu bytes\n",
sizeof(fullkey) - 3);
487 fullkey_len = snprintf(fullkey,
sizeof(fullkey),
"/%s/%s", family, key);
489 ast_mutex_lock(&dblock);
490 if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
491 ast_log(LOG_WARNING,
"Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
493 }
else if (sqlite3_step(del_stmt) != SQLITE_DONE) {
494 ast_debug(1,
"Unable to find key '%s' in family '%s'\n", key, family);
497 sqlite3_reset(del_stmt);
499 ast_mutex_unlock(&dblock);
506 char fullkey[MAX_DB_FIELD];
511 if (strlen(family) + strlen(key) + 2 >
sizeof(fullkey) - 1) {
512 ast_log(LOG_WARNING,
"Family and key length must be less than %zu bytes\n",
sizeof(fullkey) - 3);
516 fullkey_len = snprintf(fullkey,
sizeof(fullkey),
"/%s/%s", family, key);
518 ast_mutex_lock(&dblock);
519 if (
ast_db_get(family, key, tmp,
sizeof(tmp))) {
520 ast_log(LOG_WARNING,
"AstDB key %s does not exist\n", fullkey);
522 }
else if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
523 ast_log(LOG_WARNING,
"Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
525 }
else if ((mres = sqlite3_step(del_stmt) != SQLITE_DONE)) {
526 ast_log(LOG_WARNING,
"AstDB error (%s): %s\n", fullkey, sqlite3_errstr(mres));
529 sqlite3_reset(del_stmt);
531 ast_mutex_unlock(&dblock);
538 sqlite3_stmt *stmt = deltree_stmt;
539 char prefix[MAX_DB_FIELD];
542 if (!ast_strlen_zero(family)) {
543 if (!ast_strlen_zero(keytree)) {
545 snprintf(prefix,
sizeof(prefix),
"/%s/%s", family, keytree);
548 snprintf(prefix,
sizeof(prefix),
"/%s", family);
552 stmt = deltree_all_stmt;
555 ast_mutex_lock(&dblock);
556 if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
557 ast_log(LOG_WARNING,
"Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
559 }
else if (sqlite3_step(stmt) != SQLITE_DONE) {
560 ast_log(LOG_WARNING,
"Couldn't execute stmt: %s\n", sqlite3_errmsg(astdb));
563 res = sqlite3_changes(astdb);
566 ast_mutex_unlock(&dblock);
571 static struct ast_db_entry *db_gettree_common(sqlite3_stmt *stmt)
575 while (sqlite3_step(stmt) == SQLITE_ROW) {
576 const char *key, *value;
577 size_t key_len, value_len;
579 key = (
const char *) sqlite3_column_text(stmt, 0);
580 value = (
const char *) sqlite3_column_text(stmt, 1);
582 if (!key || !value) {
586 key_len = strlen(key);
587 value_len = strlen(value);
589 cur =
ast_malloc(
sizeof(*cur) + key_len + value_len + 2);
595 cur->key = cur->data + value_len + 1;
596 memcpy(cur->data, value, value_len + 1);
597 memcpy(cur->key, key, key_len + 1);
612 char prefix[MAX_DB_FIELD];
613 sqlite3_stmt *stmt = gettree_stmt;
617 if (!ast_strlen_zero(family)) {
618 if (!ast_strlen_zero(keytree)) {
620 res = snprintf(prefix,
sizeof(prefix),
"/%s/%s", family, keytree);
623 res = snprintf(prefix,
sizeof(prefix),
"/%s", family);
626 if (res >=
sizeof(prefix)) {
627 ast_log(LOG_WARNING,
"Requested prefix is too long: %s\n", keytree);
632 stmt = gettree_all_stmt;
635 ast_mutex_lock(&dblock);
636 if (res && (sqlite3_bind_text(stmt, 1, prefix, res, SQLITE_STATIC) != SQLITE_OK)) {
637 ast_log(LOG_WARNING,
"Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
639 ast_mutex_unlock(&dblock);
643 ret = db_gettree_common(stmt);
645 ast_mutex_unlock(&dblock);
652 char prefix[MAX_DB_FIELD];
656 res = snprintf(prefix,
sizeof(prefix),
"/%s/%s", family, key_prefix);
657 if (res >=
sizeof(prefix)) {
658 ast_log(LOG_WARNING,
"Requested key prefix is too long: %s\n", key_prefix);
662 ast_mutex_lock(&dblock);
663 if (sqlite3_bind_text(gettree_prefix_stmt, 1, prefix, res, SQLITE_STATIC) != SQLITE_OK) {
664 ast_log(LOG_WARNING,
"Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
665 sqlite3_reset(gettree_prefix_stmt);
666 ast_mutex_unlock(&dblock);
670 ret = db_gettree_common(gettree_prefix_stmt);
671 sqlite3_reset(gettree_prefix_stmt);
672 ast_mutex_unlock(&dblock);
695 "Usage: database put <family> <key> <value>\n"
696 " Adds or updates an entry in the Asterisk database for\n"
697 " a given family, key, and value.\n";
704 return CLI_SHOWUSAGE;
705 res =
ast_db_put(a->argv[2], a->argv[3], a->argv[4]);
707 ast_cli(a->fd,
"Failed to update entry\n");
709 ast_cli(a->fd,
"Updated database successfully\n");
717 char tmp[MAX_DB_FIELD];
723 "Usage: database get <family> <key>\n"
724 " Retrieves an entry in the Asterisk database for a given\n"
725 " family and key.\n";
732 return CLI_SHOWUSAGE;
733 res =
ast_db_get(a->argv[2], a->argv[3], tmp,
sizeof(tmp));
735 ast_cli(a->fd,
"Database entry not found.\n");
737 ast_cli(a->fd,
"Value: %s\n", tmp);
750 "Usage: database del <family> <key>\n"
751 " Deletes an entry in the Asterisk database for a given\n"
752 " family and key.\n";
759 return CLI_SHOWUSAGE;
762 ast_cli(a->fd,
"Database entry could not be removed.\n");
764 ast_cli(a->fd,
"Database entry removed.\n");
775 e->
command =
"database deltree";
777 "Usage: database deltree <family> [keytree]\n"
778 " OR: database deltree <family>[/keytree]\n"
779 " Deletes a family or specific keytree within a family\n"
780 " in the Asterisk database. The two arguments may be\n"
781 " separated by either a space or a slash.\n";
787 if ((a->argc < 3) || (a->argc > 4))
788 return CLI_SHOWUSAGE;
794 if (num_deleted < 0) {
795 ast_cli(a->fd,
"Database unavailable.\n");
796 }
else if (num_deleted == 0) {
797 ast_cli(a->fd,
"Database entries do not exist.\n");
799 ast_cli(a->fd,
"%d database entries removed.\n",num_deleted);
806 char prefix[MAX_DB_FIELD];
808 sqlite3_stmt *stmt = gettree_stmt;
814 "Usage: database show [family [keytree]]\n"
815 " OR: database show [family[/keytree]]\n"
816 " Shows Asterisk database contents, optionally restricted\n"
817 " to a given family, or family and keytree. The two arguments\n"
818 " may be separated either by a space or by a slash.\n";
826 snprintf(prefix,
sizeof(prefix),
"/%s/%s", a->argv[2], a->argv[3]);
827 }
else if (a->argc == 3) {
829 snprintf(prefix,
sizeof(prefix),
"/%s", a->argv[2]);
830 }
else if (a->argc == 2) {
833 stmt = gettree_all_stmt;
836 return CLI_SHOWUSAGE;
839 ast_mutex_lock(&dblock);
840 if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
841 ast_log(LOG_WARNING,
"Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
843 ast_mutex_unlock(&dblock);
847 while (sqlite3_step(stmt) == SQLITE_ROW) {
848 const char *key_s, *value_s;
849 if (!(key_s = (
const char *) sqlite3_column_text(stmt, 0))) {
850 ast_log(LOG_WARNING,
"Skipping invalid key!\n");
853 if (!(value_s = (
const char *) sqlite3_column_text(stmt, 1))) {
854 ast_log(LOG_WARNING,
"Skipping invalid value!\n");
858 ast_cli(a->fd,
"%-50s: %-25s\n", key_s, value_s);
862 ast_mutex_unlock(&dblock);
864 ast_cli(a->fd,
"%d results found.\n", counter);
874 e->
command =
"database showkey";
876 "Usage: database showkey <keytree>\n"
877 " Shows Asterisk database contents, restricted to a given key.\n";
884 return CLI_SHOWUSAGE;
887 ast_mutex_lock(&dblock);
888 if (!ast_strlen_zero(a->argv[2]) && (sqlite3_bind_text(showkey_stmt, 1, a->argv[2], -1, SQLITE_STATIC) != SQLITE_OK)) {
889 ast_log(LOG_WARNING,
"Couldn't bind %s to stmt: %s\n", a->argv[2], sqlite3_errmsg(astdb));
890 sqlite3_reset(showkey_stmt);
891 ast_mutex_unlock(&dblock);
895 while (sqlite3_step(showkey_stmt) == SQLITE_ROW) {
896 const char *key_s, *value_s;
897 if (!(key_s = (
const char *) sqlite3_column_text(showkey_stmt, 0))) {
900 if (!(value_s = (
const char *) sqlite3_column_text(showkey_stmt, 1))) {
904 ast_cli(a->fd,
"%-50s: %-25s\n", key_s, value_s);
906 sqlite3_reset(showkey_stmt);
907 ast_mutex_unlock(&dblock);
909 ast_cli(a->fd,
"%d results found.\n", counter);
913 static int display_results(
void *arg,
int columns,
char **
values,
char **colnames)
918 for (x = 0; x <
columns; x++) {
919 ast_cli(a->fd,
"%-5s: %-50s\n", colnames[x], values[x]);
921 ast_cli(a->fd,
"\n");
933 "Usage: database query \"<SQL Statement>\"\n"
934 " Run a user-specified SQL query on the database. Be careful.\n";
941 return CLI_SHOWUSAGE;
944 ast_mutex_lock(&dblock);
945 db_execute_sql(a->argv[2], display_results, a);
947 ast_mutex_unlock(&dblock);
953 AST_CLI_DEFINE(handle_cli_database_show,
"Shows database contents"),
954 AST_CLI_DEFINE(handle_cli_database_showkey,
"Shows database contents"),
955 AST_CLI_DEFINE(handle_cli_database_get,
"Gets database value"),
956 AST_CLI_DEFINE(handle_cli_database_put,
"Adds/updates database value"),
957 AST_CLI_DEFINE(handle_cli_database_del,
"Removes database key/value"),
958 AST_CLI_DEFINE(handle_cli_database_deltree,
"Removes database keytree/values"),
959 AST_CLI_DEFINE(handle_cli_database_query,
"Run a user-specified query on the astdb"),
969 if (ast_strlen_zero(family)) {
973 if (ast_strlen_zero(key)) {
993 char tmp[MAX_DB_FIELD];
996 if (ast_strlen_zero(family)) {
1000 if (ast_strlen_zero(key)) {
1006 if (!ast_strlen_zero(
id))
1007 snprintf(idText,
sizeof(idText) ,
"ActionID: %s\r\n",
id);
1009 res =
ast_db_get(family, key, tmp,
sizeof(tmp));
1021 family, key, tmp, idText);
1031 char prefix[MAX_DB_FIELD];
1036 sqlite3_stmt *stmt = gettree_stmt;
1039 if (!ast_strlen_zero(family) && !ast_strlen_zero(key)) {
1041 snprintf(prefix,
sizeof(prefix),
"/%s/%s", family, key);
1042 }
else if (!ast_strlen_zero(family)) {
1044 snprintf(prefix,
sizeof(prefix),
"/%s", family);
1048 stmt = gettree_all_stmt;
1052 if (!ast_strlen_zero(
id)) {
1053 snprintf(idText,
sizeof(idText) ,
"ActionID: %s\r\n",
id);
1056 ast_mutex_lock(&dblock);
1057 if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
1058 ast_log(LOG_WARNING,
"Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
1059 sqlite3_reset(stmt);
1060 ast_mutex_unlock(&dblock);
1067 while (sqlite3_step(stmt) == SQLITE_ROW) {
1068 const char *key_s, *value_s;
1069 if (!(key_s = (
const char *) sqlite3_column_text(stmt, 0))) {
1070 ast_log(LOG_WARNING,
"Skipping invalid key!\n");
1073 if (!(value_s = (
const char *) sqlite3_column_text(stmt, 1))) {
1074 ast_log(LOG_WARNING,
"Skipping invalid value!\n");
1082 key_s, value_s, idText);
1086 sqlite3_reset(stmt);
1087 ast_mutex_unlock(&dblock);
1101 if (ast_strlen_zero(family)) {
1106 if (ast_strlen_zero(key)) {
1126 if (ast_strlen_zero(family)) {
1131 if (!ast_strlen_zero(key)) {
1137 if (num_deleted < 0) {
1139 }
else if (num_deleted == 0) {
1154 static void db_sync(
void)
1157 ast_cond_signal(&dbcond);
1172 ast_mutex_lock(&dblock);
1173 ast_db_begin_transaction();
1180 ast_cond_wait(&dbcond, &dblock);
1183 if (ast_db_commit_transaction()) {
1184 ast_db_rollback_transaction();
1187 ast_mutex_unlock(&dblock);
1190 ast_db_begin_transaction();
1191 ast_mutex_unlock(&dblock);
1193 ast_mutex_lock(&dblock);
1203 static void astdb_atexit(
void)
1214 ast_mutex_lock(&dblock);
1217 ast_mutex_unlock(&dblock);
1219 pthread_join(syncthread, NULL);
1220 ast_mutex_lock(&dblock);
1222 if (sqlite3_close(astdb) == SQLITE_OK) {
1225 ast_mutex_unlock(&dblock);
1230 ast_cond_init(&dbcond, NULL);
1236 if (ast_pthread_create_background(&syncthread, NULL,
db_sync_thread, NULL)) {
static int db_open(struct realtime_sqlite3_db *db)
Open a database and appropriately set debugging on the db handle.
void astman_append(struct mansession *s, const char *fmt,...)
Asterisk main include file. File version handling, generic pbx functions.
static void * db_sync_thread(void *data)
Wrap commands in transactions increased write performance.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
int ast_db_exists(const char *family, const char *key)
Check if family/key exitsts.
Convenient Signal Processing routines.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
descriptor for a cli entry.
int ast_db_del2(const char *family, const char *key)
Same as ast_db_del, but with more stringent error checking.
void ast_db_freetree(struct ast_db_entry *dbe)
Free structure created by ast_db_gettree()
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
#define ast_strdup(str)
A wrapper for strdup()
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
In case you didn't read that giant block of text above the mansession_session struct, the mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
#define ast_malloc(len)
A wrapper for malloc()
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
struct ast_db_entry * ast_db_gettree_by_prefix(const char *family, const char *key_prefix)
Get a list of values with the given key prefix.
Prototypes for public functions only of internal interest,.
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
int ast_db_get_allocated(const char *family, const char *key, char **out)
Get key value specified by family/key as a heap allocated string.
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Persistent data storage (akin to *doze registry)
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.