Asterisk - The Open Source Telephony Project GIT-master-3dae2cf
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 <markster@digium.com>
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 <markster@digium.com>
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="DBGetTree" language="en_US">
69 <synopsis>
70 Get DB entries, optionally at a particular family/key
71 </synopsis>
72 <syntax>
73 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
74 <parameter name="Family" required="false" />
75 <parameter name="Key" required="false" />
76 </syntax>
77 <description>
78 </description>
79 </manager>
80 <manager name="DBPut" language="en_US">
81 <synopsis>
82 Put DB entry.
83 </synopsis>
84 <syntax>
85 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
86 <parameter name="Family" required="true" />
87 <parameter name="Key" required="true" />
88 <parameter name="Val" />
89 </syntax>
90 <description>
91 </description>
92 </manager>
93 <manager name="DBDel" language="en_US">
94 <synopsis>
95 Delete DB entry.
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" required="true" />
101 </syntax>
102 <description>
103 </description>
104 </manager>
105 <manager name="DBDelTree" language="en_US">
106 <synopsis>
107 Delete DB Tree.
108 </synopsis>
109 <syntax>
110 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
111 <parameter name="Family" required="true" />
112 <parameter name="Key" />
113 </syntax>
114 <description>
115 </description>
116 </manager>
117 ***/
118
121static sqlite3 *astdb;
122static pthread_t syncthread;
123static int doexit;
124static int dosync;
125
126static void db_sync(void);
127
128#define DEFINE_SQL_STATEMENT(stmt,sql) static sqlite3_stmt *stmt; \
129 const char stmt##_sql[] = sql;
130
131DEFINE_SQL_STATEMENT(put_stmt, "INSERT OR REPLACE INTO astdb (key, value) VALUES (?, ?)")
132DEFINE_SQL_STATEMENT(get_stmt, "SELECT value FROM astdb WHERE key=?")
133DEFINE_SQL_STATEMENT(exists_stmt, "SELECT CAST(COUNT(1) AS INTEGER) AS 'exists' FROM astdb WHERE key=?")
134DEFINE_SQL_STATEMENT(del_stmt, "DELETE FROM astdb WHERE key=?")
135DEFINE_SQL_STATEMENT(deltree_stmt, "DELETE FROM astdb WHERE key || '/' LIKE ? || '/' || '%'")
136DEFINE_SQL_STATEMENT(deltree_all_stmt, "DELETE FROM astdb")
137DEFINE_SQL_STATEMENT(gettree_stmt, "SELECT key, value FROM astdb WHERE key || '/' LIKE ? || '/' || '%' ORDER BY key")
138DEFINE_SQL_STATEMENT(gettree_all_stmt, "SELECT key, value FROM astdb ORDER BY key")
139DEFINE_SQL_STATEMENT(showkey_stmt, "SELECT key, value FROM astdb WHERE key LIKE '%' || '/' || ? ORDER BY key")
140DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key TEXT, value TEXT, PRIMARY KEY(key))")
141
142/* This query begs an explanation:
143 *
144 * First, the parameter binding syntax used here is slightly different than the other
145 * queries in that we use a numbered parameter so that we can bind once and get the same
146 * value substituted multiple times within the executed query.
147 *
148 * Second, the key comparison is being used to find all keys that are lexicographically
149 * greater than the provided key, but less than the provided key with a high (but
150 * invalid) Unicode codepoint appended to it. This will give us all keys in the database
151 * that have 'key' as a prefix and performs much better than the equivalent "LIKE key ||
152 * '%'" operation.
153 */
154DEFINE_SQL_STATEMENT(gettree_prefix_stmt, "SELECT key, value FROM astdb WHERE key > ?1 AND key <= ?1 || X'ffff'")
155
156static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len)
157{
159 if (sqlite3_prepare(astdb, sql, len, stmt, NULL) != SQLITE_OK) {
160 ast_log(LOG_WARNING, "Couldn't prepare statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
162 return -1;
163 }
165
166 return 0;
167}
168
169/*! \internal
170 * \brief Clean up the prepared SQLite3 statement
171 * \note dblock should already be locked prior to calling this method
172 */
173static int clean_stmt(sqlite3_stmt **stmt, const char *sql)
174{
175 if (sqlite3_finalize(*stmt) != SQLITE_OK) {
176 ast_log(LOG_WARNING, "Couldn't finalize statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
177 *stmt = NULL;
178 return -1;
179 }
180 *stmt = NULL;
181 return 0;
182}
183
184/*! \internal
185 * \brief Clean up all prepared SQLite3 statements
186 * \note dblock should already be locked prior to calling this method
187 */
188static void clean_statements(void)
189{
190 clean_stmt(&get_stmt, get_stmt_sql);
191 clean_stmt(&exists_stmt, exists_stmt_sql);
192 clean_stmt(&del_stmt, del_stmt_sql);
193 clean_stmt(&deltree_stmt, deltree_stmt_sql);
194 clean_stmt(&deltree_all_stmt, deltree_all_stmt_sql);
195 clean_stmt(&gettree_stmt, gettree_stmt_sql);
196 clean_stmt(&gettree_all_stmt, gettree_all_stmt_sql);
197 clean_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql);
198 clean_stmt(&showkey_stmt, showkey_stmt_sql);
199 clean_stmt(&put_stmt, put_stmt_sql);
200 clean_stmt(&create_astdb_stmt, create_astdb_stmt_sql);
201}
202
203static int init_statements(void)
204{
205 /* Don't initialize create_astdb_statement here as the astdb table needs to exist
206 * brefore these statements can be initialized */
207 return init_stmt(&get_stmt, get_stmt_sql, sizeof(get_stmt_sql))
208 || init_stmt(&exists_stmt, exists_stmt_sql, sizeof(exists_stmt_sql))
209 || init_stmt(&del_stmt, del_stmt_sql, sizeof(del_stmt_sql))
210 || init_stmt(&deltree_stmt, deltree_stmt_sql, sizeof(deltree_stmt_sql))
211 || init_stmt(&deltree_all_stmt, deltree_all_stmt_sql, sizeof(deltree_all_stmt_sql))
212 || init_stmt(&gettree_stmt, gettree_stmt_sql, sizeof(gettree_stmt_sql))
213 || init_stmt(&gettree_all_stmt, gettree_all_stmt_sql, sizeof(gettree_all_stmt_sql))
214 || init_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql, sizeof(gettree_prefix_stmt_sql))
215 || init_stmt(&showkey_stmt, showkey_stmt_sql, sizeof(showkey_stmt_sql))
216 || init_stmt(&put_stmt, put_stmt_sql, sizeof(put_stmt_sql));
217}
218
220{
221 char *cmd;
222 int res;
223
224 res = ast_asprintf(&cmd, "%s/astdb2sqlite3 '%s'\n", ast_config_AST_SBIN_DIR, ast_config_AST_DB);
225 if (0 <= res) {
226 res = ast_safe_system(cmd);
227 ast_free(cmd);
228 }
229
230 return res;
231}
232
233static int db_create_astdb(void)
234{
235 int res = 0;
236
237 if (!create_astdb_stmt) {
238 init_stmt(&create_astdb_stmt, create_astdb_stmt_sql, sizeof(create_astdb_stmt_sql));
239 }
240
242 if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) {
243 ast_log(LOG_WARNING, "Couldn't create astdb table: %s\n", sqlite3_errmsg(astdb));
244 res = -1;
245 }
246 sqlite3_reset(create_astdb_stmt);
247 db_sync();
249
250 return res;
251}
252
253static int db_open(void)
254{
255 char *dbname;
256 struct stat dont_care;
257
258 if (!(dbname = ast_alloca(strlen(ast_config_AST_DB) + sizeof(".sqlite3")))) {
259 return -1;
260 }
261 strcpy(dbname, ast_config_AST_DB);
262 strcat(dbname, ".sqlite3");
263
264 if (stat(dbname, &dont_care) && !stat(ast_config_AST_DB, &dont_care)) {
266 ast_log(LOG_ERROR, "*** Database conversion failed!\n");
267 ast_log(LOG_ERROR, "*** Asterisk now uses SQLite3 for its internal\n");
268 ast_log(LOG_ERROR, "*** database. Conversion from the old astdb\n");
269 ast_log(LOG_ERROR, "*** failed. Most likely the astdb2sqlite3 utility\n");
270 ast_log(LOG_ERROR, "*** was not selected for build. To convert the\n");
271 ast_log(LOG_ERROR, "*** old astdb, please delete '%s'\n", dbname);
272 ast_log(LOG_ERROR, "*** and re-run 'make menuselect' and select astdb2sqlite3\n");
273 ast_log(LOG_ERROR, "*** in the Utilities section, then 'make && make install'.\n");
274 ast_log(LOG_ERROR, "*** It is also imperative that the user under which\n");
275 ast_log(LOG_ERROR, "*** Asterisk runs have write permission to the directory\n");
276 ast_log(LOG_ERROR, "*** where the database resides.\n");
277 sleep(5);
278 } else {
279 ast_log(LOG_NOTICE, "Database conversion succeeded!\n");
280 }
281 }
282
284 if (sqlite3_open(dbname, &astdb) != SQLITE_OK) {
285 ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb));
286 sqlite3_close(astdb);
288 return -1;
289 }
290
292
293 return 0;
294}
295
296static int db_init(void)
297{
298 if (astdb) {
299 return 0;
300 }
301
302 if (db_open() || db_create_astdb() || init_statements()) {
303 return -1;
304 }
305
306 return 0;
307}
308
309/* We purposely don't lock around the sqlite3 call because the transaction
310 * calls will be called with the database lock held. For any other use, make
311 * sure to take the dblock yourself. */
312static int db_execute_sql(const char *sql, int (*callback)(void *, int, char **, char **), void *arg)
313{
314 char *errmsg = NULL;
315 int res =0;
316
317 if (sqlite3_exec(astdb, sql, callback, arg, &errmsg) != SQLITE_OK) {
318 ast_log(LOG_WARNING, "Error executing SQL (%s): %s\n", sql, errmsg);
319 sqlite3_free(errmsg);
320 res = -1;
321 }
322
323 return res;
324}
325
327{
328 return db_execute_sql("BEGIN TRANSACTION", NULL, NULL);
329}
330
332{
333 return db_execute_sql("COMMIT", NULL, NULL);
334}
335
337{
338 return db_execute_sql("ROLLBACK", NULL, NULL);
339}
340
341int ast_db_put(const char *family, const char *key, const char *value)
342{
343 char *fullkey;
344 int fullkey_len;
345 int res = 0;
346
347 fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
348 if (fullkey_len < 0) {
349 ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
350 family, key);
351 return -1;
352 }
353
355 if (sqlite3_bind_text(put_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
356 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
357 res = -1;
358 } else if (sqlite3_bind_text(put_stmt, 2, value, -1, SQLITE_STATIC) != SQLITE_OK) {
359 ast_log(LOG_WARNING, "Couldn't bind value to stmt: %s\n", sqlite3_errmsg(astdb));
360 res = -1;
361 } else if (sqlite3_step(put_stmt) != SQLITE_DONE) {
362 ast_log(LOG_WARNING, "Couldn't execute statement: %s\n", sqlite3_errmsg(astdb));
363 res = -1;
364 }
365 sqlite3_reset(put_stmt);
366 db_sync();
368 ast_free(fullkey);
369
370 return res;
371}
372
373/*!
374 * \internal
375 * \brief Get key value specified by family/key.
376 *
377 * Gets the value associated with the specified \a family and \a key, and
378 * stores it, either into the fixed sized buffer specified by \a buffer
379 * and \a bufferlen, or as a heap allocated string if \a bufferlen is -1.
380 *
381 * \note If \a bufferlen is -1, \a buffer points to heap allocated memory
382 * and must be freed by calling ast_free().
383 *
384 * \retval -1 An error occurred
385 * \retval 0 Success
386 */
387static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen)
388{
389 const unsigned char *result;
390 char *fullkey;
391 int fullkey_len;
392 int res = 0;
393
394 fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
395 if (fullkey_len < 0) {
396 ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
397 family, key);
398 return -1;
399 }
400
402 if (sqlite3_bind_text(get_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
403 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
404 res = -1;
405 } else if (sqlite3_step(get_stmt) != SQLITE_ROW) {
406 ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
407 res = -1;
408 } else if (!(result = sqlite3_column_text(get_stmt, 0))) {
409 ast_log(LOG_WARNING, "Couldn't get value\n");
410 res = -1;
411 } else {
412 const char *value = (const char *) result;
413
414 if (bufferlen == -1) {
415 *buffer = ast_strdup(value);
416 } else {
417 ast_copy_string(*buffer, value, bufferlen);
418 }
419 }
420 sqlite3_reset(get_stmt);
422 ast_free(fullkey);
423
424 return res;
425}
426
427int ast_db_get(const char *family, const char *key, char *value, int valuelen)
428{
430
431 /* Make sure we initialize */
432 value[0] = 0;
433
434 return db_get_common(family, key, &value, valuelen);
435}
436
437int ast_db_get_allocated(const char *family, const char *key, char **out)
438{
439 *out = NULL;
440
441 return db_get_common(family, key, out, -1);
442}
443
444int ast_db_exists(const char *family, const char *key)
445{
446 int result;
447 char *fullkey;
448 int fullkey_len;
449 int res = 0;
450
451 fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
452 if (fullkey_len < 0) {
453 ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
454 family, key);
455 return -1;
456 }
457
459 res = sqlite3_bind_text(exists_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC);
460 if (res != SQLITE_OK) {
461 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %d:%s\n", res, sqlite3_errmsg(astdb));
462 res = 0;
463 } else if (sqlite3_step(exists_stmt) != SQLITE_ROW) {
464 res = 0;
465 } else if (!(result = sqlite3_column_int(exists_stmt, 0))) {
466 res = 0;
467 } else {
468 res = result;
469 }
470 sqlite3_reset(exists_stmt);
472 ast_free(fullkey);
473
474 return res;
475}
476
477
478int ast_db_del(const char *family, const char *key)
479{
480 char *fullkey;
481 int fullkey_len;
482 int res = 0;
483
484 fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
485 if (fullkey_len < 0) {
486 ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
487 family, key);
488 return -1;
489 }
490
492 if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
493 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
494 res = -1;
495 } else if (sqlite3_step(del_stmt) != SQLITE_DONE) {
496 ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
497 res = -1;
498 }
499 sqlite3_reset(del_stmt);
500 db_sync();
502 ast_free(fullkey);
503
504 return res;
505}
506
507int ast_db_del2(const char *family, const char *key)
508{
509 char *fullkey;
510 char tmp[1];
511 int fullkey_len;
512 int mres, res = 0;
513
514 fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
515 if (fullkey_len < 0) {
516 ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
517 family, key);
518 return -1;
519 }
520
522 if (ast_db_get(family, key, tmp, sizeof(tmp))) {
523 ast_log(LOG_WARNING, "AstDB key %s does not exist\n", fullkey);
524 res = -1;
525 } else if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
526 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
527 res = -1;
528 } else if ((mres = sqlite3_step(del_stmt) != SQLITE_DONE)) {
529 ast_log(LOG_WARNING, "AstDB error (%s): %s\n", fullkey, sqlite3_errstr(mres));
530 res = -1;
531 }
532 sqlite3_reset(del_stmt);
533 db_sync();
535 ast_free(fullkey);
536
537 return res;
538}
539
540static char *create_prefix(const char *family, const char *keytree,
541 int *prefix_len)
542{
543 char *prefix = NULL;
544 *prefix_len = 0;
545
546 if (!ast_strlen_zero(family)) {
547 if (!ast_strlen_zero(keytree)) {
548 /* Family and key tree */
549 *prefix_len = ast_asprintf(&prefix, "/%s/%s", family, keytree);
550 } else {
551 /* Family only */
552 *prefix_len = ast_asprintf(&prefix, "/%s", family);
553 }
554 if (*prefix_len < 0) {
555 ast_log(LOG_WARNING, "Unable to allocate memory for family/keytree '/%s%s%s'\n",
556 S_OR(family, ""), S_COR(keytree, "/", ""), S_OR(keytree, ""));
557 return NULL;
558 }
559 } else {
560 prefix = ast_strdup("");
561 }
562 return prefix;
563}
564
565int ast_db_deltree(const char *family, const char *keytree)
566{
567 sqlite3_stmt *stmt = deltree_stmt;
568 char *prefix = NULL;
569 int prefix_len = 0;
570 int res = 0;
571
572 if (ast_strlen_zero(family) && !ast_strlen_zero(keytree)) {
573 ast_log(LOG_WARNING, "Key tree '%s' specified without family\n", keytree);
574 return -1;
575 }
576
577 prefix = create_prefix(family, keytree, &prefix_len);
578 if (!prefix) {
579 return -1;
580 }
581 if (prefix_len == 0) {
582 stmt = deltree_all_stmt;
583 }
584
586 if (prefix_len && (sqlite3_bind_text(stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
587 ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
588 res = -1;
589 } else if (sqlite3_step(stmt) != SQLITE_DONE) {
590 ast_log(LOG_WARNING, "Couldn't execute stmt: %s\n", sqlite3_errmsg(astdb));
591 res = -1;
592 }
593 res = sqlite3_changes(astdb);
594 sqlite3_reset(stmt);
595 db_sync();
598
599 return res;
600}
601
602static struct ast_db_entry *db_gettree_common(sqlite3_stmt *stmt)
603{
604 struct ast_db_entry *head = NULL, *prev = NULL, *cur;
605
606 while (sqlite3_step(stmt) == SQLITE_ROW) {
607 const char *key, *value;
608 size_t key_len, value_len;
609
610 key = (const char *) sqlite3_column_text(stmt, 0);
611 value = (const char *) sqlite3_column_text(stmt, 1);
612
613 if (!key || !value) {
614 break;
615 }
616
617 key_len = strlen(key);
618 value_len = strlen(value);
619
620 cur = ast_malloc(sizeof(*cur) + key_len + value_len + 2);
621 if (!cur) {
622 break;
623 }
624
625 cur->next = NULL;
626 cur->key = cur->data + value_len + 1;
627 memcpy(cur->data, value, value_len + 1);
628 memcpy(cur->key, key, key_len + 1);
629
630 if (prev) {
631 prev->next = cur;
632 } else {
633 head = cur;
634 }
635 prev = cur;
636 }
637
638 return head;
639}
640
641struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
642{
643 char *prefix = NULL;
644 int prefix_len = 0;
645 sqlite3_stmt *stmt = gettree_stmt;
646 struct ast_db_entry *ret;
647
648 prefix = create_prefix(family, keytree, &prefix_len);
649 if (!prefix) {
650 return NULL;
651 }
652 if (prefix_len == 0) {
653 stmt = gettree_all_stmt;
654 }
655
657 if (prefix_len && (sqlite3_bind_text(stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
658 ast_log(LOG_WARNING, "Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
659 sqlite3_reset(stmt);
662 return NULL;
663 }
664
665 ret = db_gettree_common(stmt);
666 sqlite3_reset(stmt);
669
670 return ret;
671}
672
673struct ast_db_entry *ast_db_gettree_by_prefix(const char *family, const char *key_prefix)
674{
675 char *prefix = NULL;
676 int prefix_len = 0;
677 struct ast_db_entry *ret;
678
679 prefix = create_prefix(family, key_prefix, &prefix_len);
680 if (!prefix) {
681 return NULL;
682 }
683
685 if (sqlite3_bind_text(gettree_prefix_stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK) {
686 ast_log(LOG_WARNING, "Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
687 sqlite3_reset(gettree_prefix_stmt);
690 return NULL;
691 }
692
693 ret = db_gettree_common(gettree_prefix_stmt);
694 sqlite3_reset(gettree_prefix_stmt);
697
698 return ret;
699}
700
702{
703 struct ast_db_entry *last;
704 while (dbe) {
705 last = dbe;
706 dbe = dbe->next;
707 ast_free(last);
708 }
709}
710
711static char *handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
712{
713 int res;
714
715 switch (cmd) {
716 case CLI_INIT:
717 e->command = "database put";
718 e->usage =
719 "Usage: database put <family> <key> <value>\n"
720 " Adds or updates an entry in the Asterisk database for\n"
721 " a given family, key, and value.\n";
722 return NULL;
723 case CLI_GENERATE:
724 return NULL;
725 }
726
727 if (a->argc != 5)
728 return CLI_SHOWUSAGE;
729 res = ast_db_put(a->argv[2], a->argv[3], a->argv[4]);
730 if (res) {
731 ast_cli(a->fd, "Failed to update entry\n");
732 } else {
733 ast_cli(a->fd, "Updated database successfully\n");
734 }
735 return CLI_SUCCESS;
736}
737
738static char *handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
739{
740 int res;
741 char *tmp = NULL;
742
743 switch (cmd) {
744 case CLI_INIT:
745 e->command = "database get";
746 e->usage =
747 "Usage: database get <family> <key>\n"
748 " Retrieves an entry in the Asterisk database for a given\n"
749 " family and key.\n";
750 return NULL;
751 case CLI_GENERATE:
752 return NULL;
753 }
754
755 if (a->argc != 4)
756 return CLI_SHOWUSAGE;
757 res = ast_db_get_allocated(a->argv[2], a->argv[3], &tmp);
758 if (res) {
759 ast_cli(a->fd, "Database entry not found.\n");
760 } else {
761 ast_cli(a->fd, "Value: %s\n", tmp);
762 ast_free(tmp);
763 }
764
765 return CLI_SUCCESS;
766}
767
768static char *handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
769{
770 int res;
771
772 switch (cmd) {
773 case CLI_INIT:
774 e->command = "database del";
775 e->usage =
776 "Usage: database del <family> <key>\n"
777 " Deletes an entry in the Asterisk database for a given\n"
778 " family and key.\n";
779 return NULL;
780 case CLI_GENERATE:
781 return NULL;
782 }
783
784 if (a->argc != 4)
785 return CLI_SHOWUSAGE;
786 res = ast_db_del2(a->argv[2], a->argv[3]);
787 if (res) {
788 ast_cli(a->fd, "Database entry could not be removed.\n");
789 } else {
790 ast_cli(a->fd, "Database entry removed.\n");
791 }
792 return CLI_SUCCESS;
793}
794
795static char *handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
796{
797 int num_deleted;
798
799 switch (cmd) {
800 case CLI_INIT:
801 e->command = "database deltree";
802 e->usage =
803 "Usage: database deltree <family> [keytree]\n"
804 " OR: database deltree <family>[/keytree]\n"
805 " Deletes a family or specific keytree within a family\n"
806 " in the Asterisk database. The two arguments may be\n"
807 " separated by either a space or a slash.\n";
808 return NULL;
809 case CLI_GENERATE:
810 return NULL;
811 }
812
813 if ((a->argc < 3) || (a->argc > 4))
814 return CLI_SHOWUSAGE;
815 if (a->argc == 4) {
816 num_deleted = ast_db_deltree(a->argv[2], a->argv[3]);
817 } else {
818 num_deleted = ast_db_deltree(a->argv[2], NULL);
819 }
820 if (num_deleted < 0) {
821 ast_cli(a->fd, "Database unavailable.\n");
822 } else if (num_deleted == 0) {
823 ast_cli(a->fd, "Database entries do not exist.\n");
824 } else {
825 ast_cli(a->fd, "%d database entries removed.\n",num_deleted);
826 }
827 return CLI_SUCCESS;
828}
829
830static char *handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
831{
832 char *prefix = NULL;
833 int prefix_len = 0;
834 const char *family = a->argc > 2 ? a->argv[2] : "";
835 const char *keytree = a->argc > 3 ? a->argv[3] : "";
836 int counter = 0;
837 sqlite3_stmt *stmt = gettree_stmt;
838
839 switch (cmd) {
840 case CLI_INIT:
841 e->command = "database show";
842 e->usage =
843 "Usage: database show [family [keytree]]\n"
844 " OR: database show [family[/keytree]]\n"
845 " Shows Asterisk database contents, optionally restricted\n"
846 " to a given family, or family and keytree. The two arguments\n"
847 " may be separated either by a space or by a slash.\n";
848 return NULL;
849 case CLI_GENERATE:
850 return NULL;
851 }
852
853 if (a->argc > 4) {
854 return CLI_SHOWUSAGE;
855 }
856
857 prefix = create_prefix(family, keytree, &prefix_len);
858 if (!prefix) {
859 return NULL;
860 }
861 if (prefix_len == 0) {
862 stmt = gettree_all_stmt;
863 }
864
866 if (prefix_len && (sqlite3_bind_text(stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
867 ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
868 sqlite3_reset(stmt);
871 return NULL;
872 }
873
874 while (sqlite3_step(stmt) == SQLITE_ROW) {
875 const char *key_s, *value_s;
876 if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
877 ast_log(LOG_WARNING, "Skipping invalid key!\n");
878 continue;
879 }
880 if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
881 ast_log(LOG_WARNING, "Skipping invalid value!\n");
882 continue;
883 }
884 ++counter;
885 ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
886 }
887
888 sqlite3_reset(stmt);
891
892 ast_cli(a->fd, "%d results found.\n", counter);
893 return CLI_SUCCESS;
894}
895
896static char *handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
897{
898 int counter = 0;
899
900 switch (cmd) {
901 case CLI_INIT:
902 e->command = "database showkey";
903 e->usage =
904 "Usage: database showkey <keytree>\n"
905 " Shows Asterisk database contents, restricted to a given key.\n";
906 return NULL;
907 case CLI_GENERATE:
908 return NULL;
909 }
910
911 if (a->argc != 3) {
912 return CLI_SHOWUSAGE;
913 }
914
916 if (!ast_strlen_zero(a->argv[2]) && (sqlite3_bind_text(showkey_stmt, 1, a->argv[2], -1, SQLITE_STATIC) != SQLITE_OK)) {
917 ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", a->argv[2], sqlite3_errmsg(astdb));
918 sqlite3_reset(showkey_stmt);
920 return NULL;
921 }
922
923 while (sqlite3_step(showkey_stmt) == SQLITE_ROW) {
924 const char *key_s, *value_s;
925 if (!(key_s = (const char *) sqlite3_column_text(showkey_stmt, 0))) {
926 break;
927 }
928 if (!(value_s = (const char *) sqlite3_column_text(showkey_stmt, 1))) {
929 break;
930 }
931 ++counter;
932 ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
933 }
934 sqlite3_reset(showkey_stmt);
936
937 ast_cli(a->fd, "%d results found.\n", counter);
938 return CLI_SUCCESS;
939}
940
941static int display_results(void *arg, int columns, char **values, char **colnames)
942{
943 struct ast_cli_args *a = arg;
944 size_t x;
945
946 for (x = 0; x < columns; x++) {
947 ast_cli(a->fd, "%-5s: %-50s\n", colnames[x], values[x]);
948 }
949 ast_cli(a->fd, "\n");
950
951 return 0;
952}
953
954static char *handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
955{
956
957 switch (cmd) {
958 case CLI_INIT:
959 e->command = "database query";
960 e->usage =
961 "Usage: database query \"<SQL Statement>\"\n"
962 " Run a user-specified SQL query on the database. Be careful.\n";
963 return NULL;
964 case CLI_GENERATE:
965 return NULL;
966 }
967
968 if (a->argc != 3) {
969 return CLI_SHOWUSAGE;
970 }
971
973 db_execute_sql(a->argv[2], display_results, a);
974 db_sync(); /* Go ahead and sync the db in case they write */
976
977 return CLI_SUCCESS;
978}
979
980static struct ast_cli_entry cli_database[] = {
981 AST_CLI_DEFINE(handle_cli_database_show, "Shows database contents"),
982 AST_CLI_DEFINE(handle_cli_database_showkey, "Shows database contents"),
983 AST_CLI_DEFINE(handle_cli_database_get, "Gets database value"),
984 AST_CLI_DEFINE(handle_cli_database_put, "Adds/updates database value"),
985 AST_CLI_DEFINE(handle_cli_database_del, "Removes database key/value"),
986 AST_CLI_DEFINE(handle_cli_database_deltree, "Removes database keytree/values"),
987 AST_CLI_DEFINE(handle_cli_database_query, "Run a user-specified query on the astdb"),
988};
989
990static int manager_dbput(struct mansession *s, const struct message *m)
991{
992 const char *family = astman_get_header(m, "Family");
993 const char *key = astman_get_header(m, "Key");
994 const char *val = astman_get_header(m, "Val");
995 int res;
996
997 if (ast_strlen_zero(family)) {
998 astman_send_error(s, m, "No family specified");
999 return 0;
1000 }
1001 if (ast_strlen_zero(key)) {
1002 astman_send_error(s, m, "No key specified");
1003 return 0;
1004 }
1005
1006 res = ast_db_put(family, key, S_OR(val, ""));
1007 if (res) {
1008 astman_send_error(s, m, "Failed to update entry");
1009 } else {
1010 astman_send_ack(s, m, "Updated database successfully");
1011 }
1012 return 0;
1013}
1014
1015static int manager_dbget(struct mansession *s, const struct message *m)
1016{
1017 const char *id = astman_get_header(m,"ActionID");
1018 char idText[256];
1019 const char *family = astman_get_header(m, "Family");
1020 const char *key = astman_get_header(m, "Key");
1021 char *tmp = NULL;
1022 int res;
1023
1024 if (ast_strlen_zero(family)) {
1025 astman_send_error(s, m, "No family specified.");
1026 return 0;
1027 }
1028 if (ast_strlen_zero(key)) {
1029 astman_send_error(s, m, "No key specified.");
1030 return 0;
1031 }
1032
1033 idText[0] = '\0';
1034 if (!ast_strlen_zero(id))
1035 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
1036
1037 res = ast_db_get_allocated(family, key, &tmp);
1038 if (res) {
1039 astman_send_error(s, m, "Database entry not found");
1040 } else {
1041 astman_send_listack(s, m, "Result will follow", "start");
1042
1043 astman_append(s, "Event: DBGetResponse\r\n"
1044 "Family: %s\r\n"
1045 "Key: %s\r\n"
1046 "Val: %s\r\n"
1047 "%s"
1048 "\r\n",
1049 family, key, tmp, idText);
1050 ast_free(tmp);
1051 astman_send_list_complete_start(s, m, "DBGetComplete", 1);
1053 }
1054 return 0;
1055}
1056
1057static int manager_db_tree_get(struct mansession *s, const struct message *m)
1058{
1059 char *prefix;
1060 int prefix_len = 0;
1061 char idText[256];
1062 const char *id = astman_get_header(m,"ActionID");
1063 const char *family = astman_get_header(m, "Family");
1064 const char *key = astman_get_header(m, "Key");
1065 sqlite3_stmt *stmt = gettree_stmt;
1066 int count = 0;
1067
1068 prefix = create_prefix(family, key, &prefix_len);
1069 if (!prefix) {
1070 astman_send_error(s, m, "Unable to allocate memory for Family/Key");
1071 return 0;
1072 }
1073 if (prefix_len == 0) {
1074 stmt = gettree_all_stmt;
1075 }
1076
1077 idText[0] = '\0';
1078 if (!ast_strlen_zero(id)) {
1079 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
1080 }
1081
1083 if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
1084 ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
1085 sqlite3_reset(stmt);
1088 astman_send_error(s, m, "Unable to search database");
1089 return 0;
1090 }
1091
1092 astman_send_listack(s, m, "Result will follow", "start");
1093
1094 while (sqlite3_step(stmt) == SQLITE_ROW) {
1095 const char *key_s, *value_s;
1096 if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
1097 ast_log(LOG_WARNING, "Skipping invalid key!\n");
1098 continue;
1099 }
1100 if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
1101 ast_log(LOG_WARNING, "Skipping invalid value!\n");
1102 continue;
1103 }
1104 astman_append(s, "Event: DBGetTreeResponse\r\n"
1105 "Key: %s\r\n"
1106 "Val: %s\r\n"
1107 "%s"
1108 "\r\n",
1109 key_s, value_s, idText);
1110 count++;
1111 }
1112
1113 sqlite3_reset(stmt);
1116
1117 astman_send_list_complete_start(s, m, "DBGetTreeComplete", count);
1119
1120 return 0;
1121}
1122
1123static int manager_dbdel(struct mansession *s, const struct message *m)
1124{
1125 const char *family = astman_get_header(m, "Family");
1126 const char *key = astman_get_header(m, "Key");
1127 int res;
1128
1129 if (ast_strlen_zero(family)) {
1130 astman_send_error(s, m, "No family specified.");
1131 return 0;
1132 }
1133
1134 if (ast_strlen_zero(key)) {
1135 astman_send_error(s, m, "No key specified.");
1136 return 0;
1137 }
1138
1139 res = ast_db_del2(family, key);
1140 if (res)
1141 astman_send_error(s, m, "Database entry could not be deleted");
1142 else
1143 astman_send_ack(s, m, "Key deleted successfully");
1144
1145 return 0;
1146}
1147
1148static int manager_dbdeltree(struct mansession *s, const struct message *m)
1149{
1150 const char *family = astman_get_header(m, "Family");
1151 const char *key = astman_get_header(m, "Key");
1152 int num_deleted;
1153
1154 if (ast_strlen_zero(family)) {
1155 astman_send_error(s, m, "No family specified.");
1156 return 0;
1157 }
1158
1159 if (!ast_strlen_zero(key)) {
1160 num_deleted = ast_db_deltree(family, key);
1161 } else {
1162 num_deleted = ast_db_deltree(family, NULL);
1163 }
1164
1165 if (num_deleted < 0) {
1166 astman_send_error(s, m, "Database unavailable");
1167 } else if (num_deleted == 0) {
1168 astman_send_error(s, m, "Database entry not found");
1169 } else {
1170 astman_send_ack(s, m, "Key tree deleted successfully");
1171 }
1172
1173 return 0;
1174}
1175
1176/*!
1177 * \internal
1178 * \brief Signal the astdb sync thread to do its thing.
1179 *
1180 * \note dblock is assumed to be held when calling this function.
1181 */
1182static void db_sync(void)
1183{
1184 dosync = 1;
1186}
1187
1188/*!
1189 * \internal
1190 * \brief astdb sync thread
1191 *
1192 * This thread is in charge of syncing astdb to disk after a change.
1193 * By pushing it off to this thread to take care of, this I/O bound operation
1194 * will not block other threads from performing other critical processing.
1195 * If changes happen rapidly, this thread will also ensure that the sync
1196 * operations are rate limited.
1197 */
1198static void *db_sync_thread(void *data)
1199{
1202 for (;;) {
1203 /* If dosync is set, db_sync() was called during sleep(1),
1204 * and the pending transaction should be committed.
1205 * Otherwise, block until db_sync() is called.
1206 */
1207 while (!dosync) {
1209 }
1210 dosync = 0;
1213 }
1214 if (doexit) {
1216 break;
1217 }
1220 sleep(1);
1222 }
1223
1224 return NULL;
1225}
1226
1227/*!
1228 * \internal
1229 * \brief Clean up resources on Asterisk shutdown
1230 */
1231static void astdb_atexit(void)
1232{
1234 ast_manager_unregister("DBGet");
1235 ast_manager_unregister("DBGetTree");
1236 ast_manager_unregister("DBPut");
1237 ast_manager_unregister("DBDel");
1238 ast_manager_unregister("DBDelTree");
1239
1240 /* Set doexit to 1 to kill thread. db_sync must be called with
1241 * mutex held. */
1243 doexit = 1;
1244 db_sync();
1246
1247 pthread_join(syncthread, NULL);
1250 if (sqlite3_close(astdb) == SQLITE_OK) {
1251 astdb = NULL;
1252 }
1254}
1255
1256int astdb_init(void)
1257{
1259
1260 if (db_init()) {
1261 return -1;
1262 }
1263
1265 return -1;
1266 }
1267
1275 return 0;
1276}
Prototypes for public functions only of internal interest,.
struct sla_ringing_trunk * last
Definition: app_sla.c:332
#define EXISTS(a, b, c, d)
#define COUNT(a, b)
#define DELETE(a, b, c, d)
static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len)
Persistent data storage (akin to *doze registry)
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: clicompat.c:13
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_log
Definition: astobj2.c:42
static int tmp()
Definition: bt_open.c:389
static char * columns
static PGresult * result
Definition: cel_pgsql.c:84
General Asterisk PBX channel definitions.
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
Convenient Signal Processing routines.
Generic File Format Support. Should be included by clients of the file handling routines....
static int exists(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_logic.c:157
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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:2011
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1969
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:2047
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2001
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1630
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2055
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1890
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7606
static char prefix[MAX_PREFIX]
Definition: http.c:144
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
#define ast_cond_wait(cond, mutex)
Definition: lock.h:205
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_mutex_unlock(a)
Definition: lock.h:190
pthread_cond_t ast_cond_t
Definition: lock.h:178
#define ast_mutex_lock(a)
Definition: lock.h:189
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:520
#define ast_cond_signal(cond)
Definition: lock.h:203
static char * handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:795
static int manager_dbdel(struct mansession *s, const struct message *m)
Definition: main/db.c:1123
static void db_sync(void)
Definition: main/db.c:1182
static int doexit
Definition: main/db.c:123
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:341
static void clean_statements(void)
Definition: main/db.c:188
static char * handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:896
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:673
static int manager_db_tree_get(struct mansession *s, const struct message *m)
Definition: main/db.c:1057
int ast_db_del2(const char *family, const char *key)
Same as ast_db_del, but with more stringent error checking.
Definition: main/db.c:507
static int manager_dbdeltree(struct mansession *s, const struct message *m)
Definition: main/db.c:1148
static struct ast_cli_entry cli_database[]
Definition: main/db.c:980
void ast_db_freetree(struct ast_db_entry *dbe)
Free structure created by ast_db_gettree()
Definition: main/db.c:701
static struct ast_db_entry * db_gettree_common(sqlite3_stmt *stmt)
Definition: main/db.c:602
static int manager_dbget(struct mansession *s, const struct message *m)
Definition: main/db.c:1015
static int db_init(void)
Definition: main/db.c:296
static char * handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:954
int astdb_init(void)
Definition: main/db.c:1256
static sqlite3 * astdb
Definition: main/db.c:121
static int convert_bdb_to_sqlite3(void)
Definition: main/db.c:219
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:437
static int manager_dbput(struct mansession *s, const struct message *m)
Definition: main/db.c:990
static int db_execute_sql(const char *sql, int(*callback)(void *, int, char **, char **), void *arg)
Definition: main/db.c:312
static int display_results(void *arg, int columns, char **values, char **colnames)
Definition: main/db.c:941
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
static int ast_db_begin_transaction(void)
Definition: main/db.c:326
static int db_create_astdb(void)
Definition: main/db.c:233
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:478
static int ast_db_commit_transaction(void)
Definition: main/db.c:331
static int db_open(void)
Definition: main/db.c:253
static ast_mutex_t dblock
Definition: main/db.c:119
#define DEFINE_SQL_STATEMENT(stmt, sql)
Definition: main/db.c:128
static void * db_sync_thread(void *data)
Definition: main/db.c:1198
static ast_cond_t dbcond
Definition: main/db.c:120
static char * handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:830
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:641
static char * create_prefix(const char *family, const char *keytree, int *prefix_len)
Definition: main/db.c:540
static int dosync
Definition: main/db.c:124
static pthread_t syncthread
Definition: main/db.c:122
static char * handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:738
static void astdb_atexit(void)
Definition: main/db.c:1231
static int init_statements(void)
Definition: main/db.c:203
static char * handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:768
static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen)
Definition: main/db.c:387
static int clean_stmt(sqlite3_stmt **stmt, const char *sql)
Definition: main/db.c:173
static int ast_db_rollback_transaction(void)
Definition: main/db.c:336
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
Definition: main/db.c:565
static char * handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:711
int ast_db_exists(const char *family, const char *key)
Check if family/key exitsts.
Definition: main/db.c:444
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define EVENT_FLAG_REPORTING
Definition: manager.h:84
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:202
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_SBIN_DIR
Definition: options.c:163
const char * ast_config_AST_DB
Definition: options.c:165
static char dbname[MAX_DB_OPTION_SIZE]
#define NULL
Definition: resample.c:96
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Definition: astdb.h:31
struct ast_db_entry * next
Definition: astdb.h:32
char * key
Definition: astdb.h:33
In case you didn't read that giant block of text above the mansession_session struct,...
Definition: manager.c:326
Definition: ast_expr2.c:325
int value
Definition: syslog.c:37
@ KEY
Definition: test_db.c:41
static struct test_val a
FILE * out
Definition: utils/frame.c:33
Utility functions.
#define ast_assert(a)
Definition: utils.h:739
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592
#define ARRAY_LEN(a)
Definition: utils.h:666