145#define DEFINE_SQL_STATEMENT(stmt,sql) static sqlite3_stmt *stmt; \ 
  146    const char stmt##_sql[] = sql; 
 
  173static 
int init_stmt(sqlite3_stmt **stmt, const 
char *sql, 
size_t len)
 
  176    if (sqlite3_prepare(
astdb, sql, 
len, stmt, 
NULL) != SQLITE_OK) {
 
 
  192    if (sqlite3_finalize(*stmt) != SQLITE_OK) {
 
 
  211    clean_stmt(&deltree_all_stmt, deltree_all_stmt_sql);
 
  213    clean_stmt(&gettree_all_stmt, gettree_all_stmt_sql);
 
  214    clean_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql);
 
  217    clean_stmt(&create_astdb_stmt, create_astdb_stmt_sql);
 
 
  224    return init_stmt(&get_stmt, get_stmt_sql, 
sizeof(get_stmt_sql))
 
  225    || init_stmt(&exists_stmt, exists_stmt_sql, 
sizeof(exists_stmt_sql))
 
  226    || init_stmt(&del_stmt, del_stmt_sql, 
sizeof(del_stmt_sql))
 
  227    || init_stmt(&deltree_stmt, deltree_stmt_sql, 
sizeof(deltree_stmt_sql))
 
  228    || init_stmt(&deltree_all_stmt, deltree_all_stmt_sql, 
sizeof(deltree_all_stmt_sql))
 
  229    || init_stmt(&gettree_stmt, gettree_stmt_sql, 
sizeof(gettree_stmt_sql))
 
  230    || init_stmt(&gettree_all_stmt, gettree_all_stmt_sql, 
sizeof(gettree_all_stmt_sql))
 
  231    || init_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql, 
sizeof(gettree_prefix_stmt_sql))
 
  232    || init_stmt(&showkey_stmt, showkey_stmt_sql, 
sizeof(showkey_stmt_sql))
 
  233    || init_stmt(&put_stmt, put_stmt_sql, 
sizeof(put_stmt_sql));
 
 
  240    if (!create_astdb_stmt) {
 
  241        init_stmt(&create_astdb_stmt, create_astdb_stmt_sql, 
sizeof(create_astdb_stmt_sql));
 
  245    if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) {
 
  249    sqlite3_reset(create_astdb_stmt);
 
 
  258    struct stat dont_care;
 
  262    strcat(
dbname, 
".sqlite3");
 
  265        ast_log(
LOG_ERROR, 
"When Asterisk 10.0.0 was released, the format of Asterisk's internal\n");
 
  266        ast_log(
LOG_ERROR, 
"database was changed from Berkeley DB to SQLite3. Part of that change\n");
 
  267        ast_log(
LOG_ERROR, 
"involved the creation of a conversion utility - astdb2sqlite3 - that\n");
 
  268        ast_log(
LOG_ERROR, 
"was shipped with Asterisk. This conversion utility performed a\n");
 
  269        ast_log(
LOG_ERROR, 
"one-time migration from the old format to the new one.\n");
 
  271        ast_log(
LOG_ERROR, 
"Starting with Asterisk 23.0.0, astdb2sqlite3 no longer ships as part\n");
 
  272        ast_log(
LOG_ERROR, 
"of the Asterisk distribution. If you are upgrading from a version of\n");
 
  273        ast_log(
LOG_ERROR, 
"Asterisk that still uses the Berkeley DB implementation, you will need\n");
 
  274        ast_log(
LOG_ERROR, 
"to acquire astdb2sqlite3 from an earlier release of Asterisk.\n");
 
  280        sqlite3_close(
astdb);
 
 
  311    if (sqlite3_exec(
astdb, sql, 
callback, arg, &errmsg) != SQLITE_OK) {
 
  313        sqlite3_free(errmsg);
 
 
  341    fullkey_len = 
ast_asprintf(&fullkey, 
"/%s/%s", family, key);
 
  342    if (fullkey_len < 0) {
 
  349    if (sqlite3_bind_text(put_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
 
  352    } 
else if (sqlite3_bind_text(put_stmt, 2, 
value, -1, SQLITE_STATIC) != SQLITE_OK) {
 
  355    } 
else if (sqlite3_step(put_stmt) != SQLITE_DONE) {
 
  359    sqlite3_reset(put_stmt);
 
 
  381static int db_get_common(
const char *family, 
const char *key, 
char **buffer, 
int bufferlen)
 
  383    const unsigned char *
result;
 
  388    fullkey_len = 
ast_asprintf(&fullkey, 
"/%s/%s", family, key);
 
  389    if (fullkey_len < 0) {
 
  396    if (sqlite3_bind_text(get_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
 
  399    } 
else if (sqlite3_step(get_stmt) != SQLITE_ROW) {
 
  400        ast_debug(1, 
"Unable to find key '%s' in family '%s'\n", key, family);
 
  402    } 
else if (!(
result = sqlite3_column_text(get_stmt, 0))) {
 
  408        if (bufferlen == -1) {
 
  414    sqlite3_reset(get_stmt);
 
 
  445    fullkey_len = 
ast_asprintf(&fullkey, 
"/%s/%s", family, key);
 
  446    if (fullkey_len < 0) {
 
  453    res = sqlite3_bind_text(exists_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC);
 
  454    if (res != SQLITE_OK) {
 
  457    } 
else if (sqlite3_step(exists_stmt) != SQLITE_ROW) {
 
  459    } 
else if (!(
result = sqlite3_column_int(exists_stmt, 0))) {
 
  464    sqlite3_reset(exists_stmt);
 
 
  478    fullkey_len = 
ast_asprintf(&fullkey, 
"/%s/%s", family, key);
 
  479    if (fullkey_len < 0) {
 
  486    if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
 
  489    } 
else if (sqlite3_step(del_stmt) != SQLITE_DONE) {
 
  490        ast_debug(1, 
"Unable to find key '%s' in family '%s'\n", key, family);
 
  493    sqlite3_reset(del_stmt);
 
 
  508    fullkey_len = 
ast_asprintf(&fullkey, 
"/%s/%s", family, key);
 
  509    if (fullkey_len < 0) {
 
  516    if (
ast_db_get(family, key, tmp, 
sizeof(tmp))) {
 
  519    } 
else if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
 
  522    } 
else if ((mres = sqlite3_step(del_stmt) != SQLITE_DONE)) {
 
  526    sqlite3_reset(del_stmt);
 
 
  548        if (*prefix_len < 0) {
 
  550                S_OR(family, 
""), 
S_COR(keytree, 
"/", 
""), 
S_OR(keytree, 
""));
 
 
  561    sqlite3_stmt *stmt = deltree_stmt;
 
  575    if (prefix_len == 0) {
 
  576        stmt = deltree_all_stmt;
 
  580    if (prefix_len && (sqlite3_bind_text(stmt, 1, 
prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
 
  583    } 
else if (sqlite3_step(stmt) != SQLITE_DONE) {
 
  587    res = sqlite3_changes(
astdb);
 
 
  600    while (sqlite3_step(stmt) == SQLITE_ROW) {
 
  602        size_t key_len, value_len;
 
  604        key   = (
const char *) sqlite3_column_text(stmt, 0);
 
  605        value = (
const char *) sqlite3_column_text(stmt, 1);
 
  611        key_len = strlen(
key);
 
  612        value_len = strlen(
value);
 
  614        cur = 
ast_malloc(
sizeof(*cur) + key_len + value_len + 2);
 
  620        cur->key = cur->data + value_len + 1;
 
  621        memcpy(cur->data, 
value, value_len + 1);
 
  622        memcpy(cur->key, 
key, key_len + 1);
 
 
  639    sqlite3_stmt *stmt = gettree_stmt;
 
  646    if (prefix_len == 0) {
 
  647        stmt = gettree_all_stmt;
 
  651    if (prefix_len && (sqlite3_bind_text(stmt, 1, 
prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
 
 
  679    if (sqlite3_bind_text(gettree_prefix_stmt, 1, 
prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK) {
 
  681        sqlite3_reset(gettree_prefix_stmt);
 
  688    sqlite3_reset(gettree_prefix_stmt);
 
 
  713            "Usage: database put <family> <key> <value>\n" 
  714            "       Adds or updates an entry in the Asterisk database for\n" 
  715            "       a given family, key, and value.\n";
 
  725        ast_cli(
a->fd, 
"Failed to update entry\n");
 
  727        ast_cli(
a->fd, 
"Updated database successfully\n");
 
 
  741            "Usage: database get <family> <key>\n" 
  742            "       Retrieves an entry in the Asterisk database for a given\n" 
  743            "       family and key.\n";
 
  753        ast_cli(
a->fd, 
"Database entry not found.\n");
 
 
  770            "Usage: database del <family> <key>\n" 
  771            "       Deletes an entry in the Asterisk database for a given\n" 
  772            "       family and key.\n";
 
  782        ast_cli(
a->fd, 
"Database entry could not be removed.\n");
 
  784        ast_cli(
a->fd, 
"Database entry removed.\n");
 
 
  795        e->
command = 
"database deltree";
 
  797            "Usage: database deltree <family> [keytree]\n" 
  798            "   OR: database deltree <family>[/keytree]\n" 
  799            "       Deletes a family or specific keytree within a family\n" 
  800            "       in the Asterisk database.  The two arguments may be\n" 
  801            "       separated by either a space or a slash.\n";
 
  807    if ((
a->argc < 3) || (
a->argc > 4))
 
  814    if (num_deleted < 0) {
 
  815        ast_cli(
a->fd, 
"Database unavailable.\n");
 
  816    } 
else if (num_deleted == 0) {
 
  817        ast_cli(
a->fd, 
"Database entries do not exist.\n");
 
  819        ast_cli(
a->fd, 
"%d database entries removed.\n",num_deleted);
 
 
  828    const char *family = 
a->argc > 2 ? 
a->argv[2] : 
"";
 
  829    const char *keytree = 
a->argc > 3 ? 
a->argv[3] : 
"";
 
  831    sqlite3_stmt *stmt = gettree_stmt;
 
  837            "Usage: database show [family [keytree]]\n" 
  838            "   OR: database show [family[/keytree]]\n" 
  839            "       Shows Asterisk database contents, optionally restricted\n" 
  840            "       to a given family, or family and keytree. The two arguments\n" 
  841            "       may be separated either by a space or by a slash.\n";
 
  855    if (prefix_len == 0) {
 
  856        stmt = gettree_all_stmt;
 
  860    if (prefix_len && (sqlite3_bind_text(stmt, 1, 
prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
 
  868    while (sqlite3_step(stmt) == SQLITE_ROW) {
 
  869        const char *key_s, *value_s;
 
  870        if (!(key_s = (
const char *) sqlite3_column_text(stmt, 0))) {
 
  874        if (!(value_s = (
const char *) sqlite3_column_text(stmt, 1))) {
 
  879        ast_cli(
a->fd, 
"%-50s: %-25s\n", key_s, value_s);
 
  886    ast_cli(
a->fd, 
"%d results found.\n", counter);
 
 
  896        e->
command = 
"database showkey";
 
  898            "Usage: database showkey <keytree>\n" 
  899            "       Shows Asterisk database contents, restricted to a given key.\n";
 
  910    if (!
ast_strlen_zero(
a->argv[2]) && (sqlite3_bind_text(showkey_stmt, 1, 
a->argv[2], -1, SQLITE_STATIC) != SQLITE_OK)) {
 
  912        sqlite3_reset(showkey_stmt);
 
  917    while (sqlite3_step(showkey_stmt) == SQLITE_ROW) {
 
  918        const char *key_s, *value_s;
 
  919        if (!(key_s = (
const char *) sqlite3_column_text(showkey_stmt, 0))) {
 
  922        if (!(value_s = (
const char *) sqlite3_column_text(showkey_stmt, 1))) {
 
  926        ast_cli(
a->fd, 
"%-50s: %-25s\n", key_s, value_s);
 
  928    sqlite3_reset(showkey_stmt);
 
  931    ast_cli(
a->fd, 
"%d results found.\n", counter);
 
 
  940    for (x = 0; x < 
columns; x++) {
 
 
  955            "Usage: database query \"<SQL Statement>\"\n" 
  956            "       Run a user-specified SQL query on the database. Be careful.\n";
 
 
 1029        snprintf(idText, 
sizeof(idText) ,
"ActionID: %s\r\n", 
id);
 
 1043                family, key, tmp, idText);
 
 
 1059    sqlite3_stmt *stmt = gettree_stmt;
 
 1067    if (prefix_len == 0) {
 
 1068        stmt = gettree_all_stmt;
 
 1073        snprintf(idText, 
sizeof(idText) ,
"ActionID: %s\r\n", 
id);
 
 1079        sqlite3_reset(stmt);
 
 1088    while (sqlite3_step(stmt) == SQLITE_ROW) {
 
 1089        const char *key_s, *value_s;
 
 1090        if (!(key_s = (
const char *) sqlite3_column_text(stmt, 0))) {
 
 1094        if (!(value_s = (
const char *) sqlite3_column_text(stmt, 1))) {
 
 1103            key_s, value_s, idText);
 
 1107    sqlite3_reset(stmt);
 
 
 1159    if (num_deleted < 0) {
 
 1161    } 
else if (num_deleted == 0) {
 
 
 1244    if (sqlite3_close(
astdb) == SQLITE_OK) {
 
 
Prototypes for public functions only of internal interest,.
void ast_cli_unregister_multiple(void)
struct sla_ringing_trunk * last
#define EXISTS(a, b, c, d)
#define DELETE(a, b, c, d)
Persistent data storage (akin to *doze registry)
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
#define ast_strdup(str)
A wrapper for strdup()
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_malloc(len)
A wrapper for malloc()
General Asterisk PBX channel definitions.
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
Standard Command Line Interface.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
static char * handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int manager_dbdel(struct mansession *s, const struct message *m)
static void db_sync(void)
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
static void clean_statements(void)
static char * handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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.
static int manager_db_tree_get(struct mansession *s, const struct message *m)
int ast_db_del2(const char *family, const char *key)
Same as ast_db_del, but with more stringent error checking.
static int manager_dbdeltree(struct mansession *s, const struct message *m)
static struct ast_cli_entry cli_database[]
void ast_db_freetree(struct ast_db_entry *dbe)
Free structure created by ast_db_gettree()
static struct ast_db_entry * db_gettree_common(sqlite3_stmt *stmt)
static int manager_dbget(struct mansession *s, const struct message *m)
static char * handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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.
static int manager_dbput(struct mansession *s, const struct message *m)
static int db_execute_sql(const char *sql, int(*callback)(void *, int, char **, char **), void *arg)
static int display_results(void *arg, int columns, char **values, char **colnames)
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
static int ast_db_begin_transaction(void)
static int db_create_astdb(void)
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
static int ast_db_commit_transaction(void)
static ast_mutex_t dblock
#define DEFINE_SQL_STATEMENT(stmt, sql)
static void * db_sync_thread(void *data)
static char * handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
static char * create_prefix(const char *family, const char *keytree, int *prefix_len)
static pthread_t syncthread
static char * handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void astdb_atexit(void)
static int init_statements(void)
static char * handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen)
static int clean_stmt(sqlite3_stmt **stmt, const char *sql)
static int ast_db_rollback_transaction(void)
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
static char * handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int ast_db_exists(const char *family, const char *key)
Check if family/key exitsts.
Convenient Signal Processing routines.
Generic File Format Support. Should be included by clients of the file handling routines....
static int exists(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
void astman_append(struct mansession *s, const char *fmt,...)
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
static char prefix[MAX_PREFIX]
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_cond_wait(cond, mutex)
#define ast_cond_init(cond, attr)
#define ast_mutex_unlock(a)
pthread_cond_t ast_cond_t
#define ast_mutex_lock(a)
#define AST_MUTEX_DEFINE_STATIC(mutex)
#define ast_cond_signal(cond)
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define EVENT_FLAG_REPORTING
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
#define EVENT_FLAG_SYSTEM
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_DB
static char dbname[MAX_DB_OPTION_SIZE]
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
static force_inline int attribute_pure ast_strlen_zero(const char *s)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
descriptor for a cli entry.
struct ast_db_entry * next
In case you didn't read that giant block of text above the mansession_session struct,...
#define ast_pthread_create_background(a, b, c, d)