forked from cory/tildefriends
Move reading settings from the database off of the main thread. It now happens periodically in a worker, which means I don't think there's anything blocking the main thread anymore.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4504 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
parent
13c8b05f9a
commit
29d2a45abc
153
src/ssb.c
153
src/ssb.c
@ -188,6 +188,7 @@ typedef struct _tf_ssb_t
|
|||||||
uv_timer_t broadcast_cleanup_timer;
|
uv_timer_t broadcast_cleanup_timer;
|
||||||
uv_timer_t broadcast_timer;
|
uv_timer_t broadcast_timer;
|
||||||
uv_timer_t trace_timer;
|
uv_timer_t trace_timer;
|
||||||
|
uv_timer_t settings_timer;
|
||||||
uv_tcp_t server;
|
uv_tcp_t server;
|
||||||
|
|
||||||
uint8_t pub[crypto_sign_PUBLICKEYBYTES];
|
uint8_t pub[crypto_sign_PUBLICKEYBYTES];
|
||||||
@ -236,6 +237,8 @@ typedef struct _tf_ssb_t
|
|||||||
int ref_count;
|
int ref_count;
|
||||||
|
|
||||||
uv_thread_t thread_self;
|
uv_thread_t thread_self;
|
||||||
|
bool is_room;
|
||||||
|
char* room_name;
|
||||||
} tf_ssb_t;
|
} tf_ssb_t;
|
||||||
|
|
||||||
typedef struct _tf_ssb_connection_message_request_t
|
typedef struct _tf_ssb_connection_message_request_t
|
||||||
@ -333,6 +336,8 @@ static void _tf_ssb_connection_close(tf_ssb_connection_t* connection, const char
|
|||||||
static void _tf_ssb_nonce_inc(uint8_t* nonce);
|
static void _tf_ssb_nonce_inc(uint8_t* nonce);
|
||||||
static void _tf_ssb_write(tf_ssb_connection_t* connection, void* data, size_t size);
|
static void _tf_ssb_write(tf_ssb_connection_t* connection, void* data, size_t size);
|
||||||
static void _tf_ssb_connection_finalizer(JSRuntime* runtime, JSValue value);
|
static void _tf_ssb_connection_finalizer(JSRuntime* runtime, JSValue value);
|
||||||
|
static void _tf_ssb_update_settings(tf_ssb_t* ssb);
|
||||||
|
static void _tf_ssb_start_update_settings(tf_ssb_t* ssb, int delay_ms);
|
||||||
|
|
||||||
static void _tf_ssb_add_debug_close(tf_ssb_t* ssb, tf_ssb_connection_t* connection, const char* reason)
|
static void _tf_ssb_add_debug_close(tf_ssb_t* ssb, tf_ssb_connection_t* connection, const char* reason)
|
||||||
{
|
{
|
||||||
@ -2157,7 +2162,9 @@ tf_ssb_t* tf_ssb_create(uv_loop_t* loop, JSContext* context, const char* db_path
|
|||||||
|
|
||||||
ssb->connections_tracker = tf_ssb_connections_create(ssb);
|
ssb->connections_tracker = tf_ssb_connections_create(ssb);
|
||||||
|
|
||||||
|
_tf_ssb_update_settings(ssb);
|
||||||
tf_ssb_rpc_register(ssb);
|
tf_ssb_rpc_register(ssb);
|
||||||
|
_tf_ssb_start_update_settings(ssb, 5000);
|
||||||
return ssb;
|
return ssb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2327,11 +2334,17 @@ void tf_ssb_destroy(tf_ssb_t* ssb)
|
|||||||
uv_close((uv_handle_t*)&ssb->server, _tf_ssb_on_handle_close);
|
uv_close((uv_handle_t*)&ssb->server, _tf_ssb_on_handle_close);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ssb->settings_timer.data && !uv_is_closing((uv_handle_t*)&ssb->settings_timer))
|
||||||
|
{
|
||||||
|
uv_close((uv_handle_t*)&ssb->settings_timer, _tf_ssb_on_handle_close);
|
||||||
|
}
|
||||||
|
|
||||||
while (ssb->broadcast_listener.data ||
|
while (ssb->broadcast_listener.data ||
|
||||||
ssb->broadcast_sender.data ||
|
ssb->broadcast_sender.data ||
|
||||||
ssb->broadcast_timer.data ||
|
ssb->broadcast_timer.data ||
|
||||||
ssb->broadcast_cleanup_timer.data ||
|
ssb->broadcast_cleanup_timer.data ||
|
||||||
ssb->trace_timer.data ||
|
ssb->trace_timer.data ||
|
||||||
|
ssb->settings_timer.data ||
|
||||||
ssb->server.data ||
|
ssb->server.data ||
|
||||||
ssb->ref_count)
|
ssb->ref_count)
|
||||||
{
|
{
|
||||||
@ -2430,6 +2443,8 @@ void tf_ssb_destroy(tf_ssb_t* ssb)
|
|||||||
uv_mutex_destroy(&ssb->db_readers_lock);
|
uv_mutex_destroy(&ssb->db_readers_lock);
|
||||||
uv_mutex_destroy(&ssb->db_writer_lock);
|
uv_mutex_destroy(&ssb->db_writer_lock);
|
||||||
tf_free((void*)ssb->db_path);
|
tf_free((void*)ssb->db_path);
|
||||||
|
tf_free(ssb->room_name);
|
||||||
|
ssb->room_name = NULL;
|
||||||
tf_free(ssb);
|
tf_free(ssb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3646,9 +3661,9 @@ void tf_ssb_unref(tf_ssb_t* ssb)
|
|||||||
ssb->ref_count--;
|
ssb->ref_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tf_ssb_set_main_thread(tf_ssb_t* ssb)
|
void tf_ssb_set_main_thread(tf_ssb_t* ssb, bool main_thread)
|
||||||
{
|
{
|
||||||
ssb->thread_self = uv_thread_self();
|
ssb->thread_self = main_thread ? uv_thread_self() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _connection_work_t
|
typedef struct _connection_work_t
|
||||||
@ -3713,3 +3728,137 @@ void tf_ssb_connection_run_work(
|
|||||||
_tf_ssb_connection_after_work_callback(&work->work, result);
|
_tf_ssb_connection_after_work_callback(&work->work, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tf_ssb_is_room(tf_ssb_t* ssb)
|
||||||
|
{
|
||||||
|
return ssb->is_room;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tf_ssb_set_is_room(tf_ssb_t* ssb, bool is_room)
|
||||||
|
{
|
||||||
|
ssb->is_room = is_room;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* tf_ssb_get_room_name(tf_ssb_t* ssb)
|
||||||
|
{
|
||||||
|
return ssb->room_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tf_ssb_set_room_name(tf_ssb_t* ssb, const char* room_name)
|
||||||
|
{
|
||||||
|
tf_free(ssb->room_name);
|
||||||
|
ssb->room_name = tf_strdup(room_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _update_settings_t
|
||||||
|
{
|
||||||
|
uv_work_t work;
|
||||||
|
tf_ssb_t* ssb;
|
||||||
|
bool is_room;
|
||||||
|
char room_name[1024];
|
||||||
|
} update_settings_t;
|
||||||
|
|
||||||
|
static bool _get_global_setting_string(tf_ssb_t* ssb, const char* name, char* out_value, size_t size)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||||
|
sqlite3_stmt* statement;
|
||||||
|
if (sqlite3_prepare(db, "SELECT json_extract(value, '$.' || ?) FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
|
||||||
|
{
|
||||||
|
if (sqlite3_bind_text(statement, 1, name, -1, NULL) == SQLITE_OK)
|
||||||
|
{
|
||||||
|
if (sqlite3_step(statement) == SQLITE_ROW)
|
||||||
|
{
|
||||||
|
snprintf(out_value, size, "%s", sqlite3_column_text(statement, 0));
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3_finalize(statement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
|
||||||
|
}
|
||||||
|
tf_ssb_release_db_reader(ssb, db);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _get_global_setting_bool(tf_ssb_t* ssb, const char* name, bool default_value)
|
||||||
|
{
|
||||||
|
bool result = default_value;
|
||||||
|
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||||
|
sqlite3_stmt* statement;
|
||||||
|
if (sqlite3_prepare(db, "SELECT json_extract(value, '$.' || ?) FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
|
||||||
|
{
|
||||||
|
if (sqlite3_bind_text(statement, 1, name, -1, NULL) == SQLITE_OK)
|
||||||
|
{
|
||||||
|
if (sqlite3_step(statement) == SQLITE_ROW)
|
||||||
|
{
|
||||||
|
result = sqlite3_column_int(statement, 0) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3_finalize(statement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
|
||||||
|
}
|
||||||
|
tf_ssb_release_db_reader(ssb, db);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _tf_ssb_update_settings_work(uv_work_t* work)
|
||||||
|
{
|
||||||
|
update_settings_t* update = work->data;
|
||||||
|
update->is_room = _get_global_setting_bool(update->ssb, "room", true);
|
||||||
|
_get_global_setting_string(update->ssb, "room_name", update->room_name, sizeof(update->room_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _tf_ssb_update_settings_after_work(uv_work_t* work, int result)
|
||||||
|
{
|
||||||
|
update_settings_t* update = work->data;
|
||||||
|
tf_ssb_set_is_room(update->ssb, update->is_room);
|
||||||
|
tf_ssb_set_room_name(update->ssb, update->room_name);
|
||||||
|
tf_free(update);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _tf_ssb_start_update_settings_timer(uv_timer_t* timer)
|
||||||
|
{
|
||||||
|
update_settings_t* update = tf_malloc(sizeof(update_settings_t));
|
||||||
|
*update = (update_settings_t)
|
||||||
|
{
|
||||||
|
.work =
|
||||||
|
{
|
||||||
|
.data = update,
|
||||||
|
},
|
||||||
|
.ssb = timer->data,
|
||||||
|
};
|
||||||
|
int result = uv_queue_work(tf_ssb_get_loop(timer->data), &update->work, _tf_ssb_update_settings_work, _tf_ssb_update_settings_after_work);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
_tf_ssb_update_settings_after_work(&update->work, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _tf_ssb_update_settings(tf_ssb_t* ssb)
|
||||||
|
{
|
||||||
|
update_settings_t* update = tf_malloc(sizeof(update_settings_t));
|
||||||
|
*update = (update_settings_t)
|
||||||
|
{
|
||||||
|
.work =
|
||||||
|
{
|
||||||
|
.data = update,
|
||||||
|
},
|
||||||
|
.ssb = ssb,
|
||||||
|
};
|
||||||
|
_tf_ssb_update_settings_work(&update->work);
|
||||||
|
_tf_ssb_update_settings_after_work(&update->work, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _tf_ssb_start_update_settings(tf_ssb_t* ssb, int delay_ms)
|
||||||
|
{
|
||||||
|
ssb->settings_timer.data = ssb;
|
||||||
|
uv_timer_init(ssb->loop, &ssb->settings_timer);
|
||||||
|
uv_timer_start(&ssb->settings_timer, _tf_ssb_start_update_settings_timer, delay_ms, delay_ms);
|
||||||
|
uv_unref((uv_handle_t*)&ssb->settings_timer);
|
||||||
|
}
|
||||||
|
@ -216,4 +216,9 @@ tf_ssb_store_queue_t* tf_ssb_get_store_queue(tf_ssb_t* ssb);
|
|||||||
void tf_ssb_ref(tf_ssb_t* ssb);
|
void tf_ssb_ref(tf_ssb_t* ssb);
|
||||||
void tf_ssb_unref(tf_ssb_t* ssb);
|
void tf_ssb_unref(tf_ssb_t* ssb);
|
||||||
|
|
||||||
void tf_ssb_set_main_thread(tf_ssb_t* ssb);
|
void tf_ssb_set_main_thread(tf_ssb_t* ssb, bool main_thread);
|
||||||
|
|
||||||
|
bool tf_ssb_is_room(tf_ssb_t* ssb);
|
||||||
|
void tf_ssb_set_is_room(tf_ssb_t* ssb, bool is_room);
|
||||||
|
const char* tf_ssb_get_room_name(tf_ssb_t* ssb);
|
||||||
|
void tf_ssb_set_room_name(tf_ssb_t* ssb, const char* room_name);
|
||||||
|
@ -45,55 +45,6 @@ static int64_t _get_global_setting_int64(tf_ssb_t* ssb, const char* name, int64_
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _get_global_setting_bool(tf_ssb_t* ssb, const char* name, bool default_value)
|
|
||||||
{
|
|
||||||
bool result = default_value;
|
|
||||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
|
||||||
sqlite3_stmt* statement;
|
|
||||||
if (sqlite3_prepare(db, "SELECT json_extract(value, '$.' || ?) FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
|
|
||||||
{
|
|
||||||
if (sqlite3_bind_text(statement, 1, name, -1, NULL) == SQLITE_OK)
|
|
||||||
{
|
|
||||||
if (sqlite3_step(statement) == SQLITE_ROW)
|
|
||||||
{
|
|
||||||
result = sqlite3_column_int(statement, 0) != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sqlite3_finalize(statement);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
|
|
||||||
}
|
|
||||||
tf_ssb_release_db_reader(ssb, db);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _get_global_setting_string(tf_ssb_t* ssb, const char* name, char* out_value, size_t size)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
|
||||||
sqlite3_stmt* statement;
|
|
||||||
if (sqlite3_prepare(db, "SELECT json_extract(value, '$.' || ?) FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
|
|
||||||
{
|
|
||||||
if (sqlite3_bind_text(statement, 1, name, -1, NULL) == SQLITE_OK)
|
|
||||||
{
|
|
||||||
if (sqlite3_step(statement) == SQLITE_ROW)
|
|
||||||
{
|
|
||||||
snprintf(out_value, size, "%s", sqlite3_column_text(statement, 0));
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sqlite3_finalize(statement);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
|
|
||||||
}
|
|
||||||
tf_ssb_release_db_reader(ssb, db);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _tf_ssb_rpc_gossip_ping_callback(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
|
static void _tf_ssb_rpc_gossip_ping_callback(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
|
||||||
{
|
{
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
@ -328,7 +279,7 @@ void _tf_ssb_rpc_tunnel_cleanup(tf_ssb_t* ssb, void* user_data)
|
|||||||
static void _tf_ssb_rpc_tunnel_connect(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
|
static void _tf_ssb_rpc_tunnel_connect(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
|
||||||
{
|
{
|
||||||
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||||
if (!_get_global_setting_bool(ssb, "room", true))
|
if (!tf_ssb_is_room(ssb))
|
||||||
{
|
{
|
||||||
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "tunnel.connect");
|
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "tunnel.connect");
|
||||||
return;
|
return;
|
||||||
@ -427,12 +378,10 @@ static void _tf_ssb_rpc_room_meta(tf_ssb_connection_t* connection, uint8_t flags
|
|||||||
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||||
JSContext* context = tf_ssb_get_context(ssb);
|
JSContext* context = tf_ssb_get_context(ssb);
|
||||||
JSValue response = JS_FALSE;
|
JSValue response = JS_FALSE;
|
||||||
if (_get_global_setting_bool(ssb, "room", true))
|
if (tf_ssb_is_room(ssb))
|
||||||
{
|
{
|
||||||
char room_name[1024] = "tilde friends tunnel";
|
|
||||||
_get_global_setting_string(ssb, "room_name", room_name, sizeof(room_name));
|
|
||||||
response = JS_NewObject(context);
|
response = JS_NewObject(context);
|
||||||
JS_SetPropertyStr(context, response, "name", JS_NewString(context, room_name));
|
JS_SetPropertyStr(context, response, "name", JS_NewString(context, tf_ssb_get_room_name(ssb)));
|
||||||
JS_SetPropertyStr(context, response, "membership", JS_FALSE);
|
JS_SetPropertyStr(context, response, "membership", JS_FALSE);
|
||||||
JSValue features = JS_NewArray(context);
|
JSValue features = JS_NewArray(context);
|
||||||
JS_SetPropertyUint32(context, features, 0, JS_NewString(context, "tunnel"));
|
JS_SetPropertyUint32(context, features, 0, JS_NewString(context, "tunnel"));
|
||||||
@ -454,7 +403,7 @@ static void _tf_ssb_rpc_room_meta(tf_ssb_connection_t* connection, uint8_t flags
|
|||||||
static void _tf_ssb_rpc_room_attendants(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
|
static void _tf_ssb_rpc_room_attendants(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
|
||||||
{
|
{
|
||||||
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||||
if (!_get_global_setting_bool(ssb, "room", true))
|
if (!tf_ssb_is_room(ssb))
|
||||||
{
|
{
|
||||||
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "room.attendants");
|
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "room.attendants");
|
||||||
return;
|
return;
|
||||||
|
@ -638,8 +638,8 @@ void tf_ssb_test_bench(const tf_test_options_t* options)
|
|||||||
uint8_t id0bin[k_id_bin_len];
|
uint8_t id0bin[k_id_bin_len];
|
||||||
tf_ssb_id_str_to_bin(id0bin, id0);
|
tf_ssb_id_str_to_bin(id0bin, id0);
|
||||||
|
|
||||||
tf_ssb_set_main_thread(ssb0);
|
tf_ssb_set_main_thread(ssb0, true);
|
||||||
tf_ssb_set_main_thread(ssb1);
|
tf_ssb_set_main_thread(ssb1, true);
|
||||||
|
|
||||||
uv_idle_t idle0 = { .data = ssb0 };
|
uv_idle_t idle0 = { .data = ssb0 };
|
||||||
uv_idle_init(&loop, &idle0);
|
uv_idle_init(&loop, &idle0);
|
||||||
@ -666,6 +666,8 @@ void tf_ssb_test_bench(const tf_test_options_t* options)
|
|||||||
tf_ssb_remove_message_added_callback(ssb1, _message_added, &count);
|
tf_ssb_remove_message_added_callback(ssb1, _message_added, &count);
|
||||||
clock_gettime(CLOCK_REALTIME, &end_time);
|
clock_gettime(CLOCK_REALTIME, &end_time);
|
||||||
|
|
||||||
|
tf_ssb_set_main_thread(ssb0, false);
|
||||||
|
tf_ssb_set_main_thread(ssb1, false);
|
||||||
count = _ssb_test_count_messages(ssb1);
|
count = _ssb_test_count_messages(ssb1);
|
||||||
if (count < k_messages)
|
if (count < k_messages)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user