From 0530d71b22598d722b3e05d43a0dda0c91662312 Mon Sep 17 00:00:00 2001 From: Valtteri Koskivuori Date: Sun, 5 Nov 2023 00:21:43 +0200 Subject: [PATCH] Fix some cluster sync state issues Namely, the sync threads weren't always reporting that they were done, so the master node would just wait on them forever instead of moving on. --- src/utils/protocol/server.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/utils/protocol/server.c b/src/utils/protocol/server.c index a3d884bb..85cd5661 100644 --- a/src/utils/protocol/server.c +++ b/src/utils/protocol/server.c @@ -281,13 +281,13 @@ struct syncThreadParams { bool done; }; -//TODO: Rename to clientSyncThread -static void *handleClientSync(void *arg) { +static void *client_sync_thread(void *arg) { block_signals(); struct syncThreadParams *params = (struct syncThreadParams *)thread_user_data(arg); struct renderClient *client = params->client; if (client->status != Connected) { logr(warning, "Won't sync with client %i, no connection.\n", client->id); + params->done = true; return NULL; } client->status = Syncing; @@ -295,6 +295,7 @@ static void *handleClientSync(void *arg) { // Handshake with the client if (!sendJSON(client->socket, makeHandshake(), NULL)) { client->status = SyncFailed; + params->done = true; return NULL; } cJSON *response = readJSON(client->socket); @@ -302,6 +303,7 @@ static void *handleClientSync(void *arg) { cJSON *error = cJSON_GetObjectItem(response, "error"); logr(warning, "Client handshake error: %s\n", error->valuestring); client->status = SyncFailed; + params->done = true; cJSON_Delete(response); return NULL; } @@ -321,12 +323,14 @@ static void *handleClientSync(void *arg) { if (!response) { logr(debug, "no response\n"); client->status = SyncFailed; + params->done = true; return NULL; } if (cJSON_HasObjectItem(response, "error")) { cJSON *error = cJSON_GetObjectItem(response, "error"); logr(warning, "Client scene sync error: %s\n", error->valuestring); client->status = SyncFailed; + params->done = true; cJSON_Delete(error); cJSON_Delete(response); disconnectFromClient(client); @@ -418,7 +422,7 @@ struct renderClient *syncWithClients(const struct renderer *r, size_t *count) { struct cr_thread *sync_threads = calloc(clientCount, sizeof(*sync_threads)); for (size_t i = 0; i < clientCount; ++i) { sync_threads[i] = (struct cr_thread){ - .thread_fn = handleClientSync, + .thread_fn = client_sync_thread, .user_data = ¶ms[i] }; } @@ -452,8 +456,26 @@ struct renderClient *syncWithClients(const struct renderer *r, size_t *count) { free(assetCache); for (size_t i = 0; i < clientCount; ++i) printf("\n"); logr(info, "Client sync finished.\n"); - //FIXME: We should prune clients that dropped out during sync here - if (count) *count = clientCount; + + size_t validClients = 0; + for (size_t i = 0; i < clientCount; ++i) { + validClients += clients[i].status == ConnectionFailed ? 0 : 1; + } + if (validClients < clientCount) { + // Prune unavailable clients + struct renderClient *confirmedClients = calloc(validClients, sizeof(*confirmedClients)); + size_t j = 0; + for (size_t i = 0; i < clientCount; ++i) { + if (clients[i].status == Synced) { + confirmedClients[j++] = clients[i]; + } + } + free(clients); + clients = confirmedClients; + logr(debug, "Pruned %zu clients that failed to sync\n", clientCount - validClients); + } + + if (count) *count = validClients; free(sync_threads); return clients; }