added idb_lock functions

This commit is contained in:
2025-11-24 23:51:00 +05:00
parent 571fdd900f
commit 7a3808ba59
12 changed files with 279 additions and 118 deletions

View File

@@ -39,13 +39,11 @@ void ClientCLI_destroy(ClientCLI* self){
Client_free(self->client);
idb_close(self->db);
pthread_mutex_destroy(&self->servers_cache_mutex);
List_destroy(self->servers_cache_list);
HashMap_destroy(&self->servers_addr_id_map);
List_destroy(&self->servers.list);
HashMap_destroy(&self->servers.addr_id_map);
}
void ClientCLI_construct(ClientCLI* self){
memset(self, 0, sizeof(*self));
pthread_mutex_init(&self->servers_cache_mutex, NULL);
}
Result(void) ClientCLI_run(ClientCLI* self) {
@@ -227,18 +225,19 @@ static Result(void) ClientCLI_joinNewServer(ClientCLI* self){
static Result(void) ClientCLI_selectServerFromCache(ClientCLI* self){
Deferral(8);
// lock servers cache
try_stderrcode(pthread_mutex_lock(&self->servers_cache_mutex));
Defer(pthread_mutex_unlock(&self->servers_cache_mutex));
// Lock table until this function returns.
// It may not change any data in table, but it uses associated cache structures.
idb_lockTable(self->servers.table);
Defer(idb_unlockTable(self->servers.table));
u32 servers_count = List_len(self->servers_cache_list, ServerInfo);
u32 servers_count = List_len(self->servers.list, ServerInfo);
if(servers_count == 0){
printf("No servers found in cache\n");
Return RESULT_VOID;
}
for(u32 id = 0; id < servers_count; id++){
ServerInfo* row = &List_index(self->servers_cache_list, ServerInfo, id);
ServerInfo* row = &List_index(self->servers.list, ServerInfo, id);
printf("[%02u] "FMT_str" "FMT_str"\n",
id, row->address_len, row->address, row->name_len, row->name);
}
@@ -262,7 +261,7 @@ static Result(void) ClientCLI_selectServerFromCache(ClientCLI* self){
}
else break;
}
ServerInfo* server = &List_index(self->servers_cache_list, ServerInfo, id);
ServerInfo* server = &List_index(self->servers.list, ServerInfo, id);
printf("Connecting to '"FMT_str"'...\n", server->address_len, server->address);
try_void(Client_connect(self->client, server->address, server->pk_base64));
@@ -290,7 +289,7 @@ static Result(void) ClientCLI_selectServerFromCache(ClientCLI* self){
memcpy(server->desc, desc.data, server->desc_len);
}
if(server_info_changed){
try_void(idb_updateRow(self->db_servers_table, id, server));
try_void(idb_updateRow(self->servers.table, id, server, false));
}
try_void(ClientCLI_showServerInfo(self, server));
@@ -320,20 +319,34 @@ static Result(void) ClientCLI_openUserDB(ClientCLI* self){
str user_db_dir = str_from_cstr(strcat_malloc("client-db", path_seps, username.data));
Defer(free(user_db_dir.data));
try(self->db, p, idb_open(user_db_dir, user_data_key));
// Lock DB until this function returns.
idb_lockDB(self->db);
Defer(idb_unlockDB(self->db));
// Load servers table
try(self->servers.table, p,
idb_getOrCreateTable(self->db, STR("servers"), sizeof(ServerInfo), false)
);
// load servers table
try(self->db_servers_table, p, idb_getOrCreateTable(self->db, STR("servers"), sizeof(ServerInfo)));
// load whole table to list
try(u64 servers_count, u, idb_getRowCount(self->db_servers_table));
self->servers_cache_list = List_alloc(ServerInfo, servers_count);
try_void(idb_getRows(self->db_servers_table, 0, self->servers_cache_list.data, servers_count));
self->servers_cache_list.size = sizeof(ServerInfo) * servers_count;
// Lock table until this function returns.
idb_lockTable(self->servers.table);
Defer(idb_unlockTable(self->servers.table));
// load whole servers table to list
try_void(
idb_createListFromTable(self->servers.table, &self->servers.list, false)
);
// build address-id map
HashMap_construct(&self->servers_addr_id_map, u64, NULL);
try(u64 servers_count, u,
idb_getRowCount(self->servers.table, false)
);
HashMap_construct(&self->servers.addr_id_map, u64, NULL);
for(u64 id = 0; id < servers_count; id++){
ServerInfo* row = &List_index(self->servers_cache_list, ServerInfo, id);
ServerInfo* row = &List_index(self->servers.list, ServerInfo, id);
str key = str_construct(row->address, row->address_len, true);
if(!HashMap_tryPush(&self->servers_addr_id_map, key, &id)){
if(!HashMap_tryPush(&self->servers.addr_id_map, key, &id)){
Return RESULT_ERROR_FMT("duplicate server address '"FMT_str"'", key.size, key.data);
}
}
@@ -369,29 +382,30 @@ static Result(ServerInfo*) ClientCLI_saveServerInfo(ClientCLI* self,
server.desc_len = desc.size;
memcpy(server.desc, desc.data, server.desc_len);
// lock servers cache
try_stderrcode(pthread_mutex_lock(&self->servers_cache_mutex));
Defer(pthread_mutex_unlock(&self->servers_cache_mutex));
// Lock table until this function returns.
// It may not change any data in table, but it uses associated cache structures.
idb_lockTable(self->servers.table);
Defer(idb_unlockTable(self->servers.table));
// try find server id in cache
ServerInfo* cached_row_ptr = NULL;
u64* id_ptr = NULL;
id_ptr = HashMap_tryGetPtr(&self->servers_addr_id_map, addr);
id_ptr = HashMap_tryGetPtr(&self->servers.addr_id_map, addr);
if(id_ptr){
// update existing server
u64 id = *id_ptr;
try_void(idb_updateRow(self->db_servers_table, id, &server));
try_assert(id < List_len(self->servers_cache_list, ServerInfo));
cached_row_ptr = &List_index(self->servers_cache_list, ServerInfo, id);
try_void(idb_updateRow(self->servers.table, id, &server, false));
try_assert(id < List_len(self->servers.list, ServerInfo));
cached_row_ptr = &List_index(self->servers.list, ServerInfo, id);
memcpy(cached_row_ptr, &server, sizeof(ServerInfo));
}
else {
// push new server
try(u64 id, u, idb_pushRow(self->db_servers_table, &server));
try_assert(id == List_len(self->servers_cache_list, ServerInfo));
List_pushMany(&self->servers_cache_list, ServerInfo, &server, 1);
cached_row_ptr = &List_index(self->servers_cache_list, ServerInfo, id);
try_assert(HashMap_tryPush(&self->servers_addr_id_map, addr, &id));
try(u64 id, u, idb_pushRow(self->servers.table, &server, false));
try_assert(id == List_len(self->servers.list, ServerInfo));
List_pushMany(&self->servers.list, ServerInfo, &server, 1);
cached_row_ptr = &List_index(self->servers.list, ServerInfo, id);
try_assert(HashMap_tryPush(&self->servers.addr_id_map, addr, &id));
}
Return RESULT_VALUE(p, cached_row_ptr);