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 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 350979 $")
00033
00034 #include "asterisk/_private.h"
00035 #include "asterisk/paths.h"
00036 #include <sys/time.h>
00037 #include <sys/types.h>
00038 #include <sys/stat.h>
00039 #include <unistd.h>
00040 #include <signal.h>
00041 #include <dirent.h>
00042 #include <sqlite3.h>
00043
00044 #include "asterisk/channel.h"
00045 #include "asterisk/file.h"
00046 #include "asterisk/app.h"
00047 #include "asterisk/dsp.h"
00048 #include "asterisk/astdb.h"
00049 #include "asterisk/cli.h"
00050 #include "asterisk/utils.h"
00051 #include "asterisk/manager.h"
00052
00053
00054
00055
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 #define MAX_DB_FIELD 256
00106 AST_MUTEX_DEFINE_STATIC(dblock);
00107 static ast_cond_t dbcond;
00108 static sqlite3 *astdb;
00109 static pthread_t syncthread;
00110 static int doexit;
00111
00112 static void db_sync(void);
00113
00114 #define DEFINE_SQL_STATEMENT(stmt,sql) static sqlite3_stmt *stmt; \
00115 const char stmt##_sql[] = sql;
00116
00117 DEFINE_SQL_STATEMENT(put_stmt, "INSERT OR REPLACE INTO astdb (key, value) VALUES (?, ?)")
00118 DEFINE_SQL_STATEMENT(get_stmt, "SELECT value FROM astdb WHERE key=?")
00119 DEFINE_SQL_STATEMENT(del_stmt, "DELETE FROM astdb WHERE key=?")
00120 DEFINE_SQL_STATEMENT(deltree_stmt, "DELETE FROM astdb WHERE key || '/' LIKE ? || '/' || '%'")
00121 DEFINE_SQL_STATEMENT(deltree_all_stmt, "DELETE FROM astdb")
00122 DEFINE_SQL_STATEMENT(gettree_stmt, "SELECT key, value FROM astdb WHERE key || '/' LIKE ? || '/' || '%' ORDER BY key")
00123 DEFINE_SQL_STATEMENT(gettree_all_stmt, "SELECT key, value FROM astdb ORDER BY key")
00124 DEFINE_SQL_STATEMENT(showkey_stmt, "SELECT key, value FROM astdb WHERE key LIKE '%' || '/' || ? ORDER BY key")
00125 DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key VARCHAR(256), value VARCHAR(256), PRIMARY KEY(key))")
00126
00127 static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len)
00128 {
00129 ast_mutex_lock(&dblock);
00130 if (sqlite3_prepare(astdb, sql, len, stmt, NULL) != SQLITE_OK) {
00131 ast_log(LOG_WARNING, "Couldn't prepare statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
00132 ast_mutex_unlock(&dblock);
00133 return -1;
00134 }
00135 ast_mutex_unlock(&dblock);
00136
00137 return 0;
00138 }
00139
00140 static int init_statements(void)
00141 {
00142
00143
00144 return init_stmt(&get_stmt, get_stmt_sql, sizeof(get_stmt_sql))
00145 || init_stmt(&del_stmt, del_stmt_sql, sizeof(del_stmt_sql))
00146 || init_stmt(&deltree_stmt, deltree_stmt_sql, sizeof(deltree_stmt_sql))
00147 || init_stmt(&deltree_all_stmt, deltree_all_stmt_sql, sizeof(deltree_all_stmt_sql))
00148 || init_stmt(&gettree_stmt, gettree_stmt_sql, sizeof(gettree_stmt_sql))
00149 || init_stmt(&gettree_all_stmt, gettree_all_stmt_sql, sizeof(gettree_all_stmt_sql))
00150 || init_stmt(&showkey_stmt, showkey_stmt_sql, sizeof(showkey_stmt_sql))
00151 || init_stmt(&put_stmt, put_stmt_sql, sizeof(put_stmt_sql));
00152 }
00153
00154 static int convert_bdb_to_sqlite3(void)
00155 {
00156 char *cmd;
00157 int res;
00158
00159 ast_asprintf(&cmd, "%s/astdb2sqlite3 '%s'\n", ast_config_AST_SBIN_DIR, ast_config_AST_DB);
00160 res = ast_safe_system(cmd);
00161 ast_free(cmd);
00162
00163 return res;
00164 }
00165
00166 static int db_create_astdb(void)
00167 {
00168 int res = 0;
00169
00170 if (!create_astdb_stmt) {
00171 init_stmt(&create_astdb_stmt, create_astdb_stmt_sql, sizeof(create_astdb_stmt_sql));
00172 }
00173
00174 ast_mutex_lock(&dblock);
00175 if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) {
00176 ast_log(LOG_WARNING, "Couldn't create astdb table: %s\n", sqlite3_errmsg(astdb));
00177 res = -1;
00178 }
00179 sqlite3_reset(create_astdb_stmt);
00180 db_sync();
00181 ast_mutex_unlock(&dblock);
00182
00183 return res;
00184 }
00185
00186 static int db_open(void)
00187 {
00188 char *dbname;
00189 struct stat dont_care;
00190
00191 if (!(dbname = alloca(strlen(ast_config_AST_DB) + sizeof(".sqlite3")))) {
00192 return -1;
00193 }
00194 strcpy(dbname, ast_config_AST_DB);
00195 strcat(dbname, ".sqlite3");
00196
00197 if (stat(dbname, &dont_care) && !stat(ast_config_AST_DB, &dont_care)) {
00198 if (convert_bdb_to_sqlite3()) {
00199 ast_log(LOG_ERROR, "*** Database conversion failed!\n");
00200 ast_log(LOG_ERROR, "*** Asterisk now uses SQLite3 for its internal\n");
00201 ast_log(LOG_ERROR, "*** database. Conversion from the old astdb\n");
00202 ast_log(LOG_ERROR, "*** failed. Most likely the astdb2sqlite3 utility\n");
00203 ast_log(LOG_ERROR, "*** was not selected for build. To convert the\n");
00204 ast_log(LOG_ERROR, "*** old astdb, please delete '%s'\n", dbname);
00205 ast_log(LOG_ERROR, "*** and re-run 'make menuselect' and select astdb2sqlite3\n");
00206 ast_log(LOG_ERROR, "*** in the Utilities section, then 'make && make install'.\n");
00207 ast_log(LOG_ERROR, "*** It is also imperative that the user under which\n");
00208 ast_log(LOG_ERROR, "*** Asterisk runs have write permission to the directory\n");
00209 ast_log(LOG_ERROR, "*** where the database resides.\n");
00210 sleep(5);
00211 } else {
00212 ast_log(LOG_NOTICE, "Database conversion succeeded!\n");
00213 }
00214 }
00215
00216 ast_mutex_lock(&dblock);
00217 if (sqlite3_open(dbname, &astdb) != SQLITE_OK) {
00218 ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb));
00219 sqlite3_close(astdb);
00220 ast_mutex_unlock(&dblock);
00221 return -1;
00222 }
00223 ast_mutex_unlock(&dblock);
00224
00225 return 0;
00226 }
00227
00228 static int db_init(void)
00229 {
00230 if (astdb) {
00231 return 0;
00232 }
00233
00234 if (db_open() || db_create_astdb() || init_statements()) {
00235 return -1;
00236 }
00237
00238 return 0;
00239 }
00240
00241
00242
00243
00244 static int db_execute_sql(const char *sql, int (*callback)(void *, int, char **, char **), void *arg)
00245 {
00246 char *errmsg = NULL;
00247 int res =0;
00248
00249 sqlite3_exec(astdb, sql, callback, arg, &errmsg);
00250 if (errmsg) {
00251 ast_log(LOG_WARNING, "Error executing SQL: %s\n", errmsg);
00252 sqlite3_free(errmsg);
00253 res = -1;
00254 }
00255
00256 return res;
00257 }
00258
00259 static int ast_db_begin_transaction(void)
00260 {
00261 return db_execute_sql("BEGIN TRANSACTION", NULL, NULL);
00262 }
00263
00264 static int ast_db_commit_transaction(void)
00265 {
00266 return db_execute_sql("COMMIT", NULL, NULL);
00267 }
00268
00269 static int ast_db_rollback_transaction(void)
00270 {
00271 return db_execute_sql("ROLLBACK", NULL, NULL);
00272 }
00273
00274 int ast_db_put(const char *family, const char *key, const char *value)
00275 {
00276 char fullkey[MAX_DB_FIELD];
00277 size_t fullkey_len;
00278 int res = 0;
00279
00280 if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
00281 ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
00282 return -1;
00283 }
00284
00285 fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
00286
00287 ast_mutex_lock(&dblock);
00288 if (sqlite3_bind_text(put_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
00289 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
00290 res = -1;
00291 } else if (sqlite3_bind_text(put_stmt, 2, value, -1, SQLITE_STATIC) != SQLITE_OK) {
00292 ast_log(LOG_WARNING, "Couldn't bind value to stmt: %s\n", sqlite3_errmsg(astdb));
00293 res = -1;
00294 } else if (sqlite3_step(put_stmt) != SQLITE_DONE) {
00295 ast_log(LOG_WARNING, "Couldn't execute statment: %s\n", sqlite3_errmsg(astdb));
00296 res = -1;
00297 }
00298
00299 sqlite3_reset(put_stmt);
00300 db_sync();
00301 ast_mutex_unlock(&dblock);
00302
00303 return res;
00304 }
00305
00306 int ast_db_get(const char *family, const char *key, char *value, int valuelen)
00307 {
00308 const unsigned char *result;
00309 char fullkey[MAX_DB_FIELD];
00310 size_t fullkey_len;
00311 int res = 0;
00312
00313 if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
00314 ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
00315 return -1;
00316 }
00317
00318 fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
00319
00320 ast_mutex_lock(&dblock);
00321 if (sqlite3_bind_text(get_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
00322 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
00323 res = -1;
00324 } else if (sqlite3_step(get_stmt) != SQLITE_ROW) {
00325 ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
00326 res = -1;
00327 } else if (!(result = sqlite3_column_text(get_stmt, 0))) {
00328 ast_log(LOG_WARNING, "Couldn't get value\n");
00329 res = -1;
00330 } else {
00331 strncpy(value, (const char *) result, valuelen);
00332 }
00333 sqlite3_reset(get_stmt);
00334 ast_mutex_unlock(&dblock);
00335
00336 return res;
00337 }
00338
00339 int ast_db_del(const char *family, const char *key)
00340 {
00341 char fullkey[MAX_DB_FIELD];
00342 size_t fullkey_len;
00343 int res = 0;
00344
00345 if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
00346 ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
00347 return -1;
00348 }
00349
00350 fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
00351
00352 ast_mutex_lock(&dblock);
00353 if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
00354 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
00355 res = -1;
00356 } else if (sqlite3_step(del_stmt) != SQLITE_DONE) {
00357 ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
00358 res = -1;
00359 }
00360 sqlite3_reset(del_stmt);
00361 db_sync();
00362 ast_mutex_unlock(&dblock);
00363
00364 return res;
00365 }
00366
00367 int ast_db_deltree(const char *family, const char *keytree)
00368 {
00369 sqlite3_stmt *stmt = deltree_stmt;
00370 char prefix[MAX_DB_FIELD];
00371 int res = 0;
00372
00373 if (!ast_strlen_zero(family)) {
00374 if (!ast_strlen_zero(keytree)) {
00375
00376 snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
00377 } else {
00378
00379 snprintf(prefix, sizeof(prefix), "/%s", family);
00380 }
00381 } else {
00382 prefix[0] = '\0';
00383 stmt = deltree_all_stmt;
00384 }
00385
00386 ast_mutex_lock(&dblock);
00387 if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
00388 ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
00389 res = -1;
00390 } else if (sqlite3_step(stmt) != SQLITE_DONE) {
00391 ast_log(LOG_WARNING, "Couldn't execute stmt: %s\n", sqlite3_errmsg(astdb));
00392 res = -1;
00393 }
00394 res = sqlite3_changes(astdb);
00395 sqlite3_reset(stmt);
00396 db_sync();
00397 ast_mutex_unlock(&dblock);
00398
00399 return res;
00400 }
00401
00402 struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
00403 {
00404 char prefix[MAX_DB_FIELD];
00405 sqlite3_stmt *stmt = gettree_stmt;
00406 struct ast_db_entry *cur, *last = NULL, *ret = NULL;
00407
00408 if (!ast_strlen_zero(family)) {
00409 if (!ast_strlen_zero(keytree)) {
00410
00411 snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
00412 } else {
00413
00414 snprintf(prefix, sizeof(prefix), "/%s", family);
00415 }
00416 } else {
00417 prefix[0] = '\0';
00418 stmt = gettree_all_stmt;
00419 }
00420
00421 ast_mutex_lock(&dblock);
00422 if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
00423 ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
00424 sqlite3_reset(stmt);
00425 ast_mutex_unlock(&dblock);
00426 return NULL;
00427 }
00428
00429 while (sqlite3_step(stmt) == SQLITE_ROW) {
00430 const char *key_s, *value_s;
00431 if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
00432 break;
00433 }
00434 if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
00435 break;
00436 }
00437 if (!(cur = ast_malloc(sizeof(*cur) + strlen(key_s) + strlen(value_s) + 2))) {
00438 break;
00439 }
00440 cur->next = NULL;
00441 cur->key = cur->data + strlen(value_s) + 1;
00442 strcpy(cur->data, value_s);
00443 strcpy(cur->key, key_s);
00444 if (last) {
00445 last->next = cur;
00446 } else {
00447 ret = cur;
00448 }
00449 last = cur;
00450 }
00451 sqlite3_reset(stmt);
00452 ast_mutex_unlock(&dblock);
00453
00454 return ret;
00455 }
00456
00457 void ast_db_freetree(struct ast_db_entry *dbe)
00458 {
00459 struct ast_db_entry *last;
00460 while (dbe) {
00461 last = dbe;
00462 dbe = dbe->next;
00463 ast_free(last);
00464 }
00465 }
00466
00467 static char *handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00468 {
00469 int res;
00470
00471 switch (cmd) {
00472 case CLI_INIT:
00473 e->command = "database put";
00474 e->usage =
00475 "Usage: database put <family> <key> <value>\n"
00476 " Adds or updates an entry in the Asterisk database for\n"
00477 " a given family, key, and value.\n";
00478 return NULL;
00479 case CLI_GENERATE:
00480 return NULL;
00481 }
00482
00483 if (a->argc != 5)
00484 return CLI_SHOWUSAGE;
00485 res = ast_db_put(a->argv[2], a->argv[3], a->argv[4]);
00486 if (res) {
00487 ast_cli(a->fd, "Failed to update entry\n");
00488 } else {
00489 ast_cli(a->fd, "Updated database successfully\n");
00490 }
00491 return CLI_SUCCESS;
00492 }
00493
00494 static char *handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00495 {
00496 int res;
00497 char tmp[MAX_DB_FIELD];
00498
00499 switch (cmd) {
00500 case CLI_INIT:
00501 e->command = "database get";
00502 e->usage =
00503 "Usage: database get <family> <key>\n"
00504 " Retrieves an entry in the Asterisk database for a given\n"
00505 " family and key.\n";
00506 return NULL;
00507 case CLI_GENERATE:
00508 return NULL;
00509 }
00510
00511 if (a->argc != 4)
00512 return CLI_SHOWUSAGE;
00513 res = ast_db_get(a->argv[2], a->argv[3], tmp, sizeof(tmp));
00514 if (res) {
00515 ast_cli(a->fd, "Database entry not found.\n");
00516 } else {
00517 ast_cli(a->fd, "Value: %s\n", tmp);
00518 }
00519 return CLI_SUCCESS;
00520 }
00521
00522 static char *handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00523 {
00524 int res;
00525
00526 switch (cmd) {
00527 case CLI_INIT:
00528 e->command = "database del";
00529 e->usage =
00530 "Usage: database del <family> <key>\n"
00531 " Deletes an entry in the Asterisk database for a given\n"
00532 " family and key.\n";
00533 return NULL;
00534 case CLI_GENERATE:
00535 return NULL;
00536 }
00537
00538 if (a->argc != 4)
00539 return CLI_SHOWUSAGE;
00540 res = ast_db_del(a->argv[2], a->argv[3]);
00541 if (res) {
00542 ast_cli(a->fd, "Database entry does not exist.\n");
00543 } else {
00544 ast_cli(a->fd, "Database entry removed.\n");
00545 }
00546 return CLI_SUCCESS;
00547 }
00548
00549 static char *handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00550 {
00551 int res;
00552
00553 switch (cmd) {
00554 case CLI_INIT:
00555 e->command = "database deltree";
00556 e->usage =
00557 "Usage: database deltree <family> [keytree]\n"
00558 " OR: database deltree <family>[/keytree]\n"
00559 " Deletes a family or specific keytree within a family\n"
00560 " in the Asterisk database. The two arguments may be\n"
00561 " separated by either a space or a slash.\n";
00562 return NULL;
00563 case CLI_GENERATE:
00564 return NULL;
00565 }
00566
00567 if ((a->argc < 3) || (a->argc > 4))
00568 return CLI_SHOWUSAGE;
00569 if (a->argc == 4) {
00570 res = ast_db_deltree(a->argv[2], a->argv[3]);
00571 } else {
00572 res = ast_db_deltree(a->argv[2], NULL);
00573 }
00574 if (res < 0) {
00575 ast_cli(a->fd, "Database entries do not exist.\n");
00576 } else {
00577 ast_cli(a->fd, "%d database entries removed.\n",res);
00578 }
00579 return CLI_SUCCESS;
00580 }
00581
00582 static char *handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00583 {
00584 char prefix[MAX_DB_FIELD];
00585 int counter = 0;
00586 sqlite3_stmt *stmt = gettree_stmt;
00587
00588 switch (cmd) {
00589 case CLI_INIT:
00590 e->command = "database show";
00591 e->usage =
00592 "Usage: database show [family [keytree]]\n"
00593 " OR: database show [family[/keytree]]\n"
00594 " Shows Asterisk database contents, optionally restricted\n"
00595 " to a given family, or family and keytree. The two arguments\n"
00596 " may be separated either by a space or by a slash.\n";
00597 return NULL;
00598 case CLI_GENERATE:
00599 return NULL;
00600 }
00601
00602 if (a->argc == 4) {
00603
00604 snprintf(prefix, sizeof(prefix), "/%s/%s", a->argv[2], a->argv[3]);
00605 } else if (a->argc == 3) {
00606
00607 snprintf(prefix, sizeof(prefix), "/%s", a->argv[2]);
00608 } else if (a->argc == 2) {
00609
00610 prefix[0] = '\0';
00611 stmt = gettree_all_stmt;
00612
00613 } else {
00614 return CLI_SHOWUSAGE;
00615 }
00616
00617 ast_mutex_lock(&dblock);
00618 if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
00619 ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
00620 sqlite3_reset(stmt);
00621 ast_mutex_unlock(&dblock);
00622 return NULL;
00623 }
00624
00625 while (sqlite3_step(stmt) == SQLITE_ROW) {
00626 const char *key_s, *value_s;
00627 if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
00628 ast_log(LOG_WARNING, "Skipping invalid key!\n");
00629 continue;
00630 }
00631 if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
00632 ast_log(LOG_WARNING, "Skipping invalid value!\n");
00633 continue;
00634 }
00635 ++counter;
00636 ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
00637 }
00638
00639 sqlite3_reset(stmt);
00640 ast_mutex_unlock(&dblock);
00641
00642 ast_cli(a->fd, "%d results found.\n", counter);
00643 return CLI_SUCCESS;
00644 }
00645
00646 static char *handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00647 {
00648 int counter = 0;
00649
00650 switch (cmd) {
00651 case CLI_INIT:
00652 e->command = "database showkey";
00653 e->usage =
00654 "Usage: database showkey <keytree>\n"
00655 " Shows Asterisk database contents, restricted to a given key.\n";
00656 return NULL;
00657 case CLI_GENERATE:
00658 return NULL;
00659 }
00660
00661 if (a->argc != 3) {
00662 return CLI_SHOWUSAGE;
00663 }
00664
00665 ast_mutex_lock(&dblock);
00666 if (!ast_strlen_zero(a->argv[2]) && (sqlite3_bind_text(showkey_stmt, 1, a->argv[2], -1, SQLITE_STATIC) != SQLITE_OK)) {
00667 ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", a->argv[2], sqlite3_errmsg(astdb));
00668 sqlite3_reset(showkey_stmt);
00669 ast_mutex_unlock(&dblock);
00670 return NULL;
00671 }
00672
00673 while (sqlite3_step(showkey_stmt) == SQLITE_ROW) {
00674 const char *key_s, *value_s;
00675 if (!(key_s = (const char *) sqlite3_column_text(showkey_stmt, 0))) {
00676 break;
00677 }
00678 if (!(value_s = (const char *) sqlite3_column_text(showkey_stmt, 1))) {
00679 break;
00680 }
00681 ++counter;
00682 ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
00683 }
00684 sqlite3_reset(showkey_stmt);
00685 ast_mutex_unlock(&dblock);
00686
00687 ast_cli(a->fd, "%d results found.\n", counter);
00688 return CLI_SUCCESS;
00689 }
00690
00691 static int display_results(void *arg, int columns, char **values, char **colnames)
00692 {
00693 struct ast_cli_args *a = arg;
00694 size_t x;
00695
00696 for (x = 0; x < columns; x++) {
00697 ast_cli(a->fd, "%-5s: %-50s\n", colnames[x], values[x]);
00698 }
00699 ast_cli(a->fd, "\n");
00700
00701 return 0;
00702 }
00703
00704 static char *handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00705 {
00706
00707 switch (cmd) {
00708 case CLI_INIT:
00709 e->command = "database query";
00710 e->usage =
00711 "Usage: database query \"<SQL Statement>\"\n"
00712 " Run a user-specified SQL query on the database. Be careful.\n";
00713 return NULL;
00714 case CLI_GENERATE:
00715 return NULL;
00716 }
00717
00718 if (a->argc != 3) {
00719 return CLI_SHOWUSAGE;
00720 }
00721
00722 ast_mutex_lock(&dblock);
00723 db_execute_sql(a->argv[2], display_results, a);
00724 db_sync();
00725 ast_mutex_unlock(&dblock);
00726
00727 return CLI_SUCCESS;
00728 }
00729
00730 static struct ast_cli_entry cli_database[] = {
00731 AST_CLI_DEFINE(handle_cli_database_show, "Shows database contents"),
00732 AST_CLI_DEFINE(handle_cli_database_showkey, "Shows database contents"),
00733 AST_CLI_DEFINE(handle_cli_database_get, "Gets database value"),
00734 AST_CLI_DEFINE(handle_cli_database_put, "Adds/updates database value"),
00735 AST_CLI_DEFINE(handle_cli_database_del, "Removes database key/value"),
00736 AST_CLI_DEFINE(handle_cli_database_deltree, "Removes database keytree/values"),
00737 AST_CLI_DEFINE(handle_cli_database_query, "Run a user-specified query on the astdb"),
00738 };
00739
00740 static int manager_dbput(struct mansession *s, const struct message *m)
00741 {
00742 const char *family = astman_get_header(m, "Family");
00743 const char *key = astman_get_header(m, "Key");
00744 const char *val = astman_get_header(m, "Val");
00745 int res;
00746
00747 if (ast_strlen_zero(family)) {
00748 astman_send_error(s, m, "No family specified");
00749 return 0;
00750 }
00751 if (ast_strlen_zero(key)) {
00752 astman_send_error(s, m, "No key specified");
00753 return 0;
00754 }
00755
00756 res = ast_db_put(family, key, S_OR(val, ""));
00757 if (res) {
00758 astman_send_error(s, m, "Failed to update entry");
00759 } else {
00760 astman_send_ack(s, m, "Updated database successfully");
00761 }
00762 return 0;
00763 }
00764
00765 static int manager_dbget(struct mansession *s, const struct message *m)
00766 {
00767 const char *id = astman_get_header(m,"ActionID");
00768 char idText[256] = "";
00769 const char *family = astman_get_header(m, "Family");
00770 const char *key = astman_get_header(m, "Key");
00771 char tmp[MAX_DB_FIELD];
00772 int res;
00773
00774 if (ast_strlen_zero(family)) {
00775 astman_send_error(s, m, "No family specified.");
00776 return 0;
00777 }
00778 if (ast_strlen_zero(key)) {
00779 astman_send_error(s, m, "No key specified.");
00780 return 0;
00781 }
00782
00783 if (!ast_strlen_zero(id))
00784 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
00785
00786 res = ast_db_get(family, key, tmp, sizeof(tmp));
00787 if (res) {
00788 astman_send_error(s, m, "Database entry not found");
00789 } else {
00790 astman_send_ack(s, m, "Result will follow");
00791 astman_append(s, "Event: DBGetResponse\r\n"
00792 "Family: %s\r\n"
00793 "Key: %s\r\n"
00794 "Val: %s\r\n"
00795 "%s"
00796 "\r\n",
00797 family, key, tmp, idText);
00798 astman_append(s, "Event: DBGetComplete\r\n"
00799 "%s"
00800 "\r\n",
00801 idText);
00802 }
00803 return 0;
00804 }
00805
00806 static int manager_dbdel(struct mansession *s, const struct message *m)
00807 {
00808 const char *family = astman_get_header(m, "Family");
00809 const char *key = astman_get_header(m, "Key");
00810 int res;
00811
00812 if (ast_strlen_zero(family)) {
00813 astman_send_error(s, m, "No family specified.");
00814 return 0;
00815 }
00816
00817 if (ast_strlen_zero(key)) {
00818 astman_send_error(s, m, "No key specified.");
00819 return 0;
00820 }
00821
00822 res = ast_db_del(family, key);
00823 if (res)
00824 astman_send_error(s, m, "Database entry not found");
00825 else
00826 astman_send_ack(s, m, "Key deleted successfully");
00827
00828 return 0;
00829 }
00830
00831 static int manager_dbdeltree(struct mansession *s, const struct message *m)
00832 {
00833 const char *family = astman_get_header(m, "Family");
00834 const char *key = astman_get_header(m, "Key");
00835 int res;
00836
00837 if (ast_strlen_zero(family)) {
00838 astman_send_error(s, m, "No family specified.");
00839 return 0;
00840 }
00841
00842 if (!ast_strlen_zero(key))
00843 res = ast_db_deltree(family, key);
00844 else
00845 res = ast_db_deltree(family, NULL);
00846
00847 if (res <= 0)
00848 astman_send_error(s, m, "Database entry not found");
00849 else
00850 astman_send_ack(s, m, "Key tree deleted successfully");
00851
00852 return 0;
00853 }
00854
00855
00856
00857
00858
00859
00860
00861 static void db_sync(void)
00862 {
00863 ast_cond_signal(&dbcond);
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876 static void *db_sync_thread(void *data)
00877 {
00878 ast_mutex_lock(&dblock);
00879 ast_db_begin_transaction();
00880 for (;;) {
00881
00882 ast_cond_wait(&dbcond, &dblock);
00883 if (ast_db_commit_transaction()) {
00884 ast_db_rollback_transaction();
00885 }
00886 if (doexit) {
00887 ast_mutex_unlock(&dblock);
00888 break;
00889 }
00890 ast_db_begin_transaction();
00891 ast_mutex_unlock(&dblock);
00892 sleep(1);
00893 ast_mutex_lock(&dblock);
00894
00895
00896
00897
00898
00899 if (doexit) {
00900 ast_mutex_unlock(&dblock);
00901 break;
00902 }
00903 }
00904
00905 return NULL;
00906 }
00907
00908 static void astdb_atexit(void)
00909 {
00910
00911
00912 doexit = 1;
00913 ast_mutex_lock(&dblock);
00914 db_sync();
00915 ast_mutex_unlock(&dblock);
00916
00917 pthread_join(syncthread, NULL);
00918 ast_mutex_lock(&dblock);
00919 sqlite3_close(astdb);
00920 ast_mutex_unlock(&dblock);
00921 }
00922
00923 int astdb_init(void)
00924 {
00925 if (db_init()) {
00926 return -1;
00927 }
00928
00929 ast_cond_init(&dbcond, NULL);
00930 if (ast_pthread_create_background(&syncthread, NULL, db_sync_thread, NULL)) {
00931 return -1;
00932 }
00933
00934 ast_register_atexit(astdb_atexit);
00935 ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database));
00936 ast_manager_register_xml("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget);
00937 ast_manager_register_xml("DBPut", EVENT_FLAG_SYSTEM, manager_dbput);
00938 ast_manager_register_xml("DBDel", EVENT_FLAG_SYSTEM, manager_dbdel);
00939 ast_manager_register_xml("DBDelTree", EVENT_FLAG_SYSTEM, manager_dbdeltree);
00940 return 0;
00941 }