Asterisk - The Open Source Telephony Project GIT-master-55f4e6d
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
119#define MAX_DB_FIELD 256
122static sqlite3 *astdb;
123static pthread_t syncthread;
124static int doexit;
125static int dosync;
126
127static void db_sync(void);
128
129#define DEFINE_SQL_STATEMENT(stmt,sql) static sqlite3_stmt *stmt; \
130 const char stmt##_sql[] = sql;
131
132DEFINE_SQL_STATEMENT(put_stmt, "INSERT OR REPLACE INTO astdb (key, value) VALUES (?, ?)")
133DEFINE_SQL_STATEMENT(get_stmt, "SELECT value FROM astdb WHERE key=?")
134DEFINE_SQL_STATEMENT(exists_stmt, "SELECT CAST(COUNT(1) AS INTEGER) AS 'exists' FROM astdb WHERE key=?")
135DEFINE_SQL_STATEMENT(del_stmt, "DELETE FROM astdb WHERE key=?")
136DEFINE_SQL_STATEMENT(deltree_stmt, "DELETE FROM astdb WHERE key || '/' LIKE ? || '/' || '%'")
137DEFINE_SQL_STATEMENT(deltree_all_stmt, "DELETE FROM astdb")
138DEFINE_SQL_STATEMENT(gettree_stmt, "SELECT key, value FROM astdb WHERE key || '/' LIKE ? || '/' || '%' ORDER BY key")
139DEFINE_SQL_STATEMENT(gettree_all_stmt, "SELECT key, value FROM astdb ORDER BY key")
140DEFINE_SQL_STATEMENT(showkey_stmt, "SELECT key, value FROM astdb WHERE key LIKE '%' || '/' || ? ORDER BY key")
141DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key VARCHAR(256), value VARCHAR(256), PRIMARY KEY(key))")
142
143/* This query begs an explanation:
144 *
145 * First, the parameter binding syntax used here is slightly different than the other
146 * queries in that we use a numbered parameter so that we can bind once and get the same
147 * value substituted multiple times within the executed query.
148 *
149 * Second, the key comparison is being used to find all keys that are lexicographically
150 * greater than the provided key, but less than the provided key with a high (but
151 * invalid) Unicode codepoint appended to it. This will give us all keys in the database
152 * that have 'key' as a prefix and performs much better than the equivalent "LIKE key ||
153 * '%'" operation.
154 */
155DEFINE_SQL_STATEMENT(gettree_prefix_stmt, "SELECT key, value FROM astdb WHERE key > ?1 AND key <= ?1 || X'ffff'")
156
157static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len)
158{
160 if (sqlite3_prepare(astdb, sql, len, stmt, NULL) != SQLITE_OK) {
161 ast_log(LOG_WARNING, "Couldn't prepare statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
163 return -1;
164 }
166
167 return 0;
168}
169
170/*! \internal
171 * \brief Clean up the prepared SQLite3 statement
172 * \note dblock should already be locked prior to calling this method
173 */
174static int clean_stmt(sqlite3_stmt **stmt, const char *sql)
175{
176 if (sqlite3_finalize(*stmt) != SQLITE_OK) {
177 ast_log(LOG_WARNING, "Couldn't finalize statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
178 *stmt = NULL;
179 return -1;
180 }
181 *stmt = NULL;
182 return 0;
183}
184
185/*! \internal
186 * \brief Clean up all prepared SQLite3 statements
187 * \note dblock should already be locked prior to calling this method
188 */
189static void clean_statements(void)
190{
191 clean_stmt(&get_stmt, get_stmt_sql);
192 clean_stmt(&exists_stmt, exists_stmt_sql);
193 clean_stmt(&del_stmt, del_stmt_sql);
194 clean_stmt(&deltree_stmt, deltree_stmt_sql);
195 clean_stmt(&deltree_all_stmt, deltree_all_stmt_sql);
196 clean_stmt(&gettree_stmt, gettree_stmt_sql);
197 clean_stmt(&gettree_all_stmt, gettree_all_stmt_sql);
198 clean_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql);
199 clean_stmt(&showkey_stmt, showkey_stmt_sql);
200 clean_stmt(&put_stmt, put_stmt_sql);
201 clean_stmt(&create_astdb_stmt, create_astdb_stmt_sql);
202}
203
204static int init_statements(void)
205{
206 /* Don't initialize create_astdb_statement here as the astdb table needs to exist
207 * brefore these statements can be initialized */
208 return init_stmt(&get_stmt, get_stmt_sql, sizeof(get_stmt_sql))
209 || init_stmt(&exists_stmt, exists_stmt_sql, sizeof(exists_stmt_sql))
210 || init_stmt(&del_stmt, del_stmt_sql, sizeof(del_stmt_sql))
211 || init_stmt(&deltree_stmt, deltree_stmt_sql, sizeof(deltree_stmt_sql))
212 || init_stmt(&deltree_all_stmt, deltree_all_stmt_sql, sizeof(deltree_all_stmt_sql))
213 || init_stmt(&gettree_stmt, gettree_stmt_sql, sizeof(gettree_stmt_sql))
214 || init_stmt(&gettree_all_stmt, gettree_all_stmt_sql, sizeof(gettree_all_stmt_sql))
215 || init_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql, sizeof(gettree_prefix_stmt_sql))
216 || init_stmt(&showkey_stmt, showkey_stmt_sql, sizeof(showkey_stmt_sql))
217 || init_stmt(&put_stmt, put_stmt_sql, sizeof(put_stmt_sql));
218}
219
221{
222 char *cmd;
223 int res;
224
225 res = ast_asprintf(&cmd, "%s/astdb2sqlite3 '%s'\n", ast_config_AST_SBIN_DIR, ast_config_AST_DB);
226 if (0 <= res) {
227 res = ast_safe_system(cmd);
228 ast_free(cmd);
229 }
230
231 return res;
232}
233
234static int db_create_astdb(void)
235{
236 int res = 0;
237
238 if (!create_astdb_stmt) {
239 init_stmt(&create_astdb_stmt, create_astdb_stmt_sql, sizeof(create_astdb_stmt_sql));
240 }
241
243 if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) {
244 ast_log(LOG_WARNING, "Couldn't create astdb table: %s\n", sqlite3_errmsg(astdb));
245 res = -1;
246 }
247 sqlite3_reset(create_astdb_stmt);
248 db_sync();
250
251 return res;
252}
253
254static int db_open(void)
255{
256 char *dbname;
257 struct stat dont_care;
258
259 if (!(dbname = ast_alloca(strlen(ast_config_AST_DB) + sizeof(".sqlite3")))) {
260 return -1;
261 }
262 strcpy(dbname, ast_config_AST_DB);
263 strcat(dbname, ".sqlite3");
264
265 if (stat(dbname, &dont_care) && !stat(ast_config_AST_DB, &dont_care)) {
267 ast_log(LOG_ERROR, "*** Database conversion failed!\n");
268 ast_log(LOG_ERROR, "*** Asterisk now uses SQLite3 for its internal\n");
269 ast_log(LOG_ERROR, "*** database. Conversion from the old astdb\n");
270 ast_log(LOG_ERROR, "*** failed. Most likely the astdb2sqlite3 utility\n");
271 ast_log(LOG_ERROR, "*** was not selected for build. To convert the\n");
272 ast_log(LOG_ERROR, "*** old astdb, please delete '%s'\n", dbname);
273 ast_log(LOG_ERROR, "*** and re-run 'make menuselect' and select astdb2sqlite3\n");
274 ast_log(LOG_ERROR, "*** in the Utilities section, then 'make && make install'.\n");
275 ast_log(LOG_ERROR, "*** It is also imperative that the user under which\n");
276 ast_log(LOG_ERROR, "*** Asterisk runs have write permission to the directory\n");
277 ast_log(LOG_ERROR, "*** where the database resides.\n");
278 sleep(5);
279 } else {
280 ast_log(LOG_NOTICE, "Database conversion succeeded!\n");
281 }
282 }
283
285 if (sqlite3_open(dbname, &astdb) != SQLITE_OK) {
286 ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb));
287 sqlite3_close(astdb);
289 return -1;
290 }
291
293
294 return 0;
295}
296
297static int db_init(void)
298{
299 if (astdb) {
300 return 0;
301 }
302
303 if (db_open() || db_create_astdb() || init_statements()) {
304 return -1;
305 }
306
307 return 0;
308}
309
310/* We purposely don't lock around the sqlite3 call because the transaction
311 * calls will be called with the database lock held. For any other use, make
312 * sure to take the dblock yourself. */
313static int db_execute_sql(const char *sql, int (*callback)(void *, int, char **, char **), void *arg)
314{
315 char *errmsg = NULL;
316 int res =0;
317
318 if (sqlite3_exec(astdb, sql, callback, arg, &errmsg) != SQLITE_OK) {
319 ast_log(LOG_WARNING, "Error executing SQL (%s): %s\n", sql, errmsg);
320 sqlite3_free(errmsg);
321 res = -1;
322 }
323
324 return res;
325}
326
328{
329 return db_execute_sql("BEGIN TRANSACTION", NULL, NULL);
330}
331
333{
334 return db_execute_sql("COMMIT", NULL, NULL);
335}
336
338{
339 return db_execute_sql("ROLLBACK", NULL, NULL);
340}
341
342int ast_db_put(const char *family, const char *key, const char *value)
343{
344 char fullkey[MAX_DB_FIELD];
345 size_t fullkey_len;
346 int res = 0;
347
348 if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
349 ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
350 return -1;
351 }
352
353 fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
354
356 if (sqlite3_bind_text(put_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
357 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
358 res = -1;
359 } else if (sqlite3_bind_text(put_stmt, 2, value, -1, SQLITE_STATIC) != SQLITE_OK) {
360 ast_log(LOG_WARNING, "Couldn't bind value to stmt: %s\n", sqlite3_errmsg(astdb));
361 res = -1;
362 } else if (sqlite3_step(put_stmt) != SQLITE_DONE) {
363 ast_log(LOG_WARNING, "Couldn't execute statement: %s\n", sqlite3_errmsg(astdb));
364 res = -1;
365 }
366
367 sqlite3_reset(put_stmt);
368 db_sync();
370
371 return res;
372}
373
374/*!
375 * \internal
376 * \brief Get key value specified by family/key.
377 *
378 * Gets the value associated with the specified \a family and \a key, and
379 * stores it, either into the fixed sized buffer specified by \a buffer
380 * and \a bufferlen, or as a heap allocated string if \a bufferlen is -1.
381 *
382 * \note If \a bufferlen is -1, \a buffer points to heap allocated memory
383 * and must be freed by calling ast_free().
384 *
385 * \retval -1 An error occurred
386 * \retval 0 Success
387 */
388static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen)
389{
390 const unsigned char *result;
391 char fullkey[MAX_DB_FIELD];
392 size_t fullkey_len;
393 int res = 0;
394
395 if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
396 ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
397 return -1;
398 }
399
400 fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
401
403 if (sqlite3_bind_text(get_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
404 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
405 res = -1;
406 } else if (sqlite3_step(get_stmt) != SQLITE_ROW) {
407 ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
408 res = -1;
409 } else if (!(result = sqlite3_column_text(get_stmt, 0))) {
410 ast_log(LOG_WARNING, "Couldn't get value\n");
411 res = -1;
412 } else {
413 const char *value = (const char *) result;
414
415 if (bufferlen == -1) {
416 *buffer = ast_strdup(value);
417 } else {
418 ast_copy_string(*buffer, value, bufferlen);
419 }
420 }
421 sqlite3_reset(get_stmt);
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[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
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);
471
472 return res;
473}
474
475
476int ast_db_del(const char *family, const char *key)
477{
478 char fullkey[MAX_DB_FIELD];
479 size_t fullkey_len;
480 int res = 0;
481
482 if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
483 ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
484 return -1;
485 }
486
487 fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
488
490 if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
491 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
492 res = -1;
493 } else if (sqlite3_step(del_stmt) != SQLITE_DONE) {
494 ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
495 res = -1;
496 }
497 sqlite3_reset(del_stmt);
498 db_sync();
500
501 return res;
502}
503
504int ast_db_del2(const char *family, const char *key)
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
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();
532
533 return res;
534}
535
536int ast_db_deltree(const char *family, const char *keytree)
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
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();
567
568 return res;
569}
570
571static struct ast_db_entry *db_gettree_common(sqlite3_stmt *stmt)
572{
573 struct ast_db_entry *head = NULL, *prev = NULL, *cur;
574
575 while (sqlite3_step(stmt) == SQLITE_ROW) {
576 const char *key, *value;
577 size_t key_len, value_len;
578
579 key = (const char *) sqlite3_column_text(stmt, 0);
580 value = (const char *) sqlite3_column_text(stmt, 1);
581
582 if (!key || !value) {
583 break;
584 }
585
586 key_len = strlen(key);
587 value_len = strlen(value);
588
589 cur = ast_malloc(sizeof(*cur) + key_len + value_len + 2);
590 if (!cur) {
591 break;
592 }
593
594 cur->next = NULL;
595 cur->key = cur->data + value_len + 1;
596 memcpy(cur->data, value, value_len + 1);
597 memcpy(cur->key, key, key_len + 1);
598
599 if (prev) {
600 prev->next = cur;
601 } else {
602 head = cur;
603 }
604 prev = cur;
605 }
606
607 return head;
608}
609
610struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
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
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);
640 return NULL;
641 }
642
643 ret = db_gettree_common(stmt);
644 sqlite3_reset(stmt);
646
647 return ret;
648}
649
650struct ast_db_entry *ast_db_gettree_by_prefix(const char *family, const char *key_prefix)
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
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);
667 return NULL;
668 }
669
670 ret = db_gettree_common(gettree_prefix_stmt);
671 sqlite3_reset(gettree_prefix_stmt);
673
674 return ret;
675}
676
678{
679 struct ast_db_entry *last;
680 while (dbe) {
681 last = dbe;
682 dbe = dbe->next;
683 ast_free(last);
684 }
685}
686
687static char *handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
688{
689 int res;
690
691 switch (cmd) {
692 case CLI_INIT:
693 e->command = "database put";
694 e->usage =
695 "Usage: database put <family> <key> <value>\n"
696 " Adds or updates an entry in the Asterisk database for\n"
697 " a given family, key, and value.\n";
698 return NULL;
699 case CLI_GENERATE:
700 return NULL;
701 }
702
703 if (a->argc != 5)
704 return CLI_SHOWUSAGE;
705 res = ast_db_put(a->argv[2], a->argv[3], a->argv[4]);
706 if (res) {
707 ast_cli(a->fd, "Failed to update entry\n");
708 } else {
709 ast_cli(a->fd, "Updated database successfully\n");
710 }
711 return CLI_SUCCESS;
712}
713
714static char *handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
715{
716 int res;
717 char tmp[MAX_DB_FIELD];
718
719 switch (cmd) {
720 case CLI_INIT:
721 e->command = "database get";
722 e->usage =
723 "Usage: database get <family> <key>\n"
724 " Retrieves an entry in the Asterisk database for a given\n"
725 " family and key.\n";
726 return NULL;
727 case CLI_GENERATE:
728 return NULL;
729 }
730
731 if (a->argc != 4)
732 return CLI_SHOWUSAGE;
733 res = ast_db_get(a->argv[2], a->argv[3], tmp, sizeof(tmp));
734 if (res) {
735 ast_cli(a->fd, "Database entry not found.\n");
736 } else {
737 ast_cli(a->fd, "Value: %s\n", tmp);
738 }
739 return CLI_SUCCESS;
740}
741
742static char *handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
743{
744 int res;
745
746 switch (cmd) {
747 case CLI_INIT:
748 e->command = "database del";
749 e->usage =
750 "Usage: database del <family> <key>\n"
751 " Deletes an entry in the Asterisk database for a given\n"
752 " family and key.\n";
753 return NULL;
754 case CLI_GENERATE:
755 return NULL;
756 }
757
758 if (a->argc != 4)
759 return CLI_SHOWUSAGE;
760 res = ast_db_del2(a->argv[2], a->argv[3]);
761 if (res) {
762 ast_cli(a->fd, "Database entry could not be removed.\n");
763 } else {
764 ast_cli(a->fd, "Database entry removed.\n");
765 }
766 return CLI_SUCCESS;
767}
768
769static char *handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
770{
771 int num_deleted;
772
773 switch (cmd) {
774 case CLI_INIT:
775 e->command = "database deltree";
776 e->usage =
777 "Usage: database deltree <family> [keytree]\n"
778 " OR: database deltree <family>[/keytree]\n"
779 " Deletes a family or specific keytree within a family\n"
780 " in the Asterisk database. The two arguments may be\n"
781 " separated by either a space or a slash.\n";
782 return NULL;
783 case CLI_GENERATE:
784 return NULL;
785 }
786
787 if ((a->argc < 3) || (a->argc > 4))
788 return CLI_SHOWUSAGE;
789 if (a->argc == 4) {
790 num_deleted = ast_db_deltree(a->argv[2], a->argv[3]);
791 } else {
792 num_deleted = ast_db_deltree(a->argv[2], NULL);
793 }
794 if (num_deleted < 0) {
795 ast_cli(a->fd, "Database unavailable.\n");
796 } else if (num_deleted == 0) {
797 ast_cli(a->fd, "Database entries do not exist.\n");
798 } else {
799 ast_cli(a->fd, "%d database entries removed.\n",num_deleted);
800 }
801 return CLI_SUCCESS;
802}
803
804static char *handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
805{
806 char prefix[MAX_DB_FIELD];
807 int counter = 0;
808 sqlite3_stmt *stmt = gettree_stmt;
809
810 switch (cmd) {
811 case CLI_INIT:
812 e->command = "database show";
813 e->usage =
814 "Usage: database show [family [keytree]]\n"
815 " OR: database show [family[/keytree]]\n"
816 " Shows Asterisk database contents, optionally restricted\n"
817 " to a given family, or family and keytree. The two arguments\n"
818 " may be separated either by a space or by a slash.\n";
819 return NULL;
820 case CLI_GENERATE:
821 return NULL;
822 }
823
824 if (a->argc == 4) {
825 /* Family and key tree */
826 snprintf(prefix, sizeof(prefix), "/%s/%s", a->argv[2], a->argv[3]);
827 } else if (a->argc == 3) {
828 /* Family only */
829 snprintf(prefix, sizeof(prefix), "/%s", a->argv[2]);
830 } else if (a->argc == 2) {
831 /* Neither */
832 prefix[0] = '\0';
833 stmt = gettree_all_stmt;
834
835 } else {
836 return CLI_SHOWUSAGE;
837 }
838
840 if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
841 ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
842 sqlite3_reset(stmt);
844 return NULL;
845 }
846
847 while (sqlite3_step(stmt) == SQLITE_ROW) {
848 const char *key_s, *value_s;
849 if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
850 ast_log(LOG_WARNING, "Skipping invalid key!\n");
851 continue;
852 }
853 if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
854 ast_log(LOG_WARNING, "Skipping invalid value!\n");
855 continue;
856 }
857 ++counter;
858 ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
859 }
860
861 sqlite3_reset(stmt);
863
864 ast_cli(a->fd, "%d results found.\n", counter);
865 return CLI_SUCCESS;
866}
867
868static char *handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
869{
870 int counter = 0;
871
872 switch (cmd) {
873 case CLI_INIT:
874 e->command = "database showkey";
875 e->usage =
876 "Usage: database showkey <keytree>\n"
877 " Shows Asterisk database contents, restricted to a given key.\n";
878 return NULL;
879 case CLI_GENERATE:
880 return NULL;
881 }
882
883 if (a->argc != 3) {
884 return CLI_SHOWUSAGE;
885 }
886
888 if (!ast_strlen_zero(a->argv[2]) && (sqlite3_bind_text(showkey_stmt, 1, a->argv[2], -1, SQLITE_STATIC) != SQLITE_OK)) {
889 ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", a->argv[2], sqlite3_errmsg(astdb));
890 sqlite3_reset(showkey_stmt);
892 return NULL;
893 }
894
895 while (sqlite3_step(showkey_stmt) == SQLITE_ROW) {
896 const char *key_s, *value_s;
897 if (!(key_s = (const char *) sqlite3_column_text(showkey_stmt, 0))) {
898 break;
899 }
900 if (!(value_s = (const char *) sqlite3_column_text(showkey_stmt, 1))) {
901 break;
902 }
903 ++counter;
904 ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
905 }
906 sqlite3_reset(showkey_stmt);
908
909 ast_cli(a->fd, "%d results found.\n", counter);
910 return CLI_SUCCESS;
911}
912
913static int display_results(void *arg, int columns, char **values, char **colnames)
914{
915 struct ast_cli_args *a = arg;
916 size_t x;
917
918 for (x = 0; x < columns; x++) {
919 ast_cli(a->fd, "%-5s: %-50s\n", colnames[x], values[x]);
920 }
921 ast_cli(a->fd, "\n");
922
923 return 0;
924}
925
926static char *handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
927{
928
929 switch (cmd) {
930 case CLI_INIT:
931 e->command = "database query";
932 e->usage =
933 "Usage: database query \"<SQL Statement>\"\n"
934 " Run a user-specified SQL query on the database. Be careful.\n";
935 return NULL;
936 case CLI_GENERATE:
937 return NULL;
938 }
939
940 if (a->argc != 3) {
941 return CLI_SHOWUSAGE;
942 }
943
945 db_execute_sql(a->argv[2], display_results, a);
946 db_sync(); /* Go ahead and sync the db in case they write */
948
949 return CLI_SUCCESS;
950}
951
952static struct ast_cli_entry cli_database[] = {
953 AST_CLI_DEFINE(handle_cli_database_show, "Shows database contents"),
954 AST_CLI_DEFINE(handle_cli_database_showkey, "Shows database contents"),
955 AST_CLI_DEFINE(handle_cli_database_get, "Gets database value"),
956 AST_CLI_DEFINE(handle_cli_database_put, "Adds/updates database value"),
957 AST_CLI_DEFINE(handle_cli_database_del, "Removes database key/value"),
958 AST_CLI_DEFINE(handle_cli_database_deltree, "Removes database keytree/values"),
959 AST_CLI_DEFINE(handle_cli_database_query, "Run a user-specified query on the astdb"),
960};
961
962static int manager_dbput(struct mansession *s, const struct message *m)
963{
964 const char *family = astman_get_header(m, "Family");
965 const char *key = astman_get_header(m, "Key");
966 const char *val = astman_get_header(m, "Val");
967 int res;
968
969 if (ast_strlen_zero(family)) {
970 astman_send_error(s, m, "No family specified");
971 return 0;
972 }
973 if (ast_strlen_zero(key)) {
974 astman_send_error(s, m, "No key specified");
975 return 0;
976 }
977
978 res = ast_db_put(family, key, S_OR(val, ""));
979 if (res) {
980 astman_send_error(s, m, "Failed to update entry");
981 } else {
982 astman_send_ack(s, m, "Updated database successfully");
983 }
984 return 0;
985}
986
987static int manager_dbget(struct mansession *s, const struct message *m)
988{
989 const char *id = astman_get_header(m,"ActionID");
990 char idText[256];
991 const char *family = astman_get_header(m, "Family");
992 const char *key = astman_get_header(m, "Key");
993 char tmp[MAX_DB_FIELD];
994 int res;
995
996 if (ast_strlen_zero(family)) {
997 astman_send_error(s, m, "No family specified.");
998 return 0;
999 }
1000 if (ast_strlen_zero(key)) {
1001 astman_send_error(s, m, "No key specified.");
1002 return 0;
1003 }
1004
1005 idText[0] = '\0';
1006 if (!ast_strlen_zero(id))
1007 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
1008
1009 res = ast_db_get(family, key, tmp, sizeof(tmp));
1010 if (res) {
1011 astman_send_error(s, m, "Database entry not found");
1012 } else {
1013 astman_send_listack(s, m, "Result will follow", "start");
1014
1015 astman_append(s, "Event: DBGetResponse\r\n"
1016 "Family: %s\r\n"
1017 "Key: %s\r\n"
1018 "Val: %s\r\n"
1019 "%s"
1020 "\r\n",
1021 family, key, tmp, idText);
1022
1023 astman_send_list_complete_start(s, m, "DBGetComplete", 1);
1025 }
1026 return 0;
1027}
1028
1029static int manager_db_tree_get(struct mansession *s, const struct message *m)
1030{
1031 char prefix[MAX_DB_FIELD];
1032 char idText[256];
1033 const char *id = astman_get_header(m,"ActionID");
1034 const char *family = astman_get_header(m, "Family");
1035 const char *key = astman_get_header(m, "Key");
1036 sqlite3_stmt *stmt = gettree_stmt;
1037 int count = 0;
1038
1039 if (!ast_strlen_zero(family) && !ast_strlen_zero(key)) {
1040 /* Family and key tree */
1041 snprintf(prefix, sizeof(prefix), "/%s/%s", family, key);
1042 } else if (!ast_strlen_zero(family)) {
1043 /* Family only */
1044 snprintf(prefix, sizeof(prefix), "/%s", family);
1045 } else {
1046 /* Neither */
1047 prefix[0] = '\0';
1048 stmt = gettree_all_stmt;
1049 }
1050
1051 idText[0] = '\0';
1052 if (!ast_strlen_zero(id)) {
1053 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
1054 }
1055
1057 if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
1058 ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
1059 sqlite3_reset(stmt);
1061 astman_send_error(s, m, "Unable to search database");
1062 return 0;
1063 }
1064
1065 astman_send_listack(s, m, "Result will follow", "start");
1066
1067 while (sqlite3_step(stmt) == SQLITE_ROW) {
1068 const char *key_s, *value_s;
1069 if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
1070 ast_log(LOG_WARNING, "Skipping invalid key!\n");
1071 continue;
1072 }
1073 if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
1074 ast_log(LOG_WARNING, "Skipping invalid value!\n");
1075 continue;
1076 }
1077 astman_append(s, "Event: DBGetTreeResponse\r\n"
1078 "Key: %s\r\n"
1079 "Val: %s\r\n"
1080 "%s"
1081 "\r\n",
1082 key_s, value_s, idText);
1083 count++;
1084 }
1085
1086 sqlite3_reset(stmt);
1088
1089 astman_send_list_complete_start(s, m, "DBGetTreeComplete", count);
1091
1092 return 0;
1093}
1094
1095static int manager_dbdel(struct mansession *s, const struct message *m)
1096{
1097 const char *family = astman_get_header(m, "Family");
1098 const char *key = astman_get_header(m, "Key");
1099 int res;
1100
1101 if (ast_strlen_zero(family)) {
1102 astman_send_error(s, m, "No family specified.");
1103 return 0;
1104 }
1105
1106 if (ast_strlen_zero(key)) {
1107 astman_send_error(s, m, "No key specified.");
1108 return 0;
1109 }
1110
1111 res = ast_db_del2(family, key);
1112 if (res)
1113 astman_send_error(s, m, "Database entry could not be deleted");
1114 else
1115 astman_send_ack(s, m, "Key deleted successfully");
1116
1117 return 0;
1118}
1119
1120static int manager_dbdeltree(struct mansession *s, const struct message *m)
1121{
1122 const char *family = astman_get_header(m, "Family");
1123 const char *key = astman_get_header(m, "Key");
1124 int num_deleted;
1125
1126 if (ast_strlen_zero(family)) {
1127 astman_send_error(s, m, "No family specified.");
1128 return 0;
1129 }
1130
1131 if (!ast_strlen_zero(key)) {
1132 num_deleted = ast_db_deltree(family, key);
1133 } else {
1134 num_deleted = ast_db_deltree(family, NULL);
1135 }
1136
1137 if (num_deleted < 0) {
1138 astman_send_error(s, m, "Database unavailable");
1139 } else if (num_deleted == 0) {
1140 astman_send_error(s, m, "Database entry not found");
1141 } else {
1142 astman_send_ack(s, m, "Key tree deleted successfully");
1143 }
1144
1145 return 0;
1146}
1147
1148/*!
1149 * \internal
1150 * \brief Signal the astdb sync thread to do its thing.
1151 *
1152 * \note dblock is assumed to be held when calling this function.
1153 */
1154static void db_sync(void)
1155{
1156 dosync = 1;
1158}
1159
1160/*!
1161 * \internal
1162 * \brief astdb sync thread
1163 *
1164 * This thread is in charge of syncing astdb to disk after a change.
1165 * By pushing it off to this thread to take care of, this I/O bound operation
1166 * will not block other threads from performing other critical processing.
1167 * If changes happen rapidly, this thread will also ensure that the sync
1168 * operations are rate limited.
1169 */
1170static void *db_sync_thread(void *data)
1171{
1174 for (;;) {
1175 /* If dosync is set, db_sync() was called during sleep(1),
1176 * and the pending transaction should be committed.
1177 * Otherwise, block until db_sync() is called.
1178 */
1179 while (!dosync) {
1181 }
1182 dosync = 0;
1185 }
1186 if (doexit) {
1188 break;
1189 }
1192 sleep(1);
1194 }
1195
1196 return NULL;
1197}
1198
1199/*!
1200 * \internal
1201 * \brief Clean up resources on Asterisk shutdown
1202 */
1203static void astdb_atexit(void)
1204{
1206 ast_manager_unregister("DBGet");
1207 ast_manager_unregister("DBGetTree");
1208 ast_manager_unregister("DBPut");
1209 ast_manager_unregister("DBDel");
1210 ast_manager_unregister("DBDelTree");
1211
1212 /* Set doexit to 1 to kill thread. db_sync must be called with
1213 * mutex held. */
1215 doexit = 1;
1216 db_sync();
1218
1219 pthread_join(syncthread, NULL);
1222 if (sqlite3_close(astdb) == SQLITE_OK) {
1223 astdb = NULL;
1224 }
1226}
1227
1228int astdb_init(void)
1229{
1231
1232 if (db_init()) {
1233 return -1;
1234 }
1235
1237 return -1;
1238 }
1239
1247 return 0;
1248}
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:3431
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3389
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:3467
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3421
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3050
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3475
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3310
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:8057
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:769
static int manager_dbdel(struct mansession *s, const struct message *m)
Definition: main/db.c:1095
static void db_sync(void)
Definition: main/db.c:1154
static int doexit
Definition: main/db.c:124
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:342
static void clean_statements(void)
Definition: main/db.c:189
static char * handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:868
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:650
static int manager_db_tree_get(struct mansession *s, const struct message *m)
Definition: main/db.c:1029
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:504
static int manager_dbdeltree(struct mansession *s, const struct message *m)
Definition: main/db.c:1120
static struct ast_cli_entry cli_database[]
Definition: main/db.c:952
void ast_db_freetree(struct ast_db_entry *dbe)
Free structure created by ast_db_gettree()
Definition: main/db.c:677
static struct ast_db_entry * db_gettree_common(sqlite3_stmt *stmt)
Definition: main/db.c:571
static int manager_dbget(struct mansession *s, const struct message *m)
Definition: main/db.c:987
static int db_init(void)
Definition: main/db.c:297
static char * handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:926
int astdb_init(void)
Definition: main/db.c:1228
static sqlite3 * astdb
Definition: main/db.c:122
static int convert_bdb_to_sqlite3(void)
Definition: main/db.c:220
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:962
static int db_execute_sql(const char *sql, int(*callback)(void *, int, char **, char **), void *arg)
Definition: main/db.c:313
static int display_results(void *arg, int columns, char **values, char **colnames)
Definition: main/db.c:913
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:327
static int db_create_astdb(void)
Definition: main/db.c:234
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:476
static int ast_db_commit_transaction(void)
Definition: main/db.c:332
static int db_open(void)
Definition: main/db.c:254
static ast_mutex_t dblock
Definition: main/db.c:120
#define DEFINE_SQL_STATEMENT(stmt, sql)
Definition: main/db.c:129
static void * db_sync_thread(void *data)
Definition: main/db.c:1170
static ast_cond_t dbcond
Definition: main/db.c:121
static char * handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:804
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:610
static int dosync
Definition: main/db.c:125
static pthread_t syncthread
Definition: main/db.c:123
static char * handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:714
static void astdb_atexit(void)
Definition: main/db.c:1203
static int init_statements(void)
Definition: main/db.c:204
static char * handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:742
static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen)
Definition: main/db.c:388
static int clean_stmt(sqlite3_stmt **stmt, const char *sql)
Definition: main/db.c:174
static int ast_db_rollback_transaction(void)
Definition: main/db.c:337
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
Definition: main/db.c:536
static char * handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/db.c:687
int ast_db_exists(const char *family, const char *key)
Check if family/key exitsts.
Definition: main/db.c:444
#define MAX_DB_FIELD
Definition: main/db.c:119
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
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:1785
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