Improve simulation coverage by adding multiple chunk servers
Two changes to improve code coverage in deterministic simulation testing:
1. Add 3 chunk servers (was 1) to match the replication factor
- This enables testing of chunk replication and chunk-to-chunk
server communication code paths in chunk_server.c
- Covers: process_chunk_server_download_*, start_download,
download_targets_* functions
2. Fix Quakey bug where events targeting a closed descriptor caused
assertion failures
- Added remove_events_targeting_desc() to clean up DISCONNECT and
DATA events when a descriptor is freed
- Modified desc_free() to accept Sim pointer and call cleanup
- This was exposed by running multiple chunk servers which create
more connection activity
This commit is contained in:
+27
-3
@@ -369,6 +369,7 @@ static void time_event_wakeup(Sim *sim, Nanos time, Host *host);
|
|||||||
static void time_event_connect(Sim *sim, Nanos time, Desc *desc);
|
static void time_event_connect(Sim *sim, Nanos time, Desc *desc);
|
||||||
static void time_event_disconnect(Sim *sim, Nanos time, Desc *desc, b32 rst);
|
static void time_event_disconnect(Sim *sim, Nanos time, Desc *desc, b32 rst);
|
||||||
static void time_event_send_data(Sim *sim, Nanos time, Desc *desc);
|
static void time_event_send_data(Sim *sim, Nanos time, Desc *desc);
|
||||||
|
static void remove_events_targeting_desc(Sim *sim, Desc *desc);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
@@ -776,7 +777,7 @@ static bool accept_queue_empty(AcceptQueue *queue)
|
|||||||
// If the descriptor is a connection socket and rst=true,
|
// If the descriptor is a connection socket and rst=true,
|
||||||
// the peer connection will be marked as "reset" instead
|
// the peer connection will be marked as "reset" instead
|
||||||
// of simply closed.
|
// of simply closed.
|
||||||
static void desc_free(Desc *desc, bool rst)
|
static void desc_free(Sim *sim, Desc *desc, bool rst)
|
||||||
{
|
{
|
||||||
switch (desc->type) {
|
switch (desc->type) {
|
||||||
case DESC_EMPTY:
|
case DESC_EMPTY:
|
||||||
@@ -793,6 +794,9 @@ static void desc_free(Desc *desc, bool rst)
|
|||||||
accept_queue_free(&desc->accept_queue);
|
accept_queue_free(&desc->accept_queue);
|
||||||
break;
|
break;
|
||||||
case DESC_SOCKET_C:
|
case DESC_SOCKET_C:
|
||||||
|
// Remove any pending events targeting this descriptor before freeing it
|
||||||
|
if (sim)
|
||||||
|
remove_events_targeting_desc(sim, desc);
|
||||||
if (desc->peer) {
|
if (desc->peer) {
|
||||||
// A connection was previously established.
|
// A connection was previously established.
|
||||||
// We need to update the other end of the connection.
|
// We need to update the other end of the connection.
|
||||||
@@ -989,7 +993,7 @@ static void host_free(Host *host)
|
|||||||
|
|
||||||
for (int i = 0; i < HOST_DESC_LIMIT; i++) {
|
for (int i = 0; i < HOST_DESC_LIMIT; i++) {
|
||||||
if (host->desc[i].type != DESC_EMPTY)
|
if (host->desc[i].type != DESC_EMPTY)
|
||||||
desc_free(&host->desc[i], true);
|
desc_free(host->sim, &host->desc[i], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(host->state);
|
free(host->state);
|
||||||
@@ -1285,7 +1289,7 @@ static int host_close(Host *host, int desc_idx, bool expect_socket)
|
|||||||
if (host->desc[desc_idx].type == DESC_SOCKET_C)
|
if (host->desc[desc_idx].type == DESC_SOCKET_C)
|
||||||
time_event_disconnect(host->sim, host->sim->current_time + 10000000, &host->desc[desc_idx], false);
|
time_event_disconnect(host->sim, host->sim->current_time + 10000000, &host->desc[desc_idx], false);
|
||||||
|
|
||||||
desc_free(&host->desc[desc_idx], false);
|
desc_free(host->sim, &host->desc[desc_idx], false);
|
||||||
host->num_desc--;
|
host->num_desc--;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1934,6 +1938,26 @@ static b32 remove_connect_event(Sim *sim, Desc *desc)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove all events that target a specific descriptor (DISCONNECT and DATA events)
|
||||||
|
static void remove_events_targeting_desc(Sim *sim, Desc *desc)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (i < sim->num_events) {
|
||||||
|
TimeEvent *event = &sim->events[i];
|
||||||
|
if (event->dst_desc == desc) {
|
||||||
|
// Free any resources associated with the event
|
||||||
|
if (event->type == EVENT_TYPE_DATA && event->data_queue) {
|
||||||
|
socket_queue_unref(event->data_queue);
|
||||||
|
}
|
||||||
|
// Remove by swapping with last element
|
||||||
|
sim->events[i] = sim->events[--sim->num_events];
|
||||||
|
// Don't increment i - need to check the swapped element
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void time_event_disconnect(Sim *sim, Nanos time, Desc *desc, b32 rst)
|
static void time_event_disconnect(Sim *sim, Nanos time, Desc *desc, b32 rst)
|
||||||
{
|
{
|
||||||
if (remove_connect_event(sim, desc))
|
if (remove_connect_event(sim, desc))
|
||||||
|
|||||||
+34
-2
@@ -160,10 +160,10 @@ int main(void)
|
|||||||
quakey_spawn(quakey, config, "ms --addr 127.0.0.3 --port 8080");
|
quakey_spawn(quakey, config, "ms --addr 127.0.0.3 --port 8080");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chunk Server
|
// Chunk Server 1
|
||||||
{
|
{
|
||||||
QuakeySpawn config = {
|
QuakeySpawn config = {
|
||||||
.name = "cs",
|
.name = "cs1",
|
||||||
.state_size = sizeof(ChunkServer),
|
.state_size = sizeof(ChunkServer),
|
||||||
.init_func = chunk_server_init,
|
.init_func = chunk_server_init,
|
||||||
.tick_func = chunk_server_tick,
|
.tick_func = chunk_server_tick,
|
||||||
@@ -176,6 +176,38 @@ int main(void)
|
|||||||
quakey_spawn(quakey, config, "cs --addr 127.0.0.4 --port 8081 --remote-addr 127.0.0.3 --remote-port 8080");
|
quakey_spawn(quakey, config, "cs --addr 127.0.0.4 --port 8081 --remote-addr 127.0.0.3 --remote-port 8080");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Chunk Server 2
|
||||||
|
{
|
||||||
|
QuakeySpawn config = {
|
||||||
|
.name = "cs2",
|
||||||
|
.state_size = sizeof(ChunkServer),
|
||||||
|
.init_func = chunk_server_init,
|
||||||
|
.tick_func = chunk_server_tick,
|
||||||
|
.free_func = chunk_server_free,
|
||||||
|
.addrs = (char*[]) { "127.0.0.5" },
|
||||||
|
.num_addrs = 1,
|
||||||
|
.disk_size = 10<<20,
|
||||||
|
.platform = QUAKEY_LINUX,
|
||||||
|
};
|
||||||
|
quakey_spawn(quakey, config, "cs --addr 127.0.0.5 --port 8082 --remote-addr 127.0.0.3 --remote-port 8080");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chunk Server 3
|
||||||
|
{
|
||||||
|
QuakeySpawn config = {
|
||||||
|
.name = "cs3",
|
||||||
|
.state_size = sizeof(ChunkServer),
|
||||||
|
.init_func = chunk_server_init,
|
||||||
|
.tick_func = chunk_server_tick,
|
||||||
|
.free_func = chunk_server_free,
|
||||||
|
.addrs = (char*[]) { "127.0.0.6" },
|
||||||
|
.num_addrs = 1,
|
||||||
|
.disk_size = 10<<20,
|
||||||
|
.platform = QUAKEY_LINUX,
|
||||||
|
};
|
||||||
|
quakey_spawn(quakey, config, "cs --addr 127.0.0.6 --port 8083 --remote-addr 127.0.0.3 --remote-port 8080");
|
||||||
|
}
|
||||||
|
|
||||||
while (simulation_running)
|
while (simulation_running)
|
||||||
quakey_schedule_one(quakey);
|
quakey_schedule_one(quakey);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user