Merge pull request #4 from cozis/claude/implement-simulation-client-011CUj21MCf7ic4fnk94r8sS
Simulation client implementation by Claude
This commit is contained in:
+4
-2
@@ -764,7 +764,7 @@ process_client_message(ChunkServer *state, int conn_idx, uint16_t type, ByteView
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int chunk_server_init(ChunkServer *state, int argc, char **argv, void **contexts, struct pollfd *polled)
|
int chunk_server_init(ChunkServer *state, int argc, char **argv, void **contexts, struct pollfd *polled, int *timeout)
|
||||||
{
|
{
|
||||||
(void) argc;
|
(void) argc;
|
||||||
(void) argv;
|
(void) argv;
|
||||||
@@ -805,6 +805,7 @@ int chunk_server_init(ChunkServer *state, int argc, char **argv, void **contexts
|
|||||||
|
|
||||||
state->metadata_server_disconnect_time = 0;
|
state->metadata_server_disconnect_time = 0;
|
||||||
|
|
||||||
|
*timeout = -1; // No timeout needed for chunk server initially
|
||||||
return tcp_register_events(&state->tcp, contexts, polled);
|
return tcp_register_events(&state->tcp, contexts, polled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -816,7 +817,7 @@ int chunk_server_free(ChunkServer *state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int chunk_server_step(ChunkServer *state, void **contexts, struct pollfd *polled, int num_polled)
|
int chunk_server_step(ChunkServer *state, void **contexts, struct pollfd *polled, int num_polled, int *timeout)
|
||||||
{
|
{
|
||||||
Event events[MAX_CONNS+1];
|
Event events[MAX_CONNS+1];
|
||||||
int num_events = tcp_translate_events(&state->tcp, events, contexts, polled, num_polled);
|
int num_events = tcp_translate_events(&state->tcp, events, contexts, polled, num_polled);
|
||||||
@@ -937,5 +938,6 @@ int chunk_server_step(ChunkServer *state, void **contexts, struct pollfd *polled
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*timeout = -1; // No timeout needed for chunk server
|
||||||
return tcp_register_events(&state->tcp, contexts, polled);
|
return tcp_register_events(&state->tcp, contexts, polled);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -35,8 +35,8 @@ typedef struct {
|
|||||||
PendingDownloadList pending_download_list;
|
PendingDownloadList pending_download_list;
|
||||||
} ChunkServer;
|
} ChunkServer;
|
||||||
|
|
||||||
int chunk_server_init(ChunkServer *state, int argc, char **argv, void **contexts, struct pollfd *polled);
|
int chunk_server_init(ChunkServer *state, int argc, char **argv, void **contexts, struct pollfd *polled, int *timeout);
|
||||||
int chunk_server_free(ChunkServer *state);
|
int chunk_server_free(ChunkServer *state);
|
||||||
int chunk_server_step(ChunkServer *state, void **contexts, struct pollfd *polled, int num_polled);
|
int chunk_server_step(ChunkServer *state, void **contexts, struct pollfd *polled, int num_polled, int *timeout);
|
||||||
|
|
||||||
#endif // CHUNK_SERVER_INCLUDED
|
#endif // CHUNK_SERVER_INCLUDED
|
||||||
|
|||||||
+6
-4
@@ -18,14 +18,15 @@ int metadata_server_main(int argc, char **argv)
|
|||||||
void *contexts[MAX_CONNS+1];
|
void *contexts[MAX_CONNS+1];
|
||||||
struct pollfd polled[MAX_CONNS+1];
|
struct pollfd polled[MAX_CONNS+1];
|
||||||
int num_polled;
|
int num_polled;
|
||||||
|
int timeout = -1;
|
||||||
MetadataServer state;
|
MetadataServer state;
|
||||||
num_polled = metadata_server_init(
|
num_polled = metadata_server_init(
|
||||||
&state, argc, argv, contexts, polled);
|
&state, argc, argv, contexts, polled, &timeout);
|
||||||
if (num_polled < 0) return -1;
|
if (num_polled < 0) return -1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
POLL(polled, num_polled, -1);
|
POLL(polled, num_polled, -1);
|
||||||
num_polled = metadata_server_step(
|
num_polled = metadata_server_step(
|
||||||
&state, contexts, polled, num_polled);
|
&state, contexts, polled, num_polled, &timeout);
|
||||||
if (num_polled < 0) return -1;
|
if (num_polled < 0) return -1;
|
||||||
}
|
}
|
||||||
metadata_server_free(&state);
|
metadata_server_free(&state);
|
||||||
@@ -37,14 +38,15 @@ int chunk_server_main(int argc, char **argv)
|
|||||||
void *contexts[MAX_CONNS+1];
|
void *contexts[MAX_CONNS+1];
|
||||||
struct pollfd polled[MAX_CONNS+1];
|
struct pollfd polled[MAX_CONNS+1];
|
||||||
int num_polled;
|
int num_polled;
|
||||||
|
int timeout = -1;
|
||||||
ChunkServer state;
|
ChunkServer state;
|
||||||
num_polled = chunk_server_init(
|
num_polled = chunk_server_init(
|
||||||
&state, argc, argv, contexts, polled);
|
&state, argc, argv, contexts, polled, &timeout);
|
||||||
if (num_polled < 0) return -1;
|
if (num_polled < 0) return -1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
POLL(polled, num_polled, -1);
|
POLL(polled, num_polled, -1);
|
||||||
num_polled = chunk_server_step(
|
num_polled = chunk_server_step(
|
||||||
&state, contexts, polled, num_polled);
|
&state, contexts, polled, num_polled, &timeout);
|
||||||
if (num_polled < 0) return -1;
|
if (num_polled < 0) return -1;
|
||||||
}
|
}
|
||||||
chunk_server_free(&state);
|
chunk_server_free(&state);
|
||||||
|
|||||||
+45
-2
@@ -1,5 +1,6 @@
|
|||||||
#ifdef BUILD_TEST
|
#ifdef BUILD_TEST
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
@@ -9,10 +10,31 @@ static sig_atomic_t simulation_should_stop = false;
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
// TODO: set simulation_should_stop=true on ctrl+C
|
// TODO: set simulation_should_stop=true on ctrl+C
|
||||||
|
|
||||||
spawn_simulated_process("--addr 127.0.0.1 8080 --leader");
|
fprintf(stderr, "=== Starting TinyDFS simulation ===\n");
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
startup_simulation();
|
||||||
|
|
||||||
|
// Spawn metadata server (leader)
|
||||||
|
fprintf(stderr, "Spawning metadata server...\n");
|
||||||
|
fflush(stderr);
|
||||||
|
int ret = spawn_simulated_process("--addr 127.0.0.1 8080 --leader");
|
||||||
|
fprintf(stderr, "spawn returned: %d\n", ret);
|
||||||
|
fflush(stderr);
|
||||||
|
fprintf(stderr, "Metadata server spawned\n");
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
// Spawn chunk servers
|
||||||
|
fprintf(stderr, "Spawning chunk server 1...\n");
|
||||||
|
fflush(stderr);
|
||||||
spawn_simulated_process("--addr 127.0.0.1 8081");
|
spawn_simulated_process("--addr 127.0.0.1 8081");
|
||||||
|
fprintf(stderr, "Spawning chunk server 2...\n");
|
||||||
|
fflush(stderr);
|
||||||
spawn_simulated_process("--addr 127.0.0.1 8082");
|
spawn_simulated_process("--addr 127.0.0.1 8082");
|
||||||
spawn_simulated_process("--addr 127.0.0.1 8083");
|
spawn_simulated_process("--addr 127.0.0.1 8083");
|
||||||
spawn_simulated_process("--addr 127.0.0.1 8084");
|
spawn_simulated_process("--addr 127.0.0.1 8084");
|
||||||
@@ -23,10 +45,31 @@ int main(int argc, char **argv)
|
|||||||
spawn_simulated_process("--addr 127.0.0.1 8089");
|
spawn_simulated_process("--addr 127.0.0.1 8089");
|
||||||
spawn_simulated_process("--addr 127.0.0.1 8090");
|
spawn_simulated_process("--addr 127.0.0.1 8090");
|
||||||
|
|
||||||
while (!simulation_should_stop)
|
// Spawn simulation client
|
||||||
|
spawn_simulated_process("--client --server 127.0.0.1 8080");
|
||||||
|
|
||||||
|
printf("Running simulation (press Ctrl+C to stop)...\n");
|
||||||
|
|
||||||
|
// Run for a limited number of iterations for testing
|
||||||
|
int iteration = 0;
|
||||||
|
int max_iterations = 100000; // Increased to allow client operations to complete
|
||||||
|
while (!simulation_should_stop && iteration < max_iterations) {
|
||||||
update_simulation();
|
update_simulation();
|
||||||
|
iteration++;
|
||||||
|
|
||||||
|
// Print progress every 10000 iterations
|
||||||
|
if (iteration % 10000 == 0) {
|
||||||
|
fprintf(stderr, "Iteration %d...\n", iteration);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iteration >= max_iterations) {
|
||||||
|
printf("\nSimulation stopped after %d iterations\n", max_iterations);
|
||||||
|
}
|
||||||
|
|
||||||
cleanup_simulation();
|
cleanup_simulation();
|
||||||
|
printf("Simulation complete!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -750,7 +750,7 @@ static bool is_chunk_server_message_type(uint16_t type)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int metadata_server_init(MetadataServer *state, int argc, char **argv, void **contexts, struct pollfd *polled)
|
int metadata_server_init(MetadataServer *state, int argc, char **argv, void **contexts, struct pollfd *polled, int *timeout)
|
||||||
{
|
{
|
||||||
(void) argc;
|
(void) argc;
|
||||||
(void) argv;
|
(void) argv;
|
||||||
@@ -778,6 +778,7 @@ int metadata_server_init(MetadataServer *state, int argc, char **argv, void **co
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*timeout = -1; // No timeout needed for metadata server
|
||||||
return tcp_register_events(&state->tcp, contexts, polled);
|
return tcp_register_events(&state->tcp, contexts, polled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -788,7 +789,7 @@ int metadata_server_free(MetadataServer *state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int metadata_server_step(MetadataServer *state, void **contexts, struct pollfd *polled, int num_polled)
|
int metadata_server_step(MetadataServer *state, void **contexts, struct pollfd *polled, int num_polled, int *timeout)
|
||||||
{
|
{
|
||||||
Event events[MAX_CONNS+1];
|
Event events[MAX_CONNS+1];
|
||||||
int num_events = tcp_translate_events(&state->tcp, events, contexts, polled, num_polled);
|
int num_events = tcp_translate_events(&state->tcp, events, contexts, polled, num_polled);
|
||||||
@@ -852,5 +853,6 @@ int metadata_server_step(MetadataServer *state, void **contexts, struct pollfd *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*timeout = -1; // No timeout needed for metadata server
|
||||||
return tcp_register_events(&state->tcp, contexts, polled);
|
return tcp_register_events(&state->tcp, contexts, polled);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ typedef struct {
|
|||||||
|
|
||||||
} MetadataServer;
|
} MetadataServer;
|
||||||
|
|
||||||
int metadata_server_init(MetadataServer *state, int argc, char **argv, void **contexts, struct pollfd *polled);
|
int metadata_server_init(MetadataServer *state, int argc, char **argv, void **contexts, struct pollfd *polled, int *timeout);
|
||||||
int metadata_server_free(MetadataServer *state);
|
int metadata_server_free(MetadataServer *state);
|
||||||
int metadata_server_step(MetadataServer *state, void **contexts, struct pollfd *polled, int num_polled);
|
int metadata_server_step(MetadataServer *state, void **contexts, struct pollfd *polled, int num_polled, int *timeout);
|
||||||
|
|
||||||
#endif // METADATA_SERVER_INCLUDED
|
#endif // METADATA_SERVER_INCLUDED
|
||||||
|
|||||||
@@ -0,0 +1,274 @@
|
|||||||
|
#ifdef BUILD_TEST
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "simulation_client.h"
|
||||||
|
#include "tcp.h"
|
||||||
|
|
||||||
|
// Helper function to parse address and port from command line
|
||||||
|
static bool parse_server_addr(int argc, char **argv, char **addr, uint16_t *port)
|
||||||
|
{
|
||||||
|
// Default to metadata server
|
||||||
|
*addr = "127.0.0.1";
|
||||||
|
*port = 8080;
|
||||||
|
|
||||||
|
for (int i = 0; i < argc - 1; i++) {
|
||||||
|
if (!strcmp(argv[i], "--server") || !strcmp(argv[i], "-s")) {
|
||||||
|
*addr = argv[i + 1];
|
||||||
|
if (i + 2 < argc) {
|
||||||
|
*port = (uint16_t)atoi(argv[i + 2]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int simulation_client_init(SimulationClient *client, int argc, char **argv,
|
||||||
|
void **contexts, struct pollfd *polled, int *timeout)
|
||||||
|
{
|
||||||
|
char *addr;
|
||||||
|
uint16_t port;
|
||||||
|
parse_server_addr(argc, argv, &addr, &port);
|
||||||
|
|
||||||
|
printf("[Client] Initializing TinyDFS client, connecting to %s:%u\n", addr, port);
|
||||||
|
|
||||||
|
client->tdfs = tinydfs_init(addr, port);
|
||||||
|
if (client->tdfs == NULL) {
|
||||||
|
fprintf(stderr, "[Client] Failed to initialize TinyDFS client\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->state = CLIENT_STATE_INIT;
|
||||||
|
client->step = 0;
|
||||||
|
client->create_dir_op = -1;
|
||||||
|
client->create_file_op = -1;
|
||||||
|
client->write_op = -1;
|
||||||
|
client->read_op = -1;
|
||||||
|
client->list_op = -1;
|
||||||
|
client->delete_op = -1;
|
||||||
|
|
||||||
|
printf("[Client] Initialized successfully\n");
|
||||||
|
|
||||||
|
// Return no polled descriptors for now; we'll handle them in step
|
||||||
|
*timeout = 0; // Wake up immediately to start processing
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int simulation_client_step(SimulationClient *client, void **contexts,
|
||||||
|
struct pollfd *polled, int num_polled, int *timeout)
|
||||||
|
{
|
||||||
|
TinyDFS_Result result;
|
||||||
|
|
||||||
|
// Process any pending events from the network and get new poll descriptors
|
||||||
|
num_polled = tinydfs_process_events(client->tdfs, contexts, polled, num_polled);
|
||||||
|
|
||||||
|
// State machine for running test operations
|
||||||
|
switch (client->step) {
|
||||||
|
case 0:
|
||||||
|
// Step 0: Create a directory
|
||||||
|
printf("[Client] Step 0: Creating directory /test_dir\n");
|
||||||
|
client->create_dir_op = tinydfs_submit_create(client->tdfs, "/test_dir", -1, true, 0);
|
||||||
|
if (client->create_dir_op < 0) {
|
||||||
|
fprintf(stderr, "[Client] Failed to submit create directory operation\n");
|
||||||
|
client->state = CLIENT_STATE_DONE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
client->step++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
// Step 1: Wait for directory creation to complete
|
||||||
|
if (tinydfs_isdone(client->tdfs, client->create_dir_op, &result)) {
|
||||||
|
if (result.type == TINYDFS_RESULT_CREATE_SUCCESS) {
|
||||||
|
printf("[Client] Step 1: Directory created successfully\n");
|
||||||
|
client->step++;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "[Client] Step 1: Failed to create directory\n");
|
||||||
|
client->state = CLIENT_STATE_DONE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tinydfs_result_free(&result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
// Step 2: Create a file
|
||||||
|
printf("[Client] Step 2: Creating file /test_dir/test_file.txt\n");
|
||||||
|
client->create_file_op = tinydfs_submit_create(client->tdfs, "/test_dir/test_file.txt", -1, false, 1024);
|
||||||
|
if (client->create_file_op < 0) {
|
||||||
|
fprintf(stderr, "[Client] Failed to submit create file operation\n");
|
||||||
|
client->state = CLIENT_STATE_DONE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
client->step++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
// Step 3: Wait for file creation to complete
|
||||||
|
if (tinydfs_isdone(client->tdfs, client->create_file_op, &result)) {
|
||||||
|
if (result.type == TINYDFS_RESULT_CREATE_SUCCESS) {
|
||||||
|
printf("[Client] Step 3: File created successfully\n");
|
||||||
|
client->step++;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "[Client] Step 3: Failed to create file\n");
|
||||||
|
client->state = CLIENT_STATE_DONE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tinydfs_result_free(&result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
// Step 4: Write data to the file
|
||||||
|
printf("[Client] Step 4: Writing data to /test_dir/test_file.txt\n");
|
||||||
|
{
|
||||||
|
const char *data = "Hello, TinyDFS! This is a test.";
|
||||||
|
client->write_op = tinydfs_submit_write(client->tdfs, "/test_dir/test_file.txt", -1, 0, (void *)data, strlen(data));
|
||||||
|
if (client->write_op < 0) {
|
||||||
|
fprintf(stderr, "[Client] Failed to submit write operation\n");
|
||||||
|
client->state = CLIENT_STATE_DONE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client->step++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
// Step 5: Wait for write to complete
|
||||||
|
if (tinydfs_isdone(client->tdfs, client->write_op, &result)) {
|
||||||
|
if (result.type == TINYDFS_RESULT_WRITE_SUCCESS) {
|
||||||
|
printf("[Client] Step 5: Data written successfully\n");
|
||||||
|
client->step++;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "[Client] Step 5: Failed to write data\n");
|
||||||
|
client->state = CLIENT_STATE_DONE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tinydfs_result_free(&result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
// Step 6: Read data from the file
|
||||||
|
printf("[Client] Step 6: Reading data from /test_dir/test_file.txt\n");
|
||||||
|
memset(client->read_buffer, 0, sizeof(client->read_buffer));
|
||||||
|
client->read_op = tinydfs_submit_read(client->tdfs, "/test_dir/test_file.txt", -1, 0, client->read_buffer, sizeof(client->read_buffer) - 1);
|
||||||
|
if (client->read_op < 0) {
|
||||||
|
fprintf(stderr, "[Client] Failed to submit read operation\n");
|
||||||
|
client->state = CLIENT_STATE_DONE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
client->step++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
// Step 7: Wait for read to complete
|
||||||
|
if (tinydfs_isdone(client->tdfs, client->read_op, &result)) {
|
||||||
|
if (result.type == TINYDFS_RESULT_READ_SUCCESS) {
|
||||||
|
printf("[Client] Step 7: Data read successfully: '%s'\n", client->read_buffer);
|
||||||
|
client->step++;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "[Client] Step 7: Failed to read data\n");
|
||||||
|
client->state = CLIENT_STATE_DONE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tinydfs_result_free(&result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
// Step 8: List directory contents
|
||||||
|
printf("[Client] Step 8: Listing /test_dir\n");
|
||||||
|
client->list_op = tinydfs_submit_list(client->tdfs, "/test_dir", -1);
|
||||||
|
if (client->list_op < 0) {
|
||||||
|
fprintf(stderr, "[Client] Failed to submit list operation\n");
|
||||||
|
client->state = CLIENT_STATE_DONE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
client->step++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 9:
|
||||||
|
// Step 9: Wait for list to complete
|
||||||
|
if (tinydfs_isdone(client->tdfs, client->list_op, &result)) {
|
||||||
|
if (result.type == TINYDFS_RESULT_LIST_SUCCESS) {
|
||||||
|
printf("[Client] Step 9: Directory listing:\n");
|
||||||
|
for (int i = 0; i < result.num_entities; i++) {
|
||||||
|
printf("[Client] - %s %s\n",
|
||||||
|
result.entities[i].is_dir ? "[DIR]" : "[FILE]",
|
||||||
|
result.entities[i].name);
|
||||||
|
}
|
||||||
|
client->step++;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "[Client] Step 9: Failed to list directory\n");
|
||||||
|
client->state = CLIENT_STATE_DONE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tinydfs_result_free(&result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
// Step 10: Delete the file
|
||||||
|
printf("[Client] Step 10: Deleting /test_dir/test_file.txt\n");
|
||||||
|
client->delete_op = tinydfs_submit_delete(client->tdfs, "/test_dir/test_file.txt", -1);
|
||||||
|
if (client->delete_op < 0) {
|
||||||
|
fprintf(stderr, "[Client] Failed to submit delete operation\n");
|
||||||
|
client->state = CLIENT_STATE_DONE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
client->step++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 11:
|
||||||
|
// Step 11: Wait for delete to complete
|
||||||
|
if (tinydfs_isdone(client->tdfs, client->delete_op, &result)) {
|
||||||
|
if (result.type == TINYDFS_RESULT_DELETE_SUCCESS) {
|
||||||
|
printf("[Client] Step 11: File deleted successfully\n");
|
||||||
|
client->step++;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "[Client] Step 11: Failed to delete file\n");
|
||||||
|
client->state = CLIENT_STATE_DONE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tinydfs_result_free(&result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 12:
|
||||||
|
// All operations complete
|
||||||
|
printf("[Client] All operations completed successfully!\n");
|
||||||
|
client->state = CLIENT_STATE_DONE;
|
||||||
|
client->step++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Stay in DONE state
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're done, no need to wake up again
|
||||||
|
if (client->state == CLIENT_STATE_DONE) {
|
||||||
|
*timeout = -1;
|
||||||
|
} else {
|
||||||
|
// Wake up soon to continue processing
|
||||||
|
*timeout = 10; // 10ms
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the poll array from the TinyDFS client
|
||||||
|
return num_polled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void simulation_client_free(SimulationClient *client)
|
||||||
|
{
|
||||||
|
if (client->tdfs) {
|
||||||
|
tinydfs_free(client->tdfs);
|
||||||
|
client->tdfs = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BUILD_TEST
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef SIMULATION_CLIENT_INCLUDED
|
||||||
|
#define SIMULATION_CLIENT_INCLUDED
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
|
#include <poll.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "TinyDFS.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CLIENT_STATE_INIT,
|
||||||
|
CLIENT_STATE_RUNNING,
|
||||||
|
CLIENT_STATE_DONE,
|
||||||
|
} ClientState;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
TinyDFS *tdfs;
|
||||||
|
ClientState state;
|
||||||
|
|
||||||
|
// Track operations
|
||||||
|
int create_dir_op;
|
||||||
|
int create_file_op;
|
||||||
|
int write_op;
|
||||||
|
int read_op;
|
||||||
|
int list_op;
|
||||||
|
int delete_op;
|
||||||
|
|
||||||
|
// Read buffer
|
||||||
|
char read_buffer[1024];
|
||||||
|
|
||||||
|
// Test step counter
|
||||||
|
int step;
|
||||||
|
} SimulationClient;
|
||||||
|
|
||||||
|
int simulation_client_init(SimulationClient *client, int argc, char **argv,
|
||||||
|
void **contexts, struct pollfd *polled, int *timeout);
|
||||||
|
int simulation_client_step(SimulationClient *client, void **contexts,
|
||||||
|
struct pollfd *polled, int num_polled, int *timeout);
|
||||||
|
void simulation_client_free(SimulationClient *client);
|
||||||
|
|
||||||
|
#endif // SIMULATION_CLIENT_INCLUDED
|
||||||
+84
-19
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef BUILD_TEST
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -5,6 +7,7 @@
|
|||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "chunk_server.h"
|
#include "chunk_server.h"
|
||||||
#include "metadata_server.h"
|
#include "metadata_server.h"
|
||||||
|
#include "simulation_client.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define NATIVE_HANDLE HANDLE
|
#define NATIVE_HANDLE HANDLE
|
||||||
@@ -131,6 +134,12 @@ typedef struct {
|
|||||||
int line;
|
int line;
|
||||||
} Allocation;
|
} Allocation;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PROCESS_TYPE_METADATA_SERVER,
|
||||||
|
PROCESS_TYPE_CHUNK_SERVER,
|
||||||
|
PROCESS_TYPE_CLIENT,
|
||||||
|
} ProcessType;
|
||||||
|
|
||||||
struct Process {
|
struct Process {
|
||||||
|
|
||||||
int num_desc;
|
int num_desc;
|
||||||
@@ -141,10 +150,11 @@ struct Process {
|
|||||||
|
|
||||||
Time wakeup_time;
|
Time wakeup_time;
|
||||||
|
|
||||||
bool leader;
|
ProcessType type;
|
||||||
union {
|
union {
|
||||||
ChunkServer chunk_server;
|
ChunkServer chunk_server;
|
||||||
MetadataServer metadata_server;
|
MetadataServer metadata_server;
|
||||||
|
SimulationClient simulation_client;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -153,6 +163,14 @@ static Process *processes[MAX_PROCESSES];
|
|||||||
static Process *current_process = NULL;
|
static Process *current_process = NULL;
|
||||||
static uint64_t current_time = 1;
|
static uint64_t current_time = 1;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
// Simulated time for deterministic clock_gettime behavior
|
||||||
|
static struct timespec simulated_time = {0, 0};
|
||||||
|
#else
|
||||||
|
// On Windows, simulated_time is used for QueryPerformanceCounter
|
||||||
|
static struct timespec simulated_time = {0, 0};
|
||||||
|
#endif
|
||||||
|
|
||||||
// Helper to set socket errors correctly on Windows vs Linux
|
// Helper to set socket errors correctly on Windows vs Linux
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define SET_SOCKET_ERROR(err) WSASetLastError(err)
|
#define SET_SOCKET_ERROR(err) WSASetLastError(err)
|
||||||
@@ -228,6 +246,14 @@ static bool is_leader(int argc, char **argv)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_client(int argc, char **argv)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < argc; i++)
|
||||||
|
if (!strcmp("--client", argv[i]) || !strcmp("-c", argv[i]))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#define MAX_ARGS 128
|
#define MAX_ARGS 128
|
||||||
|
|
||||||
static bool is_space(char c)
|
static bool is_space(char c)
|
||||||
@@ -275,12 +301,21 @@ int spawn_simulated_process(char *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool leader = is_leader(argc, argv);
|
bool leader = is_leader(argc, argv);
|
||||||
|
bool client = is_client(argc, argv);
|
||||||
|
|
||||||
Process *process = malloc(sizeof(Process));
|
Process *process = malloc(sizeof(Process));
|
||||||
if (process == NULL)
|
if (process == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
process->leader = leader;
|
// Determine process type
|
||||||
|
if (client) {
|
||||||
|
process->type = PROCESS_TYPE_CLIENT;
|
||||||
|
} else if (leader) {
|
||||||
|
process->type = PROCESS_TYPE_METADATA_SERVER;
|
||||||
|
} else {
|
||||||
|
process->type = PROCESS_TYPE_CHUNK_SERVER;
|
||||||
|
}
|
||||||
|
|
||||||
process->num_desc = 0;
|
process->num_desc = 0;
|
||||||
process->num_allocs = 0;
|
process->num_allocs = 0;
|
||||||
|
|
||||||
@@ -290,18 +325,30 @@ int spawn_simulated_process(char *args)
|
|||||||
void *contexts[MAX_CONNS+1];
|
void *contexts[MAX_CONNS+1];
|
||||||
struct pollfd polled[MAX_CONNS+1];
|
struct pollfd polled[MAX_CONNS+1];
|
||||||
int num_polled;
|
int num_polled;
|
||||||
|
int timeout = -1;
|
||||||
|
|
||||||
current_process = process;
|
current_process = process;
|
||||||
int timeout = -1;
|
|
||||||
if (leader) {
|
switch (process->type) {
|
||||||
num_polled = metadata_server_init(&process->metadata_server, argc, argv, contexts, polled, &timeout);
|
case PROCESS_TYPE_METADATA_SERVER:
|
||||||
} else {
|
num_polled = metadata_server_init(&process->metadata_server, argc, argv, contexts, polled, &timeout);
|
||||||
num_polled = chunk_server_init(&process->chunk_server, argc, argv, contexts, polled, &timeout);
|
break;
|
||||||
|
case PROCESS_TYPE_CHUNK_SERVER:
|
||||||
|
num_polled = chunk_server_init(&process->chunk_server, argc, argv, contexts, polled, &timeout);
|
||||||
|
break;
|
||||||
|
case PROCESS_TYPE_CLIENT:
|
||||||
|
num_polled = simulation_client_init(&process->simulation_client, argc, argv, contexts, polled, &timeout);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
num_polled = -1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_process = NULL;
|
current_process = NULL;
|
||||||
if (num_polled < 0) {
|
if (num_polled < 0) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeout < 0) {
|
if (timeout < 0) {
|
||||||
process->wakeup_time = INVALID_TIME;
|
process->wakeup_time = INVALID_TIME;
|
||||||
} else {
|
} else {
|
||||||
@@ -311,22 +358,32 @@ int spawn_simulated_process(char *args)
|
|||||||
process_poll_array(process, contexts, polled, num_polled);
|
process_poll_array(process, contexts, polled, num_polled);
|
||||||
|
|
||||||
processes[num_processes++] = process;
|
processes[num_processes++] = process;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_process(Process *process)
|
static void free_process(Process *process)
|
||||||
{
|
{
|
||||||
if (process->leader) {
|
switch (process->type) {
|
||||||
metadata_server_free(&process->metadata_server);
|
case PROCESS_TYPE_METADATA_SERVER:
|
||||||
} else {
|
metadata_server_free(&process->metadata_server);
|
||||||
chunk_server_free(&process->chunk_server);
|
break;
|
||||||
|
case PROCESS_TYPE_CHUNK_SERVER:
|
||||||
|
chunk_server_free(&process->chunk_server);
|
||||||
|
break;
|
||||||
|
case PROCESS_TYPE_CLIENT:
|
||||||
|
simulation_client_free(&process->simulation_client);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
free(process);
|
free(process);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup_simulation(void)
|
void cleanup_simulation(void)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < num_processes; i++)
|
for (int i = 0; i < num_processes; i++) {
|
||||||
|
current_process = processes[i];
|
||||||
free_process(processes[i]);
|
free_process(processes[i]);
|
||||||
|
current_process = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool addr_eql_2(DescriptorAddress a, DescriptorAddress b)
|
static bool addr_eql_2(DescriptorAddress a, DescriptorAddress b)
|
||||||
@@ -491,10 +548,16 @@ void update_simulation(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int timeout = -1;
|
int timeout = -1;
|
||||||
if (current_process->leader) {
|
switch (current_process->type) {
|
||||||
num_polled = metadata_server_step(¤t_process->metadata_server, contexts, polled, num_polled, &timeout);
|
case PROCESS_TYPE_METADATA_SERVER:
|
||||||
} else {
|
num_polled = metadata_server_step(¤t_process->metadata_server, contexts, polled, num_polled, &timeout);
|
||||||
num_polled = chunk_server_step(¤t_process->chunk_server, contexts, polled, num_polled, &timeout);
|
break;
|
||||||
|
case PROCESS_TYPE_CHUNK_SERVER:
|
||||||
|
num_polled = chunk_server_step(¤t_process->chunk_server, contexts, polled, num_polled, &timeout);
|
||||||
|
break;
|
||||||
|
case PROCESS_TYPE_CLIENT:
|
||||||
|
num_polled = simulation_client_step(¤t_process->simulation_client, contexts, polled, num_polled, &timeout);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_polled < 0) {
|
if (num_polled < 0) {
|
||||||
@@ -1401,4 +1464,6 @@ int mock_mkdir(char *path, mode_t mode)
|
|||||||
return mkdir(path, mode);
|
return mkdir(path, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif // !_WIN32
|
||||||
|
|
||||||
|
#endif // BUILD_TEST
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#ifdef BUILD_TEST
|
#ifdef BUILD_TEST
|
||||||
|
|
||||||
|
void startup_simulation(void);
|
||||||
int spawn_simulated_process(char *args);
|
int spawn_simulated_process(char *args);
|
||||||
void update_simulation(void);
|
void update_simulation(void);
|
||||||
void cleanup_simulation(void);
|
void cleanup_simulation(void);
|
||||||
|
|||||||
Reference in New Issue
Block a user