main/db.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief ASTdb Management
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  *
00025  * \note DB3 is licensed under Sleepycat Public License and is thus incompatible
00026  * with GPL.  To avoid having to make another exception (and complicate
00027  * licensing even further) we elect to use DB1 which is BSD licensed
00028  */
00029 
00030 /*** MODULEINFO
00031    <support_level>core</support_level>
00032  ***/
00033 
00034 #include "asterisk.h"
00035 
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 430509 $")
00037 
00038 #include "asterisk/_private.h"
00039 #include "asterisk/paths.h"   /* use ast_config_AST_DB */
00040 #include <sys/time.h>
00041 #include <sys/types.h>
00042 #include <sys/stat.h>
00043 #include <unistd.h>
00044 #include <signal.h>
00045 #include <dirent.h>
00046 #include <sqlite3.h>
00047 
00048 #include "asterisk/channel.h"
00049 #include "asterisk/file.h"
00050 #include "asterisk/app.h"
00051 #include "asterisk/dsp.h"
00052 #include "asterisk/astdb.h"
00053 #include "asterisk/cli.h"
00054 #include "asterisk/utils.h"
00055 #include "asterisk/manager.h"
00056 
00057 /*** DOCUMENTATION
00058    <manager name="DBGet" language="en_US">
00059       <synopsis>
00060          Get DB Entry.
00061       </synopsis>
00062       <syntax>
00063          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00064          <parameter name="Family" required="true" />
00065          <parameter name="Key" required="true" />
00066       </syntax>
00067       <description>
00068       </description>
00069    </manager>
00070    <manager name="DBPut" language="en_US">
00071       <synopsis>
00072          Put DB entry.
00073       </synopsis>
00074       <syntax>
00075          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00076          <parameter name="Family" required="true" />
00077          <parameter name="Key" required="true" />
00078          <parameter name="Val" />
00079       </syntax>
00080       <description>
00081       </description>
00082    </manager>
00083    <manager name="DBDel" language="en_US">
00084       <synopsis>
00085          Delete DB entry.
00086       </synopsis>
00087       <syntax>
00088          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00089          <parameter name="Family" required="true" />
00090          <parameter name="Key" required="true" />
00091       </syntax>
00092       <description>
00093       </description>
00094    </manager>
00095    <manager name="DBDelTree" language="en_US">
00096       <synopsis>
00097          Delete DB Tree.
00098       </synopsis>
00099       <syntax>
00100          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00101          <parameter name="Family" required="true" />
00102          <parameter name="Key" />
00103       </syntax>
00104       <description>
00105       </description>
00106    </manager>
00107  ***/
00108 
00109 #define MAX_DB_FIELD 256
00110 AST_MUTEX_DEFINE_STATIC(dblock);
00111 static ast_cond_t dbcond;
00112 static sqlite3 *astdb;
00113 static pthread_t syncthread;
00114 static int doexit;
00115 static int dosync;
00116 
00117 static void db_sync(void);
00118 
00119 #define DEFINE_SQL_STATEMENT(stmt,sql) static sqlite3_stmt *stmt; \
00120    const char stmt##_sql[] = sql;
00121 
00122 DEFINE_SQL_STATEMENT(put_stmt, "INSERT OR REPLACE INTO astdb (key, value) VALUES (?, ?)")
00123 DEFINE_SQL_STATEMENT(get_stmt, "SELECT value FROM astdb WHERE key=?")
00124 DEFINE_SQL_STATEMENT(del_stmt, "DELETE FROM astdb WHERE key=?")
00125 DEFINE_SQL_STATEMENT(deltree_stmt, "DELETE FROM astdb WHERE key || '/' LIKE ? || '/' || '%'")
00126 DEFINE_SQL_STATEMENT(deltree_all_stmt, "DELETE FROM astdb")
00127 DEFINE_SQL_STATEMENT(gettree_stmt, "SELECT key, value FROM astdb WHERE key || '/' LIKE ? || '/' || '%' ORDER BY key")
00128 DEFINE_SQL_STATEMENT(gettree_all_stmt, "SELECT key, value FROM astdb ORDER BY key")
00129 DEFINE_SQL_STATEMENT(showkey_stmt, "SELECT key, value FROM astdb WHERE key LIKE '%' || '/' || ? ORDER BY key")
00130 DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key VARCHAR(256), value VARCHAR(256), PRIMARY KEY(key))")
00131 
00132 static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len)
00133 {
00134    ast_mutex_lock(&dblock);
00135    if (sqlite3_prepare(astdb, sql, len, stmt, NULL) != SQLITE_OK) {
00136       ast_log(LOG_WARNING, "Couldn't prepare statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
00137       ast_mutex_unlock(&dblock);
00138       return -1;
00139    }
00140    ast_mutex_unlock(&dblock);
00141 
00142    return 0;
00143 }
00144 
00145 /*! \internal
00146  * \brief Clean up the prepared SQLite3 statement
00147  * \note dblock should already be locked prior to calling this method
00148  */
00149 static int clean_stmt(sqlite3_stmt **stmt, const char *sql)
00150 {
00151    if (sqlite3_finalize(*stmt) != SQLITE_OK) {
00152       ast_log(LOG_WARNING, "Couldn't finalize statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
00153       *stmt = NULL;
00154       return -1;
00155    }
00156    *stmt = NULL;
00157    return 0;
00158 }
00159 
00160 /*! \internal
00161  * \brief Clean up all prepared SQLite3 statements
00162  * \note dblock should already be locked prior to calling this method
00163  */
00164 static void clean_statements(void)
00165 {
00166    clean_stmt(&get_stmt, get_stmt_sql);
00167    clean_stmt(&del_stmt, del_stmt_sql);
00168    clean_stmt(&deltree_stmt, deltree_stmt_sql);
00169    clean_stmt(&deltree_all_stmt, deltree_all_stmt_sql);
00170    clean_stmt(&gettree_stmt, gettree_stmt_sql);
00171    clean_stmt(&gettree_all_stmt, gettree_all_stmt_sql);
00172    clean_stmt(&showkey_stmt, showkey_stmt_sql);
00173    clean_stmt(&put_stmt, put_stmt_sql);
00174    clean_stmt(&create_astdb_stmt, create_astdb_stmt_sql);
00175 }
00176 
00177 static int init_statements(void)
00178 {
00179    /* Don't initialize create_astdb_statment here as the astdb table needs to exist
00180     * brefore these statments can be initialized */
00181    return init_stmt(&get_stmt, get_stmt_sql, sizeof(get_stmt_sql))
00182    || init_stmt(&del_stmt, del_stmt_sql, sizeof(del_stmt_sql))
00183    || init_stmt(&deltree_stmt, deltree_stmt_sql, sizeof(deltree_stmt_sql))
00184    || init_stmt(&deltree_all_stmt, deltree_all_stmt_sql, sizeof(deltree_all_stmt_sql))
00185    || init_stmt(&gettree_stmt, gettree_stmt_sql, sizeof(gettree_stmt_sql))
00186    || init_stmt(&gettree_all_stmt, gettree_all_stmt_sql, sizeof(gettree_all_stmt_sql))
00187    || init_stmt(&showkey_stmt, showkey_stmt_sql, sizeof(showkey_stmt_sql))
00188    || init_stmt(&put_stmt, put_stmt_sql, sizeof(put_stmt_sql));
00189 }
00190 
00191 static int convert_bdb_to_sqlite3(void)
00192 {
00193    char *cmd;
00194    int res;
00195 
00196    ast_asprintf(&cmd, "%s/astdb2sqlite3 '%s'\n", ast_config_AST_SBIN_DIR, ast_config_AST_DB);
00197    res = ast_safe_system(cmd);
00198    ast_free(cmd);
00199 
00200    return res;
00201 }
00202 
00203 static int db_create_astdb(void)
00204 {
00205    int res = 0;
00206 
00207    if (!create_astdb_stmt) {
00208       init_stmt(&create_astdb_stmt, create_astdb_stmt_sql, sizeof(create_astdb_stmt_sql));
00209    }
00210 
00211    ast_mutex_lock(&dblock);
00212    if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) {
00213       ast_log(LOG_WARNING, "Couldn't create astdb table: %s\n", sqlite3_errmsg(astdb));
00214       res = -1;
00215    }
00216    sqlite3_reset(create_astdb_stmt);
00217    db_sync();
00218    ast_mutex_unlock(&dblock);
00219 
00220    return res;
00221 }
00222 
00223 static int db_open(void)
00224 {
00225    char *dbname;
00226    struct stat dont_care;
00227 
00228    if (!(dbname = ast_alloca(strlen(ast_config_AST_DB) + sizeof(".sqlite3")))) {
00229       return -1;
00230    }
00231    strcpy(dbname, ast_config_AST_DB);
00232    strcat(dbname, ".sqlite3");
00233 
00234    if (stat(dbname, &dont_care) && !stat(ast_config_AST_DB, &dont_care)) {
00235       if (convert_bdb_to_sqlite3()) {
00236          ast_log(LOG_ERROR, "*** Database conversion failed!\n");
00237          ast_log(LOG_ERROR, "*** Asterisk now uses SQLite3 for its internal\n");
00238          ast_log(LOG_ERROR, "*** database. Conversion from the old astdb\n");
00239          ast_log(LOG_ERROR, "*** failed. Most likely the astdb2sqlite3 utility\n");
00240          ast_log(LOG_ERROR, "*** was not selected for build. To convert the\n");
00241          ast_log(LOG_ERROR, "*** old astdb, please delete '%s'\n", dbname);
00242          ast_log(LOG_ERROR, "*** and re-run 'make menuselect' and select astdb2sqlite3\n");
00243          ast_log(LOG_ERROR, "*** in the Utilities section, then 'make && make install'.\n");
00244          ast_log(LOG_ERROR, "*** It is also imperative that the user under which\n");
00245          ast_log(LOG_ERROR, "*** Asterisk runs have write permission to the directory\n");
00246          ast_log(LOG_ERROR, "*** where the database resides.\n");
00247          sleep(5);
00248       } else {
00249          ast_log(LOG_NOTICE, "Database conversion succeeded!\n");
00250       }
00251    }
00252 
00253    ast_mutex_lock(&dblock);
00254    if (sqlite3_open(dbname, &astdb) != SQLITE_OK) {
00255       ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb));
00256       sqlite3_close(astdb);
00257       ast_mutex_unlock(&dblock);
00258       return -1;
00259    }
00260 
00261    ast_mutex_unlock(&dblock);
00262 
00263    return 0;
00264 }
00265 
00266 static int db_init(void)
00267 {
00268    if (astdb) {
00269       return 0;
00270    }
00271 
00272    if (db_open() || db_create_astdb() || init_statements()) {
00273       return -1;
00274    }
00275 
00276    return 0;
00277 }
00278 
00279 /* We purposely don't lock around the sqlite3 call because the transaction
00280  * calls will be called with the database lock held. For any other use, make
00281  * sure to take the dblock yourself. */
00282 static int db_execute_sql(const char *sql, int (*callback)(void *, int, char **, char **), void *arg)
00283 {
00284    char *errmsg = NULL;
00285    int res =0;
00286 
00287    if (sqlite3_exec(astdb, sql, callback, arg, &errmsg) != SQLITE_OK) {
00288       ast_log(LOG_WARNING, "Error executing SQL (%s): %s\n", sql, errmsg);
00289       sqlite3_free(errmsg);
00290       res = -1;
00291    }
00292 
00293    return res;
00294 }
00295 
00296 static int ast_db_begin_transaction(void)
00297 {
00298    return db_execute_sql("BEGIN TRANSACTION", NULL, NULL);
00299 }
00300 
00301 static int ast_db_commit_transaction(void)
00302 {
00303    return db_execute_sql("COMMIT", NULL, NULL);
00304 }
00305 
00306 static int ast_db_rollback_transaction(void)
00307 {
00308    return db_execute_sql("ROLLBACK", NULL, NULL);
00309 }
00310 
00311 int ast_db_put(const char *family, const char *key, const char *value)
00312 {
00313    char fullkey[MAX_DB_FIELD];
00314    size_t fullkey_len;
00315    int res = 0;
00316 
00317    if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
00318       ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
00319       return -1;
00320    }
00321 
00322    fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
00323 
00324    ast_mutex_lock(&dblock);
00325    if (sqlite3_bind_text(put_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
00326       ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
00327       res = -1;
00328    } else if (sqlite3_bind_text(put_stmt, 2, value, -1, SQLITE_STATIC) != SQLITE_OK) {
00329       ast_log(LOG_WARNING, "Couldn't bind value to stmt: %s\n", sqlite3_errmsg(astdb));
00330       res = -1;
00331    } else if (sqlite3_step(put_stmt) != SQLITE_DONE) {
00332       ast_log(LOG_WARNING, "Couldn't execute statment: %s\n", sqlite3_errmsg(astdb));
00333       res = -1;
00334    }
00335 
00336    sqlite3_reset(put_stmt);
00337    db_sync();
00338    ast_mutex_unlock(&dblock);
00339 
00340    return res;
00341 }
00342 
00343 /*!
00344  * \internal
00345  * \brief Get key value specified by family/key.
00346  *
00347  * Gets the value associated with the specified \a family and \a key, and
00348  * stores it, either into the fixed sized buffer specified by \a buffer
00349  * and \a bufferlen, or as a heap allocated string if \a bufferlen is -1.
00350  *
00351  * \note If \a bufferlen is -1, \a buffer points to heap allocated memory
00352  *       and must be freed by calling ast_free().
00353  *
00354  * \retval -1 An error occurred
00355  * \retval 0 Success
00356  */
00357 static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen)
00358 {
00359    const unsigned char *result;
00360    char fullkey[MAX_DB_FIELD];
00361    size_t fullkey_len;
00362    int res = 0;
00363 
00364    if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
00365       ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
00366       return -1;
00367    }
00368 
00369    fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
00370 
00371    ast_mutex_lock(&dblock);
00372    if (sqlite3_bind_text(get_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
00373       ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
00374       res = -1;
00375    } else if (sqlite3_step(get_stmt) != SQLITE_ROW) {
00376       ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
00377       res = -1;
00378    } else if (!(result = sqlite3_column_text(get_stmt, 0))) {
00379       ast_log(LOG_WARNING, "Couldn't get value\n");
00380       res = -1;
00381    } else {
00382       const char *value = (const char *) result;
00383 
00384       if (bufferlen == -1) {
00385          *buffer = ast_strdup(value);
00386       } else {
00387          ast_copy_string(*buffer, value, bufferlen);
00388       }
00389    }
00390    sqlite3_reset(get_stmt);
00391    ast_mutex_unlock(&dblock);
00392 
00393    return res;
00394 }
00395 
00396 int ast_db_get(const char *family, const char *key, char *value, int valuelen)
00397 {
00398    ast_assert(value != NULL);
00399 
00400    /* Make sure we initialize */
00401    value[0] = 0;
00402 
00403    return db_get_common(family, key, &value, valuelen);
00404 }
00405 
00406 int ast_db_get_allocated(const char *family, const char *key, char **out)
00407 {
00408    *out = NULL;
00409 
00410    return db_get_common(family, key, out, -1);
00411 }
00412 
00413 int ast_db_del(const char *family, const char *key)
00414 {
00415    char fullkey[MAX_DB_FIELD];
00416    size_t fullkey_len;
00417    int res = 0;
00418 
00419    if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
00420       ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
00421       return -1;
00422    }
00423 
00424    fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
00425 
00426    ast_mutex_lock(&dblock);
00427    if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
00428       ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
00429       res = -1;
00430    } else if (sqlite3_step(del_stmt) != SQLITE_DONE) {
00431       ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
00432       res = -1;
00433    }
00434    sqlite3_reset(del_stmt);
00435    db_sync();
00436    ast_mutex_unlock(&dblock);
00437 
00438    return res;
00439 }
00440 
00441 int ast_db_deltree(const char *family, const char *keytree)
00442 {
00443    sqlite3_stmt *stmt = deltree_stmt;
00444    char prefix[MAX_DB_FIELD];
00445    int res = 0;
00446 
00447    if (!ast_strlen_zero(family)) {
00448       if (!ast_strlen_zero(keytree)) {
00449          /* Family and key tree */
00450          snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
00451       } else {
00452          /* Family only */
00453          snprintf(prefix, sizeof(prefix), "/%s", family);
00454       }
00455    } else {
00456       prefix[0] = '\0';
00457       stmt = deltree_all_stmt;
00458    }
00459 
00460    ast_mutex_lock(&dblock);
00461    if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
00462       ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
00463       res = -1;
00464    } else if (sqlite3_step(stmt) != SQLITE_DONE) {
00465       ast_log(LOG_WARNING, "Couldn't execute stmt: %s\n", sqlite3_errmsg(astdb));
00466       res = -1;
00467    }
00468    res = sqlite3_changes(astdb);
00469    sqlite3_reset(stmt);
00470    db_sync();
00471    ast_mutex_unlock(&dblock);
00472 
00473    return res;
00474 }
00475 
00476 struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
00477 {
00478    char prefix[MAX_DB_FIELD];
00479    sqlite3_stmt *stmt = gettree_stmt;
00480    struct ast_db_entry *cur, *last = NULL, *ret = NULL;
00481 
00482    if (!ast_strlen_zero(family)) {
00483       if (!ast_strlen_zero(keytree)) {
00484          /* Family and key tree */
00485          snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
00486       } else {
00487          /* Family only */
00488          snprintf(prefix, sizeof(prefix), "/%s", family);
00489       }
00490    } else {
00491       prefix[0] = '\0';
00492       stmt = gettree_all_stmt;
00493    }
00494 
00495    ast_mutex_lock(&dblock);
00496    if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
00497       ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
00498       sqlite3_reset(stmt);
00499       ast_mutex_unlock(&dblock);
00500       return NULL;
00501    }
00502 
00503    while (sqlite3_step(stmt) == SQLITE_ROW) {
00504       const char *key_s, *value_s;
00505       if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
00506          break;
00507       }
00508       if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
00509          break;
00510       }
00511       if (!(cur = ast_malloc(sizeof(*cur) + strlen(key_s) + strlen(value_s) + 2))) {
00512          break;
00513       }
00514       cur->next = NULL;
00515       cur->key = cur->data + strlen(value_s) + 1;
00516       strcpy(cur->data, value_s);
00517       strcpy(cur->key, key_s);
00518       if (last) {
00519          last->next = cur;
00520       } else {
00521          ret = cur;
00522       }
00523       last = cur;
00524    }
00525    sqlite3_reset(stmt);
00526    ast_mutex_unlock(&dblock);
00527 
00528    return ret;
00529 }
00530 
00531 void ast_db_freetree(struct ast_db_entry *dbe)
00532 {
00533    struct ast_db_entry *last;
00534    while (dbe) {
00535       last = dbe;
00536       dbe = dbe->next;
00537       ast_free(last);
00538    }
00539 }
00540 
00541 static char *handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00542 {
00543    int res;
00544 
00545    switch (cmd) {
00546    case CLI_INIT:
00547       e->command = "database put";
00548       e->usage =
00549          "Usage: database put <family> <key> <value>\n"
00550          "       Adds or updates an entry in the Asterisk database for\n"
00551          "       a given family, key, and value.\n";
00552       return NULL;
00553    case CLI_GENERATE:
00554       return NULL;
00555    }
00556 
00557    if (a->argc != 5)
00558       return CLI_SHOWUSAGE;
00559    res = ast_db_put(a->argv[2], a->argv[3], a->argv[4]);
00560    if (res)  {
00561       ast_cli(a->fd, "Failed to update entry\n");
00562    } else {
00563       ast_cli(a->fd, "Updated database successfully\n");
00564    }
00565    return CLI_SUCCESS;
00566 }
00567 
00568 static char *handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00569 {
00570    int res;
00571    char tmp[MAX_DB_FIELD];
00572 
00573    switch (cmd) {
00574    case CLI_INIT:
00575       e->command = "database get";
00576       e->usage =
00577          "Usage: database get <family> <key>\n"
00578          "       Retrieves an entry in the Asterisk database for a given\n"
00579          "       family and key.\n";
00580       return NULL;
00581    case CLI_GENERATE:
00582       return NULL;
00583    }
00584 
00585    if (a->argc != 4)
00586       return CLI_SHOWUSAGE;
00587    res = ast_db_get(a->argv[2], a->argv[3], tmp, sizeof(tmp));
00588    if (res) {
00589       ast_cli(a->fd, "Database entry not found.\n");
00590    } else {
00591       ast_cli(a->fd, "Value: %s\n", tmp);
00592    }
00593    return CLI_SUCCESS;
00594 }
00595 
00596 static char *handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00597 {
00598    int res;
00599 
00600    switch (cmd) {
00601    case CLI_INIT:
00602       e->command = "database del";
00603       e->usage =
00604          "Usage: database del <family> <key>\n"
00605          "       Deletes an entry in the Asterisk database for a given\n"
00606          "       family and key.\n";
00607       return NULL;
00608    case CLI_GENERATE:
00609       return NULL;
00610    }
00611 
00612    if (a->argc != 4)
00613       return CLI_SHOWUSAGE;
00614    res = ast_db_del(a->argv[2], a->argv[3]);
00615    if (res) {
00616       ast_cli(a->fd, "Database entry does not exist.\n");
00617    } else {
00618       ast_cli(a->fd, "Database entry removed.\n");
00619    }
00620    return CLI_SUCCESS;
00621 }
00622 
00623 static char *handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00624 {
00625    int num_deleted;
00626 
00627    switch (cmd) {
00628    case CLI_INIT:
00629       e->command = "database deltree";
00630       e->usage =
00631          "Usage: database deltree <family> [keytree]\n"
00632          "   OR: database deltree <family>[/keytree]\n"
00633          "       Deletes a family or specific keytree within a family\n"
00634          "       in the Asterisk database.  The two arguments may be\n"
00635          "       separated by either a space or a slash.\n";
00636       return NULL;
00637    case CLI_GENERATE:
00638       return NULL;
00639    }
00640 
00641    if ((a->argc < 3) || (a->argc > 4))
00642       return CLI_SHOWUSAGE;
00643    if (a->argc == 4) {
00644       num_deleted = ast_db_deltree(a->argv[2], a->argv[3]);
00645    } else {
00646       num_deleted = ast_db_deltree(a->argv[2], NULL);
00647    }
00648    if (num_deleted < 0) {
00649       ast_cli(a->fd, "Database unavailable.\n");
00650    } else if (num_deleted == 0) {
00651       ast_cli(a->fd, "Database entries do not exist.\n");
00652    } else {
00653       ast_cli(a->fd, "%d database entries removed.\n",num_deleted);
00654    }
00655    return CLI_SUCCESS;
00656 }
00657 
00658 static char *handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00659 {
00660    char prefix[MAX_DB_FIELD];
00661    int counter = 0;
00662    sqlite3_stmt *stmt = gettree_stmt;
00663 
00664    switch (cmd) {
00665    case CLI_INIT:
00666       e->command = "database show";
00667       e->usage =
00668          "Usage: database show [family [keytree]]\n"
00669          "   OR: database show [family[/keytree]]\n"
00670          "       Shows Asterisk database contents, optionally restricted\n"
00671          "       to a given family, or family and keytree. The two arguments\n"
00672          "       may be separated either by a space or by a slash.\n";
00673       return NULL;
00674    case CLI_GENERATE:
00675       return NULL;
00676    }
00677 
00678    if (a->argc == 4) {
00679       /* Family and key tree */
00680       snprintf(prefix, sizeof(prefix), "/%s/%s", a->argv[2], a->argv[3]);
00681    } else if (a->argc == 3) {
00682       /* Family only */
00683       snprintf(prefix, sizeof(prefix), "/%s", a->argv[2]);
00684    } else if (a->argc == 2) {
00685       /* Neither */
00686       prefix[0] = '\0';
00687       stmt = gettree_all_stmt;
00688 
00689    } else {
00690       return CLI_SHOWUSAGE;
00691    }
00692 
00693    ast_mutex_lock(&dblock);
00694    if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
00695       ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
00696       sqlite3_reset(stmt);
00697       ast_mutex_unlock(&dblock);
00698       return NULL;
00699    }
00700 
00701    while (sqlite3_step(stmt) == SQLITE_ROW) {
00702       const char *key_s, *value_s;
00703       if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
00704          ast_log(LOG_WARNING, "Skipping invalid key!\n");
00705          continue;
00706       }
00707       if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
00708          ast_log(LOG_WARNING, "Skipping invalid value!\n");
00709          continue;
00710       }
00711       ++counter;
00712       ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
00713    }
00714 
00715    sqlite3_reset(stmt);
00716    ast_mutex_unlock(&dblock);
00717 
00718    ast_cli(a->fd, "%d results found.\n", counter);
00719    return CLI_SUCCESS;
00720 }
00721 
00722 static char *handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00723 {
00724    int counter = 0;
00725 
00726    switch (cmd) {
00727    case CLI_INIT:
00728       e->command = "database showkey";
00729       e->usage =
00730          "Usage: database showkey <keytree>\n"
00731          "       Shows Asterisk database contents, restricted to a given key.\n";
00732       return NULL;
00733    case CLI_GENERATE:
00734       return NULL;
00735    }
00736 
00737    if (a->argc != 3) {
00738       return CLI_SHOWUSAGE;
00739    }
00740 
00741    ast_mutex_lock(&dblock);
00742    if (!ast_strlen_zero(a->argv[2]) && (sqlite3_bind_text(showkey_stmt, 1, a->argv[2], -1, SQLITE_STATIC) != SQLITE_OK)) {
00743       ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", a->argv[2], sqlite3_errmsg(astdb));
00744       sqlite3_reset(showkey_stmt);
00745       ast_mutex_unlock(&dblock);
00746       return NULL;
00747    }
00748 
00749    while (sqlite3_step(showkey_stmt) == SQLITE_ROW) {
00750       const char *key_s, *value_s;
00751       if (!(key_s = (const char *) sqlite3_column_text(showkey_stmt, 0))) {
00752          break;
00753       }
00754       if (!(value_s = (const char *) sqlite3_column_text(showkey_stmt, 1))) {
00755          break;
00756       }
00757       ++counter;
00758       ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
00759    }
00760    sqlite3_reset(showkey_stmt);
00761    ast_mutex_unlock(&dblock);
00762 
00763    ast_cli(a->fd, "%d results found.\n", counter);
00764    return CLI_SUCCESS;
00765 }
00766 
00767 static int display_results(void *arg, int columns, char **values, char **colnames)
00768 {
00769    struct ast_cli_args *a = arg;
00770    size_t x;
00771 
00772    for (x = 0; x < columns; x++) {
00773       ast_cli(a->fd, "%-5s: %-50s\n", colnames[x], values[x]);
00774    }
00775    ast_cli(a->fd, "\n");
00776 
00777    return 0;
00778 }
00779 
00780 static char *handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00781 {
00782 
00783    switch (cmd) {
00784    case CLI_INIT:
00785       e->command = "database query";
00786       e->usage =
00787          "Usage: database query \"<SQL Statement>\"\n"
00788          "       Run a user-specified SQL query on the database. Be careful.\n";
00789       return NULL;
00790    case CLI_GENERATE:
00791       return NULL;
00792    }
00793 
00794    if (a->argc != 3) {
00795       return CLI_SHOWUSAGE;
00796    }
00797 
00798    ast_mutex_lock(&dblock);
00799    db_execute_sql(a->argv[2], display_results, a);
00800    db_sync(); /* Go ahead and sync the db in case they write */
00801    ast_mutex_unlock(&dblock);
00802 
00803    return CLI_SUCCESS;
00804 }
00805 
00806 static struct ast_cli_entry cli_database[] = {
00807    AST_CLI_DEFINE(handle_cli_database_show,    "Shows database contents"),
00808    AST_CLI_DEFINE(handle_cli_database_showkey, "Shows database contents"),
00809    AST_CLI_DEFINE(handle_cli_database_get,     "Gets database value"),
00810    AST_CLI_DEFINE(handle_cli_database_put,     "Adds/updates database value"),
00811    AST_CLI_DEFINE(handle_cli_database_del,     "Removes database key/value"),
00812    AST_CLI_DEFINE(handle_cli_database_deltree, "Removes database keytree/values"),
00813    AST_CLI_DEFINE(handle_cli_database_query,   "Run a user-specified query on the astdb"),
00814 };
00815 
00816 static int manager_dbput(struct mansession *s, const struct message *m)
00817 {
00818    const char *family = astman_get_header(m, "Family");
00819    const char *key = astman_get_header(m, "Key");
00820    const char *val = astman_get_header(m, "Val");
00821    int res;
00822 
00823    if (ast_strlen_zero(family)) {
00824       astman_send_error(s, m, "No family specified");
00825       return 0;
00826    }
00827    if (ast_strlen_zero(key)) {
00828       astman_send_error(s, m, "No key specified");
00829       return 0;
00830    }
00831 
00832    res = ast_db_put(family, key, S_OR(val, ""));
00833    if (res) {
00834       astman_send_error(s, m, "Failed to update entry");
00835    } else {
00836       astman_send_ack(s, m, "Updated database successfully");
00837    }
00838    return 0;
00839 }
00840 
00841 static int manager_dbget(struct mansession *s, const struct message *m)
00842 {
00843    const char *id = astman_get_header(m,"ActionID");
00844    char idText[256];
00845    const char *family = astman_get_header(m, "Family");
00846    const char *key = astman_get_header(m, "Key");
00847    char tmp[MAX_DB_FIELD];
00848    int res;
00849 
00850    if (ast_strlen_zero(family)) {
00851       astman_send_error(s, m, "No family specified.");
00852       return 0;
00853    }
00854    if (ast_strlen_zero(key)) {
00855       astman_send_error(s, m, "No key specified.");
00856       return 0;
00857    }
00858 
00859    idText[0] = '\0';
00860    if (!ast_strlen_zero(id))
00861       snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
00862 
00863    res = ast_db_get(family, key, tmp, sizeof(tmp));
00864    if (res) {
00865       astman_send_error(s, m, "Database entry not found");
00866    } else {
00867       astman_send_listack(s, m, "Result will follow", "start");
00868 
00869       astman_append(s, "Event: DBGetResponse\r\n"
00870             "Family: %s\r\n"
00871             "Key: %s\r\n"
00872             "Val: %s\r\n"
00873             "%s"
00874             "\r\n",
00875             family, key, tmp, idText);
00876 
00877       astman_send_list_complete_start(s, m, "DBGetComplete", 1);
00878       astman_send_list_complete_end(s);
00879    }
00880    return 0;
00881 }
00882 
00883 static int manager_dbdel(struct mansession *s, const struct message *m)
00884 {
00885    const char *family = astman_get_header(m, "Family");
00886    const char *key = astman_get_header(m, "Key");
00887    int res;
00888 
00889    if (ast_strlen_zero(family)) {
00890       astman_send_error(s, m, "No family specified.");
00891       return 0;
00892    }
00893 
00894    if (ast_strlen_zero(key)) {
00895       astman_send_error(s, m, "No key specified.");
00896       return 0;
00897    }
00898 
00899    res = ast_db_del(family, key);
00900    if (res)
00901       astman_send_error(s, m, "Database entry not found");
00902    else
00903       astman_send_ack(s, m, "Key deleted successfully");
00904 
00905    return 0;
00906 }
00907 
00908 static int manager_dbdeltree(struct mansession *s, const struct message *m)
00909 {
00910    const char *family = astman_get_header(m, "Family");
00911    const char *key = astman_get_header(m, "Key");
00912    int num_deleted;
00913 
00914    if (ast_strlen_zero(family)) {
00915       astman_send_error(s, m, "No family specified.");
00916       return 0;
00917    }
00918 
00919    if (!ast_strlen_zero(key)) {
00920       num_deleted = ast_db_deltree(family, key);
00921    } else {
00922       num_deleted = ast_db_deltree(family, NULL);
00923    }
00924 
00925    if (num_deleted < 0) {
00926       astman_send_error(s, m, "Database unavailable");
00927    } else if (num_deleted == 0) {
00928       astman_send_error(s, m, "Database entry not found");
00929    } else {
00930       astman_send_ack(s, m, "Key tree deleted successfully");
00931    }
00932 
00933    return 0;
00934 }
00935 
00936 /*!
00937  * \internal
00938  * \brief Signal the astdb sync thread to do its thing.
00939  *
00940  * \note dblock is assumed to be held when calling this function.
00941  */
00942 static void db_sync(void)
00943 {
00944    dosync = 1;
00945    ast_cond_signal(&dbcond);
00946 }
00947 
00948 /*!
00949  * \internal
00950  * \brief astdb sync thread
00951  *
00952  * This thread is in charge of syncing astdb to disk after a change.
00953  * By pushing it off to this thread to take care of, this I/O bound operation
00954  * will not block other threads from performing other critical processing.
00955  * If changes happen rapidly, this thread will also ensure that the sync
00956  * operations are rate limited.
00957  */
00958 static void *db_sync_thread(void *data)
00959 {
00960    ast_mutex_lock(&dblock);
00961    ast_db_begin_transaction();
00962    for (;;) {
00963       /* If dosync is set, db_sync() was called during sleep(1), 
00964        * and the pending transaction should be committed. 
00965        * Otherwise, block until db_sync() is called.
00966        */
00967       while (!dosync) {
00968          ast_cond_wait(&dbcond, &dblock);
00969       }
00970       dosync = 0;
00971       if (ast_db_commit_transaction()) {
00972          ast_db_rollback_transaction();
00973       }
00974       if (doexit) {
00975          ast_mutex_unlock(&dblock);
00976          break;
00977       }
00978       ast_db_begin_transaction();
00979       ast_mutex_unlock(&dblock);
00980       sleep(1);
00981       ast_mutex_lock(&dblock);
00982    }
00983 
00984    return NULL;
00985 }
00986 
00987 /*!
00988  * \internal
00989  * \brief Clean up resources on Asterisk shutdown
00990  */
00991 static void astdb_atexit(void)
00992 {
00993    ast_cli_unregister_multiple(cli_database, ARRAY_LEN(cli_database));
00994    ast_manager_unregister("DBGet");
00995    ast_manager_unregister("DBPut");
00996    ast_manager_unregister("DBDel");
00997    ast_manager_unregister("DBDelTree");
00998 
00999    /* Set doexit to 1 to kill thread. db_sync must be called with
01000     * mutex held. */
01001    ast_mutex_lock(&dblock);
01002    doexit = 1;
01003    db_sync();
01004    ast_mutex_unlock(&dblock);
01005 
01006    pthread_join(syncthread, NULL);
01007    ast_mutex_lock(&dblock);
01008    clean_statements();
01009    if (sqlite3_close(astdb) == SQLITE_OK) {
01010       astdb = NULL;
01011    }
01012    ast_mutex_unlock(&dblock);
01013 }
01014 
01015 int astdb_init(void)
01016 {
01017    if (db_init()) {
01018       return -1;
01019    }
01020 
01021    ast_cond_init(&dbcond, NULL);
01022    if (ast_pthread_create_background(&syncthread, NULL, db_sync_thread, NULL)) {
01023       return -1;
01024    }
01025 
01026    ast_register_atexit(astdb_atexit);
01027    ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database));
01028    ast_manager_register_xml_core("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget);
01029    ast_manager_register_xml_core("DBPut", EVENT_FLAG_SYSTEM, manager_dbput);
01030    ast_manager_register_xml_core("DBDel", EVENT_FLAG_SYSTEM, manager_dbdel);
01031    ast_manager_register_xml_core("DBDelTree", EVENT_FLAG_SYSTEM, manager_dbdeltree);
01032    return 0;
01033 }

Generated on Thu Apr 16 06:27:32 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6