Skip to content

Commit

Permalink
Fix some cluster sync state issues
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
vkoskiv committed Nov 4, 2023
1 parent 6433eb7 commit 0530d71
Showing 1 changed file with 27 additions and 5 deletions.
32 changes: 27 additions & 5 deletions src/utils/protocol/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,27 +281,29 @@ 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;

// Handshake with the client
if (!sendJSON(client->socket, makeHandshake(), NULL)) {
client->status = SyncFailed;
params->done = true;
return NULL;
}
cJSON *response = readJSON(client->socket);
if (cJSON_HasObjectItem(response, "error")) {
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;
}
Expand All @@ -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);
Expand Down Expand Up @@ -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 = &params[i]
};
}
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 0530d71

Please sign in to comment.