return sqlite3_open(filename, ppDb);
}
+SWITCH_DECLARE(int) switch_core_db_open_v2(const char *filename, switch_core_db_t **ppDb)
+{
+ return sqlite3_open_v2(filename, ppDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, NULL);
+}
+
SWITCH_DECLARE(int) switch_core_db_close(switch_core_db_t *db)
{
return sqlite3_close(db);
while (--sane > 0) {
ret = sqlite3_exec(db, sql, callback, data, &err);
if (ret == SQLITE_BUSY || ret == SQLITE_LOCKED) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SQLite is %s, sane=%d [%s]\n", (ret == SQLITE_BUSY ? "BUSY" : "LOCKED"), sane, sql);
if (sane > 1) {
switch_core_db_free(err);
switch_yield(100000);
return ret;
}
+static int switch_core_db_connection_setup(switch_core_db_t *db, switch_bool_t in_memory) {
+ int db_ret;
+
+ if ((db_ret = switch_core_db_exec(db, "PRAGMA synchronous=OFF;", NULL, NULL, NULL)) != SQLITE_OK) {
+ goto end;
+ }
+ if ((db_ret = switch_core_db_exec(db, "PRAGMA count_changes=OFF;", NULL, NULL, NULL)) != SQLITE_OK) {
+ goto end;
+ }
+ if ((db_ret = switch_core_db_exec(db, "PRAGMA temp_store=MEMORY;", NULL, NULL, NULL)) != SQLITE_OK) {
+ goto end;
+ }
+ if (!in_memory) {
+ if ((db_ret = switch_core_db_exec(db, "PRAGMA cache_size=8000;", NULL, NULL, NULL)) != SQLITE_OK) {
+ goto end;
+ }
+ } else {
+ if ((db_ret = switch_core_db_exec(db, "PRAGMA cache_size=-8192;", NULL, NULL, NULL)) != SQLITE_OK) {
+ goto end;
+ }
+ if ((db_ret = switch_core_db_exec(db, "PRAGMA journal_mode=OFF;", NULL, NULL, NULL)) != SQLITE_OK) {
+ goto end;
+ }
+ }
+
+end:
+ return db_ret;
+}
+
SWITCH_DECLARE(switch_core_db_t *) switch_core_db_open_file(const char *filename)
{
switch_core_db_t *db;
if ((db_ret = switch_core_db_open(path, &db)) != SQLITE_OK) {
goto end;
}
- if ((db_ret = switch_core_db_exec(db, "PRAGMA synchronous=OFF;", NULL, NULL, NULL)) != SQLITE_OK) {
+ if ((db_ret = switch_core_db_connection_setup(db, SWITCH_FALSE)) != SQLITE_OK) {
goto end;
}
- if ((db_ret = switch_core_db_exec(db, "PRAGMA count_changes=OFF;", NULL, NULL, NULL)) != SQLITE_OK) {
- goto end;
+
+end:
+ if (db_ret != SQLITE_OK) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n", switch_core_db_errmsg(db));
+ switch_core_db_close(db);
+ db = NULL;
}
- if ((db_ret = switch_core_db_exec(db, "PRAGMA cache_size=8000;", NULL, NULL, NULL)) != SQLITE_OK) {
+ return db;
+}
+
+SWITCH_DECLARE(switch_core_db_t *) switch_core_db_open_in_memory(const char *uri)
+{
+ switch_core_db_t *db;
+ int db_ret;
+
+ if ((db_ret = switch_core_db_open_v2(uri, &db)) != SQLITE_OK) {
goto end;
}
- if ((db_ret = switch_core_db_exec(db, "PRAGMA temp_store=MEMORY;", NULL, NULL, NULL)) != SQLITE_OK) {
+ if ((db_ret = switch_core_db_connection_setup(db, SWITCH_TRUE)) != SQLITE_OK) {
goto end;
}
return new_dbh;
}
+static void destroy_handle(switch_cache_db_handle_t **dbh)
+{
+ if (dbh && *dbh && (*dbh)->pool) {
+ switch_core_destroy_memory_pool(&(*dbh)->pool);
+ *dbh = NULL;
+ }
+}
+
static void add_handle(switch_cache_db_handle_t *dbh, const char *db_str, const char *db_callsite_str, const char *thread_str)
{
switch_ssize_t hlen = -1;
del_handle(dbh_ptr);
switch_mutex_unlock(dbh_ptr->mutex);
- switch_core_destroy_memory_pool(&dbh_ptr->pool);
+ destroy_handle(&dbh_ptr);
}
}
diff = (time_t) prune - dbh->last_used;
}
- if (prune > 0 && (dbh->use_count || (diff < SQL_CACHE_TIMEOUT && !switch_test_flag(dbh, CDF_PRUNE)))) {
+ if (prune > 0 && (dbh->use_count || switch_test_flag(dbh, CDF_NONEXPIRING) || (diff < SQL_CACHE_TIMEOUT && !switch_test_flag(dbh, CDF_PRUNE)))) {
continue;
}
break;
case SCDB_TYPE_CORE_DB:
{
- switch_core_db_close(dbh->native_handle.core_db_dbh);
- dbh->native_handle.core_db_dbh = NULL;
+ switch_core_db_close(dbh->native_handle.core_db_dbh->handle);
+ dbh->native_handle.core_db_dbh->handle = NULL;
}
break;
}
if (!strncasecmp(dsn, "sqlite://", 9)) {
type = SCDB_TYPE_CORE_DB;
connection_options.core_db_options.db_path = (char *)(dsn + 9);
+ if (!strncasecmp(connection_options.core_db_options.db_path, "memory://", 9)) {
+ connection_options.core_db_options.in_memory = SWITCH_TRUE;
+ connection_options.core_db_options.db_path = (char *)(connection_options.core_db_options.db_path + 9);
+ }
}
else if ((!(i = strncasecmp(dsn, "odbc://", 7))) || (strchr(dsn + 2, ':') && !colon_slashes)) {
type = SCDB_TYPE_ODBC;
break;
case SCDB_TYPE_CORE_DB:
{
- db = switch_core_db_open_file(connection_options->core_db_options.db_path);
+ if (!connection_options->core_db_options.in_memory) {
+ db = switch_core_db_open_file(connection_options->core_db_options.db_path);
+ } else {
+ db = switch_core_db_open_in_memory(connection_options->core_db_options.db_path);
+ }
}
break;
if (database_interface_dbh) {
new_dbh->native_handle.database_interface_dbh = database_interface_dbh;
} else if (db) {
- new_dbh->native_handle.core_db_dbh = db;
+ if (!(new_dbh->native_handle.core_db_dbh = switch_core_alloc(new_dbh->pool, sizeof(*new_dbh->native_handle.core_db_dbh)))) {
+ destroy_handle(&new_dbh);
+ switch_core_db_close(db);
+ goto end;
+ }
+ new_dbh->native_handle.core_db_dbh->handle = db;
+ new_dbh->native_handle.core_db_dbh->in_memory = connection_options->core_db_options.in_memory;
} else if (odbc_dbh) {
new_dbh->native_handle.odbc_dbh = odbc_dbh;
}
break;
case SCDB_TYPE_CORE_DB:
{
- int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh, sql, NULL, NULL, &errmsg);
+ int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, sql, NULL, NULL, &errmsg);
type = "NATIVE";
if (ret == SWITCH_CORE_DB_OK) {
switch (dbh->type) {
case SCDB_TYPE_CORE_DB:
{
- return switch_core_db_changes(dbh->native_handle.core_db_dbh);
+ return switch_core_db_changes(dbh->native_handle.core_db_dbh->handle);
}
break;
case SCDB_TYPE_ODBC:
case SCDB_TYPE_CORE_DB:
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "try to load extension [%s]!\n", extension);
- return switch_core_db_load_extension(dbh->native_handle.core_db_dbh, extension);
+ return switch_core_db_load_extension(dbh->native_handle.core_db_dbh->handle, extension);
}
break;
case SCDB_TYPE_ODBC:
{
switch_core_db_stmt_t *stmt;
- if (switch_core_db_prepare(dbh->native_handle.core_db_dbh, sql, -1, &stmt, 0)) {
+ if (switch_core_db_prepare(dbh->native_handle.core_db_dbh->handle, sql, -1, &stmt, 0)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Statement Error [%s]!\n", sql);
goto end;
} else {
break;
case SCDB_TYPE_CORE_DB:
{
- int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh, sql, helper_callback, &h, &errmsg);
+ int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, sql, helper_callback, &h, &errmsg);
if (ret == SWITCH_CORE_DB_OK || ret == SWITCH_CORE_DB_ABORT) {
status = SWITCH_STATUS_SUCCESS;
break;
case SCDB_TYPE_CORE_DB:
{
- int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh, sql, helper_callback, &h, &errmsg);
+ int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, sql, helper_callback, &h, &errmsg);
if (ret == SWITCH_CORE_DB_OK || ret == SWITCH_CORE_DB_ABORT) {
status = SWITCH_STATUS_SUCCESS;
break;
case SCDB_TYPE_CORE_DB:
{
- int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh, sql, callback, pdata, &errmsg);
+ int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, sql, callback, pdata, &errmsg);
if (ret == SWITCH_CORE_DB_OK || ret == SWITCH_CORE_DB_ABORT) {
status = SWITCH_STATUS_SUCCESS;
break;
case SCDB_TYPE_CORE_DB:
{
- int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh, sql, callback, pdata, &errmsg);
+ int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, sql, callback, pdata, &errmsg);
if (ret == SWITCH_CORE_DB_OK || ret == SWITCH_CORE_DB_ABORT) {
status = SWITCH_STATUS_SUCCESS;
case SCDB_TYPE_CORE_DB:
{
char *errmsg = NULL;
- switch_core_db_exec(dbh->native_handle.core_db_dbh, test_sql, NULL, NULL, &errmsg);
+ switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, test_sql, NULL, NULL, &errmsg);
if (errmsg) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\nAuto Generating Table!\n", errmsg, test_sql);
switch_core_db_free(errmsg);
errmsg = NULL;
if (drop_sql) {
- switch_core_db_exec(dbh->native_handle.core_db_dbh, drop_sql, NULL, NULL, &errmsg);
+ switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, drop_sql, NULL, NULL, &errmsg);
}
if (errmsg) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Ignoring SQL ERR [%s]\n[%s]\n", errmsg, drop_sql);
switch_core_db_free(errmsg);
errmsg = NULL;
}
- switch_core_db_exec(dbh->native_handle.core_db_dbh, reactive_sql, NULL, NULL, &errmsg);
+ switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, reactive_sql, NULL, NULL, &errmsg);
if (errmsg) {
r = SWITCH_FALSE;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\n", errmsg, reactive_sql);
switch_cache_db_execute_sql(sql_manager.dbh, create_tasks_sql, NULL);
switch_cache_db_execute_sql(sql_manager.dbh, detailed_calls_sql, NULL);
switch_cache_db_execute_sql(sql_manager.dbh, basic_calls_sql, NULL);
+
+ if (sql_manager.dbh->native_handle.core_db_dbh->in_memory == SWITCH_TRUE) {
+ switch_set_flag(sql_manager.dbh, CDF_NONEXPIRING);
+ }
}
break;
}
used++;
}
- stream->write_function(stream, "%s\n\tType: %s\n\tLast used: %d\n\tTotal used: %ld\n\tFlags: %s, %s(%d)\n"
+ stream->write_function(stream, "%s\n\tType: %s\n\tLast used: %d\n\tTotal used: %ld\n\tFlags: %s, %s(%d)%s\n"
"\tCreator: %s\n\tLast User: %s\n",
cleankey_str,
switch_cache_db_type_name(dbh->type),
diff,
dbh->total_used_count,
locked ? "Locked" : "Unlocked",
- dbh->use_count ? "Attached" : "Detached", dbh->use_count, dbh->creator, dbh->last_user);
+ dbh->use_count ? "Attached" : "Detached", dbh->use_count, switch_test_flag(dbh, CDF_NONEXPIRING) ? ", Non-expiring" : "", dbh->creator, dbh->last_user);
}
stream->write_function(stream, "%d total. %d in use.\n", count, used);