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: 362307 $")
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
00319 if (db->debug) {
00320 sqlite3_trace(db->handle, trace_cb, db);
00321 } else {
00322 sqlite3_trace(db->handle, NULL, NULL);
00323 }
00324
00325 ao2_unlock(db);
00326
00327 return 0;
00328 }
00329
00330 static void db_sync(struct realtime_sqlite3_db *db)
00331 {
00332 db->wakeup = 1;
00333 ast_cond_signal(&db->cond);
00334 }
00335
00336 void db_start_batch(struct realtime_sqlite3_db *db)
00337 {
00338 if (db->batch) {
00339 ast_cond_init(&db->cond, NULL);
00340 ao2_ref(db, +1);
00341 ast_pthread_create_background(&db->syncthread, NULL, db_sync_thread, db);
00342 }
00343 }
00344
00345 void db_stop_batch(struct realtime_sqlite3_db *db)
00346 {
00347 if (db->batch) {
00348 db->exiting = 1;
00349 db_sync(db);
00350 pthread_join(db->syncthread, NULL);
00351 }
00352 }
00353
00354
00355
00356
00357 static struct realtime_sqlite3_db *new_realtime_sqlite3_db(struct ast_config *config, const char *cat)
00358 {
00359 struct ast_variable *var;
00360 struct realtime_sqlite3_db *db;
00361
00362 if (!(db = ao2_alloc(sizeof(*db), db_destructor))) {
00363 return NULL;
00364 }
00365
00366 if (ast_string_field_init(db, 64)) {
00367 unref_db(&db);
00368 return NULL;
00369 }
00370
00371
00372 db->requirements = REALTIME_SQLITE3_REQ_WARN;
00373 db->batch = 100;
00374 ast_string_field_set(db, name, cat);
00375
00376 for (var = ast_variable_browse(config, cat); var; var = var->next) {
00377 if (!strcasecmp(var->name, "dbfile")) {
00378 ast_string_field_set(db, filename, var->value);
00379 } else if (!strcasecmp(var->name, "requirements")) {
00380 db->requirements = str_to_requirements(var->value);
00381 } else if (!strcasecmp(var->name, "batch")) {
00382 ast_app_parse_timelen(var->value, (int *) &db->batch, TIMELEN_MILLISECONDS);
00383 } else if (!strcasecmp(var->name, "debug")) {
00384 db->debug = ast_true(var->value);
00385 }
00386 }
00387
00388 if (ast_strlen_zero(db->filename)) {
00389 ast_log(LOG_WARNING, "Must specify dbfile in res_config_sqlite3.conf\n");
00390 unref_db(&db);
00391 return NULL;
00392 }
00393
00394 return db;
00395 }
00396
00397
00398
00399
00400
00401
00402 static int update_realtime_sqlite3_db(struct realtime_sqlite3_db *db, struct ast_config *config, const char *cat)
00403 {
00404 struct realtime_sqlite3_db *new;
00405
00406 if (!(new = new_realtime_sqlite3_db(config, cat))) {
00407 return -1;
00408 }
00409
00410
00411 db->requirements = new->requirements;
00412
00413
00414 if (db->debug != new->debug) {
00415 if (db->debug) {
00416 sqlite3_trace(db->handle, NULL, NULL);
00417 } else {
00418 sqlite3_trace(db->handle, trace_cb, db);
00419 }
00420 db->debug = new->debug;
00421 }
00422
00423 if (strcmp(db->filename, new->filename)) {
00424 sqlite3_close(db->handle);
00425 ast_string_field_set(db, filename, new->filename);
00426 db_open(db);
00427 }
00428
00429 if (db->batch != new->batch) {
00430 if (db->batch == 0) {
00431 db->batch = new->batch;
00432 db_start_batch(db);
00433 } else if (new->batch == 0) {
00434 db->batch = new->batch;
00435 db_stop_batch(db);
00436 }
00437 db->batch = new->batch;
00438 }
00439
00440 db->dirty = 0;
00441 unref_db(&new);
00442
00443 return 0;
00444 }
00445
00446
00447 static int row_to_varlist(void *arg, int num_columns, char **values, char **columns)
00448 {
00449 struct ast_variable **head = arg, *tail;
00450 int i;
00451 struct ast_variable *new;
00452
00453 if (!(new = ast_variable_new(columns[0], S_OR(values[0], ""), ""))) {
00454 return SQLITE_ABORT;
00455 }
00456 *head = tail = new;
00457
00458 for (i = 1; i < num_columns; i++) {
00459 if (!(new = ast_variable_new(columns[i], S_OR(values[i], ""), ""))) {
00460 ast_variables_destroy(*head);
00461 *head = NULL;
00462 return SQLITE_ABORT;
00463 }
00464 tail->next = new;
00465 tail = new;
00466 }
00467
00468 return 0;
00469 }
00470
00471
00472 static int append_row_to_cfg(void *arg, int num_columns, char **values, char **columns)
00473 {
00474 struct ast_config *cfg = arg;
00475 struct ast_category *cat;
00476 int i;
00477
00478 if (!(cat = ast_category_new("", "", 99999))) {
00479 return SQLITE_ABORT;
00480 }
00481
00482 for (i = 0; i < num_columns; i++) {
00483 struct ast_variable *var;
00484 if (!(var = ast_variable_new(columns[i], S_OR(values[i], ""), ""))) {
00485 ast_log(LOG_ERROR, "Could not create new variable for '%s: %s', throwing away list\n", columns[i], values[i]);
00486 continue;
00487 }
00488 ast_variable_append(cat, var);
00489 }
00490 ast_category_append(cfg, cat);
00491
00492 return 0;
00493 }
00494
00495
00496
00497
00498
00499
00500 struct cfg_entry_args {
00501 struct ast_config *cfg;
00502 struct ast_category *cat;
00503 char *cat_name;
00504 struct ast_flags flags;
00505 const char *who_asked;
00506 };
00507
00508
00509
00510
00511
00512
00513 static int realtime_sqlite3_execute_handle(struct realtime_sqlite3_db *db, const char *sql, int (*callback)(void*, int, char **, char **), void *arg, int sync)
00514 {
00515 int res = 0;
00516 char *errmsg;
00517
00518 ao2_lock(db);
00519 if (sqlite3_exec(db->handle, sql, callback, arg, &errmsg) != SQLITE_OK) {
00520 ast_log(LOG_WARNING, "Could not execute '%s': %s\n", sql, errmsg);
00521 sqlite3_free(errmsg);
00522 res = -1;
00523 } else {
00524 res = sqlite3_changes(db->handle);
00525 }
00526 ao2_unlock(db);
00527
00528 if (sync) {
00529 db_sync(db);
00530 }
00531
00532 return res;
00533 }
00534
00535
00536
00537
00538
00539
00540 static int realtime_sqlite3_execute(const char *database, const char *sql, int (*callback)(void*, int, char **, char **), void *arg, int sync)
00541 {
00542 struct realtime_sqlite3_db *db;
00543 int res;
00544
00545 if (!(db = find_database(database))) {
00546 ast_log(LOG_WARNING, "Could not find database: %s\n", database);
00547 return -1;
00548 }
00549
00550 res = realtime_sqlite3_execute_handle(db, sql, callback, arg, sync);
00551 ao2_ref(db, -1);
00552
00553 return res;
00554 }
00555
00556
00557 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";
00558 enum {
00559 COL_CATEGORY,
00560 COL_VAR_NAME,
00561 COL_VAR_VAL,
00562 COL_COLUMNS,
00563 };
00564
00565 static int static_realtime_cb(void *arg, int num_columns, char **values, char **columns)
00566 {
00567 struct cfg_entry_args *args = arg;
00568 struct ast_variable *var;
00569
00570 if (!strcmp(values[COL_VAR_NAME], "#include")) {
00571 struct ast_config *cfg;
00572 char *val;
00573
00574 val = values[COL_VAR_VAL];
00575 if (!(cfg = ast_config_internal_load(val, args->cfg, args->flags, "", args->who_asked))) {
00576 ast_log(LOG_WARNING, "Unable to include %s\n", val);
00577 return SQLITE_ABORT;
00578 } else {
00579 args->cfg = cfg;
00580 return 0;
00581 }
00582 }
00583
00584 if (!args->cat_name || strcmp(args->cat_name, values[COL_CATEGORY])) {
00585 if (!(args->cat = ast_category_new(values[COL_CATEGORY], "", 99999))) {
00586 ast_log(LOG_WARNING, "Unable to allocate category\n");
00587 return SQLITE_ABORT;
00588 }
00589
00590 ast_free(args->cat_name);
00591
00592 if (!(args->cat_name = ast_strdup(values[COL_CATEGORY]))) {
00593 ast_category_destroy(args->cat);
00594 return SQLITE_ABORT;
00595 }
00596
00597 ast_category_append(args->cfg, args->cat);
00598 }
00599
00600 if (!(var = ast_variable_new(values[COL_VAR_NAME], values[COL_VAR_VAL], ""))) {
00601 ast_log(LOG_WARNING, "Unable to allocate variable\n");
00602 return SQLITE_ABORT;
00603 }
00604
00605 ast_variable_append(args->cat, var);
00606
00607 return 0;
00608 }
00609
00610
00611
00612
00613 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)
00614 {
00615 char *sql;
00616 struct cfg_entry_args args;
00617
00618 if (ast_strlen_zero(table)) {
00619 ast_log(LOG_WARNING, "Must have a table to query!\n");
00620 return NULL;
00621 }
00622
00623 if (!(sql = sqlite3_mprintf(static_sql, table, configfile))) {
00624 ast_log(LOG_WARNING, "Couldn't allocate query\n");
00625 return NULL;
00626 };
00627
00628 args.cfg = config;
00629 args.cat = NULL;
00630 args.cat_name = NULL;
00631 args.flags = flags;
00632 args.who_asked = who_asked;
00633
00634 realtime_sqlite3_execute(database, sql, static_realtime_cb, &args, 0);
00635
00636 sqlite3_free(sql);
00637
00638 return config;
00639 }
00640
00641
00642 static int realtime_sqlite3_helper(const char *database, const char *table, va_list ap, int is_multi, void *arg)
00643 {
00644 struct ast_str *sql;
00645 const char *param, *value;
00646 int first = 1;
00647
00648 if (ast_strlen_zero(table)) {
00649 ast_log(LOG_WARNING, "Must have a table to query!\n");
00650 return -1;
00651 }
00652
00653 if (!(sql = ast_str_create(128))) {
00654 return -1;
00655 }
00656
00657 while ((param = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
00658 if (first) {
00659 ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s %s", sqlite3_escape_table(table),
00660 sqlite3_escape_column_op(param), sqlite3_escape_value(value));
00661 first = 0;
00662 } else {
00663 ast_str_append(&sql, 0, " AND %s %s", sqlite3_escape_column_op(param),
00664 sqlite3_escape_value(value));
00665 }
00666 }
00667
00668 if (!is_multi) {
00669 ast_str_append(&sql, 0, "%s", " LIMIT 1");
00670 }
00671
00672 if (realtime_sqlite3_execute(database, ast_str_buffer(sql), is_multi ? append_row_to_cfg : row_to_varlist, arg, 0) < 0) {
00673 ast_free(sql);
00674 return -1;
00675 }
00676
00677 ast_free(sql);
00678
00679 return 0;
00680 }
00681
00682
00683
00684
00685 static struct ast_variable *realtime_sqlite3(const char *database, const char *table, va_list ap)
00686 {
00687 struct ast_variable *result_row = NULL;
00688
00689 realtime_sqlite3_helper(database, table, ap, 0, &result_row);
00690
00691 return result_row;
00692 }
00693
00694
00695
00696
00697 static struct ast_config *realtime_sqlite3_multi(const char *database, const char *table, va_list ap)
00698 {
00699 struct ast_config *cfg;
00700
00701 if (!(cfg = ast_config_new())) {
00702 return NULL;
00703 }
00704
00705 if (realtime_sqlite3_helper(database, table, ap, 1, cfg)) {
00706 ast_config_destroy(cfg);
00707 return NULL;
00708 }
00709
00710 return cfg;
00711 }
00712
00713
00714
00715
00716 static int realtime_sqlite3_update(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap)
00717 {
00718 struct ast_str *sql;
00719 const char *key, *value;
00720 int first = 1, res;
00721
00722 if (ast_strlen_zero(table)) {
00723 ast_log(LOG_WARNING, "Must have a table to query!\n");
00724 return -1;
00725 }
00726
00727 if (!(sql = ast_str_create(128))) {
00728 return -1;
00729 }
00730
00731 while ((key = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
00732 if (first) {
00733 ast_str_set(&sql, 0, "UPDATE %s SET %s = %s",
00734 sqlite3_escape_table(table), sqlite3_escape_column(key), sqlite3_escape_value(value));
00735 first = 0;
00736 } else {
00737 ast_str_append(&sql, 0, ", %s = %s", sqlite3_escape_column(key), sqlite3_escape_value(value));
00738 }
00739 }
00740
00741 ast_str_append(&sql, 0, " WHERE %s %s", sqlite3_escape_column_op(keyfield), sqlite3_escape_value(entity));
00742
00743 res = realtime_sqlite3_execute(database, ast_str_buffer(sql), NULL, NULL, 1);
00744 ast_free(sql);
00745
00746 return res;
00747 }
00748
00749
00750
00751
00752 static int realtime_sqlite3_update2(const char *database, const char *table, va_list ap)
00753 {
00754 struct ast_str *sql;
00755 struct ast_str *where_clause;
00756 const char *key, *value;
00757 int first = 1, res;
00758
00759 if (ast_strlen_zero(table)) {
00760 ast_log(LOG_WARNING, "Must have a table to query!\n");
00761 return -1;
00762 }
00763
00764 if (!(sql = ast_str_create(128))) {
00765 return -1;
00766 }
00767
00768 if (!(where_clause = ast_str_create(128))) {
00769 ast_free(sql);
00770 return -1;
00771 }
00772
00773 while ((key = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
00774 if (first) {
00775 ast_str_set(&where_clause, 0, " WHERE %s %s", sqlite3_escape_column_op(key), sqlite3_escape_value(value));
00776 first = 0;
00777 } else {
00778 ast_str_append(&where_clause, 0, " AND %s %s", sqlite3_escape_column_op(key), sqlite3_escape_value(value));
00779 }
00780 }
00781
00782 first = 1;
00783 while ((key = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
00784 if (first) {
00785 ast_str_set(&sql, 0, "UPDATE %s SET %s = %s", sqlite3_escape_table(table), sqlite3_escape_column(key), sqlite3_escape_value(value));
00786 first = 0;
00787 } else {
00788 ast_str_append(&sql, 0, ", %s = %s", sqlite3_escape_column(key), sqlite3_escape_value(value));
00789 }
00790 }
00791
00792 ast_str_append(&sql, 0, "%s", ast_str_buffer(where_clause));
00793
00794 res = realtime_sqlite3_execute(database, ast_str_buffer(sql), NULL, NULL, 1);
00795
00796 ast_free(sql);
00797 ast_free(where_clause);
00798
00799 return res;
00800 }
00801
00802
00803
00804
00805 static int realtime_sqlite3_store(const char *database, const char *table, va_list ap)
00806 {
00807 struct ast_str *sql, *values;
00808 const char *column, *value;
00809 int first = 1, res;
00810
00811 if (ast_strlen_zero(table)) {
00812 ast_log(LOG_WARNING, "Must have a table to query!\n");
00813 return -1;
00814 }
00815
00816 if (!(sql = ast_str_create(128))) {
00817 return -1;
00818 }
00819
00820 if (!(values = ast_str_create(128))) {
00821 ast_free(sql);
00822 return -1;
00823 }
00824
00825 while ((column = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
00826 if (first) {
00827 ast_str_set(&sql, 0, "INSERT INTO %s (%s", sqlite3_escape_table(table), sqlite3_escape_column(column));
00828 ast_str_set(&values, 0, ") VALUES (%s", sqlite3_escape_value(value));
00829 first = 0;
00830 } else {
00831 ast_str_append(&sql, 0, ", %s", sqlite3_escape_column(column));
00832 ast_str_append(&values, 0, ", %s", sqlite3_escape_value(value));
00833 }
00834 }
00835
00836 ast_str_append(&sql, 0, "%s)", ast_str_buffer(values));
00837
00838 res = realtime_sqlite3_execute(database, ast_str_buffer(sql), NULL, NULL, 1);
00839
00840 ast_free(sql);
00841 ast_free(values);
00842
00843 return res;
00844 }
00845
00846
00847
00848
00849 static int realtime_sqlite3_destroy(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap)
00850 {
00851 struct ast_str *sql;
00852 const char *param, *value;
00853 int first = 1, res;
00854
00855 if (ast_strlen_zero(table)) {
00856 ast_log(LOG_WARNING, "Must have a table to query!\n");
00857 return -1;
00858 }
00859
00860 if (!(sql = ast_str_create(128))) {
00861 return -1;
00862 }
00863
00864 while ((param = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
00865 if (first) {
00866 ast_str_set(&sql, 0, "DELETE FROM %s WHERE %s %s", sqlite3_escape_table(table),
00867 sqlite3_escape_column_op(param), sqlite3_escape_value(value));
00868 first = 0;
00869 } else {
00870 ast_str_append(&sql, 0, " AND %s %s", sqlite3_escape_column_op(param), sqlite3_escape_value(value));
00871 }
00872 }
00873
00874 res = realtime_sqlite3_execute(database, ast_str_buffer(sql), NULL, NULL, 1);
00875
00876 ast_free(sql);
00877
00878 return res;
00879 }
00880
00881
00882
00883
00884
00885
00886
00887 static const char *get_sqlite_column_type(int type)
00888 {
00889 switch(type) {
00890 case RQ_INTEGER1 :
00891 case RQ_UINTEGER1 :
00892 case RQ_INTEGER2 :
00893 case RQ_UINTEGER2 :
00894 case RQ_INTEGER3 :
00895 case RQ_UINTEGER3 :
00896 case RQ_INTEGER4 :
00897 case RQ_UINTEGER4 :
00898 case RQ_INTEGER8 :
00899 return "INTEGER";
00900 case RQ_UINTEGER8 :
00901 case RQ_CHAR :
00902 case RQ_DATE :
00903 case RQ_DATETIME :
00904 return "TEXT";
00905 case RQ_FLOAT :
00906 return "REAL";
00907 default :
00908 return "TEXT";
00909 }
00910
00911 return "TEXT";
00912 }
00913
00914
00915
00916 static int handle_missing_table(struct realtime_sqlite3_db *db, const char *table, va_list ap)
00917 {
00918 const char *column;
00919 int type, first = 1, res;
00920 size_t sz;
00921 struct ast_str *sql;
00922
00923 if (!(sql = ast_str_create(128))) {
00924 return -1;
00925 }
00926
00927 while ((column = va_arg(ap, typeof(column))) && (type = va_arg(ap, typeof(type))) && (sz = va_arg(ap, typeof(sz)))) {
00928 if (first) {
00929 ast_str_set(&sql, 0, "CREATE TABLE IF NOT EXISTS %s (%s %s", sqlite3_escape_table(table),
00930 sqlite3_escape_column(column), get_sqlite_column_type(type));
00931 first = 0;
00932 } else {
00933 ast_str_append(&sql, 0, ", %s %s", sqlite3_escape_column(column), get_sqlite_column_type(type));
00934 }
00935 }
00936
00937 ast_str_append(&sql, 0, ")");
00938
00939 res = realtime_sqlite3_execute_handle(db, ast_str_buffer(sql), NULL, NULL, 1) < 0 ? -1 : 0;
00940 ast_free(sql);
00941
00942 return res;
00943 }
00944
00945
00946
00947 static int handle_missing_column(struct realtime_sqlite3_db *db, const char *table, const char *column, int type, size_t sz)
00948 {
00949 char *sql;
00950 const char *sqltype = get_sqlite_column_type(type);
00951 int res;
00952
00953 if (db->requirements == REALTIME_SQLITE3_REQ_WARN) {
00954 ast_log(LOG_WARNING, "Missing column '%s' of type '%s' in %s.%s\n", column, sqltype, db->name, table);
00955 return -1;
00956 } else if (db->requirements == REALTIME_SQLITE3_REQ_CHAR) {
00957 sqltype = "TEXT";
00958 }
00959
00960 if (!(sql = sqlite3_mprintf("ALTER TABLE \"%q\" ADD COLUMN \"%q\" %s", table, column, sqltype))) {
00961 return -1;
00962 }
00963
00964 if (!(res = (realtime_sqlite3_execute_handle(db, sql, NULL, NULL, 1) < 0 ? -1 : 0))) {
00965 ast_log(LOG_NOTICE, "Creating column '%s' type %s for table %s\n", column, sqltype, table);
00966 }
00967
00968 sqlite3_free(sql);
00969
00970 return res;
00971 }
00972
00973 static int str_hash_fn(const void *obj, const int flags)
00974 {
00975 return ast_str_hash((const char *) obj);
00976 }
00977
00978 static int str_cmp_fn(void *obj, void *arg, int flags) {
00979 return !strcasecmp((const char *) obj, (const char *) arg);
00980 }
00981
00982
00983
00984 static int add_column_name(void *arg, int num_columns, char **values, char **columns)
00985 {
00986 char *column;
00987 struct ao2_container *cnames = arg;
00988
00989
00990 if (!(column = ao2_alloc(strlen(values[1]) + 1, NULL))) {
00991 return -1;
00992 }
00993
00994 strcpy(column, values[1]);
00995
00996 ao2_link(cnames, column);
00997 ao2_ref(column, -1);
00998
00999 return 0;
01000 }
01001
01002
01003
01004
01005
01006 static int realtime_sqlite3_require(const char *database, const char *table, va_list ap)
01007 {
01008 const char *column;
01009 char *sql;
01010 int type;
01011 int res;
01012 size_t sz;
01013 struct ao2_container *columns;
01014 struct realtime_sqlite3_db *db;
01015
01016
01017
01018
01019
01020
01021
01022 if (ast_strlen_zero(table)) {
01023 ast_log(LOG_WARNING, "Must have a table to query!\n");
01024 return -1;
01025 }
01026
01027 if (!(db = find_database(database))) {
01028 return -1;
01029 }
01030
01031 if (!(columns = ao2_container_alloc(31, str_hash_fn, str_cmp_fn))) {
01032 unref_db(&db);
01033 return -1;
01034 }
01035
01036 if (!(sql = sqlite3_mprintf("PRAGMA table_info(\"%q\")", table))) {
01037 unref_db(&db);
01038 ao2_ref(columns, -1);
01039 return -1;
01040 }
01041
01042 if ((res = realtime_sqlite3_execute_handle(db, sql, add_column_name, columns, 0)) < 0) {
01043 unref_db(&db);
01044 ao2_ref(columns, -1);
01045 sqlite3_free(sql);
01046 return -1;
01047 } else if (res == 0) {
01048
01049 sqlite3_free(sql);
01050 res = handle_missing_table(db, table, ap);
01051 ao2_ref(columns, -1);
01052 unref_db(&db);
01053 return res;
01054 }
01055
01056 sqlite3_free(sql);
01057
01058 while ((column = va_arg(ap, typeof(column))) && (type = va_arg(ap, typeof(type))) && (sz = va_arg(ap, typeof(sz)))) {
01059 char *found;
01060 if (!(found = ao2_find(columns, column, OBJ_POINTER | OBJ_UNLINK))) {
01061 if (handle_missing_column(db, table, column, type, sz)) {
01062 unref_db(&db);
01063 ao2_ref(columns, -1);
01064 return -1;
01065 }
01066 } else {
01067 ao2_ref(found, -1);
01068 }
01069 }
01070
01071 ao2_ref(columns, -1);
01072 unref_db(&db);
01073
01074 return 0;
01075 }
01076
01077
01078
01079
01080
01081
01082 static int realtime_sqlite3_unload(const char *database, const char *table)
01083 {
01084
01085 return -1;
01086 }
01087
01088
01089
01090 static int parse_config(int reload)
01091 {
01092 struct ast_config *config;
01093 struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME | (reload ? CONFIG_FLAG_FILEUNCHANGED : 0) };
01094 static const char *config_filename = "res_config_sqlite3.conf";
01095
01096 config = ast_config_load(config_filename, config_flags);
01097
01098 if (config == CONFIG_STATUS_FILEUNCHANGED) {
01099 ast_debug(1, "%s was unchanged, skipping parsing\n", config_filename);
01100 return 0;
01101 }
01102
01103 ast_mutex_lock(&config_lock);
01104
01105 if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
01106 ast_log(LOG_ERROR, "%s config file '%s'\n",
01107 config == CONFIG_STATUS_FILEMISSING ? "Missing" : "Invalid", config_filename);
01108 } else {
01109 const char *cat;
01110 struct realtime_sqlite3_db *db;
01111
01112 mark_all_databases_dirty();
01113 for (cat = ast_category_browse(config, NULL); cat; cat = ast_category_browse(config, cat)) {
01114 if (!strcasecmp(cat, "general")) {
01115 continue;
01116 }
01117 if (!(db = find_database(cat))) {
01118 if (!(db = new_realtime_sqlite3_db(config, cat))) {
01119 ast_log(LOG_WARNING, "Could not allocate new db for '%s' - skipping.\n", cat);
01120 continue;
01121 }
01122 if (db_open(db)) {
01123 unref_db(&db);
01124 continue;
01125 }
01126 db_start_batch(db);
01127 ao2_link(databases, db);
01128 unref_db(&db);
01129 } else {
01130 if (update_realtime_sqlite3_db(db, config, cat)) {
01131 unref_db(&db);
01132 continue;
01133 }
01134 unref_db(&db);
01135 }
01136 }
01137 unlink_dirty_databases();
01138 }
01139
01140 ast_mutex_unlock(&config_lock);
01141
01142 ast_config_destroy(config);
01143
01144 return 0;
01145 }
01146
01147 static int reload(void)
01148 {
01149 parse_config(1);
01150 return 0;
01151 }
01152
01153 static int unload_module(void)
01154 {
01155 ast_mutex_lock(&config_lock);
01156 ao2_callback(databases, OBJ_MULTIPLE | OBJ_NODATA | OBJ_UNLINK, stop_batch_cb, NULL);
01157 ao2_ref(databases, -1);
01158 databases = NULL;
01159 ast_config_engine_deregister(&sqlite3_config_engine);
01160 ast_mutex_unlock(&config_lock);
01161
01162 return 0;
01163 }
01164
01165 static int load_module(void)
01166 {
01167 if (!((databases = ao2_container_alloc(DB_BUCKETS, db_hash_fn, db_cmp_fn)))) {
01168 return AST_MODULE_LOAD_FAILURE;
01169 }
01170
01171 if (parse_config(0)) {
01172 ao2_ref(databases, -1);
01173 return AST_MODULE_LOAD_FAILURE;
01174 }
01175
01176 if (!(ast_config_engine_register(&sqlite3_config_engine))) {
01177 ast_log(LOG_ERROR, "The config API must have changed, this shouldn't happen.\n");
01178 ao2_ref(databases, -1);
01179 return AST_MODULE_LOAD_FAILURE;
01180 }
01181
01182 return AST_MODULE_LOAD_SUCCESS;
01183 }
01184
01185 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SQLite 3 realtime config engine",
01186 .load = load_module,
01187 .unload = unload_module,
01188 .reload = reload,
01189 .load_pri = AST_MODPRI_REALTIME_DRIVER,
01190 );