Asterisk - The Open Source Telephony Project  21.4.1
Macros | Functions | Variables
main/db.c File Reference

ASTdb Management. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include <dirent.h>
#include <sqlite3.h>
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/astdb.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/manager.h"

Go to the source code of this file.

Macros

#define DEFINE_SQL_STATEMENT(stmt, sql)
 
#define MAX_DB_FIELD   256
 

Functions

static int ast_db_begin_transaction (void)
 
static int ast_db_commit_transaction (void)
 
int ast_db_del (const char *family, const char *key)
 Delete entry in astdb.
 
int ast_db_del2 (const char *family, const char *key)
 Same as ast_db_del, but with more stringent error checking. More...
 
int ast_db_deltree (const char *family, const char *keytree)
 Delete one or more entries in astdb. More...
 
int ast_db_exists (const char *family, const char *key)
 Check if family/key exitsts. More...
 
void ast_db_freetree (struct ast_db_entry *dbe)
 Free structure created by ast_db_gettree()
 
int ast_db_get (const char *family, const char *key, char *value, int valuelen)
 Get key value specified by family/key.
 
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. More...
 
struct ast_db_entryast_db_gettree (const char *family, const char *keytree)
 Get a list of values within the astdb tree. More...
 
struct ast_db_entryast_db_gettree_by_prefix (const char *family, const char *key_prefix)
 Get a list of values with the given key prefix. More...
 
int ast_db_put (const char *family, const char *key, const char *value)
 Store value addressed by family/key.
 
static int ast_db_rollback_transaction (void)
 
static void astdb_atexit (void)
 
int astdb_init (void)
 
static void clean_statements (void)
 
static int clean_stmt (sqlite3_stmt **stmt, const char *sql)
 
static int convert_bdb_to_sqlite3 (void)
 
static int db_create_astdb (void)
 
static int db_execute_sql (const char *sql, int(*callback)(void *, int, char **, char **), void *arg)
 
static int db_get_common (const char *family, const char *key, char **buffer, int bufferlen)
 
static struct ast_db_entrydb_gettree_common (sqlite3_stmt *stmt)
 
static int db_init (void)
 
static int db_open (void)
 
static void db_sync (void)
 
static void * db_sync_thread (void *data)
 
 DEFINE_SQL_STATEMENT (put_stmt,"INSERT OR REPLACE INTO astdb (key, value) VALUES (?, ?)")
 
static int display_results (void *arg, int columns, char **values, char **colnames)
 
