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:
parent
51b317233a
commit
7d562ce85c
@ -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;
|
||||
}
|
||||
|
38
src/ssb.c
38
src/ssb.c
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
69
src/ssb.db.c
69
src/ssb.db.c
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user