added idb_lock functions
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user