00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "asterisk.h"
00038
00039 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 416337 $")
00040
00041 #include <sqlite3.h>
00042
00043 #include "asterisk/module.h"
00044 #include "asterisk/config.h"
00045 #include "asterisk/paths.h"
00046 #include "asterisk/astobj2.h"
00047 #include "asterisk/lock.h"
00048 #include "asterisk/utils.h"
00049 #include "asterisk/app.h"
00050
00051
00052
00053
00054 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);
00055 static struct ast_variable *realtime_sqlite3(const char *database, const char *table, va_list ap);
00056 static struct ast_config *realtime_sqlite3_multi(const char *database, const char *table, va_list ap);
00057 static int realtime_sqlite3_update(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap);
00058 static int realtime_sqlite3_update2(const char *database, const char *table, va_list ap);
00059 static int realtime_sqlite3_store(const char *database, const char *table, va_list ap);
00060 static int realtime_sqlite3_destroy(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap);
00061 static int realtime_sqlite3_require(const char *database, const char *table, va_list ap);
00062 static int realtime_sqlite3_unload(const char *database, const char *table);
00063
00064 struct ast_config_engine sqlite3_config_engine = {
00065 .name = "sqlite3",
00066 .load_func = realtime_sqlite3_load,
00067 .realtime_func = realtime_sqlite3,
00068 .realtime_multi_func = realtime_sqlite3_multi,
00069 .update_func = realtime_sqlite3_update,
00070 .update2_func = realtime_sqlite3_update2,
00071 .store_func = realtime_sqlite3_store,
00072 .destroy_func = realtime_sqlite3_destroy,
00073 .require_func = realtime_sqlite3_require,
00074 .unload_func = realtime_sqlite3_unload,
00075 };
00076
00077 enum {
00078 REALTIME_SQLITE3_REQ_WARN,
00079 REALTIME_SQLITE3_REQ_CLOSE,
00080 REALTIME_SQLITE3_REQ_CHAR,
00081 };
00082
00083 struct realtime_sqlite3_db {
00084 AST_DECLARE_STRING_FIELDS(
00085 AST_STRING_FIELD(name);
00086 AST_STRING_FIELD(filename);
00087 );
00088 sqlite3 *handle;
00089 pthread_t syncthread;
00090 ast_cond_t cond;
00091 unsigned int requirements:2;
00092 unsigned int dirty:1;
00093 unsigned int debug:1;
00094 unsigned int exiting:1;
00095 unsigned int wakeup:1;
00096 unsigned int batch;
00097 };
00098
00099 struct ao2_container *databases;
00100 #define DB_BUCKETS 7
00101
00102 AST_MUTEX_DEFINE_STATIC(config_lock);
00103
00104
00105 AST_THREADSTORAGE(escape_table_buf);
00106 AST_THREADSTORAGE(escape_column_buf);
00107 AST_THREADSTORAGE(escape_value_buf);
00108
00109 static int realtime_sqlite3_execute_handle(struct realtime_sqlite3_db *db, const char *sql, int (*callback)(void*, int, char **, char **), void *arg, int sync);
00110 void db_start_batch(struct realtime_sqlite3_db *db);
00111 void db_stop_batch(struct realtime_sqlite3_db *db);
00112
00113 static inline const char *sqlite3_escape_string_helper(struct ast_threadstorage *ts, const char *param)
00114 {
00115 size_t maxlen = strlen(param) * 2 + sizeof("\"\"");
00116
00117
00118
00119
00120 struct ast_str *buf = ast_str_thread_get(ts, maxlen);
00121 char *tmp = ast_str_buffer(buf);
00122 char q = ts == &escape_value_buf ? '\'' : '"';
00123
00124 ast_str_reset(buf);
00125 *tmp++ = q;
00126 while ((*tmp++ = *param++)) {
00127
00128 if (*(tmp - 1) == q) {
00129 *tmp++ = q;
00130 }
00131 }
00132 *tmp = '\0';
00133 *(tmp - 1) = q;
00134 ast_str_update(buf);
00135
00136 return ast_str_buffer(buf);
00137 }
00138
00139 static inline const char *sqlite3_escape_table(const char *param)
00140 {
00141 return sqlite3_escape_string_helper(&escape_table_buf, param);
00142 }
00143
00144 static inline const char *sqlite3_escape_column(const char *param)
00145 {
00146 return sqlite3_escape_string_helper(&escape_column_buf, param);
00147 }
00148
00149
00150 static const char *sqlite3_escape_column_op(const char *param)
00151 {
00152 size_t maxlen = strlen(param) * 2 + sizeof("\"\" =");
00153 struct ast_str *buf = ast_str_thread_get(&escape_column_buf, maxlen);
00154 char *tmp = ast_str_buffer(buf);
00155 int space = 0;
00156
00157 ast_str_reset(buf);
00158 *tmp++ = '"';
00159 while ((*tmp++ = *param++)) {
00160
00161
00162
00163 if (space) {
00164 continue;
00165 }
00166 if (*(tmp - 1) == ' ') {
00167 *(tmp - 1) = '"';
00168 *tmp++ = ' ';
00169 space = 1;
00170 } else if (*(tmp - 1) == '"') {
00171 *tmp++ = '"';
00172 }
00173 }
00174 if (!space) {
00175 strcpy(tmp - 1, "\" =");
00176 }
00177
00178 ast_str_update(buf);
00179
00180 return ast_str_buffer(buf);
00181 }
00182
00183 static inline const char *sqlite3_escape_value(const char *param)
00184 {
00185 return sqlite3_escape_string_helper(&escape_value_buf, param);
00186 }
00187
00188 static int db_hash_fn(const void *obj, const int flags)
00189 {
00190 const struct realtime_sqlite3_db *db = obj;
00191
00192 return ast_str_hash(flags & OBJ_KEY ? (const char *) obj : db->name);
00193 }
00194
00195 static int db_cmp_fn(void *obj, void *arg, int flags) {
00196 struct realtime_sqlite3_db *db = obj, *other = arg;
00197 const char *name = arg;
00198
00199 return !strcasecmp(db->name, flags & OBJ_KEY ? name : other->name) ? CMP_MATCH | CMP_STOP : 0;
00200 }
00201
00202 static void db_destructor(void *obj)
00203 {
00204 struct realtime_sqlite3_db *db = obj;
00205
00206 ast_debug(1, "Destroying db: %s\n", db->name);
00207 ast_string_field_free_memory(db);
00208 db_stop_batch(db);
00209 if (db->handle) {
00210 ao2_lock(db);
00211 sqlite3_close(db->handle);
00212 ao2_unlock(db);
00213 }
00214 }
00215
00216 static struct realtime_sqlite3_db *find_database(const char *database)
00217 {
00218 return ao2_find(databases, database, OBJ_KEY);
00219 }
00220
00221 static void unref_db(struct realtime_sqlite3_db **db)
00222 {
00223 ao2_ref(*db, -1);
00224 *db = NULL;
00225 }
00226
00227 static int stop_batch_cb(void *obj, void *arg, int flags)
00228 {
00229 struct realtime_sqlite3_db *db = obj;
00230
00231 db_stop_batch(db);
00232 return CMP_MATCH;
00233 }
00234
00235 static int mark_dirty_cb(void *obj, void *arg, int flags)
00236 {
00237 struct realtime_sqlite3_db *db = obj;
00238 db->dirty = 1;
00239 return CMP_MATCH;
00240 }
00241
00242 static void mark_all_databases_dirty(void)
00243 {
00244 ao2_callback(databases, OBJ_MULTIPLE | OBJ_NODATA, mark_dirty_cb, NULL);
00245 }
00246
00247 static int is_dirty_cb(void *obj, void *arg, int flags)
00248 {
00249 struct realtime_sqlite3_db *db = obj;
00250 if (db->dirty) {
00251 db_stop_batch(db);
00252 return CMP_MATCH;
00253 }
00254 return 0;
00255 }
00256
00257 static void unlink_dirty_databases(void)
00258 {
00259 ao2_callback(databases, OBJ_MULTIPLE | OBJ_NODATA | OBJ_UNLINK, is_dirty_cb, NULL);
00260 }
00261
00262 static int str_to_requirements(const char *data)
00263 {
00264 if (!strcasecmp(data, "createclose")) {
00265 return REALTIME_SQLITE3_REQ_CLOSE;
00266 } else if (!strcasecmp(data, "createchar")) {
00267 return REALTIME_SQLITE3_REQ_CHAR;
00268 }
00269
00270 return REALTIME_SQLITE3_REQ_WARN;
00271 }
00272
00273
00274 static void trace_cb(void *arg, const char *sql)
00275 {
00276 struct realtime_sqlite3_db *db = arg;
00277 ast_debug(3, "DB: %s SQL: %s\n", db->name, sql);
00278 }
00279
00280
00281 static void *db_sync_thread(void *data)
00282 {
00283 struct realtime_sqlite3_db *db = data;
00284 ao2_lock(db);
00285 realtime_sqlite3_execute_handle(db, "BEGIN TRANSACTION", NULL, NULL, 0);
00286 for (;;) {
00287 if (!db->wakeup) {
00288 ast_cond_wait(&db->cond, ao2_object_get_lockaddr(db));
00289 }
00290 db->wakeup = 0;
00291 if (realtime_sqlite3_execute_handle(db, "COMMIT", NULL, NULL, 0) < 0) {
00292 realtime_sqlite3_execute_handle(db, "ROLLBACK", NULL, NULL, 0);
00293 }
00294 if (db->exiting) {
00295 ao2_unlock(db);
00296 break;
00297 }
00298 realtime_sqlite3_execute_handle(db, "BEGIN TRANSACTION", NULL, NULL, 0);
00299 ao2_unlock(db);
00300 usleep(1000 * db->batch);
00301 ao2_lock(db);
00302 }
00303
00304 unref_db(&db);
00305
00306 return NULL;
00307 }
00308
00309
00310 static int db_open(struct realtime_sqlite3_db *db)
00311 {
00312 ao2_lock(db);
00313 if (sqlite3_open(db->filename, &db->handle) != SQLITE_OK) {
00314 ast_log(LOG_WARNING, "Could not open %s: %s\n", db->filename, sqlite3_errmsg(db->handle));
00315 ao2_unlock(db);
00316 return -1;
00317 }
00318 sqlite3_busy_timeout(db->handle, 1000);
00319
00320 if (db->debug) {
00321 sqlite3_trace(db->handle, trace_cb, db);
00322 } else {
00323 sqlite3_trace(db->handle, NULL, NULL);
00324 }
00325
00326 ao2_unlock(db);
00327
00328 return 0;
00329 }
00330
00331 static void db_sync(struct realtime_sqlite3_db *db)
00332 {
00333 db->wakeup = 1;
00334 ast_cond_signal(&db->cond);
00335 }
00336
00337 void db_start_batch(struct realtime_sqlite3_db *db)
00338 {
00339 if (db->batch) {
00340 ast_cond_init(&db->cond, NULL);
00341 ao2_ref(db, +1);
00342 ast_pthread_create_background(&db->syncthread, NULL, db_sync_thread, db);
00343 }
00344 }
00345
00346 void db_stop_batch(struct realtime_sqlite3_db *db)
00347 {
00348 if (db->batch) {
00349 db->exiting = 1;
00350 db_sync(db);
00351 pthread_join(db->syncthread, NULL);
00352 }
00353 }
00354
00355
00356
00357
00358 static struct realtime_sqlite3_db *new_realtime_sqlite3_db(struct ast_config *config, const char *cat)
00359 {
00360 struct ast_variable *var;
00361 struct realtime_sqlite3_db *db;
00362
00363 if (!(db = ao2_alloc(sizeof(*db), db_destructor))) {
00364 return NULL;
00365 }
00366
00367 if (ast_string_field_init(db, 64)) {
00368 unref_db(&db);
00369 return NULL;
00370 }
00371
00372
00373 db->requirements = REALTIME_SQLITE3_REQ_WARN;
00374 db->batch = 100;
00375 ast_string_field_set(db, name, cat);
00376
00377 for (var = ast_variable_browse(config, cat); var; var = var->next) {
00378 if (!strcasecmp(var->name, "dbfile")) {
00379 ast_string_field_set(db, filename, var->value);
00380 } else if (!strcasecmp(var->name, "requirements")) {
00381 db->requirements = str_to_requirements(var->value);
00382 } else if (!strcasecmp(var->name, "batch")) {
00383 ast_app_parse_timelen(var->value, (int *) &db->batch, TIMELEN_MILLISECONDS);
00384 } else if (!strcasecmp(var->name, "debug")) {
00385 db->debug = ast_true(var->value);
00386 }
00387 }
00388
00389 if (ast_strlen_zero(db->filename)) {
00390 ast_log(LOG_WARNING, "Must specify dbfile in res_config_sqlite3.conf\n");
00391 unref_db(&db);
00392 return NULL;
00393 }
00394
00395 return db;
00396 }
00397
00398
00399
00400
00401
00402
00403 static int update_realtime_sqlite3_db(struct realtime_sqlite3_db *db, struct ast_config *config, const char *cat)
00404 {
00405 struct realtime_sqlite3_db *new;
00406
00407 if (!(new = new_realtime_sqlite3_db(config, cat))) {
00408 return -1;
00409 }
00410
00411
00412 db->requirements = new->requirements;
00413
00414
00415 if (db->debug != new->debug) {
00416 if (db->debug) {
00417 sqlite3_trace(db->handle, NULL, NULL);
00418 } else {
00419 sqlite3_trace(db->handle, trace_cb, db);
00420 }
00421 db->debug = new->debug;
00422 }
00423
00424 if (strcmp(db->filename, new->filename)) {
00425 sqlite3_close(db->handle);
00426 ast_string_field_set(db, filename, new->filename);
00427 db_open(db);
00428 }
00429
00430 if (db->batch != new->batch) {
00431 if (db->batch == 0) {
00432 db->batch = new->batch;
00433 db_start_batch(db);
00434 } else if (new->batch == 0) {
00435 db->batch = new->batch;
00436 db_stop_batch(db);
00437 }
00438 db->batch = new->batch;
00439 }
00440
00441 db->dirty = 0;
00442 unref_db(&new);
00443
00444 return 0;
00445 }
00446
00447
00448 static int row_to_varlist(void *arg, int num_columns, char **values, char **columns)
00449 {
00450 struct ast_variable **head = arg, *tail;
00451 int i;
00452 struct ast_variable *new;
00453
00454 if (!(new = ast_variable_new(columns[0], S_OR(values[0], ""), ""))) {
00455 return SQLITE_ABORT;
00456 }
00457 *head = tail = new;
00458
00459 for (i = 1; i < num_columns; i++) {
00460 if (!(new = ast_variable_new(columns[i], S_OR(values[i], ""), ""))) {
00461 ast_variables_destroy(*head);
00462 *head = NULL;
00463 return SQLITE_ABORT;
00464 }
00465 tail->next = new;
00466 tail = new;
00467 }
00468
00469 return 0;
00470 }
00471
00472
00473 static int append_row_to_cfg(void *arg, int num_columns, char **values, char **columns)
00474 {
00475 struct ast_config *cfg = arg;
00476 struct ast_category *cat;
00477 int i;
00478
00479 if (!(cat = ast_category_new("", "", 99999))) {
00480 return SQLITE_ABORT;
00481 }
00482
00483 for (i = 0; i < num_columns; i++) {
00484 struct ast_variable *var;
00485 if (!(var = ast_variable_new(columns[i], S_OR(values[i], ""), ""))) {
00486 ast_log(LOG_ERROR, "Could not create new variable for '%s: %s', throwing away list\n", columns[i], values[i]);
00487 continue;
00488 }
00489 ast_variable_append(cat, var);
00490 }
00491 ast_category_append(cfg, cat);
00492
00493 return 0;
00494 }
00495
00496
00497
00498
00499
00500
00501 struct cfg_entry_args {
00502 struct ast_config *cfg;
00503 struct ast_category *cat;
00504 char *cat_name;
00505 struct ast_flags flags;
00506 const char *who_asked;
00507 };
00508
00509
00510
00511
00512
00513
00514 static int realtime_sqlite3_execute_handle(struct realtime_sqlite3_db *db, const char *sql, int (*callback)(void*, int, char **, char **), void *arg, int sync)
00515 {
00516 int res = 0;
00517 char *errmsg;
00518
00519 ao2_lock(db);
00520 if (sqlite3_exec(db->handle, sql, callback, arg, &errmsg) != SQLITE_OK) {
00521 ast_log(LOG_WARNING, "Could not execute '%s': %s\n", sql, errmsg);
00522 sqlite3_free(errmsg);
00523 res = -1;
00524 } else {
00525 res = sqlite3_changes(db->handle);
00526 }
00527 ao2_unlock(db);
00528
00529 if (sync) {
00530 db_sync(db);
00531 }
00532
00533 return res;
00534 }
00535
00536
00537
00538
00539
00540
00541 static int realtime_sqlite3_execute(const char *database, const char *sql, int (*callback)(void*, int, char **, char **), void *arg, int sync)
00542 {
00543 struct realtime_sqlite3_db *db;
00544 int res;
00545
00546 if (!(db = find_database(database))) {
00547 ast_log(LOG_WARNING, "Could not find database: %s\n", database);
00548 return -1;
00549 }
00550
00551 res = realtime_sqlite3_execute_handle(db, sql, callback, arg, sync);
00552 ao2_ref(db, -1);
00553
00554 return res;
00555 }
00556
00557
00558 static 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";
00559 enum {
00560 COL_CATEGORY,
00561 COL_VAR_NAME,
00562 COL_VAR_VAL,
00563 COL_COLUMNS,
00564 };
00565
00566 static int static_realtime_cb(void *arg, int num_columns, char **values, char **columns)
00567 {
00568 struct cfg_entry_args *args = arg;
00569 struct ast_variable *var;
00570
00571 if (!strcmp(values[COL_VAR_NAME], "#include")) {
00572 struct ast_config *cfg;
00573 char *val;
00574
00575 val = values[COL_VAR_VAL];
00576 if (!(cfg = ast_config_internal_load(val, args->cfg, args->flags, "", args->who_asked))) {
00577 ast_log(LOG_WARNING, "Unable to include %s\n", val);
00578 return SQLITE_ABORT;
00579 } else {
00580 args->cfg = cfg;
00581 return 0;
00582 }
00583 }
00584
00585 if (!args->cat_name || strcmp(args->cat_name, values[COL_CATEGORY])) {
00586 if (!(args->cat = ast_category_new(values[COL_CATEGORY], "", 99999))) {
00587 ast_log(LOG_WARNING, "Unable to allocate category\n");
00588 return SQLITE_ABORT;
00589 }
00590
00591 ast_free(args->cat_name);
00592
00593 if (!(args->cat_name = ast_strdup(values[COL_CATEGORY]))) {
00594 ast_category_destroy(args->cat);
00595 return SQLITE_ABORT;
00596 }
00597
00598 ast_category_append(args->cfg, args->cat);
00599 }
00600
00601 if (!(var = ast_variable_new(values[COL_VAR_NAME], values[COL_VAR_VAL], ""))) {
00602 ast_log(LOG_WARNING, "Unable to allocate variable\n");
00603 return SQLITE_ABORT;
00604 }
00605
00606 ast_variable_append(args->cat, var);
00607
00608 return 0;
00609 }
00610
00611
00612
00613
00614 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)
00615 {
00616 char *sql;
00617 struct cfg_entry_args args;
00618
00619 if (ast_strlen_zero(table)) {
00620 ast_log(LOG_WARNING, "Must have a table to query!\n");
00621 return NULL;
00622 }
00623
00624 if (!(sql = sqlite3_mprintf(static_sql, table, configfile))) {
00625 ast_log(LOG_WARNING, "Couldn't allocate query\n");
00626 return NULL;
00627 };
00628
00629 args.cfg = config;
00630 args.cat = NULL;
00631 args.cat_name = NULL;
00632 args.flags = flags;
00633 args.who_asked = who_asked;
00634
00635 realtime_sqlite3_execute(database, sql, static_realtime_cb, &args, 0);
00636
00637 sqlite3_free(sql);
00638
00639 return config;
00640 }
00641
00642
00643 static int realtime_sqlite3_helper(const char *database, const char *table, va_list ap, int is_multi, void *arg)
00644 {
00645 struct ast_str *sql;
00646 const char *param, *value;
00647 int first = 1;
00648
00649 if (ast_strlen_zero(table)) {
00650 ast_log(LOG_WARNING, "Must have a table to query!\n");
00651 return -1;
00652 }
00653
00654 if (!(sql = ast_str_create(128))) {
00655 return -1;
00656 }
00657
00658 while ((param = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
00659 if (first) {
00660 ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s %s", sqlite3_escape_table(table),
00661 sqlite3_escape_column_op(param), sqlite3_escape_value(value));
00662 first = 0;
00663 } else {
00664 ast_str_append(&sql, 0, " AND %s %s", sqlite3_escape_column_op(param),
00665 sqlite3_escape_value(value));
00666 }
00667 }
00668
00669 if (!is_multi) {
00670 ast_str_append(&sql, 0, "%s", " LIMIT 1");
00671 }
00672
00673 if (realtime_sqlite3_execute(database, ast_str_buffer(sql), is_multi ? append_row_to_cfg : row_to_varlist, arg, 0) < 0) {
00674 ast_free(sql);
00675 return -1;
00676 }
00677
00678 ast_free(sql);
00679
00680 return 0;
00681 }
00682
00683
00684
00685
00686 static struct ast_variable *realtime_sqlite3(const char *database, const char *table, va_list ap)
00687 {
00688 struct ast_variable *result_row = NULL;
00689
00690 realtime_sqlite3_helper(database, table, ap, 0, &result_row);
00691
00692 return result_row;
00693 }
00694
00695
00696
00697
00698 static struct ast_config *realtime_sqlite3_multi(const char *database, const char *table, va_list ap)
00699 {
00700 struct ast_config *cfg;
00701
00702 if (!(cfg = ast_config_new())) {
00703 return NULL;
00704 }
00705
00706 if (realtime_sqlite3_helper(database, table, ap, 1, cfg)) {
00707 ast_config_destroy(cfg);
00708 return NULL;
00709 }
00710
00711 return cfg;
00712 }
00713
00714
00715
00716
00717 static int realtime_sqlite3_update(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap)
00718 {
00719 struct ast_str *sql;
00720 const char *key, *value;
00721 int first = 1, res;
00722
00723 if (ast_strlen_zero(table)) {
00724 ast_log(LOG_WARNING, "Must have a table to query!\n");
00725 return -1;
00726 }
00727
00728 if (!(sql = ast_str_create(128))) {
00729 return -1;
00730 }
00731
00732 while ((key = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
00733 if (first) {
00734 ast_str_set(&sql, 0, "UPDATE %s SET %s = %s",
00735 sqlite3_escape_table(table), sqlite3_escape_column(key), sqlite3_escape_value(value));
00736 first = 0;
00737 } else {
00738 ast_str_append(&sql, 0, ", %s = %s", sqlite3_escape_column(key), sqlite3_escape_value(value));
00739 }
00740 }
00741
00742 ast_str_append(&sql, 0, " WHERE %s %s", sqlite3_escape_column_op(keyfield), sqlite3_escape_value(entity));
00743
00744 res = realtime_sqlite3_execute(database, ast_str_buffer(sql), NULL, NULL, 1);
00745 ast_free(sql);
00746
00747 return res;
00748 }
00749
00750
00751
00752
00753 static int realtime_sqlite3_update2(const char *database, const char *table, va_list ap)
00754 {
00755 struct ast_str *sql;
00756 struct ast_str *where_clause;
00757 const char *key, *value;
00758 int first = 1, res;
00759
00760 if (ast_strlen_zero(table)) {
00761 ast_log(LOG_WARNING, "Must have a table to query!\n");
00762 return -1;
00763 }
00764
00765 if (!(sql = ast_str_create(128))) {
00766 return -1;
00767 }
00768
00769 if (!(where_clause = ast_str_create(128))) {
00770 ast_free(sql);
00771 return -1;
00772 }
00773
00774 while ((key = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
00775 if (first) {
00776 ast_str_set(&where_clause, 0, " WHERE %s %s", sqlite3_escape_column_op(key), sqlite3_escape_value(value));
00777 first = 0;
00778 } else {
00779 ast_str_append(&where_clause, 0, " AND %s %s", sqlite3_escape_column_op(key), sqlite3_escape_value(value));
00780 }
00781 }
00782
00783 first = 1;
00784 while ((key = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
00785 if (first) {
00786 ast_str_set(&sql, 0, "UPDATE %s SET %s = %s", sqlite3_escape_table(table), sqlite3_escape_column(key), sqlite3_escape_value(value));
00787 first = 0;
00788 } else {
00789 ast_str_append(&sql, 0, ", %s = %s", sqlite3_escape_column(key), sqlite3_escape_value(value));
00790 }
00791 }
00792
00793 ast_str_append(&sql, 0, "%s", ast_str_buffer(where_clause));
00794
00795 res = realtime_sqlite3_execute(database, ast_str_buffer(sql), NULL, NULL, 1);
00796
00797 ast_free(sql);
00798 ast_free(where_clause);
00799
00800 return res;
00801 }
00802
00803
00804
00805
00806 static int realtime_sqlite3_store(const char *database, const char *table, va_list ap)
00807 {
00808 struct ast_str *sql, *values;
00809 const char *column, *value;
00810 int first = 1, res;
00811
00812 if (ast_strlen_zero(table)) {
00813 ast_log(LOG_WARNING, "Must have a table to query!\n");
00814 return -1;
00815 }
00816
00817 if (!(sql = ast_str_create(128))) {
00818 return -1;
00819 }
00820
00821 if (!(values = ast_str_create(128))) {
00822 ast_free(sql);
00823 return -1;
00824 }
00825
00826 while ((column = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
00827 if (first) {
00828 ast_str_set(&sql, 0, "INSERT INTO %s (%s", sqlite3_escape_table(table), sqlite3_escape_column(column));
00829 ast_str_set(&values, 0, ") VALUES (%s", sqlite3_escape_value(value));
00830 first = 0;
00831 } else {
00832 ast_str_append(&sql, 0, ", %s", sqlite3_escape_column(column));
00833 ast_str_append(&values, 0, ", %s", sqlite3_escape_value(value));
00834 }
00835 }
00836
00837 ast_str_append(&sql, 0, "%s)", ast_str_buffer(values));
00838
00839 res = realtime_sqlite3_execute(database, ast_str_buffer(sql), NULL, NULL, 1);
00840
00841 ast_free(sql);
00842 ast_free(values);
00843
00844 return res;
00845 }
00846
00847
00848
00849
00850 static int realtime_sqlite3_destroy(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap)
00851 {
00852 struct ast_str *sql;
00853 const char *param, *value;
00854 int first = 1, res;
00855
00856 if (ast_strlen_zero(table)) {
00857 ast_log(LOG_WARNING, "Must have a table to query!\n");
00858 return -1;
00859 }
00860
00861 if (!(sql = ast_str_create(128))) {
00862 return -1;
00863 }
00864
00865 while ((param = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
00866 if (first) {
00867 ast_str_set(&sql, 0, "DELETE FROM %s WHERE %s %s", sqlite3_escape_table(table),
00868 sqlite3_escape_column_op(param), sqlite3_escape_value(value));
00869 first = 0;
00870 } else {
00871 ast_str_append(&sql, 0, " AND %s %s", sqlite3_escape_column_op(param), sqlite3_escape_value(value));
00872 }
00873 }
00874
00875 res = realtime_sqlite3_execute(database, ast_str_buffer(sql), NULL, NULL, 1);
00876
00877 ast_free(sql);
00878
00879 return res;
00880 }
00881
00882
00883
00884
00885
00886
00887
00888 static const char *get_sqlite_column_type(int type)
00889 {
00890 switch(type) {
00891 case RQ_INTEGER1 :
00892 case RQ_UINTEGER1 :
00893 case RQ_INTEGER2 :
00894 case RQ_UINTEGER2 :
00895 case RQ_INTEGER3 :
00896 case RQ_UINTEGER3 :
00897 case RQ_INTEGER4 :
00898 case RQ_UINTEGER4 :
00899 case RQ_INTEGER8 :
00900 return "INTEGER";
00901 case RQ_UINTEGER8 :
00902 case RQ_CHAR :
00903 case RQ_DATE :
00904 case RQ_DATETIME :
00905 return "TEXT";
00906 case RQ_FLOAT :
00907 return "REAL";
00908 default :
00909 return "TEXT";
00910 }
00911
00912 return "TEXT";
00913 }
00914
00915
00916
00917 static int handle_missing_table(struct realtime_sqlite3_db *db, const char *table, va_list ap)
00918 {
00919 const char *column;
00920 int type, first = 1, res;
00921 size_t sz;
00922 struct ast_str *sql;
00923
00924 if (!(sql = ast_str_create(128))) {
00925 return -1;
00926 }
00927
00928 while ((column = va_arg(ap, typeof(column))) && (type = va_arg(ap, typeof(type))) && (sz = va_arg(ap, typeof(sz)))) {
00929 if (first) {
00930 ast_str_set(&sql, 0, "CREATE TABLE IF NOT EXISTS %s (%s %s", sqlite3_escape_table(table),
00931 sqlite3_escape_column(column), get_sqlite_column_type(type));
00932 first = 0;
00933 } else {
00934 ast_str_append(&sql, 0, ", %s %s", sqlite3_escape_column(column), get_sqlite_column_type(type));
00935 }
00936 }
00937
00938 ast_str_append(&sql, 0, ")");
00939
00940 res = realtime_sqlite3_execute_handle(db, ast_str_buffer(sql), NULL, NULL, 1) < 0 ? -1 : 0;
00941 ast_free(sql);
00942
00943 return res;
00944 }
00945
00946
00947
00948 static int handle_missing_column(struct realtime_sqlite3_db *db, const char *table, const char *column, int type, size_t sz)
00949 {
00950 char *sql;
00951 const char *sqltype = get_sqlite_column_type(type);
00952 int res;
00953
00954 if (db->requirements == REALTIME_SQLITE3_REQ_WARN) {
00955 ast_log(LOG_WARNING, "Missing column '%s' of type '%s' in %s.%s\n", column, sqltype, db->name, table);
00956 return -1;
00957 } else if (db->requirements == REALTIME_SQLITE3_REQ_CHAR) {
00958 sqltype = "TEXT";
00959 }
00960
00961 if (!(sql = sqlite3_mprintf("ALTER TABLE \"%q\" ADD COLUMN \"%q\" %s", table, column, sqltype))) {
00962 return -1;
00963 }
00964
00965 if (!(res = (realtime_sqlite3_execute_handle(db, sql, NULL, NULL, 1) < 0 ? -1 : 0))) {
00966 ast_log(LOG_NOTICE, "Creating column '%s' type %s for table %s\n", column, sqltype, table);
00967 }
00968
00969 sqlite3_free(sql);
00970
00971 return res;
00972 }
00973
00974 static int str_hash_fn(const void *obj, const int flags)
00975 {
00976 return ast_str_hash((const char *) obj);
00977 }
00978
00979 static int str_cmp_fn(void *obj, void *arg, int flags) {
00980 return !strcasecmp((const char *) obj, (const char *) arg);
00981 }
00982
00983
00984
00985 static int add_column_name(void *arg, int num_columns, char **values, char **columns)
00986 {
00987 char *column;
00988 struct ao2_container *cnames = arg;
00989
00990
00991 if (!(column = ao2_alloc(strlen(values[1]) + 1, NULL))) {
00992 return -1;
00993 }
00994
00995 strcpy(column, values[1]);
00996
00997 ao2_link(cnames, column);
00998 ao2_ref(column, -1);
00999
01000 return 0;
01001 }
01002
01003
01004
01005
01006
01007 static int realtime_sqlite3_require(const char *database, const char *table, va_list ap)
01008 {
01009 const char *column;
01010 char *sql;
01011 int type;
01012 int res;
01013 size_t sz;
01014 struct ao2_container *columns;
01015 struct realtime_sqlite3_db *db;
01016
01017
01018
01019
01020
01021
01022
01023 if (ast_strlen_zero(table)) {
01024 ast_log(LOG_WARNING, "Must have a table to query!\n");
01025 return -1;
01026 }
01027
01028 if (!(db = find_database(database))) {
01029 return -1;
01030 }
01031
01032 if (!(columns = ao2_container_alloc(31, str_hash_fn, str_cmp_fn))) {
01033 unref_db(&db);
01034 return -1;
01035 }
01036
01037 if (!(sql = sqlite3_mprintf("PRAGMA table_info(\"%q\")", table))) {
01038 unref_db(&db);
01039 ao2_ref(columns, -1);
01040 return -1;
01041 }
01042
01043 if ((res = realtime_sqlite3_execute_handle(db, sql, add_column_name, columns, 0)) < 0) {
01044 unref_db(&db);
01045 ao2_ref(columns, -1);
01046 sqlite3_free(sql);
01047 return -1;
01048 } else if (res == 0) {
01049
01050 sqlite3_free(sql);
01051 res = handle_missing_table(db, table, ap);
01052 ao2_ref(columns, -1);
01053 unref_db(&db);
01054 return res;
01055 }
01056
01057 sqlite3_free(sql);
01058
01059 while ((column = va_arg(ap, typeof(column))) && (type = va_arg(ap, typeof(type))) && (sz = va_arg(ap, typeof(sz)))) {
01060 char *found;
01061 if (!(found = ao2_find(columns, column, OBJ_POINTER | OBJ_UNLINK))) {
01062 if (handle_missing_column(db, table, column, type, sz)) {
01063 unref_db(&db);
01064 ao2_ref(columns, -1);
01065 return -1;
01066 }
01067 } else {
01068 ao2_ref(found, -1);
01069 }
01070 }
01071
01072 ao2_ref(columns, -1);
01073 unref_db(&db);
01074
01075 return 0;
01076 }
01077
01078
01079
01080
01081
01082
01083 static int realtime_sqlite3_unload(const char *database, const char *table)
01084 {
01085
01086 return -1;
01087 }
01088
01089
01090
01091 static int parse_config(int reload)
01092 {
01093 struct ast_config *config;
01094 struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME | (reload ? CONFIG_FLAG_FILEUNCHANGED : 0) };
01095 static const char *config_filename = "res_config_sqlite3.conf";
01096
01097 config = ast_config_load(config_filename, config_flags);
01098
01099 if (config == CONFIG_STATUS_FILEUNCHANGED) {
01100 ast_debug(1, "%s was unchanged, skipping parsing\n", config_filename);
01101 return 0;
01102 }
01103
01104 ast_mutex_lock(&config_lock);
01105
01106 if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
01107 ast_log(LOG_ERROR, "%s config file '%s'\n",
01108 config == CONFIG_STATUS_FILEMISSING ? "Missing" : "Invalid", config_filename);
01109 } else {
01110 const char *cat;
01111 struct realtime_sqlite3_db *db;
01112
01113 mark_all_databases_dirty();
01114 for (cat = ast_category_browse(config, NULL); cat; cat = ast_category_browse(config, cat)) {
01115 if (!strcasecmp(cat, "general")) {
01116 continue;
01117 }
01118 if (!(db = find_database(cat))) {
01119 if (!(db = new_realtime_sqlite3_db(config, cat))) {
01120 ast_log(LOG_WARNING, "Could not allocate new db for '%s' - skipping.\n", cat);
01121 continue;
01122 }
01123 if (db_open(db)) {
01124 unref_db(&db);
01125 continue;
01126 }
01127 db_start_batch(db);
01128 ao2_link(databases, db);
01129 unref_db(&db);
01130 } else {
01131 if (update_realtime_sqlite3_db(db, config, cat)) {
01132 unref_db(&db);
01133 continue;
01134 }
01135 unref_db(&db);
01136 }
01137 }
01138 unlink_dirty_databases();
01139 }
01140
01141 ast_mutex_unlock(&config_lock);
01142
01143 ast_config_destroy(config);
01144
01145 return 0;
01146 }
01147
01148 static int reload(void)
01149 {
01150 parse_config(1);
01151 return 0;
01152 }
01153
01154 static int unload_module(void)
01155 {
01156 ast_mutex_lock(&config_lock);
01157 ao2_callback(databases, OBJ_MULTIPLE | OBJ_NODATA | OBJ_UNLINK, stop_batch_cb, NULL);
01158 ao2_ref(databases, -1);
01159 databases = NULL;
01160 ast_config_engine_deregister(&sqlite3_config_engine);
01161 ast_mutex_unlock(&config_lock);
01162
01163 return 0;
01164 }
01165
01166 static int load_module(void)
01167 {
01168 if (!((databases = ao2_container_alloc(DB_BUCKETS, db_hash_fn, db_cmp_fn)))) {
01169 return AST_MODULE_LOAD_FAILURE;
01170 }
01171
01172 if (parse_config(0)) {
01173 ao2_ref(databases, -1);
01174 return AST_MODULE_LOAD_FAILURE;
01175 }
01176
01177 if (!(ast_config_engine_register(&sqlite3_config_engine))) {
01178 ast_log(LOG_ERROR, "The config API must have changed, this shouldn't happen.\n");
01179 ao2_ref(databases, -1);
01180 return AST_MODULE_LOAD_FAILURE;
01181 }
01182
01183 return AST_MODULE_LOAD_SUCCESS;
01184 }
01185
01186 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SQLite 3 realtime config engine",
01187 .load = load_module,
01188 .unload = unload_module,
01189 .reload = reload,
01190 .load_pri = AST_MODPRI_REALTIME_DRIVER,
01191 );