static char * handle_cli_database_del (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_database_deltree (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_database_get (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_database_put (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_database_query (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_database_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_database_showkey (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int init_statements (void)
 
static int manager_db_tree_get (struct mansession *s, const struct message *m)
 
static int manager_dbdel (struct mansession *s, const struct message *m)
 
static int manager_dbdeltree (struct mansession *s, const struct message *m)
 
static int manager_dbget (struct mansession *s, const struct message *m)
 
static int manager_dbput (struct mansession *s, const struct message *m)
 

Variables

static sqlite3 * astdb
 
static struct ast_cli_entry cli_database []
 
static ast_cond_t dbcond
 
static ast_mutex_t dblock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static int doexit
 
static int dosync
 
static pthread_t syncthread
 

Detailed Description

ASTdb Management.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Note
DB3 is licensed under Sleepycat Public License and is thus incompatible with GPL. To avoid having to make another exception (and complicate licensing even further) we elect to use DB1 which is BSD licensed

Definition in file main/db.c.

Macro Definition Documentation

#define DEFINE_SQL_STATEMENT (   stmt,
  sql 
)
Value:
static sqlite3_stmt *stmt; \
const char stmt##_sql[] = sql;

Definition at line 129 of file main/db.c.

Function Documentation

int ast_db_del2 ( const char *  family,
const char *  key 
)

Same as ast_db_del, but with more stringent error checking.

Unlike ast_db_del, if the key does not exist in the first place, an error is emitted and -1 is returned.

Return values
-1An error occured (including key not found to begin with)
0Successfully deleted

Definition at line 504 of file main/db.c.

References ast_db_get().

505 {
506  char fullkey[MAX_DB_FIELD];
507  char tmp[1];
508  size_t fullkey_len;
509  int mres, res = 0;
510 
511  if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
512  ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
513  return -1;
514  }
515 
516  fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
517 
518  ast_mutex_lock(&dblock);
519  if (ast_db_get(family, key, tmp, sizeof(tmp))) {
520  ast_log(LOG_WARNING, "AstDB key %s does not exist\n", fullkey);
521  res = -1;
522  } else if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
523  ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
524  res = -1;
525  } else if ((mres = sqlite3_step(del_stmt) != SQLITE_DONE)) {
526  ast_log(LOG_WARNING, "AstDB error (%s): %s\n", fullkey, sqlite3_errstr(mres));
527  res = -1;
528  }
529  sqlite3_reset(del_stmt);
530  db_sync();
531  ast_mutex_unlock(&dblock);
532 
533  return res;
534 }
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: main/db.c:427
int ast_db_deltree ( const char *  family,
const char *  keytree 
)

Delete one or more entries in astdb.

If both parameters are NULL, the entire database will be purged. If only keytree is NULL, all entries within the family will be purged. It is an error for keytree to have a value when family is NULL.

Return values
-1An error occurred
>=0 Number of records deleted

Definition at line 536 of file main/db.c.

537 {
538  sqlite3_stmt *stmt = deltree_stmt;
539  char prefix[MAX_DB_FIELD];
540  int res = 0;
541 
542  if (!ast_strlen_zero(family)) {
543  if (!ast_strlen_zero(keytree)) {
544  /* Family and key tree */
545  snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
546  } else {
547  /* Family only */
548  snprintf(prefix, sizeof(prefix), "/%s", family);
549  }
550  } else {
551  prefix[0] = '\0';
552  stmt = deltree_all_stmt;
553  }
554 
555  ast_mutex_lock(&dblock);
556  if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
557  ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
558  res = -1;
559  } else if (sqlite3_step(stmt) != SQLITE_DONE) {
560  ast_log(LOG_WARNING, "Couldn't execute stmt: %s\n", sqlite3_errmsg(astdb));
561  res = -1;
562  }
563  res = sqlite3_changes(astdb);
564  sqlite3_reset(stmt);
565  db_sync();
566  ast_mutex_unlock(&dblock);
567 
568  return res;
569 }
int ast_db_exists ( const char *  family,
const char *  key 
)

Check if family/key exitsts.

Parameters
family
key
Return values
1if family/key exists
0if family/key does not exist or an error occurred

Definition at line 444 of file main/db.c.

445 {
446  int result;
447  char fullkey[MAX_DB_FIELD];
448  size_t fullkey_len;
449  int res = 0;
450 
451  fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
452  if (fullkey_len >= sizeof(fullkey)) {
453  ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
454  return -1;
455  }
456 
457  ast_mutex_lock(&dblock);
458  res = sqlite3_bind_text(exists_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC);
459  if (res != SQLITE_OK) {
460  ast_log(LOG_WARNING, "Couldn't bind key to stmt: %d:%s\n", res, sqlite3_errmsg(astdb));
461  res = 0;
462  } else if (sqlite3_step(exists_stmt) != SQLITE_ROW) {
463  res = 0;
464  } else if (!(result = sqlite3_column_int(exists_stmt, 0))) {
465  res = 0;
466  } else {
467  res = result;
468  }
469  sqlite3_reset(exists_stmt);
470  ast_mutex_unlock(&dblock);
471 
472  return res;
473 }
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.

Given a family and key, sets out to a pointer to a heap allocated string. In the event of an error, out will be set to NULL. The string must be freed by calling ast_free().

Return values
-1An error occurred
0Success

Definition at line 437 of file main/db.c.

Referenced by reload_queue_members().

438 {
439  *out = NULL;
440 
441  return db_get_common(family, key, out, -1);
442 }
struct ast_db_entry* ast_db_gettree ( const char *  family,
const char *  keytree 
)

Get a list of values within the astdb tree.

If family is specified, only those keys will be returned. If keytree is specified, subkeys are expected to exist (separated from the key with a slash). If subkeys do not exist and keytree is specified, the tree will consist of either a single entry or NULL will be returned.

Resulting tree should be freed by passing the return value to ast_db_freetree() when usage is concluded.

Definition at line 610 of file main/db.c.

Referenced by reload_queue_members(), sorcery_astdb_retrieve_fields_common(), and stasis_app_device_states_to_json().

611 {
612  char prefix[MAX_DB_FIELD];
613  sqlite3_stmt *stmt = gettree_stmt;
614  size_t res = 0;
615  struct ast_db_entry *ret;
616 
617  if (!ast_strlen_zero(family)) {
618  if (!ast_strlen_zero(keytree)) {
619  /* Family and key tree */
620  res = snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
621  } else {
622  /* Family only */
623  res = snprintf(prefix, sizeof(prefix), "/%s", family);
624  }
625 
626  if (res >= sizeof(prefix)) {
627  ast_log(LOG_WARNING, "Requested prefix is too long: %s\n", keytree);
628  return NULL;
629  }
630  } else {
631  prefix[0] = '\0';
632  stmt = gettree_all_stmt;
633  }
634 
635  ast_mutex_lock(&dblock);
636  if (res && (sqlite3_bind_text(stmt, 1, prefix, res, SQLITE_STATIC) != SQLITE_OK)) {
637  ast_log(LOG_WARNING, "Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
638  sqlite3_reset(stmt);
639  ast_mutex_unlock(&dblock);
640  return NULL;
641  }
642 
643  ret = db_gettree_common(stmt);
644  sqlite3_reset(stmt);
645  ast_mutex_unlock(&dblock);
646 
647  return ret;
648 }
Definition: astdb.h:31
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.

Parameters
familyThe family to search under
key_prefixThe key prefix to search under
Return values
NULLAn error occurred

Definition at line 650 of file main/db.c.

651 {
652  char prefix[MAX_DB_FIELD];
653  size_t res;
654  struct ast_db_entry *ret;
655 
656  res = snprintf(prefix, sizeof(prefix), "/%s/%s", family, key_prefix);
657  if (res >= sizeof(prefix)) {
658  ast_log(LOG_WARNING, "Requested key prefix is too long: %s\n", key_prefix);
659  return NULL;
660  }
661 
662  ast_mutex_lock(&dblock);
663  if (sqlite3_bind_text(gettree_prefix_stmt, 1, prefix, res, SQLITE_STATIC) != SQLITE_OK) {
664  ast_log(LOG_WARNING, "Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
665  sqlite3_reset(gettree_prefix_stmt);
666  ast_mutex_unlock(&dblock);
667  return NULL;
668  }
669 
670  ret = db_gettree_common(gettree_prefix_stmt);
671  sqlite3_reset(gettree_prefix_stmt);
672  ast_mutex_unlock(&dblock);
673 
674  return ret;
675 }
Definition: astdb.h:31
int astdb_init ( void  )

Provided by db.c

Definition at line 1228 of file main/db.c.

References ast_cli_register_multiple, ast_manager_register_xml_core, ast_register_atexit(), and db_sync_thread().

1229 {
1230  ast_cond_init(&dbcond, NULL);
1231 
1232  if (db_init()) {
1233  return -1;
1234  }
1235 
1236  if (ast_pthread_create_background(&syncthread, NULL, db_sync_thread, NULL)) {
1237  return -1;
1238  }
1239 
1240  ast_register_atexit(astdb_atexit);
1241  ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database));
1242  ast_manager_register_xml_core("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget);
1243  ast_manager_register_xml_core("DBGetTree", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_db_tree_get);
1244  ast_manager_register_xml_core("DBPut", EVENT_FLAG_SYSTEM, manager_dbput);
1245  ast_manager_register_xml_core("DBDel", EVENT_FLAG_SYSTEM, manager_dbdel);
1246  ast_manager_register_xml_core("DBDelTree", EVENT_FLAG_SYSTEM, manager_dbdeltree);
1247  return 0;
1248 }
static void * db_sync_thread(void *data)
Wrap commands in transactions increased write performance.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:202
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: clicompat.c:13