Asterisk - The Open Source Telephony Project GIT-master-a358458
res_config_sqlite3.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2011, Terry Wilson
5 *
6 * Terry Wilson <twilson@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 SQLite 3 configuration engine
22 *
23 * \author\verbatim Terry Wilson <twilson@digium.com> \endverbatim
24 *
25 * This is a realtime configuration engine for the SQLite 3 Database
26 * \ingroup resources
27 */
28
29/*! \li \ref res_config_sqlite3.c uses the configuration file \ref res_config_sqlite3.conf
30 * \addtogroup configuration_file Configuration Files
31 */
32
33/*!
34 * \page res_config_sqlite3.conf res_config_sqlite3.conf
35 * \verbinclude res_config_sqlite3.conf.sample
36 */
37
38/*** MODULEINFO
39 <depend>sqlite3</depend>
40 <support_level>core</support_level>
41 ***/
42
43#include "asterisk.h"
44
45#include <sqlite3.h>
46
47#include "asterisk/module.h"
48#include "asterisk/config.h"
49#include "asterisk/paths.h"
50#include "asterisk/astobj2.h"
51#include "asterisk/lock.h"
52#include "asterisk/utils.h"
53#include "asterisk/app.h"
54
55/*** DOCUMENTATION
56 ***/
57
59
60static struct ast_config *realtime_sqlite3_load(const char *database, const char *table, const char *configfile, struct ast_config *config, struct ast_flags flags, const char *suggested_include_file, const char *who_asked);
61static struct ast_variable *realtime_sqlite3(const char *database, const char *table, const struct ast_variable *fields);
62static struct ast_config *realtime_sqlite3_multi(const char *database, const char *table, const struct ast_variable *fields);
63static int realtime_sqlite3_update(const char *database, const char *table, const char *keyfield, const char *entity, const struct ast_variable *fields);
64static int realtime_sqlite3_update2(const char *database, const char *table, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields);
65static int realtime_sqlite3_store(const char *database, const char *table, const struct ast_variable *fields);
66static int realtime_sqlite3_destroy(const char *database, const char *table, const char *keyfield, const char *entity, const struct ast_variable *fields);
67static int realtime_sqlite3_require(const char *database, const char *table, va_list ap);
68static int realtime_sqlite3_unload(const char *database, const char *table);
69
71 .name = "sqlite3",
72 .load_func = realtime_sqlite3_load,
73 .realtime_func = realtime_sqlite3,
74 .realtime_multi_func = realtime_sqlite3_multi,
75 .update_func = realtime_sqlite3_update,
76 .update2_func = realtime_sqlite3_update2,
77 .store_func = realtime_sqlite3_store,
78 .destroy_func = realtime_sqlite3_destroy,
79 .require_func = realtime_sqlite3_require,
80 .unload_func = realtime_sqlite3_unload,
81};
82
83enum {
87};
88
93 );
94 sqlite3 *handle;
95 pthread_t syncthread;
97 unsigned int requirements:2;
98 unsigned int dirty:1;
99 unsigned int debug:1;
100 unsigned int exiting:1;
101 unsigned int wakeup:1;
102 unsigned int has_batch_thread:1;
103 unsigned int batch;
105};
106
108#define DB_BUCKETS 7
109
111
112/* We need a separate buffer for each field we might use concurrently */
116
117typedef int (*callback_t)(void*, int, char **, char **);
118
119static int realtime_sqlite3_exec_query_with_handle(struct realtime_sqlite3_db *, const char *, callback_t, void *);
120static int realtime_sqlite3_exec_query(const char *, const char *, callback_t, void *);
121static int realtime_sqlite3_exec_update_with_handle(struct realtime_sqlite3_db *, const char *);
122static int realtime_sqlite3_exec_update(const char *, const char *);
123
126
127static inline const char *sqlite3_escape_string_helper(struct ast_threadstorage *ts, const char *param)
128{
129 size_t maxlen = strlen(param) * 2 + sizeof("\"\"");
130 /* It doesn't appear that sqlite3_snprintf will do more than double the
131 * length of a string with %q as an option. %Q could double and possibly
132 * add two quotes, and convert NULL pointers to the word "NULL", but we
133 * don't allow those anyway. Just going to use %q for now. */
134 struct ast_str *buf = ast_str_thread_get(ts, maxlen);
135 char q = ts == &escape_value_buf ? '\'' : '"';
136 char *tmp;
137
138 if (ast_str_size(buf) < maxlen) {
139 /* realloc if buf is too small */
140 ast_str_make_space(&buf, maxlen);
141 }
143
145 *tmp++ = q; /* Initial quote */
146 while ((*tmp++ = *param++)) {
147 /* Did we just copy a quote? Then double it. */
148 if (*(tmp - 1) == q) {
149 *tmp++ = q;
150 }
151 }
152 *tmp = '\0'; /* Terminate past NULL from copy */
153 *(tmp - 1) = q; /* Replace original NULL with the quote */
155
156 return ast_str_buffer(buf);
157}
158
159static inline const char *sqlite3_escape_table(const char *param)
160{
162}
163
164static inline const char *sqlite3_escape_column(const char *param)
165{
167}
168
169/* Not inlining this function because it uses strdupa and I don't know if the compiler would be dumb */
170static const char *sqlite3_escape_column_op(const char *param)
171{
172 size_t maxlen = strlen(param) * 2 + sizeof("\"\" =");
174 char *tmp;
175 int space = 0;
176
177 if (ast_str_size(buf) < maxlen) {
178 /* realloc if buf is too small */
179 ast_str_make_space(&buf, maxlen);
180 }
182
184 *tmp++ = '"';
185 while ((*tmp++ = *param++)) {
186 /* If we have seen a space, don't double quotes. XXX If we ever make the column/op field
187 * available to users via an API, we will definitely need to avoid allowing special
188 * characters like ';' in the data past the space as it will be unquoted data */
189 if (space) {
190 continue;
191 }
192 if (*(tmp - 1) == ' ') {
193 *(tmp - 1) = '"';
194 *tmp++ = ' ';
195 space = 1;
196 } else if (*(tmp - 1) == '"') {
197 *tmp++ = '"';
198 }
199 }
200 if (!space) {
201 strcpy(tmp - 1, "\" =");
202 }
203
205
206 return ast_str_buffer(buf);
207}
208
209static inline const char *sqlite3_escape_value(const char *param)
210{
212}
213
214static int db_hash_fn(const void *obj, const int flags)
215{
216 const struct realtime_sqlite3_db *db = obj;
217
218 return ast_str_hash(flags & OBJ_KEY ? (const char *) obj : db->name);
219}
220
221static int db_cmp_fn(void *obj, void *arg, int flags) {
222 struct realtime_sqlite3_db *db = obj, *other = arg;
223 const char *name = arg;
224
225 return !strcasecmp(db->name, flags & OBJ_KEY ? name : other->name) ? CMP_MATCH | CMP_STOP : 0;
226}
227
228static void db_destructor(void *obj)
229{
230 struct realtime_sqlite3_db *db = obj;
231
232 ast_debug(1, "Destroying db: %s\n", db->name);
235 if (db->handle) {
236 ao2_lock(db);
237 sqlite3_close(db->handle);
238 ao2_unlock(db);
239 }
240}
241
242static struct realtime_sqlite3_db *find_database(const char *database)
243{
244 return ao2_find(databases, database, OBJ_KEY);
245}
246
247static void unref_db(struct realtime_sqlite3_db **db)
248{
249 ao2_ref(*db, -1);
250 *db = NULL;
251}
252
253static int stop_batch_cb(void *obj, void *arg, int flags)
254{
255 struct realtime_sqlite3_db *db = obj;
256
258 return CMP_MATCH;
259}
260
261static int mark_dirty_cb(void *obj, void *arg, int flags)
262{
263 struct realtime_sqlite3_db *db = obj;
264 db->dirty = 1;
265 return CMP_MATCH;
266}
267
269{
271}
272
273static int is_dirty_cb(void *obj, void *arg, int flags)
274{
275 struct realtime_sqlite3_db *db = obj;
276 if (db->dirty) {
278 return CMP_MATCH;
279 }
280 return 0;
281}
282
283static void unlink_dirty_databases(void)
284{
286}
287
288static int str_to_requirements(const char *data)
289{
290 if (!strcasecmp(data, "createclose")) {
292 } else if (!strcasecmp(data, "createchar")) {
294 }
295 /* default */
297}
298
299/*! \note Since this is called while a query is executing, we should already hold the db lock */
300static void trace_cb(void *arg, const char *sql)
301{
302 struct realtime_sqlite3_db *db = arg;
303 ast_debug(3, "DB: %s SQL: %s\n", db->name, sql);
304}
305
306/*! \brief Wrap commands in transactions increased write performance */
307static void *db_sync_thread(void *data)
308{
309 struct realtime_sqlite3_db *db = data;
310 ao2_lock(db);
311 realtime_sqlite3_exec_query_with_handle(db, "BEGIN TRANSACTION", NULL, NULL);
312 for (;;) {
313 if (!db->wakeup) {
315 }
316 db->wakeup = 0;
319 }
320 if (db->exiting) {
321 ao2_unlock(db);
322 break;
323 }
324 realtime_sqlite3_exec_query_with_handle(db, "BEGIN TRANSACTION", NULL, NULL);
325 ao2_unlock(db);
326 usleep(1000 * db->batch);
327 ao2_lock(db);
328 }
329
330 unref_db(&db);
331
332 return NULL;
333}
334
335/*! \brief Open a database and appropriately set debugging on the db handle */
336static int db_open(struct realtime_sqlite3_db *db)
337{
338 ao2_lock(db);
339 if (sqlite3_open(db->filename, &db->handle) != SQLITE_OK) {
340 ast_log(LOG_WARNING, "Could not open %s: %s\n", db->filename, sqlite3_errmsg(db->handle));
341 ao2_unlock(db);
342 return -1;
343 }
344 sqlite3_busy_timeout(db->handle, db->busy_timeout);
345
346 if (db->debug) {
347 sqlite3_trace(db->handle, trace_cb, db);
348 } else {
349 sqlite3_trace(db->handle, NULL, NULL);
350 }
351
352 ao2_unlock(db);
353
354 return 0;
355}
356
357static void db_sync(struct realtime_sqlite3_db *db)
358{
359 db->wakeup = 1;
360 ast_cond_signal(&db->cond);
361}
362
364{
365 if (db->batch) {
366 ast_cond_init(&db->cond, NULL);
367 ao2_ref(db, +1);
368 db->has_batch_thread = !ast_pthread_create_background(&db->syncthread, NULL, db_sync_thread, db);
369 }
370}
371
373{
374 if (db->has_batch_thread) {
375 db->has_batch_thread = 0;
376 db->exiting = 1;
377 db_sync(db);
378 pthread_join(db->syncthread, NULL);
379 }
380}
381
382/*! \brief Create a db object based on a config category
383 * \note Opening the db handle and linking to databases must be handled outside of this function
384 */
385static struct realtime_sqlite3_db *new_realtime_sqlite3_db(struct ast_config *config, const char *cat)
386{
387 struct ast_variable *var;
388 struct realtime_sqlite3_db *db;
389
390 if (!(db = ao2_alloc(sizeof(*db), db_destructor))) {
391 return NULL;
392 }
393
394 if (ast_string_field_init(db, 64)) {
395 unref_db(&db);
396 return NULL;
397 }
398
399 /* Set defaults */
400 db->requirements = REALTIME_SQLITE3_REQ_WARN;
401 db->batch = 100;
403 db->busy_timeout = 1000;
404
405 for (var = ast_variable_browse(config, cat); var; var = var->next) {
406 if (!strcasecmp(var->name, "dbfile")) {
408 } else if (!strcasecmp(var->name, "requirements")) {
409 db->requirements = str_to_requirements(var->value);
410 } else if (!strcasecmp(var->name, "batch")) {
411 ast_app_parse_timelen(var->value, (int *) &db->batch, TIMELEN_MILLISECONDS);
412 } else if (!strcasecmp(var->name, "debug")) {
413 db->debug = ast_true(var->value);
414 } else if (!strcasecmp(var->name, "busy_timeout")) {
415 if (ast_parse_arg(var->value, PARSE_INT32|PARSE_DEFAULT, &(db->busy_timeout), 1000) != 0) {
416 ast_log(LOG_WARNING, "Invalid busy_timeout value '%s' at res_config_sqlite3.conf:%d. Using 1000 instead.\n", var->value, var->lineno);
417 }
418 }
419 }
420
421 if (ast_strlen_zero(db->filename)) {
422 ast_log(LOG_WARNING, "Must specify dbfile in res_config_sqlite3.conf\n");
423 unref_db(&db);
424 return NULL;
425 }
426
427 return db;
428}
429
430/*! \brief Update an existing db object based on config data
431 * \param db The database object to update
432 * \param config The configuration data with which to update the db
433 * \param cat The config category (which becomes db->name)
434 */
435static int update_realtime_sqlite3_db(struct realtime_sqlite3_db *db, struct ast_config *config, const char *cat)
436{
437 struct realtime_sqlite3_db *new;
438
439 if (!(new = new_realtime_sqlite3_db(config, cat))) {
440 return -1;
441 }
442
443 /* Copy fields that don't need anything special done on change */
444 db->requirements = new->requirements;
445
446 /* Handle changes that require immediate behavior modification */
447 if (db->debug != new->debug) {
448 if (db->debug) {
449 sqlite3_trace(db->handle, NULL, NULL);
450 } else {
451 sqlite3_trace(db->handle, trace_cb, db);
452 }
453 db->debug = new->debug;
454 }
455
456 if (strcmp(db->filename, new->filename)) {
457 sqlite3_close(db->handle);
458 ast_string_field_set(db, filename, new->filename);
459 db_open(db); /* Also handles setting appropriate debug on new handle */
460 }
461
462 if (db->busy_timeout != new->busy_timeout) {
463 db->busy_timeout = new->busy_timeout;
464 sqlite3_busy_timeout(db->handle, db->busy_timeout);
465 }
466
467 if (db->batch != new->batch) {
468 if (db->batch == 0) {
469 db->batch = new->batch;
471 } else if (new->batch == 0) {
472 db->batch = new->batch;
474 }
475 db->batch = new->batch;
476 }
477
478 db->dirty = 0;
479 unref_db(&new);
480
481 return 0;
482}
483
484/*! \brief Create a varlist from a single sqlite3 result row */
485static int row_to_varlist(void *arg, int num_columns, char **values, char **columns)
486{
487 struct ast_variable **head = arg, *tail;
488 int i;
489 struct ast_variable *new;
490
491 if (!(new = ast_variable_new(columns[0], S_OR(values[0], ""), ""))) {
492 return SQLITE_ABORT;
493 }
494 *head = tail = new;
495
496 for (i = 1; i < num_columns; i++) {
497 if (!(new = ast_variable_new(columns[i], S_OR(values[i], ""), ""))) {
499 *head = NULL;
500 return SQLITE_ABORT;
501 }
502 tail->next = new;
503 tail = new;
504 }
505
506 return 0;
507}
508
509/*! \brief Callback for creating an ast_config from a successive sqlite3 result rows */
510static int append_row_to_cfg(void *arg, int num_columns, char **values, char **columns)
511{
512 struct ast_config *cfg = arg;
513 struct ast_category *cat;
514 int i;
515
517 if (!cat) {
518 return SQLITE_ABORT;
519 }
520
521 for (i = 0; i < num_columns; i++) {
522 struct ast_variable *var;
523 if (!(var = ast_variable_new(columns[i], S_OR(values[i], ""), ""))) {
524 ast_log(LOG_ERROR, "Could not create new variable for '%s: %s', throwing away list\n", columns[i], values[i]);
525 continue;
526 }
528 }
529 ast_category_append(cfg, cat);
530
531 return 0;
532}
533
534/*!
535 * Structure sent to the SQLite 3 callback function for static configuration.
536 *
537 * \see static_realtime_cb()
538 */
542 char *cat_name;
544 const char *who_asked;
545};
546
547/*!
548 * Structure passed to row counting SQLite callback.
549 */
554};
555
556/*!
557 * \internal
558 * \brief SQLite3 callback that counts rows of a result set.
559 *
560 * \details
561 * This is used to decorate existing callbacks so that we can count the number
562 * of rows returned from a SELECT statement and still process each row
563 * independently.
564 *
565 * \param arg user data pointer passed in via sqlite3_exec()
566 * \param num_columns number of columns in the result
567 * \param values array of pointers to column values
568 * \param columns array of pointers of to column names
569 *
570 * \return the return value of the wrapped callback, or 0 if no wrapped callback
571 * is provided.
572 */
573static int row_counter_wrapper(void *arg, int num_columns, char **values, char **columns)
574{
575 struct row_counter_args *wrapped = arg;
576 wrapped->row_count++;
577 if (wrapped->wrapped_callback) {
578 return wrapped->wrapped_callback(wrapped->wrapped_arg, num_columns, values, columns);
579 }
580 return 0;
581}
582
583/*!
584 * \internal
585 * \brief Execute a SQL SELECT statement using a database handle
586 *
587 * \param db the database handle to use for the query
588 * \param sql the SQL statement to execute
589 * \param callback a user defined callback that will be called for each row of
590 * the result set
591 * \param arg data to be passed to the user defined callback
592 *
593 * \return if successful, the number of rows returned from the provided SELECT
594 * statement. -1 on failure.
595 */
596static int realtime_sqlite3_exec_query_with_handle(struct realtime_sqlite3_db *db, const char *sql, callback_t callback, void *arg)
597{
598 int res = 0;
599 char *errmsg;
600 struct row_counter_args wrapper = {
601 .wrapped_callback = callback,
602 .wrapped_arg = arg,
603 .row_count = 0,
604 };
605
606 ao2_lock(db);
607 if (sqlite3_exec(db->handle, sql, row_counter_wrapper, &wrapper, &errmsg) != SQLITE_OK) {
608 ast_log(LOG_WARNING, "Could not execute '%s': %s\n", sql, errmsg);
609 sqlite3_free(errmsg);
610 res = -1;
611 }
612 ao2_unlock(db);
613
614 return res == 0 ? wrapper.row_count : res;
615}
616
617/*!
618 * \internal
619 * \brief Execute a SQL SELECT statement on the specified database
620 *
621 * \param database the name of the database to query
622 * \param sql the SQL statement to execute
623 * \param callback a user defined callback that will be called for each row of
624 * the result set
625 * \param arg data to be passed to the user defined callback
626 *
627 * \return if successful, the number of rows returned from the provided SELECT
628 * statement. -1 on failure.
629 */
630static int realtime_sqlite3_exec_query(const char *database, const char *sql, callback_t callback, void *arg)
631{
632 struct realtime_sqlite3_db *db;
633 int res;
634
635 if (!(db = find_database(database))) {
636 ast_log(LOG_WARNING, "Could not find database: %s\n", database);
637 return -1;
638 }
639
640 res = realtime_sqlite3_exec_query_with_handle(db, sql, callback, arg);
641 ao2_ref(db, -1);
642
643 return res;
644}
645
646/*!
647 * \internal
648 * \brief Execute a SQL INSERT/UPDATE/DELETE statement using a database handle
649 *
650 * \note A database sync operation is always performed after a statement
651 * is executed.
652 *
653 * \param db the database handle to use for the query
654 * \param sql the SQL statement to execute
655 *
656 * \return if successful, the number of rows modified by the provided SQL
657 * statement. -1 on failure.
658 */
660{
661 int res = 0;
662 char *errmsg;
663
664 ao2_lock(db);
665 if (sqlite3_exec(db->handle, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
666 ast_log(LOG_WARNING, "Could not execute '%s': %s\n", sql, errmsg);
667 sqlite3_free(errmsg);
668 res = -1;
669 } else {
670 res = sqlite3_changes(db->handle);
671 }
672 ao2_unlock(db);
673
674 db_sync(db);
675
676 return res;
677}
678
679/*!
680 * \internal
681 * \brief Execute a SQL INSERT/UPDATE/DELETE statement using a database handle
682 *
683 * \note A database sync operation is always performed after a statement
684 * is executed.
685 *
686 * \param database the name of the database to query
687 * \param sql the SQL statement to execute
688 *
689 * \return if successful, the number of rows modified by the provided SQL
690 * statement. -1 on failure.
691 */
692static int realtime_sqlite3_exec_update(const char *database, const char *sql)
693{
694 struct realtime_sqlite3_db *db;
695 int res;
696
697 if (!(db = find_database(database))) {
698 ast_log(LOG_WARNING, "Could not find database: %s\n", database);
699 return -1;
700 }
701
703 ao2_ref(db, -1);
704
705 return res;
706}
707
708/*! \note It is important that the COL_* enum matches the order of the columns selected in static_sql */
709static const char *static_sql = "SELECT category, var_name, var_val FROM \"%q\" WHERE filename = %Q AND commented = 0 ORDER BY cat_metric ASC, var_metric ASC";
710enum {
715};
716
717static int static_realtime_cb(void *arg, int num_columns, char **values, char **columns)
718{
719 struct cfg_entry_args *args = arg;
720 struct ast_variable *var;
721
722 if (!strcmp(values[COL_VAR_NAME], "#include")) {
723 struct ast_config *cfg;
724 char *val;
725
727 if (!(cfg = ast_config_internal_load(val, args->cfg, args->flags, "", args->who_asked))) {
728 ast_log(LOG_WARNING, "Unable to include %s\n", val);
729 return SQLITE_ABORT;
730 } else {
731 args->cfg = cfg;
732 return 0;
733 }
734 }
735
736 if (!args->cat_name || strcmp(args->cat_name, values[COL_CATEGORY])) {
738 if (!args->cat) {
739 return SQLITE_ABORT;
740 }
741
742 ast_free(args->cat_name);
743
744 if (!(args->cat_name = ast_strdup(values[COL_CATEGORY]))) {
746 return SQLITE_ABORT;
747 }
748
749 ast_category_append(args->cfg, args->cat);
750 }
751
753 ast_log(LOG_WARNING, "Unable to allocate variable\n");
754 return SQLITE_ABORT;
755 }
756
758
759 return 0;
760}
761
762/*! \brief Realtime callback for static realtime
763 * \return ast_config on success, NULL on failure
764 */
765static struct ast_config *realtime_sqlite3_load(const char *database, const char *table, const char *configfile, struct ast_config *config, struct ast_flags flags, const char *suggested_include_file, const char *who_asked)
766{
767 char *sql;
768 struct cfg_entry_args args;
769
770 if (ast_strlen_zero(table)) {
771 ast_log(LOG_WARNING, "Must have a table to query!\n");
772 return NULL;
773 }
774
775 if (!(sql = sqlite3_mprintf(static_sql, table, configfile))) {
776 ast_log(LOG_WARNING, "Couldn't allocate query\n");
777 return NULL;
778 };
779
780 args.cfg = config;
781 args.cat = NULL;
782 args.cat_name = NULL;
783 args.flags = flags;
784 args.who_asked = who_asked;
785
787
788 sqlite3_free(sql);
789
790 return config;
791}
792
793#define IS_SQL_LIKE_CLAUSE(x) ((x) && ast_ends_with(x, " LIKE"))
794
795/*! \brief Helper function for single and multi-row realtime load functions */
796static int realtime_sqlite3_helper(const char *database, const char *table, const struct ast_variable *fields, int is_multi, void *arg)
797{
798 struct ast_str *sql;
799 const struct ast_variable *field;
800 int first = 1;
801
802 if (ast_strlen_zero(table)) {
803 ast_log(LOG_WARNING, "Must have a table to query!\n");
804 return -1;
805 }
806
807 if (!(sql = ast_str_create(128))) {
808 return -1;
809 }
810
811 for (field = fields; field; field = field->next) {
812 if (first) {
813 ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s %s", sqlite3_escape_table(table),
815 first = 0;
816 } else {
817 ast_str_append(&sql, 0, " AND %s %s", sqlite3_escape_column_op(field->name),
819 }
820
822 /*
823 * The realtime framework is going to pre-escape these
824 * for us with a backslash. We just need to make sure
825 * to tell SQLite about it
826 */
827 ast_str_append(&sql, 0, " ESCAPE '\\'");
828 }
829 }
830
831 if (!is_multi) {
832 ast_str_append(&sql, 0, "%s", " LIMIT 1");
833 }
834
835 if (realtime_sqlite3_exec_query(database, ast_str_buffer(sql), is_multi ? append_row_to_cfg : row_to_varlist, arg) < 0) {
836 ast_free(sql);
837 return -1;
838 }
839
840 ast_free(sql);
841
842 return 0;
843}
844
845/*! \brief Realtime callback for a single row query
846 * \return ast_variable list for single result on success, NULL on empty/failure
847 */
848static struct ast_variable *realtime_sqlite3(const char *database, const char *table, const struct ast_variable *fields)
849{
850 struct ast_variable *result_row = NULL;
851
852 realtime_sqlite3_helper(database, table, fields, 0, &result_row);
853
854 return result_row;
855}
856
857/*! \brief Realtime callback for a multi-row query
858 * \return ast_config containing possibly many results on success, NULL on empty/failure
859 */
860static struct ast_config *realtime_sqlite3_multi(const char *database, const char *table, const struct ast_variable *fields)
861{
862 struct ast_config *cfg;
863
864 if (!(cfg = ast_config_new())) {
865 return NULL;
866 }
867
868 if (realtime_sqlite3_helper(database, table, fields, 1, cfg)) {
870 return NULL;
871 }
872
873 return cfg;
874}
875
876/*! \brief Realtime callback for updating a row based on a single criteria
877 * \return Number of rows affected or -1 on error
878 */
879static int realtime_sqlite3_update(const char *database, const char *table, const char *keyfield, const char *entity, const struct ast_variable *fields)
880{
881 struct ast_str *sql;
882 const struct ast_variable *field;
883 int first = 1, res;
884
885 if (ast_strlen_zero(table)) {
886 ast_log(LOG_WARNING, "Must have a table to query!\n");
887 return -1;
888 }
889
890 if (!(sql = ast_str_create(128))) {
891 return -1;
892 }
893
894 for (field = fields; field; field = field->next) {
895 if (first) {
896 ast_str_set(&sql, 0, "UPDATE %s SET %s = %s",
898 first = 0;
899 } else {
900 ast_str_append(&sql, 0, ", %s = %s", sqlite3_escape_column(field->name), sqlite3_escape_value(field->value));
901 }
902 }
903
904 ast_str_append(&sql, 0, " WHERE %s %s", sqlite3_escape_column_op(keyfield), sqlite3_escape_value(entity));
905
906 res = realtime_sqlite3_exec_update(database, ast_str_buffer(sql));
907 ast_free(sql);
908
909 return res;
910}
911
912/*! \brief Realtime callback for updating a row based on multiple criteria
913 * \return Number of rows affected or -1 on error
914 */
915static int realtime_sqlite3_update2(const char *database, const char *table, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)
916{
917 struct ast_str *sql;
918 struct ast_str *where_clause;
919 const struct ast_variable *field;
920 int first = 1, res;
921
922 if (ast_strlen_zero(table)) {
923 ast_log(LOG_WARNING, "Must have a table to query!\n");
924 return -1;
925 }
926
927 if (!(sql = ast_str_create(128))) {
928 return -1;
929 }
930
931 if (!(where_clause = ast_str_create(128))) {
932 ast_free(sql);
933 return -1;
934 }
935
936 for (field = lookup_fields; field; field = field->next) {
937 if (first) {
938 ast_str_set(&where_clause, 0, " WHERE %s %s", sqlite3_escape_column_op(field->name), sqlite3_escape_value(field->value));
939 first = 0;
940 } else {
941 ast_str_append(&where_clause, 0, " AND %s %s", sqlite3_escape_column_op(field->name), sqlite3_escape_value(field->value));
942 }
943 }
944
945 first = 1;
946 for (field = update_fields; field; field = field->next) {
947 if (first) {
948 ast_str_set(&sql, 0, "UPDATE %s SET %s = %s", sqlite3_escape_table(table), sqlite3_escape_column(field->name), sqlite3_escape_value(field->value));
949 first = 0;
950 } else {
951 ast_str_append(&sql, 0, ", %s = %s", sqlite3_escape_column(field->name), sqlite3_escape_value(field->value));
952 }
953 }
954
955 ast_str_append(&sql, 0, "%s", ast_str_buffer(where_clause));
956
957 res = realtime_sqlite3_exec_update(database, ast_str_buffer(sql));
958
959 ast_free(sql);
960 ast_free(where_clause);
961
962 return res;
963}
964
965/*! \brief Realtime callback for inserting a row
966 * \return Number of rows affected or -1 on error
967 */
968static int realtime_sqlite3_store(const char *database, const char *table, const struct ast_variable *fields)
969{
970 struct ast_str *sql, *values;
971 const struct ast_variable *field;
972 int first = 1, res;
973
974 if (ast_strlen_zero(table)) {
975 ast_log(LOG_WARNING, "Must have a table to query!\n");
976 return -1;
977 }
978
979 if (!(sql = ast_str_create(128))) {
980 return -1;
981 }
982
983 if (!(values = ast_str_create(128))) {
984 ast_free(sql);
985 return -1;
986 }
987
988 for (field = fields; field; field = field->next) {
989 if (first) {
990 ast_str_set(&sql, 0, "INSERT INTO %s (%s", sqlite3_escape_table(table), sqlite3_escape_column(field->name));
991 ast_str_set(&values, 0, ") VALUES (%s", sqlite3_escape_value(field->value));
992 first = 0;
993 } else {
994 ast_str_append(&sql, 0, ", %s", sqlite3_escape_column(field->name));
995 ast_str_append(&values, 0, ", %s", sqlite3_escape_value(field->value));
996 }
997 }
998
999 ast_str_append(&sql, 0, "%s)", ast_str_buffer(values));
1000
1001 res = realtime_sqlite3_exec_update(database, ast_str_buffer(sql));
1002
1003 ast_free(sql);
1005
1006 return res;
1007}
1008
1009/*! \brief Realtime callback for deleting a row
1010 * \return Number of rows affected or -1 on error
1011 */
1012static int realtime_sqlite3_destroy(const char *database, const char *table, const char *keyfield, const char *entity, const struct ast_variable *fields)
1013{
1014 struct ast_str *sql;
1015 const struct ast_variable *field;
1016 int first = 1, res;
1017
1018 if (ast_strlen_zero(table)) {
1019 ast_log(LOG_WARNING, "Must have a table to query!\n");
1020 return -1;
1021 }
1022
1023 if (!(sql = ast_str_create(128))) {
1024 return -1;
1025 }
1026
1027 for (field = fields; field; field = field->next) {
1028 if (first) {
1029 ast_str_set(&sql, 0, "DELETE FROM %s WHERE %s %s", sqlite3_escape_table(table),
1031 first = 0;
1032 } else {
1033 ast_str_append(&sql, 0, " AND %s %s", sqlite3_escape_column_op(field->name), sqlite3_escape_value(field->value));
1034 }
1035 }
1036
1037 res = realtime_sqlite3_exec_update(database, ast_str_buffer(sql));
1038
1039 ast_free(sql);
1040
1041 return res;
1042}
1043
1044/*! \brief Convert Asterisk realtime types to SQLite 3 types
1045 * \note SQLite 3 has NULL, INTEGER, REAL, TEXT, and BLOB types. Any column other than
1046 * an INTEGER PRIMARY KEY will actually store any kind of data due to its dynamic
1047 * typing. When we create columns, we'll go ahead and use these base types instead
1048 * of messing with column widths, etc. */
1049
1050static const char *get_sqlite_column_type(int type)
1051{
1052 switch(type) {
1053 case RQ_INTEGER1 :
1054 case RQ_UINTEGER1 :
1055 case RQ_INTEGER2 :
1056 case RQ_UINTEGER2 :
1057 case RQ_INTEGER3 :
1058 case RQ_UINTEGER3 :
1059 case RQ_INTEGER4 :
1060 case RQ_UINTEGER4 :
1061 case RQ_INTEGER8 :
1062 return "INTEGER";
1063 case RQ_UINTEGER8 : /* SQLite3 stores INTEGER as signed 8-byte */
1064 case RQ_CHAR :
1065 case RQ_DATE :
1066 case RQ_DATETIME :
1067 return "TEXT";
1068 case RQ_FLOAT :
1069 return "REAL";
1070 default :
1071 return "TEXT";
1072 }
1073
1074 return "TEXT";
1075}
1076
1077/*! \brief Create a table if ast_realtime_require shows that we are configured to handle the data
1078 */
1079static int handle_missing_table(struct realtime_sqlite3_db *db, const char *table, va_list ap)
1080{
1081 const char *column;
1082 int type, first = 1, res;
1083 size_t sz;
1084 struct ast_str *sql;
1085
1086 if (!(sql = ast_str_create(128))) {
1087 return -1;
1088 }
1089
1090 while ((column = va_arg(ap, typeof(column)))) {
1091 type = va_arg(ap, typeof(type));
1092 sz = va_arg(ap, typeof(sz));
1093 if (first) {
1094 ast_str_set(&sql, 0, "CREATE TABLE IF NOT EXISTS %s (%s %s", sqlite3_escape_table(table),
1096 first = 0;
1097 } else {
1098 ast_str_append(&sql, 0, ", %s %s", sqlite3_escape_column(column), get_sqlite_column_type(type));
1099 }
1100 }
1101
1102 ast_str_append(&sql, 0, ")");
1103
1105 ast_free(sql);
1106
1107 return res;
1108}
1109
1110/*! \brief If ast_realtime_require sends info about a column we don't have, create it
1111 */
1112static int handle_missing_column(struct realtime_sqlite3_db *db, const char *table, const char *column, int type, size_t sz)
1113{
1114 char *sql;
1115 const char *sqltype = get_sqlite_column_type(type);
1116 int res;
1117
1118 if (db->requirements == REALTIME_SQLITE3_REQ_WARN) {
1119 ast_log(LOG_WARNING, "Missing column '%s' of type '%s' in %s.%s\n", column, sqltype, db->name, table);
1120 return -1;
1121 } else if (db->requirements == REALTIME_SQLITE3_REQ_CHAR) {
1122 sqltype = "TEXT";
1123 }
1124
1125 if (!(sql = sqlite3_mprintf("ALTER TABLE \"%q\" ADD COLUMN \"%q\" %s", table, column, sqltype))) {
1126 return -1;
1127 }
1128
1129 if (!(res = (realtime_sqlite3_exec_update_with_handle(db, sql) < 0 ? -1 : 0))) {
1130 ast_log(LOG_NOTICE, "Creating column '%s' type %s for table %s\n", column, sqltype, table);
1131 }
1132
1133 sqlite3_free(sql);
1134
1135 return res;
1136}
1137
1138static int str_hash_fn(const void *obj, const int flags)
1139{
1140 return ast_str_hash((const char *) obj);
1141}
1142
1143static int str_cmp_fn(void *obj, void *arg, int flags) {
1144 return !strcasecmp((const char *) obj, (const char *) arg);
1145}
1146
1147/*! \brief Callback for creating a hash of column names for comparison in realtime_sqlite3_require
1148 */
1149static int add_column_name(void *arg, int num_columns, char **values, char **columns)
1150{
1151 char *column;
1152 struct ao2_container *cnames = arg;
1153
1154
1155 if (!(column = ao2_alloc(strlen(values[1]) + 1, NULL))) {
1156 return -1;
1157 }
1158
1159 strcpy(column, values[1]);
1160
1161 ao2_link(cnames, column);
1162 ao2_ref(column, -1);
1163
1164 return 0;
1165}
1166
1167/*! \brief Callback for ast_realtime_require
1168 * \retval 0 Required fields met specified standards
1169 * \retval -1 One or more fields was missing or insufficient
1170 */
1171static int realtime_sqlite3_require(const char *database, const char *table, va_list ap)
1172{
1173 const char *column;
1174 char *sql;
1175 int type;
1176 int res;
1177 size_t sz;
1178 struct ao2_container *columns;
1179 struct realtime_sqlite3_db *db;
1180
1181 /* SQLite3 columns are dynamically typed, with type affinity. Built-in functions will
1182 * return the results as char * anyway. The only field that cannot contain text
1183 * data is an INTEGER PRIMARY KEY, which must be a 64-bit signed integer. So, for
1184 * the purposes here we really only care whether the column exists and not what its
1185 * type or length is. */
1186
1187 if (ast_strlen_zero(table)) {
1188 ast_log(LOG_WARNING, "Must have a table to query!\n");
1189 return -1;
1190 }
1191
1192 if (!(db = find_database(database))) {
1193 return -1;
1194 }
1195
1198 if (!columns) {
1199 unref_db(&db);
1200 return -1;
1201 }
1202
1203 if (!(sql = sqlite3_mprintf("PRAGMA table_info(\"%q\")", table))) {
1204 unref_db(&db);
1205 ao2_ref(columns, -1);
1206 return -1;
1207 }
1208
1210 unref_db(&db);
1211 ao2_ref(columns, -1);
1212 sqlite3_free(sql);
1213 return -1;
1214 } else if (res == 0) {
1215 /* Table does not exist */
1216 sqlite3_free(sql);
1217 res = handle_missing_table(db, table, ap);
1218 ao2_ref(columns, -1);
1219 unref_db(&db);
1220 return res;
1221 }
1222
1223 sqlite3_free(sql);
1224
1225 while ((column = va_arg(ap, typeof(column)))) {
1226 char *found;
1227 type = va_arg(ap, typeof(type));
1228 sz = va_arg(ap, typeof(sz));
1229 if (!(found = ao2_find(columns, column, OBJ_POINTER | OBJ_UNLINK))) {
1230 if (handle_missing_column(db, table, column, type, sz)) {
1231 unref_db(&db);
1232 ao2_ref(columns, -1);
1233 return -1;
1234 }
1235 } else {
1236 ao2_ref(found, -1);
1237 }
1238 }
1239
1240 ao2_ref(columns, -1);
1241 unref_db(&db);
1242
1243 return 0;
1244}
1245
1246/*! \brief Callback for clearing any cached info
1247 * \note We don't currently cache anything
1248 * \retval 0 If any cache was purged
1249 * \retval -1 If no cache was found
1250 */
1251static int realtime_sqlite3_unload(const char *database, const char *table)
1252{
1253 /* We currently do no caching */
1254 return -1;
1255}
1256
1257/*! \brief Parse the res_config_sqlite3 config file
1258 */
1259static int parse_config(int reload)
1260{
1261 struct ast_config *config;
1262 struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME | (reload ? CONFIG_FLAG_FILEUNCHANGED : 0) };
1263 static const char *config_filename = "res_config_sqlite3.conf";
1264
1265 config = ast_config_load(config_filename, config_flags);
1266
1268 ast_debug(1, "%s was unchanged, skipping parsing\n", config_filename);
1269 return 0;
1270 }
1271
1273
1275 ast_log(LOG_ERROR, "%s config file '%s'\n",
1276 config == CONFIG_STATUS_FILEMISSING ? "Missing" : "Invalid", config_filename);
1278 return 0;
1279 } else {
1280 const char *cat;
1281 struct realtime_sqlite3_db *db;
1282
1284 for (cat = ast_category_browse(config, NULL); cat; cat = ast_category_browse(config, cat)) {
1285 if (!strcasecmp(cat, "general")) {
1286 continue;
1287 }
1288 if (!(db = find_database(cat))) {
1289 if (!(db = new_realtime_sqlite3_db(config, cat))) {
1290 ast_log(LOG_WARNING, "Could not allocate new db for '%s' - skipping.\n", cat);
1291 continue;
1292 }
1293 if (db_open(db)) {
1294 unref_db(&db);
1295 continue;
1296 }
1299 unref_db(&db);
1300 } else {
1302 unref_db(&db);
1303 continue;
1304 }
1305 unref_db(&db);
1306 }
1307 }
1309 }
1310
1312
1314
1315 return 0;
1316}
1317
1318static int reload(void)
1319{
1320 parse_config(1);
1321 return 0;
1322}
1323
1324static int unload_module(void)
1325{
1328 ao2_ref(databases, -1);
1329 databases = NULL;
1332
1333 return 0;
1334}
1335
1336static void discover_sqlite3_caps(void)
1337{
1338 /*
1339 * So we cheat a little bit here. SQLite3 added support for the
1340 * 'ESCAPE' keyword in 3.1.0. They added SQLITE_VERSION_NUMBER
1341 * in 3.1.2. So if we run into 3.1.0 or 3.1.1 in the wild, we
1342 * just treat it like < 3.1.0.
1343 *
1344 * For reference: 3.1.0, 3.1.1, and 3.1.2 were all released
1345 * within 30 days of each other in Jan/Feb 2005, so I don't
1346 * imagine we'll be finding something pre-3.1.2 that often in
1347 * practice.
1348 */
1349#if defined(SQLITE_VERSION_NUMBER)
1351#else
1353#endif
1354
1355 ast_debug(3, "SQLite3 has 'LIKE ... ESCAPE ...' support? %s\n",
1356 has_explicit_like_escaping ? "Yes" : "No");
1357}
1358
1359/*!
1360 * \brief Load the module
1361 *
1362 * Module loading including tests for configuration or dependencies.
1363 * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
1364 * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
1365 * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
1366 * configuration file or other non-critical problem return
1367 * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
1368 */
1369static int load_module(void)
1370{
1372
1375 if (!databases) {
1377 }
1378
1379 if (parse_config(0)) {
1380 ao2_ref(databases, -1);
1382 }
1383
1385 ast_log(LOG_ERROR, "The config API must have changed, this shouldn't happen.\n");
1386 ao2_ref(databases, -1);
1388 }
1389
1391}
1392
1393AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SQLite 3 realtime config engine",
1394 .support_level = AST_MODULE_SUPPORT_CORE,
1395 .load = load_module,
1396 .unload = unload_module,
1397 .reload = reload,
1398 .load_pri = AST_MODPRI_REALTIME_DRIVER,
1399 .requires = "extconfig",
struct sla_ringing_trunk * first
Definition: app_sla.c:332
#define var
Definition: ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_log
Definition: astobj2.c:42
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
#define OBJ_KEY
Definition: astobj2.h:1151
#define OBJ_POINTER
Definition: astobj2.h:1150
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
@ OBJ_UNLINK
Definition: astobj2.h:1039
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
static int tmp()
Definition: bt_open.c:389
static char * table
Definition: cdr_odbc.c:55
static char * columns
static sqlite3 * db
static const char type[]
Definition: chan_ooh323.c:109
static const char config[]
Definition: chan_ooh323.c:111
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static char * config_filename
Definition: extconf.c:2120
static const char name[]
Definition: format_mp3.c:68
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
int ast_app_parse_timelen(const char *timestr, int *result, enum ast_timelen defunit)
Common routine to parse time lengths, with optional time unit specifier.
Definition: main/app.c:3263
@ TIMELEN_MILLISECONDS
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
#define CONFIG_STATUS_FILEMISSING
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3274
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
Definition: extconf.c:2833
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1177
#define ast_category_new_anonymous()
Create a nameless category that is not backed by a file.
#define ast_variable_new(name, value, filename)
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.
Definition: main/config.c:3173
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *p_result,...)
The argument parsing routine.
Definition: main/config.c:3827
void ast_category_destroy(struct ast_category *cat)
Definition: extconf.c:2845
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
struct ast_config * ast_config_internal_load(const char *configfile, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl_file, const char *who_asked)
Definition: main/config.c:3279
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
#define ast_category_new_dynamic(name)
Create a category that is not backed by a file.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
int ast_config_engine_register(struct ast_config_engine *newconfig)
Register config engine.
Definition: main/config.c:3157
@ CONFIG_FLAG_NOREALTIME
@ CONFIG_FLAG_FILEUNCHANGED
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
Asterisk locking-related definitions:
#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
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:317
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODPRI_REALTIME_DRIVER
Definition: module.h:323
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
Asterisk file paths, configured in asterisk.conf.
static int realtime_sqlite3_exec_query(const char *, const char *, callback_t, void *)
static int handle_missing_column(struct realtime_sqlite3_db *db, const char *table, const char *column, int type, size_t sz)
If ast_realtime_require sends info about a column we don't have, create it.
static int db_cmp_fn(void *obj, void *arg, int flags)
static int parse_config(int reload)
Parse the res_config_sqlite3 config file.
static int is_dirty_cb(void *obj, void *arg, int flags)
static struct ast_threadstorage escape_table_buf
static int add_column_name(void *arg, int num_columns, char **values, char **columns)
Callback for creating a hash of column names for comparison in realtime_sqlite3_require.
static struct ast_variable * realtime_sqlite3(const char *database, const char *table, const struct ast_variable *fields)
Realtime callback for a single row query.
static int realtime_sqlite3_exec_query_with_handle(struct realtime_sqlite3_db *, const char *, callback_t, void *)
static const char * sqlite3_escape_table(const char *param)
static int stop_batch_cb(void *obj, void *arg, int flags)
static int append_row_to_cfg(void *arg, int num_columns, char **values, char **columns)
Callback for creating an ast_config from a successive sqlite3 result rows.
static int realtime_sqlite3_unload(const char *database, const char *table)
Callback for clearing any cached info.
static int row_to_varlist(void *arg, int num_columns, char **values, char **columns)
Create a varlist from a single sqlite3 result row.
static int realtime_sqlite3_store(const char *database, const char *table, const struct ast_variable *fields)
Realtime callback for inserting a row.
int(* callback_t)(void *, int, char **, char **)
static int db_hash_fn(const void *obj, const int flags)
#define DB_BUCKETS
static int handle_missing_table(struct realtime_sqlite3_db *db, const char *table, va_list ap)
Create a table if ast_realtime_require shows that we are configured to handle the data.
static void unref_db(struct realtime_sqlite3_db **db)
static ast_mutex_t config_lock
static const char * sqlite3_escape_string_helper(struct ast_threadstorage *ts, const char *param)
static int realtime_sqlite3_update(const char *database, const char *table, const char *keyfield, const char *entity, const struct ast_variable *fields)
Realtime callback for updating a row based on a single criteria.
static int realtime_sqlite3_helper(const char *database, const char *table, const struct ast_variable *fields, int is_multi, void *arg)
Helper function for single and multi-row realtime load functions.
static int realtime_sqlite3_destroy(const char *database, const char *table, const char *keyfield, const char *entity, const struct ast_variable *fields)
Realtime callback for deleting a row.
static int update_realtime_sqlite3_db(struct realtime_sqlite3_db *db, struct ast_config *config, const char *cat)
Update an existing db object based on config data.
static int realtime_sqlite3_exec_update(const char *, const char *)
#define IS_SQL_LIKE_CLAUSE(x)
void db_stop_batch(struct realtime_sqlite3_db *db)
static const char * sqlite3_escape_value(const char *param)
static struct ast_config * realtime_sqlite3_multi(const char *database, const char *table, const struct ast_variable *fields)
Realtime callback for a multi-row query.
static int static_realtime_cb(void *arg, int num_columns, char **values, char **columns)
static const char * get_sqlite_column_type(int type)
Convert Asterisk realtime types to SQLite 3 types.
static struct realtime_sqlite3_db * new_realtime_sqlite3_db(struct ast_config *config, const char *cat)
Create a db object based on a config category.
static const char * static_sql
static int str_hash_fn(const void *obj, const int flags)
static int realtime_sqlite3_update2(const char *database, const char *table, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)
Realtime callback for updating a row based on multiple criteria.
static void trace_cb(void *arg, const char *sql)
static void db_destructor(void *obj)
static void * db_sync_thread(void *data)
Wrap commands in transactions increased write performance.
static int mark_dirty_cb(void *obj, void *arg, int flags)
static int realtime_sqlite3_exec_update_with_handle(struct realtime_sqlite3_db *, const char *)
static void db_sync(struct realtime_sqlite3_db *db)
static struct realtime_sqlite3_db * find_database(const char *database)
static struct ast_config * realtime_sqlite3_load(const char *database, const char *table, const char *configfile, struct ast_config *config, struct ast_flags flags, const char *suggested_include_file, const char *who_asked)
Realtime callback for static realtime.
static void mark_all_databases_dirty(void)
static int str_to_requirements(const char *data)
static int str_cmp_fn(void *obj, void *arg, int flags)
static int db_open(struct realtime_sqlite3_db *db)
Open a database and appropriately set debugging on the db handle.
static struct ast_threadstorage escape_column_buf
static int row_counter_wrapper(void *arg, int num_columns, char **values, char **columns)
static int load_module(void)
Load the module.
static int has_explicit_like_escaping
static int realtime_sqlite3_require(const char *database, const char *table, va_list ap)
Callback for ast_realtime_require.
static const char * sqlite3_escape_column_op(const char *param)
static int unload_module(void)
static int reload(void)
@ COL_COLUMNS
@ COL_VAR_VAL
@ COL_CATEGORY
@ COL_VAR_NAME
static void unlink_dirty_databases(void)
@ REALTIME_SQLITE3_REQ_WARN
@ REALTIME_SQLITE3_REQ_CLOSE
@ REALTIME_SQLITE3_REQ_CHAR
struct ast_config_engine sqlite3_config_engine
struct ao2_container * databases
static void discover_sqlite3_caps(void)
static const char * sqlite3_escape_column(const char *param)
static struct ast_threadstorage escape_value_buf
void db_start_batch(struct realtime_sqlite3_db *db)
#define NULL
Definition: resample.c:96
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:341
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:303
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#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_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1259
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:693
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
#define ast_str_make_space(buf, new_len)
Definition: strings.h:828
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
Definition: strings.h:703
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:742
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:909
Generic container type.
Configuration engine structure, used to define realtime drivers.
Structure used to handle boolean flags.
Definition: utils.h:199
Support for dynamic strings.
Definition: strings.h:623
data for a thread locally stored variable
Definition: threadstorage.h:58
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
struct ast_config * cfg
const char * who_asked
char * cat_name
struct ast_flags flags
struct ast_category * cat
const ast_string_field filename
const ast_string_field name
unsigned int has_batch_thread
callback_t wrapped_callback
Definition: ast_expr2.c:325
const char * args
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Definition: threadstorage.h:86
typedef typeof(dummy_tv_var_for_types.tv_sec) ast_time_t
Utility functions.
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592