00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "asterisk.h"
00035
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 410606 $")
00037
00038 #include "asterisk/_private.h"
00039 #include "asterisk/paths.h"
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
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
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
00146
00147
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
00161
00162
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
00180
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 ast_mutex_unlock(&dblock);
00261
00262 return 0;
00263 }
00264
00265 static int db_init(void)
00266 {
00267 if (astdb) {
00268 return 0;
00269 }
00270
00271 if (db_open() || db_create_astdb() || init_statements()) {
00272 return -1;
00273 }
00274
00275 return 0;
00276 }
00277
00278
00279
00280
00281 static int db_execute_sql(const char *sql, int (*callback)(void *, int, char **, char **), void *arg)
00282 {
00283 char *errmsg = NULL;
00284 int res =0;
00285
00286 sqlite3_exec(astdb, sql, callback, arg, &errmsg);
00287 if (errmsg) {
00288 ast_log(LOG_WARNING, "Error executing SQL: %s\n", 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
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
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
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
00450 snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
00451 } else {
00452
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
00485 snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
00486 } else {
00487
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
00680 snprintf(prefix, sizeof(prefix), "/%s/%s", a->argv[2], a->argv[3]);
00681 } else if (a->argc == 3) {
00682
00683 snprintf(prefix, sizeof(prefix), "/%s", a->argv[2]);
00684 } else if (a->argc == 2) {
00685
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();
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 if (!ast_strlen_zero(id))
00860 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
00861
00862 res = ast_db_get(family, key, tmp, sizeof(tmp));
00863 if (res) {
00864 astman_send_error(s, m, "Database entry not found");
00865 } else {
00866 astman_send_ack(s, m, "Result will follow");
00867 astman_append(s, "Event: DBGetResponse\r\n"
00868 "Family: %s\r\n"
00869 "Key: %s\r\n"
00870 "Val: %s\r\n"
00871 "%s"
00872 "\r\n",
00873 family, key, tmp, idText);
00874 astman_append(s, "Event: DBGetComplete\r\n"
00875 "%s"
00876 "\r\n",
00877 idText);
00878 }
00879 return 0;
00880 }
00881
00882 static int manager_dbdel(struct mansession *s, const struct message *m)
00883 {
00884 const char *family = astman_get_header(m, "Family");
00885 const char *key = astman_get_header(m, "Key");
00886 int res;
00887
00888 if (ast_strlen_zero(family)) {
00889 astman_send_error(s, m, "No family specified.");
00890 return 0;
00891 }
00892
00893 if (ast_strlen_zero(key)) {
00894 astman_send_error(s, m, "No key specified.");
00895 return 0;
00896 }
00897
00898 res = ast_db_del(family, key);
00899 if (res)
00900 astman_send_error(s, m, "Database entry not found");
00901 else
00902 astman_send_ack(s, m, "Key deleted successfully");
00903
00904 return 0;
00905 }
00906
00907 static int manager_dbdeltree(struct mansession *s, const struct message *m)
00908 {
00909 const char *family = astman_get_header(m, "Family");
00910 const char *key = astman_get_header(m, "Key");
00911 int num_deleted;
00912
00913 if (ast_strlen_zero(family)) {
00914 astman_send_error(s, m, "No family specified.");
00915 return 0;
00916 }
00917
00918 if (!ast_strlen_zero(key)) {
00919 num_deleted = ast_db_deltree(family, key);
00920 } else {
00921 num_deleted = ast_db_deltree(family, NULL);
00922 }
00923
00924 if (num_deleted < 0) {
00925 astman_send_error(s, m, "Database unavailable");
00926 } else if (num_deleted == 0) {
00927 astman_send_error(s, m, "Database entry not found");
00928 } else {
00929 astman_send_ack(s, m, "Key tree deleted successfully");
00930 }
00931
00932 return 0;
00933 }
00934
00935
00936
00937
00938
00939
00940
00941 static void db_sync(void)
00942 {
00943 dosync = 1;
00944 ast_cond_signal(&dbcond);
00945 }
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957 static void *db_sync_thread(void *data)
00958 {
00959 ast_mutex_lock(&dblock);
00960 ast_db_begin_transaction();
00961 for (;;) {
00962
00963
00964
00965
00966 while (!dosync) {
00967 ast_cond_wait(&dbcond, &dblock);
00968 }
00969 dosync = 0;
00970 if (ast_db_commit_transaction()) {
00971 ast_db_rollback_transaction();
00972 }
00973 if (doexit) {
00974 ast_mutex_unlock(&dblock);
00975 break;
00976 }
00977 ast_db_begin_transaction();
00978 ast_mutex_unlock(&dblock);
00979 sleep(1);
00980 ast_mutex_lock(&dblock);
00981 }
00982
00983 return NULL;
00984 }
00985
00986
00987 static void astdb_atexit(void)
00988 {
00989 ast_cli_unregister_multiple(cli_database, ARRAY_LEN(cli_database));
00990 ast_manager_unregister("DBGet");
00991 ast_manager_unregister("DBPut");
00992 ast_manager_unregister("DBDel");
00993 ast_manager_unregister("DBDelTree");
00994
00995
00996
00997 ast_mutex_lock(&dblock);
00998 doexit = 1;
00999 db_sync();
01000 ast_mutex_unlock(&dblock);
01001
01002 pthread_join(syncthread, NULL);
01003 ast_mutex_lock(&dblock);
01004 clean_statements();
01005 if (sqlite3_close(astdb) == SQLITE_OK) {
01006 astdb = NULL;
01007 }
01008 ast_mutex_unlock(&dblock);
01009 }
01010
01011 int astdb_init(void)
01012 {
01013 if (db_init()) {
01014 return -1;
01015 }
01016
01017 ast_cond_init(&dbcond, NULL);
01018 if (ast_pthread_create_background(&syncthread, NULL, db_sync_thread, NULL)) {
01019 return -1;
01020 }
01021
01022 ast_register_atexit(astdb_atexit);
01023 ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database));
01024 ast_manager_register_xml_core("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget);
01025 ast_manager_register_xml_core("DBPut", EVENT_FLAG_SYSTEM, manager_dbput);
01026 ast_manager_register_xml_core("DBDel", EVENT_FLAG_SYSTEM, manager_dbdel);
01027 ast_manager_register_xml_core("DBDelTree", EVENT_FLAG_SYSTEM, manager_dbdeltree);
01028 return 0;
01029 }