Allow the DB writer to be used from a worker thread. Not well tested, just still trying to charge forward on moving all blocking work off the main thread.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4325 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2023-06-15 00:27:49 +00:00
parent 51b317233a
commit 7d562ce85c
11 changed files with 163 additions and 92 deletions

View File

@ -19,7 +19,6 @@ typedef struct _database_t
JSContext* context;
JSValue object;
void* task;
sqlite3* db;
const char* id;
} database_t;
@ -62,16 +61,12 @@ static JSValue _database_create(JSContext* context, JSValueConst this_val, int a
++_database_count;
JSValue object = JS_NewObjectClass(context, _database_class_id);
tf_task_t* task = tf_task_get(context);
sqlite3* db = tf_ssb_get_db(tf_task_get_ssb(task));
database_t* database = tf_malloc(sizeof(database_t));
*database = (database_t)
{
.task = JS_GetContextOpaque(context),
.context = context,
.object = object,
.db = db,
};
const char* id = JS_ToCString(context, argv[0]);
database->id = tf_strdup(id);
@ -105,8 +100,10 @@ static JSValue _database_get(JSContext* context, JSValueConst this_val, int argc
database_t* database = JS_GetOpaque(this_val, _database_class_id);
if (database)
{
tf_ssb_t* ssb = tf_task_get_ssb(database->task);
sqlite3_stmt* statement;
if (sqlite3_prepare(database->db, "SELECT value FROM properties WHERE id = ? AND key = ?", -1, &statement, NULL) == SQLITE_OK)
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
if (sqlite3_prepare(db, "SELECT value FROM properties WHERE id = ? AND key = ?", -1, &statement, NULL) == SQLITE_OK)
{
size_t length;
const char* keyString = JS_ToCStringLen(context, &length, argv[0]);
@ -119,6 +116,7 @@ static JSValue _database_get(JSContext* context, JSValueConst this_val, int argc
JS_FreeCString(context, keyString);
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
}
return entry;
}
@ -129,7 +127,9 @@ JSValue _database_set(JSContext* context, JSValueConst this_val, int argc, JSVal
if (database)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(database->db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES ($1, $2, $3)", -1, &statement, NULL) == SQLITE_OK)
tf_ssb_t* ssb = tf_task_get_ssb(database->task);
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
if (sqlite3_prepare(db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES ($1, $2, $3)", -1, &statement, NULL) == SQLITE_OK)
{
size_t keyLength;
const char* keyString = JS_ToCStringLen(context, &keyLength, argv[0]);
@ -145,6 +145,7 @@ JSValue _database_set(JSContext* context, JSValueConst this_val, int argc, JSVal
JS_FreeCString(context, valueString);
sqlite3_finalize(statement);
}
tf_ssb_release_db_writer(ssb, db);
}
return JS_UNDEFINED;
}
@ -156,9 +157,11 @@ static JSValue _database_exchange(JSContext* context, JSValueConst this_val, int
if (database)
{
sqlite3_stmt* statement;
tf_ssb_t* ssb = tf_task_get_ssb(database->task);
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
if (JS_IsNull(argv[1]) || JS_IsUndefined(argv[1]))
{
if (sqlite3_prepare(database->db, "INSERT INTO properties (id, key, value) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING", -1, &statement, NULL) == SQLITE_OK)
if (sqlite3_prepare(db, "INSERT INTO properties (id, key, value) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING", -1, &statement, NULL) == SQLITE_OK)
{
size_t key_length;
size_t set_length;
@ -169,14 +172,14 @@ static JSValue _database_exchange(JSContext* context, JSValueConst this_val, int
sqlite3_bind_text(statement, 3, set, set_length, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_DONE)
{
exchanged = sqlite3_changes(database->db) != 0 ? JS_TRUE : JS_FALSE;
exchanged = sqlite3_changes(db) != 0 ? JS_TRUE : JS_FALSE;
}
JS_FreeCString(context, key);
JS_FreeCString(context, set);
sqlite3_finalize(statement);
}
}
else if (sqlite3_prepare(database->db, "UPDATE properties SET value = $1 WHERE id = $2 AND key = $3 AND value = $4", -1, &statement, NULL) == SQLITE_OK)
else if (sqlite3_prepare(db, "UPDATE properties SET value = $1 WHERE id = $2 AND key = $3 AND value = $4", -1, &statement, NULL) == SQLITE_OK)
{
size_t key_length;
size_t expected_length;
@ -190,13 +193,14 @@ static JSValue _database_exchange(JSContext* context, JSValueConst this_val, int
sqlite3_bind_text(statement, 4, expected, expected_length, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_DONE)
{
exchanged = sqlite3_changes(database->db) != 0 ? JS_TRUE : JS_FALSE;
exchanged = sqlite3_changes(db) != 0 ? JS_TRUE : JS_FALSE;
}
JS_FreeCString(context, key);
JS_FreeCString(context, expected);
JS_FreeCString(context, set);
sqlite3_finalize(statement);
}
tf_ssb_release_db_writer(ssb, db);
}
return exchanged;
}
@ -207,7 +211,9 @@ JSValue _database_remove(JSContext* context, JSValueConst this_val, int argc, JS
if (database)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(database->db, "DELETE FROM properties WHERE id = $1 AND key = $2", -1, &statement, NULL) == SQLITE_OK)
tf_ssb_t* ssb = tf_task_get_ssb(database->task);
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
if (sqlite3_prepare(db, "DELETE FROM properties WHERE id = $1 AND key = $2", -1, &statement, NULL) == SQLITE_OK)
{
size_t keyLength;
const char* keyString = JS_ToCStringLen(context, &keyLength, argv[0]);
@ -219,6 +225,7 @@ JSValue _database_remove(JSContext* context, JSValueConst this_val, int argc, JS
JS_FreeCString(context, keyString);
sqlite3_finalize(statement);
}
tf_ssb_release_db_writer(ssb, db);
}
return JS_UNDEFINED;
}
@ -230,7 +237,9 @@ JSValue _database_get_all(JSContext* context, JSValueConst this_val, int argc, J
if (database)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(database->db, "SELECT key, value FROM properties WHERE id = $1", -1, &statement, NULL) == SQLITE_OK)
tf_ssb_t* ssb = tf_task_get_ssb(database->task);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
if (sqlite3_prepare(db, "SELECT key, value FROM properties WHERE id = $1", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, database->id, -1, NULL) == SQLITE_OK)
{
@ -243,6 +252,7 @@ JSValue _database_get_all(JSContext* context, JSValueConst this_val, int argc, J
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
}
return array;
}
@ -254,7 +264,9 @@ JSValue _database_get_like(JSContext* context, JSValueConst this_val, int argc,
if (database)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(database->db, "SELECT key, value FROM properties WHERE id = ? AND KEY LIKE ?", -1, &statement, NULL) == SQLITE_OK)
tf_ssb_t* ssb = tf_task_get_ssb(database->task);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
if (sqlite3_prepare(db, "SELECT key, value FROM properties WHERE id = ? AND KEY LIKE ?", -1, &statement, NULL) == SQLITE_OK)
{
const char* pattern = JS_ToCString(context, argv[0]);
if (sqlite3_bind_text(statement, 1, database->id, -1, NULL) == SQLITE_OK &&
@ -273,6 +285,7 @@ JSValue _database_get_like(JSContext* context, JSValueConst this_val, int argc,
JS_FreeCString(context, pattern);
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
}
return result;
}
@ -280,8 +293,8 @@ JSValue _database_get_like(JSContext* context, JSValueConst this_val, int argc,
static JSValue _databases_list(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv, int magic, JSValue* data)
{
tf_task_t* task = tf_task_get(context);
sqlite3* db = tf_ssb_get_db(tf_task_get_ssb(task));
tf_ssb_t* ssb = tf_task_get_ssb(task);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
JSValue array = JS_UNDEFINED;
sqlite3_stmt* statement;
if (sqlite3_prepare(db, "SELECT DISTINCT id FROM properties WHERE id LIKE ?", -1, &statement, NULL) == SQLITE_OK)
@ -299,5 +312,6 @@ static JSValue _databases_list(JSContext* context, JSValueConst this_val, int ar
JS_FreeCString(context, pattern);
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
return array;
}

View File

@ -180,9 +180,10 @@ typedef struct _tf_ssb_t
tf_trace_t* trace;
const char* db_path;
sqlite3* db;
uv_mutex_t db_readers_lock;
uv_mutex_t db_writer_lock;
sqlite3* db_writer;
sqlite3** db_readers;
int db_readers_count;
@ -2099,6 +2100,7 @@ tf_ssb_t* tf_ssb_create(uv_loop_t* loop, JSContext* context, const char* db_path
}
uv_mutex_init(&ssb->db_readers_lock);
uv_mutex_init(&ssb->db_writer_lock);
JS_NewClassID(&_connection_class_id);
JSClassDef def =
@ -2109,7 +2111,7 @@ tf_ssb_t* tf_ssb_create(uv_loop_t* loop, JSContext* context, const char* db_path
JS_NewClass(JS_GetRuntime(ssb->context), _connection_class_id, &def);
ssb->db_path = tf_strdup(db_path);
sqlite3_open(db_path, &ssb->db);
sqlite3_open_v2(db_path, &ssb->db_writer, SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI, NULL);
tf_ssb_db_init(ssb);
if (loop)
@ -2142,11 +2144,6 @@ tf_ssb_t* tf_ssb_create(uv_loop_t* loop, JSContext* context, const char* db_path
return ssb;
}
sqlite3* tf_ssb_get_db(tf_ssb_t* ssb)
{
return ssb->db;
}
sqlite3* tf_ssb_acquire_db_reader(tf_ssb_t* ssb)
{
sqlite3* db = NULL;
@ -2157,7 +2154,7 @@ sqlite3* tf_ssb_acquire_db_reader(tf_ssb_t* ssb)
}
else
{
sqlite3_open_v2(ssb->db_path, &db, SQLITE_OPEN_READONLY, NULL);
sqlite3_open_v2(ssb->db_path, &db, SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, NULL);
tf_ssb_db_init_reader(db);
tf_trace_sqlite(ssb->trace, db);
}
@ -2173,6 +2170,22 @@ void tf_ssb_release_db_reader(tf_ssb_t* ssb, sqlite3* db)
uv_mutex_unlock(&ssb->db_readers_lock);
}
sqlite3* tf_ssb_acquire_db_writer(tf_ssb_t* ssb)
{
uv_mutex_lock(&ssb->db_writer_lock);
sqlite3* writer = ssb->db_writer;
assert(writer);
ssb->db_writer = NULL;
return writer;
}
void tf_ssb_release_db_writer(tf_ssb_t* ssb, sqlite3* db)
{
assert(ssb->db_writer == NULL);
ssb->db_writer = db;
uv_mutex_unlock(&ssb->db_writer_lock);
}
uv_loop_t* tf_ssb_get_loop(tf_ssb_t* ssb)
{
return ssb->loop;
@ -2205,10 +2218,12 @@ void tf_ssb_get_private_key(tf_ssb_t* ssb, uint8_t* out_private, size_t private_
void tf_ssb_set_trace(tf_ssb_t* ssb, tf_trace_t* trace)
{
ssb->trace = trace;
if (trace && ssb->db)
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
if (trace && db)
{
tf_trace_sqlite(trace, ssb->db);
tf_trace_sqlite(trace, db);
}
tf_ssb_release_db_writer(ssb, db);
}
tf_trace_t* tf_ssb_get_trace(tf_ssb_t* ssb)
@ -2336,7 +2351,7 @@ void tf_ssb_destroy(tf_ssb_t* ssb)
JS_FreeContext(ssb->context);
JS_FreeRuntime(ssb->runtime);
}
sqlite3_close(ssb->db);
sqlite3_close(ssb->db_writer);
while (ssb->broadcasts)
{
tf_ssb_broadcast_t* broadcast = ssb->broadcasts;
@ -2357,6 +2372,7 @@ void tf_ssb_destroy(tf_ssb_t* ssb)
}
tf_free(ssb->db_readers);
uv_mutex_destroy(&ssb->db_readers_lock);
uv_mutex_destroy(&ssb->db_writer_lock);
tf_free((void*)ssb->db_path);
tf_free(ssb);
}

View File

@ -16,7 +16,6 @@
typedef struct _tf_ssb_connections_t
{
tf_ssb_t* ssb;
sqlite3* db;
uv_timer_t timer;
} tf_ssb_connections_t;
@ -55,7 +54,8 @@ static bool _tf_ssb_connections_get_next_connection(tf_ssb_connections_t* connec
{
bool result = false;
sqlite3_stmt* statement;
if (sqlite3_prepare(connections->db, "SELECT host, port, key FROM connections WHERE last_attempt IS NULL OR (strftime('%s', 'now') - last_attempt > $1) ORDER BY last_attempt LIMIT 1", -1, &statement, NULL) == SQLITE_OK)
sqlite3* db = tf_ssb_acquire_db_reader(connections->ssb);
if (sqlite3_prepare(db, "SELECT host, port, key FROM connections WHERE last_attempt IS NULL OR (strftime('%s', 'now') - last_attempt > $1) ORDER BY last_attempt LIMIT 1", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_int(statement, 1, 60000) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_ROW)
@ -69,8 +69,9 @@ static bool _tf_ssb_connections_get_next_connection(tf_ssb_connections_t* connec
}
else
{
tf_printf("prepare: %s\n", sqlite3_errmsg(connections->db));
tf_printf("prepare: %s\n", sqlite3_errmsg(db));
}
tf_ssb_release_db_reader(connections->ssb, db);
return result;
}
@ -100,7 +101,6 @@ tf_ssb_connections_t* tf_ssb_connections_create(tf_ssb_t* ssb)
tf_ssb_connections_t* connections = tf_malloc(sizeof(tf_ssb_connections_t));
memset(connections, 0, sizeof(*connections));
connections->ssb = ssb;
connections->db = tf_ssb_get_db(ssb);
tf_ssb_add_connections_changed_callback(ssb, _tf_ssb_connections_changed_callback, NULL, connections);
@ -128,7 +128,8 @@ void tf_ssb_connections_destroy(tf_ssb_connections_t* connections)
void tf_ssb_connections_store(tf_ssb_connections_t* connections, const char* host, int port, const char* key)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(connections->db, "INSERT INTO connections (host, port, key) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING", -1, &statement, NULL) == SQLITE_OK)
sqlite3* db = tf_ssb_acquire_db_writer(connections->ssb);
if (sqlite3_prepare(db, "INSERT INTO connections (host, port, key) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, host, -1, NULL) == SQLITE_OK &&
sqlite3_bind_int(statement, 2, port) == SQLITE_OK &&
@ -137,17 +138,19 @@ void tf_ssb_connections_store(tf_ssb_connections_t* connections, const char* hos
int r = sqlite3_step(statement);
if (r != SQLITE_DONE)
{
tf_printf("tf_ssb_connections_store: %d, %s.\n", r, sqlite3_errmsg(connections->db));
tf_printf("tf_ssb_connections_store: %d, %s.\n", r, sqlite3_errmsg(db));
}
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_writer(connections->ssb, db);
}
void tf_ssb_connections_set_attempted(tf_ssb_connections_t* connections, const char* host, int port, const char* key)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(connections->db, "UPDATE connections SET last_attempt = strftime('%s', 'now') WHERE host = $1 AND port = $2 AND key = $3", -1, &statement, NULL) == SQLITE_OK)
sqlite3* db = tf_ssb_acquire_db_writer(connections->ssb);
if (sqlite3_prepare(db, "UPDATE connections SET last_attempt = strftime('%s', 'now') WHERE host = $1 AND port = $2 AND key = $3", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, host, -1, NULL) == SQLITE_OK &&
sqlite3_bind_int(statement, 2, port) == SQLITE_OK &&
@ -155,17 +158,19 @@ void tf_ssb_connections_set_attempted(tf_ssb_connections_t* connections, const c
{
if (sqlite3_step(statement) != SQLITE_DONE)
{
tf_printf("tf_ssb_connections_set_attempted: %s.\n", sqlite3_errmsg(connections->db));
tf_printf("tf_ssb_connections_set_attempted: %s.\n", sqlite3_errmsg(db));
}
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_writer(connections->ssb, db);
}
void tf_ssb_connections_set_succeeded(tf_ssb_connections_t* connections, const char* host, int port, const char* key)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(connections->db, "UPDATE connections SET last_success = strftime('%s', 'now') WHERE host = $1 AND port = $2 AND key = $3", -1, &statement, NULL) == SQLITE_OK)
sqlite3* db = tf_ssb_acquire_db_writer(connections->ssb);
if (sqlite3_prepare(db, "UPDATE connections SET last_success = strftime('%s', 'now') WHERE host = $1 AND port = $2 AND key = $3", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, host, -1, NULL) == SQLITE_OK &&
sqlite3_bind_int(statement, 2, port) == SQLITE_OK &&
@ -173,9 +178,10 @@ void tf_ssb_connections_set_succeeded(tf_ssb_connections_t* connections, const c
{
if (sqlite3_step(statement) != SQLITE_DONE)
{
tf_printf("tf_ssb_connections_set_succeeded: %s.\n", sqlite3_errmsg(connections->db));
tf_printf("tf_ssb_connections_set_succeeded: %s.\n", sqlite3_errmsg(db));
}
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_writer(connections->ssb, db);
}

View File

@ -67,7 +67,7 @@ void tf_ssb_db_init_reader(sqlite3* db)
void tf_ssb_db_init(tf_ssb_t* ssb)
{
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
_tf_ssb_db_init_internal(db);
_tf_ssb_db_exec(db,
"CREATE TABLE IF NOT EXISTS messages ("
@ -222,6 +222,7 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
tf_printf("Adding sequence_before_author column.\n");
_tf_ssb_db_exec(db, "ALTER TABLE messages ADD COLUMN sequence_before_author INTEGER");
}
tf_ssb_release_db_writer(ssb, db);
}
static bool _tf_ssb_db_previous_message_exists(sqlite3* db, const char* author, int64_t sequence, const char* previous)
@ -266,7 +267,7 @@ bool tf_ssb_db_store_message(tf_ssb_t* ssb, JSContext* context, const char* id,
JS_ToInt64(context, &sequence, sequenceval);
JS_FreeValue(context, sequenceval);
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
sqlite3_stmt* statement;
int64_t last_row_id = -1;
@ -315,7 +316,7 @@ bool tf_ssb_db_store_message(tf_ssb_t* ssb, JSContext* context, const char* id,
}
else
{
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
tf_printf("%s: prepare failed: %s\n", __FUNCTION__, sqlite3_errmsg(db));
}
JS_FreeCString(context, contentstr);
@ -348,9 +349,10 @@ bool tf_ssb_db_store_message(tf_ssb_t* ssb, JSContext* context, const char* id,
}
else
{
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
tf_printf("%s: prepare failed: %s\n", __FUNCTION__, sqlite3_errmsg(db));
}
}
tf_ssb_release_db_writer(ssb, db);
JS_FreeCString(context, author);
JS_FreeCString(context, previous);
@ -361,8 +363,9 @@ bool tf_ssb_db_message_content_get(tf_ssb_t* ssb, const char* id, uint8_t** out_
{
bool result = false;
sqlite3_stmt* statement;
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
const char* query = "SELECT content FROM messages WHERE id = ?";
if (sqlite3_prepare(tf_ssb_get_db(ssb), query, -1, &statement, NULL) == SQLITE_OK)
if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_ROW)
@ -383,6 +386,7 @@ bool tf_ssb_db_message_content_get(tf_ssb_t* ssb, const char* id, uint8_t** out_
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
return result;
}
@ -390,8 +394,9 @@ bool tf_ssb_db_blob_has(tf_ssb_t* ssb, const char* id)
{
bool result = false;
sqlite3_stmt* statement;
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
const char* query = "SELECT COUNT(*) FROM blobs WHERE id = $1";
if (sqlite3_prepare(tf_ssb_get_db(ssb), query, -1, &statement, NULL) == SQLITE_OK)
if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_ROW)
@ -400,6 +405,7 @@ bool tf_ssb_db_blob_has(tf_ssb_t* ssb, const char* id)
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
return result;
}
@ -407,8 +413,9 @@ bool tf_ssb_db_blob_get(tf_ssb_t* ssb, const char* id, uint8_t** out_blob, size_
{
bool result = false;
sqlite3_stmt* statement;
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
const char* query = "SELECT content FROM blobs WHERE id = $1";
if (sqlite3_prepare(tf_ssb_get_db(ssb), query, -1, &statement, NULL) == SQLITE_OK)
if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_ROW)
@ -432,13 +439,14 @@ bool tf_ssb_db_blob_get(tf_ssb_t* ssb, const char* id, uint8_t** out_blob, size_
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
return result;
}
bool tf_ssb_db_blob_store(tf_ssb_t* ssb, const uint8_t* blob, size_t size, char* out_id, size_t out_id_size, bool* out_new)
{
bool result = false;
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
sqlite3_stmt* statement;
uint8_t hash[crypto_hash_sha256_BYTES];
@ -468,8 +476,9 @@ bool tf_ssb_db_blob_store(tf_ssb_t* ssb, const uint8_t* blob, size_t size, char*
}
else
{
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
tf_printf("%s: prepare failed: %s\n", __FUNCTION__, sqlite3_errmsg(db));
}
tf_ssb_release_db_writer(ssb, db);
if (rows)
{
@ -496,7 +505,8 @@ bool tf_ssb_db_get_message_by_author_and_sequence(tf_ssb_t* ssb, const char* aut
bool found = false;
sqlite3_stmt* statement;
const char* query = "SELECT id, timestamp, content FROM messages WHERE author = $1 AND sequence = $2";
if (sqlite3_prepare(tf_ssb_get_db(ssb), query, -1, &statement, NULL) == SQLITE_OK)
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, author, -1, NULL) == SQLITE_OK &&
sqlite3_bind_int64(statement, 2, sequence) == SQLITE_OK &&
@ -520,8 +530,9 @@ bool tf_ssb_db_get_message_by_author_and_sequence(tf_ssb_t* ssb, const char* aut
}
else
{
tf_printf("prepare failed: %s\n", sqlite3_errmsg(tf_ssb_get_db(ssb)));
tf_printf("%s: prepare failed: %s\n", __FUNCTION__, sqlite3_errmsg(db));
}
tf_ssb_release_db_reader(ssb, db);
return found;
}
@ -529,8 +540,9 @@ bool tf_ssb_db_get_latest_message_by_author(tf_ssb_t* ssb, const char* author, i
{
bool found = false;
sqlite3_stmt* statement;
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
const char* query = "SELECT id, sequence FROM messages WHERE author = $1 AND sequence = (SELECT MAX(sequence) FROM messages WHERE author = $1)";
if (sqlite3_prepare(tf_ssb_get_db(ssb), query, -1, &statement, NULL) == SQLITE_OK)
if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, author, -1, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_ROW)
@ -549,8 +561,9 @@ bool tf_ssb_db_get_latest_message_by_author(tf_ssb_t* ssb, const char* author, i
}
else
{
tf_printf("prepare failed: %s\n", sqlite3_errmsg(tf_ssb_get_db(ssb)));
tf_printf("%s: prepare failed: %s\n", __FUNCTION__, sqlite3_errmsg(db));
}
tf_ssb_release_db_reader(ssb, db);
return found;
}
@ -686,7 +699,7 @@ static int _tf_ssb_sqlite_authorizer(void* user_data, int action_code, const cha
JSValue tf_ssb_db_visit_query(tf_ssb_t* ssb, const char* query, const JSValue binds, void (*callback)(JSValue row, void* user_data), void* user_data)
{
JSValue result = JS_UNDEFINED;
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
JSContext* context = tf_ssb_get_context(ssb);
sqlite3_stmt* statement;
sqlite3_set_authorizer(db, _tf_ssb_sqlite_authorizer, ssb);
@ -721,6 +734,7 @@ JSValue tf_ssb_db_visit_query(tf_ssb_t* ssb, const char* query, const JSValue bi
result = JS_ThrowInternalError(context, "SQL Error %s: preparing \"%s\".", sqlite3_errmsg(db), query);
}
sqlite3_set_authorizer(db, NULL, NULL);
tf_ssb_release_db_reader(ssb, db);
return result;
}
@ -874,7 +888,7 @@ bool tf_ssb_db_check(sqlite3* db, const char* check_author)
int tf_ssb_db_identity_get_count_for_user(tf_ssb_t* ssb, const char* user)
{
int count = 0;
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "SELECT COUNT(*) FROM identities WHERE user = ?", -1, &statement, NULL) == SQLITE_OK)
{
@ -887,6 +901,7 @@ int tf_ssb_db_identity_get_count_for_user(tf_ssb_t* ssb, const char* user)
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
return count;
}
@ -911,7 +926,7 @@ bool tf_ssb_db_identity_create(tf_ssb_t* ssb, const char* user, uint8_t* out_pub
bool tf_ssb_db_identity_add(tf_ssb_t* ssb, const char* user, const char* public_key, const char* private_key)
{
bool added = false;
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "INSERT INTO identities (user, public_key, private_key) VALUES (?, ?, ?) ON CONFLICT DO NOTHING", -1, &statement, NULL) == SQLITE_OK)
{
@ -929,12 +944,13 @@ bool tf_ssb_db_identity_add(tf_ssb_t* ssb, const char* user, const char* public_
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_writer(ssb, db);
return added;
}
void tf_ssb_db_identity_visit(tf_ssb_t* ssb, const char* user, void (*callback)(const char* identity, void* user_data), void* user_data)
{
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "SELECT public_key FROM identities WHERE user = ? ORDER BY public_key", -1, &statement, NULL) == SQLITE_OK)
{
@ -947,11 +963,12 @@ void tf_ssb_db_identity_visit(tf_ssb_t* ssb, const char* user, void (*callback)(
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
}
void tf_ssb_db_identity_visit_all(tf_ssb_t* ssb, void (*callback)(const char* identity, void* user_data), void* user_data)
{
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "SELECT public_key FROM identities ORDER BY public_key", -1, &statement, NULL) == SQLITE_OK)
{
@ -961,13 +978,14 @@ void tf_ssb_db_identity_visit_all(tf_ssb_t* ssb, void (*callback)(const char* id
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
}
bool tf_ssb_db_identity_get_private_key(tf_ssb_t* ssb, const char* user, const char* public_key, uint8_t* out_private_key, size_t private_key_size)
{
bool success = false;
memset(out_private_key, 0, crypto_sign_SECRETKEYBYTES);
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "SELECT private_key FROM identities WHERE user = ? AND public_key = ?", -1, &statement, NULL) == SQLITE_OK)
{
@ -983,6 +1001,7 @@ bool tf_ssb_db_identity_get_private_key(tf_ssb_t* ssb, const char* user, const c
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
return success;
}
@ -1050,7 +1069,7 @@ static following_t* _get_following(tf_ssb_t* ssb, const char* id, following_t***
if (depth < max_depth && !already_populated)
{
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "SELECT json_extract(content, '$.contact'), json_extract(content, '$.following'), json_extract(content, '$.blocking') FROM messages WHERE author = ? AND json_extract(content, '$.type') = 'contact' ORDER BY sequence", -1, &statement, NULL) == SQLITE_OK)
{
@ -1081,6 +1100,7 @@ static following_t* _get_following(tf_ssb_t* ssb, const char* id, following_t***
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
}
return entry;
}
@ -1147,7 +1167,7 @@ JSValue tf_ssb_db_get_message_by_id( tf_ssb_t* ssb, const char* id, bool is_keys
{
JSValue result = JS_UNDEFINED;
JSContext* context = tf_ssb_get_context(ssb);
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement;
if (sqlite3_prepare(db, "SELECT previous, author, id, sequence, timestamp, hash, content, signature, sequence_before_author FROM messages WHERE id = ?", -1, &statement, NULL) == SQLITE_OK)
{
@ -1182,12 +1202,13 @@ JSValue tf_ssb_db_get_message_by_id( tf_ssb_t* ssb, const char* id, bool is_keys
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
return result;
}
tf_ssb_db_stored_connection_t* tf_ssb_db_get_stored_connections(tf_ssb_t* ssb, int* out_count)
{
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
tf_ssb_db_stored_connection_t* result = NULL;
int count = 0;
@ -1207,6 +1228,7 @@ tf_ssb_db_stored_connection_t* tf_ssb_db_get_stored_connections(tf_ssb_t* ssb, i
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
*out_count = count;
return result;
@ -1214,7 +1236,7 @@ tf_ssb_db_stored_connection_t* tf_ssb_db_get_stored_connections(tf_ssb_t* ssb, i
void tf_ssb_db_forget_stored_connection(tf_ssb_t* ssb, const char* address, int port, const char* pubkey)
{
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
sqlite3_stmt* statement;
if (sqlite3_prepare(db, "DELETE FROM connections WHERE host = ? AND port = ? AND key = ?", -1, &statement, NULL) == SQLITE_OK)
{
@ -1227,4 +1249,5 @@ void tf_ssb_db_forget_stored_connection(tf_ssb_t* ssb, const char* address, int
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_writer(ssb, db);
}

View File

@ -87,9 +87,10 @@ void tf_ssb_export(tf_ssb_t* ssb, const char* key)
}
char app_blob_id[64] = { 0 };
sqlite3_busy_timeout(tf_ssb_get_db(ssb), 10000);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_busy_timeout(db, 10000);
sqlite3_stmt* statement;
if (sqlite3_prepare(tf_ssb_get_db(ssb), "SELECT value FROM properties WHERE id = $1 AND key = 'path:' || $2", -1, &statement, NULL) == SQLITE_OK)
if (sqlite3_prepare(db, "SELECT value FROM properties WHERE id = $1 AND key = 'path:' || $2", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 2, path, -1, NULL) == SQLITE_OK &&
@ -105,6 +106,7 @@ void tf_ssb_export(tf_ssb_t* ssb, const char* key)
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
if (!*app_blob_id)
{

View File

@ -69,9 +69,10 @@ typedef struct _tf_ssb_blob_wants_t
tf_ssb_t* tf_ssb_create(uv_loop_t* loop, JSContext* context, const char* db_path);
void tf_ssb_destroy(tf_ssb_t* ssb);
sqlite3* tf_ssb_get_db(tf_ssb_t* ssb);
sqlite3* tf_ssb_acquire_db_reader(tf_ssb_t* ssb);
void tf_ssb_release_db_reader(tf_ssb_t* ssb, sqlite3* db);
sqlite3* tf_ssb_acquire_db_writer(tf_ssb_t* ssb);
void tf_ssb_release_db_writer(tf_ssb_t* ssb, sqlite3* db);
uv_loop_t* tf_ssb_get_loop(tf_ssb_t* ssb);
void tf_ssb_generate_keys(tf_ssb_t* ssb);

View File

@ -20,7 +20,8 @@ static void _tf_ssb_import_add_app(tf_ssb_t* ssb, const char* user, const char*
sqlite3_stmt* statement;
JSContext* context = tf_ssb_get_context(ssb);
JSValue apps = JS_UNDEFINED;
if (sqlite3_prepare(tf_ssb_get_db(ssb), "SELECT value FROM properties WHERE id = $1 AND key = 'apps'", -1, &statement, NULL) == SQLITE_OK)
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
if (sqlite3_prepare(db, "SELECT value FROM properties WHERE id = $1 AND key = 'apps'", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_ROW)
@ -68,7 +69,7 @@ static void _tf_ssb_import_add_app(tf_ssb_t* ssb, const char* user, const char*
JSValue json = JS_JSONStringify(context, out_apps, JS_NULL, JS_NULL);
const char* text = JS_ToCString(context, json);
if (sqlite3_prepare(tf_ssb_get_db(ssb), "INSERT OR REPLACE INTO properties (id, key, value) VALUES ($1, 'apps', $2)", -1, &statement, NULL) == SQLITE_OK)
if (sqlite3_prepare(db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES ($1, 'apps', $2)", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 2, text, -1, NULL) == SQLITE_OK &&
@ -77,6 +78,7 @@ static void _tf_ssb_import_add_app(tf_ssb_t* ssb, const char* user, const char*
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_writer(ssb, db);
JS_FreeCString(context, text);
JS_FreeValue(context, json);
@ -160,19 +162,21 @@ static void _tf_ssb_import_recursive_add_files(tf_ssb_t* ssb, uv_loop_t* loop, J
static bool _tf_ssb_register_app(tf_ssb_t* ssb, const char* user, const char* app, const char* id)
{
bool result = false;
sqlite3_stmt* statement;
if (sqlite3_prepare(tf_ssb_get_db(ssb), "INSERT OR REPLACE INTO properties (id, key, value) VALUES ($1, 'path:' || $2, $3)", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK &&
sqlite3_stmt* statement;
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
if (sqlite3_prepare(db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES ($1, 'path:' || $2, $3)", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 2, app, -1, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, id, -1, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_DONE)
{
result = sqlite3_changes(tf_ssb_get_db(ssb)) != 0;
}
sqlite3_finalize(statement);
}
return result;
{
result = sqlite3_changes(db) != 0;
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_writer(ssb, db);
return result;
}
static void _tf_ssb_import_app_json(tf_ssb_t* ssb, uv_loop_t* loop, JSContext* context, const char* user, const char* path)
@ -206,7 +210,7 @@ static void _tf_ssb_import_app_json(tf_ssb_t* ssb, uv_loop_t* loop, JSContext* c
if (_tf_ssb_register_app(ssb, user, app, id))
{
tf_printf("Registered %s path:%s as %s.\n", user, app, id);
tf_printf("Registered %s path:%s as %s.\n", user, app, id);
_tf_ssb_import_add_app(ssb, user, app);
}
}
@ -229,7 +233,6 @@ static void _tf_ssb_import_app_json(tf_ssb_t* ssb, uv_loop_t* loop, JSContext* c
void tf_ssb_import(tf_ssb_t* ssb, const char* user, const char* path)
{
uv_fs_t req = { 0 };
sqlite3_busy_timeout(tf_ssb_get_db(ssb), 10000);
int r = uv_fs_scandir(tf_ssb_get_loop(ssb), &req, path, 0, NULL);
if (r >= 0)
{
@ -334,7 +337,7 @@ static void _tf_ssb_import_app_json_from_zip(tf_ssb_t* ssb, unzFile zip, JSConte
if (_tf_ssb_register_app(ssb, user, app, id))
{
tf_printf("Registered %s path:%s as %s.\n", user, app, id);
tf_printf("Registered %s path:%s as %s.\n", user, app, id);
_tf_ssb_import_add_app(ssb, user, app);
}
}

View File

@ -1091,7 +1091,7 @@ static JSValue _tf_ssb_private_message_encrypt(JSContext* context, JSValueConst
if (JS_IsUndefined(result))
{
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
uint8_t private_key[crypto_sign_SECRETKEYBYTES] = { 0 };
if (_tf_ssb_get_private_key_curve25519(db, signer_user, signer_identity, private_key))
@ -1167,6 +1167,7 @@ static JSValue _tf_ssb_private_message_encrypt(JSContext* context, JSValueConst
{
result = JS_ThrowInternalError(context, "Unable to get key for ID %s of user %s.", signer_identity, signer_user);
}
tf_ssb_release_db_reader(ssb, db);
}
JS_FreeCString(context, signer_user);
@ -1187,7 +1188,7 @@ static JSValue _tf_ssb_private_message_decrypt(JSContext* context, JSValueConst
uint8_t private_key[crypto_sign_SECRETKEYBYTES] = { 0 };
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
if (_tf_ssb_get_private_key_curve25519(db, user, identity, private_key))
{
uint8_t* decoded = tf_malloc(message_size);
@ -1238,6 +1239,7 @@ static JSValue _tf_ssb_private_message_decrypt(JSContext* context, JSValueConst
{
result = JS_ThrowInternalError(context, "Private key not found for user %s with id %s.", user, identity);
}
tf_ssb_release_db_reader(ssb, db);
JS_FreeCString(context, user);
JS_FreeCString(context, identity);

View File

@ -141,7 +141,7 @@ static void _tf_ssb_rpc_request_more_blobs(tf_ssb_connection_t* connection)
JSContext* context = tf_ssb_connection_get_context(connection);
tf_ssb_blob_wants_t* blob_wants = tf_ssb_connection_get_blob_wants_state(connection);
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement;
if (sqlite3_prepare(db, "SELECT id FROM blob_wants_view WHERE id > ? ORDER BY id LIMIT 32", -1, &statement, NULL) == SQLITE_OK)
{
@ -160,6 +160,7 @@ static void _tf_ssb_rpc_request_more_blobs(tf_ssb_connection_t* connection)
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
}
static void _tf_ssb_rpc_blobs_createWants(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
@ -192,7 +193,7 @@ static bool _get_global_setting_bool(tf_ssb_t* ssb, const char* name, bool defau
{
bool result = default_value;
JSContext* context = tf_ssb_get_context(ssb);
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement;
if (sqlite3_prepare(db, "SELECT value FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
{
@ -209,6 +210,7 @@ static bool _get_global_setting_bool(tf_ssb_t* ssb, const char* name, bool defau
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
return result;
}
@ -216,7 +218,7 @@ static bool _get_global_setting_string(tf_ssb_t* ssb, const char* name, char* ou
{
bool result = false;
JSContext* context = tf_ssb_get_context(ssb);
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement;
if (sqlite3_prepare(db, "SELECT value FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
{
@ -236,6 +238,7 @@ static bool _get_global_setting_string(tf_ssb_t* ssb, const char* name, char* ou
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
return result;
}
@ -698,7 +701,7 @@ static void _tf_ssb_connection_send_history_stream_internal(tf_ssb_connection_t*
{
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
JSContext* context = tf_ssb_get_context(ssb);
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement;
const int k_max = 32;
int64_t max_sequence_seen = 0;
@ -740,6 +743,7 @@ static void _tf_ssb_connection_send_history_stream_internal(tf_ssb_connection_t*
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
if (max_sequence_seen == sequence + k_max - 1)
{

View File

@ -127,9 +127,9 @@ void tf_ssb_test_ssb(const tf_test_options_t* options)
uv_loop_t loop = { 0 };
uv_loop_init(&loop);
tf_ssb_t* ssb0 = tf_ssb_create(&loop, NULL, ":memory:");
tf_ssb_t* ssb0 = tf_ssb_create(&loop, NULL, "file:db0?mode=memory&cache=shared");
tf_ssb_register(tf_ssb_get_context(ssb0), ssb0);
tf_ssb_t* ssb1 = tf_ssb_create(&loop, NULL, ":memory:");
tf_ssb_t* ssb1 = tf_ssb_create(&loop, NULL, "file:db1?mode=memory&cache=shared");
tf_ssb_register(tf_ssb_get_context(ssb1), ssb1);
uv_idle_t idle0 = { .data = ssb0 };
@ -311,11 +311,11 @@ void tf_ssb_test_rooms(const tf_test_options_t* options)
uv_loop_t loop = { 0 };
uv_loop_init(&loop);
tf_ssb_t* ssb0 = tf_ssb_create(&loop, NULL, ":memory:");
tf_ssb_t* ssb0 = tf_ssb_create(&loop, NULL, "file:db0?mode=memory&cache=shared");
tf_ssb_register(tf_ssb_get_context(ssb0), ssb0);
tf_ssb_t* ssb1 = tf_ssb_create(&loop, NULL, ":memory:");
tf_ssb_t* ssb1 = tf_ssb_create(&loop, NULL, "file:db1?mode=memory&cache=shared");
tf_ssb_register(tf_ssb_get_context(ssb1), ssb1);
tf_ssb_t* ssb2 = tf_ssb_create(&loop, NULL, ":memory:");
tf_ssb_t* ssb2 = tf_ssb_create(&loop, NULL, "file:db2?mode=memory&cache=shared");
tf_ssb_register(tf_ssb_get_context(ssb2), ssb2);
uv_idle_t idle0 = { .data = ssb0 };
@ -555,7 +555,7 @@ void tf_ssb_test_bench(const tf_test_options_t* options)
uv_loop_t loop = { 0 };
uv_loop_init(&loop);
tf_ssb_t* ssb0 = tf_ssb_create(&loop, NULL, ":memory:");
tf_ssb_t* ssb0 = tf_ssb_create(&loop, NULL, "file:db0?mode=memory&cache=shared");
tf_ssb_generate_keys(ssb0);
char id0[k_id_base64_len] = { 0 };
@ -579,7 +579,7 @@ void tf_ssb_test_bench(const tf_test_options_t* options)
clock_gettime(CLOCK_REALTIME, &end_time);
tf_printf("insert = %f seconds\n", (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) / 1e9);
tf_ssb_t* ssb1 = tf_ssb_create(&loop, NULL, ":memory:");
tf_ssb_t* ssb1 = tf_ssb_create(&loop, NULL, "file:db1?mode=memory&cache=shared");
tf_ssb_generate_keys(ssb1);
uint8_t id0bin[k_id_bin_len];
tf_ssb_id_str_to_bin(id0bin, id0);

View File

@ -236,7 +236,7 @@ static void _test_database(const tf_test_options_t* options)
unlink("out/testdb.sqlite");
char command[256];
snprintf(command, sizeof(command), "%s run --ssb-port=0 --db-path=:memory: --db-path=out/testdb.sqlite -s out/test.js", options->exe_path);
snprintf(command, sizeof(command), "%s run --ssb-port=0 --db-path=file:db?mode=memory\\&cache=shared -s out/test.js", options->exe_path);
tf_printf("%s\n", command);
int result = system(command);
tf_printf("returned %d\n", WEXITSTATUS(result));