Asterisk - The Open Source Telephony Project  18.5.0
main/db.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief ASTdb Management
22  *
23  * \author Mark Spencer <[email protected]>
24  *
25  * \note DB3 is licensed under Sleepycat Public License and is thus incompatible
26  * with GPL. To avoid having to make another exception (and complicate
27  * licensing even further) we elect to use DB1 which is BSD licensed
28  */
29 
30 /*** MODULEINFO
31  <support_level>core</support_level>
32  ***/
33 
34 #include "asterisk.h"
35 
36 #include "asterisk/_private.h"
37 #include "asterisk/paths.h" /* use ast_config_AST_DB */
38 #include <sys/time.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <unistd.h>
42 #include <signal.h>
43 #include <dirent.h>
44 #include <sqlite3.h>
45 
46 #include "asterisk/channel.h"
47 #include "asterisk/file.h"
48 #include "asterisk/app.h"
49 #include "asterisk/dsp.h"
50 #include "asterisk/astdb.h"
51 #include "asterisk/cli.h"
52 #include "asterisk/utils.h"
53 #include "asterisk/manager.h"
54 
55 /*** DOCUMENTATION
56  <manager name="DBGet" language="en_US">
57  <synopsis>
58  Get DB Entry.
59  </synopsis>
60  <syntax>
61  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
62  <parameter name="Family" required="true" />
63  <parameter name="Key" required="true" />
64  </syntax>
65  <description>
66  </description>
67  </manager>
68  <manager name="DBPut" language="en_US">
69  <synopsis>
70  Put DB entry.
71  </synopsis>
72  <syntax>
73  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
74  <parameter name="Family" required="true" />
75  <parameter name="Key" required="true" />
76  <parameter name="Val" />
77  </syntax>
78  <description>
79  </description>
80  </manager>
81  <manager name="DBDel" language="en_US">
82  <synopsis>
83  Delete DB entry.
84  </synopsis>
85  <syntax>
86  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
87  <parameter name="Family" required="true" />
88  <parameter name="Key" required="true" />
89  </syntax>
90  <description>
91  </description>
92  </manager>
93  <manager name="DBDelTree" language="en_US">
94  <synopsis>
95  Delete DB Tree.
96  </synopsis>
97  <syntax>
98  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
99  <parameter name="Family" required="true" />
100  <parameter name="Key" />
101  </syntax>
102  <description>
103  </description>
104  </manager>
105  ***/
106 
107 #define MAX_DB_FIELD 256
110 static sqlite3 *astdb;
111 static pthread_t syncthread;
112 static int doexit;
113 static int dosync;
114 
115 static void db_sync(void);
116 
117 #define DEFINE_SQL_STATEMENT(stmt,sql) static sqlite3_stmt *stmt; \
118  const char stmt##_sql[] = sql;
119 
120 DEFINE_SQL_STATEMENT(put_stmt, "INSERT OR REPLACE INTO astdb (key, value) VALUES (?, ?)")
121 DEFINE_SQL_STATEMENT(get_stmt, "SELECT value FROM astdb WHERE key=?")
122 DEFINE_SQL_STATEMENT(del_stmt, "DELETE FROM astdb WHERE key=?")
123 DEFINE_SQL_STATEMENT(deltree_stmt, "DELETE FROM astdb WHERE key || '/' LIKE ? || '/' || '%'")
124 DEFINE_SQL_STATEMENT(deltree_all_stmt, "DELETE FROM astdb")
125 DEFINE_SQL_STATEMENT(gettree_stmt, "SELECT key, value FROM astdb WHERE key || '/' LIKE ? || '/' || '%' ORDER BY key")
126 DEFINE_SQL_STATEMENT(gettree_all_stmt, "SELECT key, value FROM astdb ORDER BY key")
127 DEFINE_SQL_STATEMENT(showkey_stmt, "SELECT key, value FROM astdb WHERE key LIKE '%' || '/' || ? ORDER BY key")
128 DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key VARCHAR(256), value VARCHAR(256), PRIMARY KEY(key))")
129 
130 /* This query begs an explanation:
131  *
132  * First, the parameter binding syntax used here is slightly different than the other
133  * queries in that we use a numbered parameter so that we can bind once and get the same
134  * value substituted multiple times within the executed query.
135  *
136  * Second, the key comparison is being used to find all keys that are lexicographically
137  * greater than the provided key, but less than the provided key with a high (but
138  * invalid) Unicode codepoint appended to it. This will give us all keys in the database
139  * that have 'key' as a prefix and performs much better than the equivalent "LIKE key ||
140  * '%'" operation.
141  */
142 DEFINE_SQL_STATEMENT(gettree_prefix_stmt, "SELECT key, value FROM astdb WHERE key > ?1 AND key <= ?1 || X'ffff'")
143 
144 static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len)
145 {
147  if (sqlite3_prepare(astdb, sql, len, stmt, NULL) != SQLITE_OK) {
148  ast_log(LOG_WARNING, "Couldn't prepare statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
150  return -1;
151  }
153 
154  return 0;
155 }
156 
157 /*! \internal
158  * \brief Clean up the prepared SQLite3 statement
159  * \note dblock should already be locked prior to calling this method
160  */
161 static int clean_stmt(sqlite3_stmt **stmt, const char *sql)
162 {
163  if (sqlite3_finalize(*stmt) != SQLITE_OK) {
164  ast_log(LOG_WARNING, "Couldn't finalize statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
165  *stmt = NULL;
166  return -1;
167  }
168  *stmt = NULL;
169  return 0;
170 }
171 
172 /*! \internal
173  * \brief Clean up all prepared SQLite3 statements
174  * \note dblock should already be locked prior to calling this method
175  */
176 static void clean_statements(void)
177 {
178  clean_stmt(&get_stmt, get_stmt_sql);
179  clean_stmt(&del_stmt, del_stmt_sql);
180  clean_stmt(&deltree_stmt, deltree_stmt_sql);
181  clean_stmt(&deltree_all_stmt, deltree_all_stmt_sql);
182  clean_stmt(&gettree_stmt, gettree_stmt_sql);
183  clean_stmt(&gettree_all_stmt, gettree_all_stmt_sql);
184  clean_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql);
185  clean_stmt(&showkey_stmt, showkey_stmt_sql);
186  clean_stmt(&put_stmt, put_stmt_sql);
187  clean_stmt(&create_astdb_stmt, create_astdb_stmt_sql);
188 }
189 
190 static int init_statements(void)
191 {
192  /* Don't initialize create_astdb_statement here as the astdb table needs to exist
193  * brefore these statements can be initialized */
194  return init_stmt(&get_stmt, get_stmt_sql, sizeof(get_stmt_sql))
195  || init_stmt(&del_stmt, del_stmt_sql, sizeof(del_stmt_sql))
196  || init_stmt(&deltree_stmt, deltree_stmt_sql, sizeof(deltree_stmt_sql))
197  || init_stmt(&deltree_all_stmt, deltree_all_stmt_sql, sizeof(deltree_all_stmt_sql))
198  || init_stmt(&gettree_stmt, gettree_stmt_sql, sizeof(gettree_stmt_sql))
199  || init_stmt(&gettree_all_stmt, gettree_all_stmt_sql, sizeof(gettree_all_stmt_sql))
200  || init_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql, sizeof(gettree_prefix_stmt_sql))
201  || init_stmt(&showkey_stmt, showkey_stmt_sql, sizeof(showkey_stmt_sql))
202  || init_stmt(&put_stmt, put_stmt_sql, sizeof(put_stmt_sql));
203 }
204 
205 static int convert_bdb_to_sqlite3(void)
206 {
207  char *cmd;
208  int res;
209 
210  res = ast_asprintf(&cmd, "%s/astdb2sqlite3 '%s'\n", ast_config_AST_SBIN_DIR, ast_config_AST_DB);
211  if (0 <= res) {
212  res = ast_safe_system(cmd);
213  ast_free(cmd);
214  }
215 
216  return res;
217 }
218 
219 static int db_create_astdb(void)
220 {
221  int res = 0;
222 
223  if (!create_astdb_stmt) {
224  init_stmt(&create_astdb_stmt, create_astdb_stmt_sql, sizeof(create_astdb_stmt_sql));
225  }
226 
228  if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) {
229  ast_log(LOG_WARNING, "Couldn't create astdb table: %s\n", sqlite3_errmsg(astdb));
230  res = -1;
231  }
232  sqlite3_reset(create_astdb_stmt);
233  db_sync();
235 
236  return res;
237 }
238 
239 static int db_open(void)
240 {
241  char *dbname;
242  struct stat dont_care;
243 
244  if (!(dbname = ast_alloca(strlen(ast_config_AST_DB) + sizeof(".sqlite3")))) {
245  return -1;
246  }
247  strcpy(dbname, ast_config_AST_DB);
248  strcat(dbname, ".sqlite3");
249 
250  if (stat(dbname, &dont_care) && !stat(ast_config_AST_DB, &dont_care)) {
251  if (convert_bdb_to_sqlite3()) {
252  ast_log(LOG_ERROR, "*** Database conversion failed!\n");
253  ast_log(LOG_ERROR, "*** Asterisk now uses SQLite3 for its internal\n");
254  ast_log(LOG_ERROR, "*** database. Conversion from the old astdb\n");
255  ast_log(LOG_ERROR, "*** failed. Most likely the astdb2sqlite3 utility\n");
256  ast_log(LOG_ERROR, "*** was not selected for build. To convert the\n");
257  ast_log(LOG_ERROR, "*** old astdb, please delete '%s'\n", dbname);
258  ast_log(LOG_ERROR, "*** and re-run 'make menuselect' and select astdb2sqlite3\n");
259  ast_log(LOG_ERROR, "*** in the Utilities section, then 'make && make install'.\n");
260  ast_log(LOG_ERROR, "*** It is also imperative that the user under which\n");
261  ast_log(LOG_ERROR, "*** Asterisk runs have write permission to the directory\n");
262  ast_log(LOG_ERROR, "*** where the database resides.\n");
263  sleep(5);
264  } else {
265  ast_log(LOG_NOTICE, "Database conversion succeeded!\n");
266  }
267  }
268 
270  if (sqlite3_open(dbname, &astdb) != SQLITE_OK) {
271  ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb));
272  sqlite3_close(astdb);
274  return -1;
275  }
276 
278 
279  return 0;
280 }
281 
282 static int db_init(void)
283 {
284  if (astdb) {
285  return 0;
286  }
287 
288  if (db_open() || db_create_astdb() || init_statements()) {
289  return -1;
290  }
291 
292  return 0;
293 }
294 
295 /* We purposely don't lock around the sqlite3 call because the transaction
296  * calls will be called with the database lock held. For any other use, make
297  * sure to take the dblock yourself. */
298 static int db_execute_sql(const char *sql, int (*callback)(void *, int, char **, char **), void *arg)
299 {
300  char *errmsg = NULL;
301  int res =0;
302 
303  if (sqlite3_exec(astdb, sql, callback, arg, &errmsg) != SQLITE_OK) {
304  ast_log(LOG_WARNING, "Error executing SQL (%s): %s\n", sql, errmsg);
305  sqlite3_free(errmsg);
306  res = -1;
307  }
308 
309  return res;
310 }
311 
312 static int ast_db_begin_transaction(void)
313 {
314  return db_execute_sql("BEGIN TRANSACTION", NULL, NULL);
315 }
316 
318 {
319  return db_execute_sql("COMMIT", NULL, NULL);
320 }
321 
323 {
324  return db_execute_sql("ROLLBACK", NULL, NULL);
325 }
326 
327 int ast_db_put(const char *family, const char *key, const char *value)
328 {
329  char fullkey[MAX_DB_FIELD];
330  size_t fullkey_len;
331  int res = 0;
332 
333  if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
334  ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
335  return -1;
336  }
337 
338  fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
339 
341  if (sqlite3_bind_text(put_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
342  ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
343  res = -1;
344  } else if (sqlite3_bind_text(put_stmt, 2, value, -1, SQLITE_STATIC) != SQLITE_OK) {
345  ast_log(LOG_WARNING, "Couldn't bind value to stmt: %s\n", sqlite3_errmsg(astdb));
346  res = -1;
347  } else if (sqlite3_step(put_stmt) != SQLITE_DONE) {
348  ast_log(LOG_WARNING, "Couldn't execute statement: %s\n", sqlite3_errmsg(astdb));
349  res = -1;
350  }
351 
352  sqlite3_reset(put_stmt);
353  db_sync();
355 
356  return res;
357 }
358 
359 /*!
360  * \internal
361  * \brief Get key value specified by family/key.
362  *
363  * Gets the value associated with the specified \a family and \a key, and
364  * stores it, either into the fixed sized buffer specified by \a buffer
365  * and \a bufferlen, or as a heap allocated string if \a bufferlen is -1.
366  *
367  * \note If \a bufferlen is -1, \a buffer points to heap allocated memory
368  * and must be freed by calling ast_free().
369  *
370  * \retval -1 An error occurred
371  * \retval 0 Success
372  */
373 static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen)
374 {
375  const unsigned char *result;
376  char fullkey[MAX_DB_FIELD];
377  size_t fullkey_len;
378  int res = 0;
379 
380  if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
381  ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
382  return -1;
383  }
384 
385  fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
386 
388  if (sqlite3_bind_text(get_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
389  ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
390  res = -1;
391  } else if (sqlite3_step(get_stmt) != SQLITE_ROW) {
392  ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
393  res = -1;
394  } else if (!(result = sqlite3_column_text(get_stmt, 0))) {
395  ast_log(LOG_WARNING, "Couldn't get value\n");
396  res = -1;
397  } else {
398  const char *value = (const char *) result;
399 
400  if (bufferlen == -1) {
401  *buffer = ast_strdup(value);
402  } else {
403  ast_copy_string(*buffer, value, bufferlen);
404  }
405  }
406  sqlite3_reset(get_stmt);
408 
409  return res;
410 }
411 
412 int ast_db_get(const char *family, const char *key, char *value, int valuelen)
413 {
414  ast_assert(value != NULL);
415 
416  /* Make sure we initialize */
417  value[0] = 0;
418 
419  return db_get_common(family, key, &value, valuelen);
420 }
421 
422 int ast_db_get_allocated(const char *family, const char *key, char **out)
423 {
424  *out = NULL;
425 
426  return db_get_common(family, key, out, -1);
427 }
428 
429 int ast_db_del(const char *family, const char *key)
430 {
431  char fullkey[MAX_DB_FIELD];
432  size_t fullkey_len;
433  int res = 0;
434 
435  if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
436  ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
437  return -1;
438  }
439 
440  fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
441 
443  if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
444  ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
445  res = -1;
446  } else if (sqlite3_step(del_stmt) != SQLITE_DONE) {
447  ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
448  res = -1;
449  }
450  sqlite3_reset(del_stmt);
451  db_sync();
453 
454  return res;
455 }
456 
457 int ast_db_deltree(const char *family, const char *keytree)
458 {
459  sqlite3_stmt *stmt = deltree_stmt;
460  char prefix[MAX_DB_FIELD];
461  int res = 0;
462 
463  if (!ast_strlen_zero(family)) {
464  if (!ast_strlen_zero(keytree)) {
465  /* Family and key tree */
466  snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
467  } else {
468  /* Family only */
469  snprintf(prefix, sizeof(prefix), "/%s", family);
470  }
471  } else {
472  prefix[0] = '\0';
473  stmt = deltree_all_stmt;
474  }
475 
477  if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
478  ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
479  res = -1;
480  } else if (sqlite3_step(stmt) != SQLITE_DONE) {
481  ast_log(LOG_WARNING, "Couldn't execute stmt: %s\n", sqlite3_errmsg(astdb));
482  res = -1;
483  }
484  res = sqlite3_changes(astdb);
485  sqlite3_reset(stmt);
486  db_sync();
488 
489  return res;
490 }
491 
492 static struct ast_db_entry *db_gettree_common(sqlite3_stmt *stmt)
493 {
494  struct ast_db_entry *head = NULL, *prev = NULL, *cur;
495 
496  while (sqlite3_step(stmt) == SQLITE_ROW) {
497  const char *key, *value;
498  size_t key_len, value_len;
499 
500  key = (const char *) sqlite3_column_text(stmt, 0);
501  value = (const char *) sqlite3_column_text(stmt, 1);
502 
503  if (!key || !value) {
504  break;
505  }
506 
507  key_len = strlen(key);
508  value_len = strlen(value);
509 
510  cur = ast_malloc(sizeof(*cur) + key_len + value_len + 2);
511  if (!cur) {
512  break;
513  }
514 
515  cur->next = NULL;
516  cur->key = cur->data + value_len + 1;
517  memcpy(cur->data, value, value_len + 1);
518  memcpy(cur->key, key, key_len + 1);
519 
520  if (prev) {
521  prev->next = cur;
522  } else {
523  head = cur;
524  }
525  prev = cur;
526  }
527 
528  return head;
529 }
530 
531 struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
532 {
533  char prefix[MAX_DB_FIELD];
534  sqlite3_stmt *stmt = gettree_stmt;
535  size_t res = 0;
536  struct ast_db_entry *ret;
537 
538  if (!ast_strlen_zero(family)) {
539  if (!ast_strlen_zero(keytree)) {
540  /* Family and key tree */
541  res = snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
542  } else {
543  /* Family only */
544  res = snprintf(prefix, sizeof(prefix), "/%s", family);
545  }
546 
547  if (res >= sizeof(prefix)) {
548  ast_log(LOG_WARNING, "Requested prefix is too long: %s\n", keytree);
549  return NULL;
550  }
551  } else {
552  prefix[0] = '\0';
553  stmt = gettree_all_stmt;
554  }
555 
557  if (res && (sqlite3_bind_text(stmt, 1, prefix, res, SQLITE_STATIC) != SQLITE_OK)) {
558  ast_log(LOG_WARNING, "Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
559  sqlite3_reset(stmt);
561  return NULL;
562  }
563 
564  ret = db_gettree_common(stmt);
565  sqlite3_reset(stmt);
567 
568  return ret;
569 }
570 
571 struct ast_db_entry *ast_db_gettree_by_prefix(const char *family, const char *key_prefix)
572 {
573  char prefix[MAX_DB_FIELD];
574  size_t res;
575  struct ast_db_entry *ret;
576 
577  res = snprintf(prefix, sizeof(prefix), "/%s/%s", family, key_prefix);
578  if (res >= sizeof(prefix)) {
579  ast_log(LOG_WARNING, "Requested key prefix is too long: %s\n", key_prefix);
580  return NULL;
581  }
582 
584  if (sqlite3_bind_text(gettree_prefix_stmt, 1, prefix, res, SQLITE_STATIC) != SQLITE_OK) {
585  ast_log(LOG_WARNING, "Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
586  sqlite3_reset(gettree_prefix_stmt);
588  return NULL;
589  }
590 
591  ret = db_gettree_common(gettree_prefix_stmt);
592  sqlite3_reset(gettree_prefix_stmt);
594 
595  return ret;
596 }
597 
598 void ast_db_freetree(struct ast_db_entry *dbe)
599 {
600  struct ast_db_entry *last;
601  while (dbe) {
602  last = dbe;
603  dbe = dbe->next;
604  ast_free(last);
605  }
606 }
607 
608 static char *handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
609 {
610  int res;
611 
612  switch (cmd) {
613  case CLI_INIT:
614  e->command = "database put";
615  e->usage =
616  "Usage: database put <family> <key> <value>\n"
617  " Adds or updates an entry in the Asterisk database for\n"
618  " a given family, key, and value.\n";
619  return NULL;
620  case CLI_GENERATE:
621  return NULL;
622  }
623 
624  if (a->argc != 5)
625  return CLI_SHOWUSAGE;
626  res = ast_db_put(a->argv[2], a->argv[3], a->argv[4]);
627  if (res) {
628  ast_cli(a->fd, "Failed to update entry\n");
629  } else {
630  ast_cli(a->fd, "Updated database successfully\n");
631  }
632  return CLI_SUCCESS;
633 }
634 
635 static char *handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
636 {
637  int res;
638  char tmp[MAX_DB_FIELD];
639 
640  switch (cmd) {
641  case CLI_INIT:
642  e->command = "database get";
643  e->usage =
644  "Usage: database get <family> <key>\n"
645  " Retrieves an entry in the Asterisk database for a given\n"
646  " family and key.\n";
647  return NULL;
648  case CLI_GENERATE:
649  return NULL;
650  }
651 
652  if (a->argc != 4)
653  return CLI_SHOWUSAGE;
654  res = ast_db_get(a->argv[2], a->argv[3], tmp, sizeof(tmp));
655  if (res) {
656  ast_cli(a->fd, "Database entry not found.\n");
657  } else {
658  ast_cli(a->fd, "Value: %s\n", tmp);
659  }
660  return CLI_SUCCESS;
661 }
662 
663 static char *handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
664 {
665  int res;
666 
667  switch (cmd) {
668  case CLI_INIT:
669  e->command = "database del";
670  e->usage =
671  "Usage: database del <family> <key>\n"
672  " Deletes an entry in the Asterisk database for a given\n"
673  " family and key.\n";
674  return NULL;
675  case CLI_GENERATE:
676  return NULL;
677  }
678 
679  if (a->argc != 4)
680  return CLI_SHOWUSAGE;
681  res = ast_db_del(a->argv[2], a->argv[3]);
682  if (res) {
683  ast_cli(a->fd, "Database entry does not exist.\n");
684  } else {
685  ast_cli(a->fd, "Database entry removed.\n");
686  }
687  return CLI_SUCCESS;
688 }
689 
690 static char *handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
691 {
692  int num_deleted;
693 
694  switch (cmd) {
695  case CLI_INIT:
696  e->command = "database deltree";
697  e->usage =
698  "Usage: database deltree <family> [keytree]\n"
699  " OR: database deltree <family>[/keytree]\n"
700  " Deletes a family or specific keytree within a family\n"
701  " in the Asterisk database. The two arguments may be\n"
702  " separated by either a space or a slash.\n";
703  return NULL;
704  case CLI_GENERATE:
705  return NULL;
706  }
707 
708  if ((a->argc < 3) || (a->argc > 4))
709  return CLI_SHOWUSAGE;
710  if (a->argc == 4) {
711  num_deleted = ast_db_deltree(a->argv[2], a->argv[3]);
712  } else {
713  num_deleted = ast_db_deltree(a->argv[2], NULL);
714  }
715  if (num_deleted < 0) {
716  ast_cli(a->fd, "Database unavailable.\n");
717  } else if (num_deleted == 0) {
718  ast_cli(a->fd, "Database entries do not exist.\n");
719  } else {
720  ast_cli(a->fd, "%d database entries removed.\n",num_deleted);
721  }
722  return CLI_SUCCESS;
723 }
724 
725 static char *handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
726 {
727  char prefix[MAX_DB_FIELD];
728  int counter = 0;
729  sqlite3_stmt *stmt = gettree_stmt;
730 
731  switch (cmd) {
732  case CLI_INIT:
733  e->command = "database show";
734  e->usage =
735  "Usage: database show [family [keytree]]\n"
736  " OR: database show [family[/keytree]]\n"
737  " Shows Asterisk database contents, optionally restricted\n"
738  " to a given family, or family and keytree. The two arguments\n"
739  " may be separated either by a space or by a slash.\n";
740  return NULL;
741  case CLI_GENERATE:
742  return NULL;
743  }
744 
745  if (a->argc == 4) {
746  /* Family and key tree */
747  snprintf(prefix, sizeof(prefix), "/%s/%s", a->argv[2], a->argv[3]);
748  } else if (a->argc == 3) {
749  /* Family only */
750  snprintf(prefix, sizeof(prefix), "/%s", a->argv[2]);
751  } else if (a->argc == 2) {
752  /* Neither */
753  prefix[0] = '\0';
754  stmt = gettree_all_stmt;
755 
756  } else {
757  return CLI_SHOWUSAGE;
758  }
759 
761  if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
762  ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
763  sqlite3_reset(stmt);
765  return NULL;
766  }
767 
768  while (sqlite3_step(stmt) == SQLITE_ROW) {
769  const char *key_s, *value_s;
770  if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
771  ast_log(LOG_WARNING, "Skipping invalid key!\n");
772  continue;
773  }
774  if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
775  ast_log(LOG_WARNING, "Skipping invalid value!\n");
776  continue;
777  }
778  ++counter;
779  ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
780  }
781 
782  sqlite3_reset(stmt);
784 
785  ast_cli(a->fd, "%d results found.\n", counter);
786  return CLI_SUCCESS;
787 }
788 
789 static char *handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
790 {
791  int counter = 0;
792 
793  switch (cmd) {
794  case CLI_INIT:
795  e->command = "database showkey";
796  e->usage =
797  "Usage: database showkey <keytree>\n"
798  " Shows Asterisk database contents, restricted to a given key.\n";
799  return NULL;
800  case CLI_GENERATE:
801  return NULL;
802  }
803 
804  if (a->argc != 3) {
805  return CLI_SHOWUSAGE;
806  }
807 
809  if (!ast_strlen_zero(a->argv[2]) && (sqlite3_bind_text(showkey_stmt, 1, a->argv[2], -1, SQLITE_STATIC) != SQLITE_OK)) {
810  ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", a->argv[2], sqlite3_errmsg(astdb));
811  sqlite3_reset(showkey_stmt);
813  return NULL;
814  }
815 
816  while (sqlite3_step(showkey_stmt) == SQLITE_ROW) {
817  const char *key_s, *value_s;
818  if (!(key_s = (const char *) sqlite3_column_text(showkey_stmt, 0))) {
819  break;
820  }
821  if (!(value_s = (const char *) sqlite3_column_text(showkey_stmt, 1))) {
822  break;
823  }
824  ++counter;
825  ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
826  }
827  sqlite3_reset(showkey_stmt);
829 
830  ast_cli(a->fd, "%d results found.\n", counter);
831  return CLI_SUCCESS;
832 }
833 
834 static int display_results(void *arg, int columns, char **values, char **colnames)
835 {
836  struct ast_cli_args *a = arg;
837  size_t x;
838 
839  for (x = 0; x < columns; x++) {
840  ast_cli(a->fd, "%-5s: %-50s\n", colnames[x], values[x]);
841  }
842  ast_cli(a->fd, "\n");
843 
844  return 0;
845 }
846 
847 static char *handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
848 {
849 
850  switch (cmd) {
851  case CLI_INIT:
852  e->command = "database query";
853  e->usage =
854  "Usage: database query \"<SQL Statement>\"\n"
855  " Run a user-specified SQL query on the database. Be careful.\n";
856  return NULL;
857  case CLI_GENERATE:
858  return NULL;
859  }
860 
861  if (a->argc != 3) {
862  return CLI_SHOWUSAGE;
863  }
864 
867  db_sync(); /* Go ahead and sync the db in case they write */
869 
870  return CLI_SUCCESS;
871 }
872 
873 static struct ast_cli_entry cli_database[] = {
874  AST_CLI_DEFINE(handle_cli_database_show, "Shows database contents"),
875  AST_CLI_DEFINE(handle_cli_database_showkey, "Shows database contents"),
876  AST_CLI_DEFINE(handle_cli_database_get, "Gets database value"),
877  AST_CLI_DEFINE(handle_cli_database_put, "Adds/updates database value"),
878  AST_CLI_DEFINE(handle_cli_database_del, "Removes database key/value"),
879  AST_CLI_DEFINE(handle_cli_database_deltree, "Removes database keytree/values"),
880  AST_CLI_DEFINE(handle_cli_database_query, "Run a user-specified query on the astdb"),
881 };
882 
883 static int manager_dbput(struct mansession *s, const struct message *m)
884 {
885  const char *family = astman_get_header(m, "Family");
886  const char *key = astman_get_header(m, "Key");
887  const char *val = astman_get_header(m, "Val");
888  int res;
889 
890  if (ast_strlen_zero(family)) {
891  astman_send_error(s, m, "No family specified");
892  return 0;
893  }
894  if (ast_strlen_zero(key)) {
895  astman_send_error(s, m, "No key specified");
896  return 0;
897  }
898 
899  res = ast_db_put(family, key, S_OR(val, ""));
900  if (res) {
901  astman_send_error(s, m, "Failed to update entry");
902  } else {
903  astman_send_ack(s, m, "Updated database successfully");
904  }
905  return 0;
906 }
907 
908 static int manager_dbget(struct mansession *s, const struct message *m)
909 {
910  const char *id = astman_get_header(m,"ActionID");
911  char idText[256];
912  const char *family = astman_get_header(m, "Family");
913  const char *key = astman_get_header(m, "Key");
914  char tmp[MAX_DB_FIELD];
915  int res;
916 
917  if (ast_strlen_zero(family)) {
918  astman_send_error(s, m, "No family specified.");
919  return 0;
920  }
921  if (ast_strlen_zero(key)) {
922  astman_send_error(s, m, "No key specified.");
923  return 0;
924  }
925 
926  idText[0] = '\0';
927  if (!ast_strlen_zero(id))
928  snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
929 
930  res = ast_db_get(family, key, tmp, sizeof(tmp));
931  if (res) {
932  astman_send_error(s, m, "Database entry not found");
933  } else {
934  astman_send_listack(s, m, "Result will follow", "start");
935 
936  astman_append(s, "Event: DBGetResponse\r\n"
937  "Family: %s\r\n"
938  "Key: %s\r\n"
939  "Val: %s\r\n"
940  "%s"
941  "\r\n",
942  family, key, tmp, idText);
943 
944  astman_send_list_complete_start(s, m, "DBGetComplete", 1);
946  }
947  return 0;
948 }
949 
950 static int manager_dbdel(struct mansession *s, const struct message *m)
951 {
952  const char *family = astman_get_header(m, "Family");
953  const char *key = astman_get_header(m, "Key");
954  int res;
955 
956  if (ast_strlen_zero(family)) {
957  astman_send_error(s, m, "No family specified.");
958  return 0;
959  }
960 
961  if (ast_strlen_zero(key)) {
962  astman_send_error(s, m, "No key specified.");
963  return 0;
964  }
965 
966  res = ast_db_del(family, key);
967  if (res)
968  astman_send_error(s, m, "Database entry not found");
969  else
970  astman_send_ack(s, m, "Key deleted successfully");
971 
972  return 0;
973 }
974 
975 static int manager_dbdeltree(struct mansession *s, const struct message *m)
976 {
977  const char *family = astman_get_header(m, "Family");
978  const char *key = astman_get_header(m, "Key");
979  int num_deleted;
980 
981  if (ast_strlen_zero(family)) {
982  astman_send_error(s, m, "No family specified.");
983  return 0;
984  }
985 
986  if (!ast_strlen_zero(key)) {
987  num_deleted = ast_db_deltree(family, key);
988  } else {
989  num_deleted = ast_db_deltree(family, NULL);
990  }
991 
992  if (num_deleted < 0) {
993  astman_send_error(s, m, "Database unavailable");
994  } else if (num_deleted == 0) {
995  astman_send_error(s, m, "Database entry not found");
996  } else {
997  astman_send_ack(s, m, "Key tree deleted successfully");
998  }
999 
1000  return 0;
1001 }
1002 
1003 /*!
1004  * \internal
1005  * \brief Signal the astdb sync thread to do its thing.
1006  *
1007  * \note dblock is assumed to be held when calling this function.
1008  */
1009 static void db_sync(void)
1010 {
1011  dosync = 1;
1013 }
1014 
1015 /*!
1016  * \internal
1017  * \brief astdb sync thread
1018  *
1019  * This thread is in charge of syncing astdb to disk after a change.
1020  * By pushing it off to this thread to take care of, this I/O bound operation
1021  * will not block other threads from performing other critical processing.
1022  * If changes happen rapidly, this thread will also ensure that the sync
1023  * operations are rate limited.
1024  */
1025 static void *db_sync_thread(void *data)
1026 {
1029  for (;;) {
1030  /* If dosync is set, db_sync() was called during sleep(1),
1031  * and the pending transaction should be committed.
1032  * Otherwise, block until db_sync() is called.
1033  */
1034  while (!dosync) {
1036  }
1037  dosync = 0;
1038  if (ast_db_commit_transaction()) {
1040  }
1041  if (doexit) {
1043  break;
1044  }
1047  sleep(1);
1049  }
1050 
1051  return NULL;
1052 }
1053 
1054 /*!
1055  * \internal
1056  * \brief Clean up resources on Asterisk shutdown
1057  */
1058 static void astdb_atexit(void)
1059 {
1060  ast_cli_unregister_multiple(cli_database, ARRAY_LEN(cli_database));
1061  ast_manager_unregister("DBGet");
1062  ast_manager_unregister("DBPut");
1063  ast_manager_unregister("DBDel");
1064  ast_manager_unregister("DBDelTree");
1065 
1066  /* Set doexit to 1 to kill thread. db_sync must be called with
1067  * mutex held. */
1069  doexit = 1;
1070  db_sync();
1072 
1073  pthread_join(syncthread, NULL);
1075  clean_statements();
1076  if (sqlite3_close(astdb) == SQLITE_OK) {
1077  astdb = NULL;
1078  }
1080 }
1081 
1082 int astdb_init(void)
1083 {
1085 
1086  if (db_init()) {
1087  return -1;
1088  }
1089 
1091  return -1;
1092  }
1093 
1095  ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database));
1100  return 0;
1101 }
static int clean_stmt(sqlite3_stmt **stmt, const char *sql)
Definition: main/db.c:161
static struct ast_cli_entry cli_database[]
Definition: main/db.c:873
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
static void astdb_atexit(void)
Definition: main/db.c:1058
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
Asterisk main include file. File version handling, generic pbx functions.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
const char * ast_config_AST_DB
Definition: options.c:165
Definition: ast_expr2.c:325
const char * ast_config_AST_SBIN_DIR
Definition: options.c:163
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
Definition: test_db.c:41
static int manager_dbdel(struct mansession *s, const struct message *m)
Definition: main/db.c:950
static int ast_db_commit_transaction(void)
Definition: main/db.c:317
Convenient Signal Processing routines.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3237
descriptor for a cli entry.
Definition: cli.h:171
const int argc
Definition: cli.h:160
#define LOG_WARNING
Definition: logger.h:274
void ast_db_freetree(struct ast_db_entry *dbe)
Free structure created by ast_db_gettree()
Definition: main/db.c:598
static int tmp()
Definition: bt_open.c:389
static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen)
Definition: main/db.c:373
Definition: cli.h:152
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static char * handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:789
#define ast_assert(a)
Definition: utils.h:695
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static int init_statements(void)
Definition: main/db.c:190
#define NULL
Definition: resample.c:96
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
Definition: main/db.c:531
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:197
int value
Definition: syslog.c:37
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int astdb_init(void)
Definition: main/db.c:1082
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:429
#define ast_cond_signal(cond)
Definition: lock.h:201
static ast_mutex_t dblock
Definition: main/db.c:108
Utility functions.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
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:412
pthread_cond_t ast_cond_t
Definition: lock.h:176
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
static pthread_t syncthread
Definition: main/db.c:111
#define EVENT_FLAG_SYSTEM
Definition: manager.h:71
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct ast_db_entry * next
Definition: astdb.h:32
static char * handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:725
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
const int fd
Definition: cli.h:159
struct sla_ringing_trunk * last
Definition: app_meetme.c:1092
static char * handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:847
In case you didn&#39;t read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
Definition: manager.c:1625
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: clicompat.c:13
static struct ast_db_entry * db_gettree_common(sqlite3_stmt *stmt)
Definition: main/db.c:492
#define MAX_DB_FIELD
Definition: main/db.c:107
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
static int db_init(void)
Definition: main/db.c:282
#define DELETE(a, b, c, d)
static ast_cond_t dbcond
Definition: main/db.c:109
static char * handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:608
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
const char *const * argv
Definition: cli.h:161
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
static int display_results(void *arg, int columns, char **values, char **colnames)
Definition: main/db.c:834
#define LOG_ERROR
Definition: logger.h:285
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
#define CLI_SHOWUSAGE
Definition: cli.h:45
static void clean_statements(void)
Definition: main/db.c:176
static void * db_sync_thread(void *data)
Definition: main/db.c:1025
static int dosync
Definition: main/db.c:113
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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.
Definition: main/db.c:571
#define LOG_NOTICE
Definition: logger.h:263
Definition: astdb.h:31
static struct columns columns
static sqlite3 * astdb
Definition: main/db.c:110
static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len)
static struct ast_str * dbname
Definition: cdr_mysql.c:77
#define DEFINE_SQL_STATEMENT(stmt, sql)
Definition: main/db.c:117
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
static int db_execute_sql(const char *sql, int(*callback)(void *, int, char **, char **), void *arg)
Definition: main/db.c:298
Prototypes for public functions only of internal interest,.
static int doexit
Definition: main/db.c:112
static char * handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:635
static int manager_dbget(struct mansession *s, const struct message *m)
Definition: main/db.c:908
static int ast_db_rollback_transaction(void)
Definition: main/db.c:322
const char * usage
Definition: cli.h:177
static int convert_bdb_to_sqlite3(void)
Definition: main/db.c:205
static int manager_dbput(struct mansession *s, const struct message *m)
Definition: main/db.c:883
static char * handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:690
#define EVENT_FLAG_REPORTING
Definition: manager.h:80
#define CLI_SUCCESS
Definition: cli.h:44
static int manager_dbdeltree(struct mansession *s, const struct message *m)
Definition: main/db.c:975
static int db_create_astdb(void)
Definition: main/db.c:219
static char * handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:663
FILE * out
Definition: utils/frame.c:33
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
#define EXISTS(a, b, c, d)
static PGresult * result
Definition: cel_pgsql.c:88
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.
Definition: main/db.c:422
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:327
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
static int ast_db_begin_transaction(void)
Definition: main/db.c:312
Persistant data storage (akin to *doze registry)
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
Definition: main/db.c:457
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:518
static void db_sync(void)
Definition: main/db.c:1009
#define ast_mutex_unlock(a)
Definition: lock.h:188
char * key
Definition: astdb.h:33
static char prefix[MAX_PREFIX]
Definition: http.c:141
static int db_open(void)
Definition: main/db.c:239
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3201
static struct test_val a