Progress
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
|
||||
CFLAGS = -Wall -Wextra -ggdb
|
||||
CFLAGS = -Wall -Wextra -ggdb -fsanitize=address,undefined
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
LFLAGS = -lws2_32
|
||||
|
||||
+6
-11
@@ -429,18 +429,16 @@ int tinydfs_submit_delete(TinyDFS *tdfs, char *path, int path_len)
|
||||
int opidx = alloc_operation(tdfs, type, 0, NULL, 0);
|
||||
if (opidx < 0) return -1;
|
||||
|
||||
MessageWriter writer;
|
||||
metadata_server_request_start(tdfs, &writer, MESSAGE_TYPE_DELETE);
|
||||
|
||||
if (path_len > UINT16_MAX) {
|
||||
free_operation(tdfs, opidx);
|
||||
return -1;
|
||||
}
|
||||
uint16_t tmp = path_len;
|
||||
|
||||
MessageWriter writer;
|
||||
metadata_server_request_start(tdfs, &writer, MESSAGE_TYPE_DELETE);
|
||||
message_write(&writer, &tmp, sizeof(tmp));
|
||||
|
||||
message_write(&writer, path, path_len);
|
||||
|
||||
if (metadata_server_request_end(tdfs, &writer, opidx, 0) < 0) {
|
||||
free_operation(tdfs, opidx);
|
||||
return -1;
|
||||
@@ -457,16 +455,15 @@ int tinydfs_submit_list(TinyDFS *tdfs, char *path, int path_len)
|
||||
int opidx = alloc_operation(tdfs, type, 0, NULL, 0);
|
||||
if (opidx < 0) return -1;
|
||||
|
||||
MessageWriter writer;
|
||||
metadata_server_request_start(tdfs, &writer, MESSAGE_TYPE_LIST);
|
||||
|
||||
if (path_len > UINT16_MAX) {
|
||||
free_operation(tdfs, opidx);
|
||||
return -1;
|
||||
}
|
||||
uint16_t tmp = path_len;
|
||||
message_write(&writer, &tmp, sizeof(tmp));
|
||||
|
||||
MessageWriter writer;
|
||||
metadata_server_request_start(tdfs, &writer, MESSAGE_TYPE_LIST);
|
||||
message_write(&writer, &tmp, sizeof(tmp));
|
||||
message_write(&writer, path, path_len);
|
||||
|
||||
if (metadata_server_request_end(tdfs, &writer, opidx, 0) < 0) {
|
||||
@@ -485,12 +482,10 @@ static int send_read_message(TinyDFS *tdfs, int opidx, int tag, string path, uin
|
||||
|
||||
MessageWriter writer;
|
||||
metadata_server_request_start(tdfs, &writer, MESSAGE_TYPE_READ);
|
||||
|
||||
message_write(&writer, &path_len, sizeof(path_len));
|
||||
message_write(&writer, path.ptr, path.len);
|
||||
message_write(&writer, &offset, sizeof(offset));
|
||||
message_write(&writer, &length, sizeof(length));
|
||||
|
||||
if (metadata_server_request_end(tdfs, &writer, opidx, tag) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
@@ -291,6 +291,7 @@ int file_tree_create_entity(FileTree *ft, string path,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: this should return the list of unreferenced hashes
|
||||
int file_tree_delete_entity(FileTree *ft, string path)
|
||||
{
|
||||
int num_comps;
|
||||
|
||||
+5
-1
@@ -15,7 +15,7 @@ int main(int argc, char **argv)
|
||||
|
||||
// TODO: set simulation_should_stop=true on ctrl+C
|
||||
|
||||
startup_simulation();
|
||||
startup_simulation(1);
|
||||
|
||||
// Spawn metadata server (leader)
|
||||
spawn_simulated_process("--addr 127.0.0.1 --port 8080 --leader");
|
||||
@@ -34,6 +34,10 @@ int main(int argc, char **argv)
|
||||
|
||||
// Spawn simulation client
|
||||
spawn_simulated_process("--client --remote-addr 127.0.0.1 --remote-port 8080");
|
||||
spawn_simulated_process("--client --remote-addr 127.0.0.1 --remote-port 8080");
|
||||
spawn_simulated_process("--client --remote-addr 127.0.0.1 --remote-port 8080");
|
||||
spawn_simulated_process("--client --remote-addr 127.0.0.1 --remote-port 8080");
|
||||
spawn_simulated_process("--client --remote-addr 127.0.0.1 --remote-port 8080");
|
||||
|
||||
while (!simulation_should_stop)
|
||||
update_simulation();
|
||||
|
||||
+178
-185
@@ -35,25 +35,23 @@ int simulation_client_init(SimulationClient *client, int argc, char **argv,
|
||||
parse_server_addr(argc, argv, &addr, &port);
|
||||
|
||||
client->tdfs = tinydfs_init(addr, port);
|
||||
if (client->tdfs == NULL) {
|
||||
if (client->tdfs == NULL)
|
||||
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;
|
||||
client->num_pending = 0;
|
||||
|
||||
printf("Client set up (remote=%s:%d)\n", addr, port);
|
||||
|
||||
*timeout = 0; // Wake up immediately to start processing
|
||||
*timeout = 0;
|
||||
return tinydfs_process_events(client->tdfs, contexts, polled, 0);
|
||||
}
|
||||
|
||||
static int random_in_range(int min, int max)
|
||||
{
|
||||
uint64_t n = simulation_random_number();
|
||||
return min + n % (max - min + 1);
|
||||
}
|
||||
|
||||
int simulation_client_step(SimulationClient *client, void **contexts,
|
||||
struct pollfd *polled, int num_polled, int *timeout)
|
||||
{
|
||||
@@ -62,209 +60,204 @@ int simulation_client_step(SimulationClient *client, void **contexts,
|
||||
// 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;
|
||||
break;
|
||||
}
|
||||
client->step++;
|
||||
for (int i = 0; i < client->num_pending; i++) {
|
||||
|
||||
TinyDFS_Result result;
|
||||
if (!tinydfs_isdone(client->tdfs, client->pending[i].opidx, &result))
|
||||
continue;
|
||||
|
||||
PendingOperation pending = client->pending[i];
|
||||
switch (result.type) {
|
||||
|
||||
case TINYDFS_RESULT_EMPTY:
|
||||
assert(0);
|
||||
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;
|
||||
break;
|
||||
}
|
||||
tinydfs_result_free(&result);
|
||||
}
|
||||
case TINYDFS_RESULT_CREATE_ERROR:
|
||||
assert(pending.type == PENDING_OPERATION_CREATE);
|
||||
printf("[Client] create error\n");
|
||||
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;
|
||||
break;
|
||||
}
|
||||
client->step++;
|
||||
case TINYDFS_RESULT_CREATE_SUCCESS:
|
||||
assert(pending.type == PENDING_OPERATION_CREATE);
|
||||
printf("[Client] create success\n");
|
||||
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;
|
||||
break;
|
||||
}
|
||||
tinydfs_result_free(&result);
|
||||
}
|
||||
case TINYDFS_RESULT_DELETE_ERROR:
|
||||
assert(pending.type == PENDING_OPERATION_DELETE);
|
||||
printf("[Client] delete error\n");
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
client->step++;
|
||||
case TINYDFS_RESULT_DELETE_SUCCESS:
|
||||
assert(pending.type == PENDING_OPERATION_DELETE);
|
||||
printf("[Client] delete success\n");
|
||||
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;
|
||||
break;
|
||||
}
|
||||
tinydfs_result_free(&result);
|
||||
}
|
||||
case TINYDFS_RESULT_LIST_ERROR:
|
||||
assert(pending.type == PENDING_OPERATION_LIST);
|
||||
printf("[Client] list error\n");
|
||||
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;
|
||||
break;
|
||||
}
|
||||
client->step++;
|
||||
case TINYDFS_RESULT_LIST_SUCCESS:
|
||||
assert(pending.type == PENDING_OPERATION_LIST);
|
||||
printf("[Client] list success\n");
|
||||
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;
|
||||
break;
|
||||
}
|
||||
tinydfs_result_free(&result);
|
||||
}
|
||||
case TINYDFS_RESULT_READ_ERROR:
|
||||
assert(pending.type == PENDING_OPERATION_READ);
|
||||
printf("[Client] read error\n");
|
||||
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;
|
||||
break;
|
||||
}
|
||||
client->step++;
|
||||
case TINYDFS_RESULT_READ_SUCCESS:
|
||||
assert(pending.type == PENDING_OPERATION_READ);
|
||||
printf("[Client] read success\n");
|
||||
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;
|
||||
break;
|
||||
}
|
||||
tinydfs_result_free(&result);
|
||||
}
|
||||
case TINYDFS_RESULT_WRITE_ERROR:
|
||||
assert(pending.type == PENDING_OPERATION_WRITE);
|
||||
printf("[Client] write error\n");
|
||||
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;
|
||||
break;
|
||||
}
|
||||
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;
|
||||
break;
|
||||
}
|
||||
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
|
||||
case TINYDFS_RESULT_WRITE_SUCCESS:
|
||||
assert(pending.type == PENDING_OPERATION_WRITE);
|
||||
printf("[Client] write success\n");
|
||||
break;
|
||||
}
|
||||
free(pending.ptr);
|
||||
tinydfs_result_free(&result);
|
||||
client->pending[i--] = client->pending[--client->num_pending];
|
||||
}
|
||||
|
||||
// If we're done, no need to wake up again
|
||||
if (client->state == CLIENT_STATE_DONE) {
|
||||
while (client->num_pending < MAX_PENDING_OPERATION) {
|
||||
|
||||
typedef struct {
|
||||
char *path;
|
||||
bool is_dir;
|
||||
} TableEntry;
|
||||
|
||||
static const TableEntry table[] = {
|
||||
{ "/f0", false },
|
||||
{ "/f1", false },
|
||||
{ "/d0", true },
|
||||
{ "/d1", true },
|
||||
{ "/d0/f1", false },
|
||||
{ "/d0/f2", false },
|
||||
{ "/d0/d0", true },
|
||||
{ "/d0/d1", true },
|
||||
{ "/d1/f1", false },
|
||||
{ "/d1/f2", false },
|
||||
{ "/d1/d0", true },
|
||||
{ "/d1/d1", true },
|
||||
};
|
||||
static const int table_len = sizeof(table) / sizeof(table[0]);
|
||||
|
||||
static const PendingOperationType type_table[] = {
|
||||
PENDING_OPERATION_CREATE,
|
||||
PENDING_OPERATION_DELETE,
|
||||
PENDING_OPERATION_LIST,
|
||||
PENDING_OPERATION_READ,
|
||||
PENDING_OPERATION_WRITE,
|
||||
};
|
||||
static const int type_table_len = sizeof(type_table)/sizeof(type_table[0]);
|
||||
|
||||
void *ptr = NULL;
|
||||
int off = 0;
|
||||
int len = 0;
|
||||
int ret;
|
||||
|
||||
PendingOperationType type = type_table[random_in_range(0, type_table_len-1)];
|
||||
switch (type) {
|
||||
|
||||
TableEntry entry;
|
||||
uint32_t chunk_size;
|
||||
|
||||
case PENDING_OPERATION_CREATE:
|
||||
entry = table[random_in_range(0, table_len-1)];
|
||||
chunk_size = entry.is_dir ? 0 : random_in_range(0, 5000);
|
||||
ret = tinydfs_submit_create(
|
||||
client->tdfs,
|
||||
entry.path,
|
||||
-1,
|
||||
entry.is_dir,
|
||||
chunk_size
|
||||
);
|
||||
printf("[Client] submit create (path=%s, is_dir=%s, chunk_size=%d)\n", entry.path, entry.is_dir ? "true" : "false", chunk_size);
|
||||
break;
|
||||
|
||||
case PENDING_OPERATION_DELETE:
|
||||
entry = table[random_in_range(0, table_len-1)];
|
||||
ret = tinydfs_submit_delete(
|
||||
client->tdfs,
|
||||
entry.path,
|
||||
-1
|
||||
);
|
||||
printf("[Client] submit delete (path=%s)\n", entry.path);
|
||||
break;
|
||||
|
||||
case PENDING_OPERATION_LIST:
|
||||
entry = table[random_in_range(0, table_len-1)];
|
||||
ret = tinydfs_submit_list(
|
||||
client->tdfs,
|
||||
entry.path,
|
||||
-1
|
||||
);
|
||||
printf("[Client] submit list (path=%s)\n", entry.path);
|
||||
break;
|
||||
|
||||
case PENDING_OPERATION_READ:
|
||||
entry = table[random_in_range(0, table_len-1)];
|
||||
off = random_in_range(0, 10000);
|
||||
len = random_in_range(0, 5000);
|
||||
ptr = malloc(len);
|
||||
if (ptr == NULL) assert(0);
|
||||
ret = tinydfs_submit_read(client->tdfs,
|
||||
entry.path,
|
||||
-1,
|
||||
off,
|
||||
ptr,
|
||||
len
|
||||
);
|
||||
printf("[Client] submit read (path=%s, off=%d, len=%d)\n", entry.path, off, len);
|
||||
break;
|
||||
|
||||
case PENDING_OPERATION_WRITE:
|
||||
entry = table[random_in_range(0, table_len-1)];
|
||||
off = random_in_range(0, 10000);
|
||||
len = random_in_range(0, 5000);
|
||||
ptr = malloc(len);
|
||||
if (ptr == NULL) assert(0);
|
||||
memset(ptr, 'a', len);
|
||||
ret = tinydfs_submit_write(
|
||||
client->tdfs,
|
||||
entry.path,
|
||||
-1,
|
||||
off,
|
||||
ptr,
|
||||
len
|
||||
);
|
||||
printf("[Client] submit write (path=%s, off=%d, len=%d)\n", entry.path, off, len);
|
||||
break;
|
||||
}
|
||||
if (ret < 0)
|
||||
break;
|
||||
PendingOperation pending = {
|
||||
.type = type,
|
||||
.opidx = ret,
|
||||
.ptr = ptr,
|
||||
};
|
||||
client->pending[client->num_pending++] = pending;
|
||||
}
|
||||
|
||||
if (client->num_pending == 0)
|
||||
*timeout = 10;
|
||||
else
|
||||
*timeout = -1;
|
||||
} else {
|
||||
// Wake up soon to continue processing
|
||||
*timeout = 10; // 10ms
|
||||
}
|
||||
|
||||
// Return the poll array from the TinyDFS client
|
||||
return tinydfs_process_events(client->tdfs, contexts, polled, 0);
|
||||
}
|
||||
|
||||
void simulation_client_free(SimulationClient *client)
|
||||
{
|
||||
if (client->tdfs) {
|
||||
tinydfs_free(client->tdfs);
|
||||
client->tdfs = NULL;
|
||||
}
|
||||
tinydfs_free(client->tdfs);
|
||||
}
|
||||
|
||||
#endif // BUILD_TEST
|
||||
|
||||
+16
-19
@@ -12,29 +12,26 @@
|
||||
|
||||
#include "TinyDFS.h"
|
||||
|
||||
#define MAX_PENDING_OPERATION 128
|
||||
|
||||
typedef enum {
|
||||
CLIENT_STATE_INIT,
|
||||
CLIENT_STATE_RUNNING,
|
||||
CLIENT_STATE_DONE,
|
||||
} ClientState;
|
||||
PENDING_OPERATION_CREATE,
|
||||
PENDING_OPERATION_DELETE,
|
||||
PENDING_OPERATION_LIST,
|
||||
PENDING_OPERATION_READ,
|
||||
PENDING_OPERATION_WRITE,
|
||||
} PendingOperationType;
|
||||
|
||||
typedef struct {
|
||||
PendingOperationType type;
|
||||
int opidx;
|
||||
void *ptr;
|
||||
} PendingOperation;
|
||||
|
||||
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;
|
||||
int num_pending;
|
||||
PendingOperation pending[MAX_PENDING_OPERATION];
|
||||
} SimulationClient;
|
||||
|
||||
int simulation_client_init(SimulationClient *client, int argc, char **argv,
|
||||
|
||||
+17
-23
@@ -166,7 +166,9 @@ static int num_processes = 0;
|
||||
static Process *processes[MAX_PROCESSES];
|
||||
static Process *current_process = NULL;
|
||||
static uint64_t current_time = 1;
|
||||
static uint64_t seed;
|
||||
|
||||
// TODO: use current_time instead of these fields
|
||||
#ifndef _WIN32
|
||||
// Simulated time for deterministic clock_gettime behavior
|
||||
static struct timespec simulated_time = {0, 0};
|
||||
@@ -260,12 +262,26 @@ static bool is_space(char c)
|
||||
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
|
||||
}
|
||||
|
||||
void startup_simulation(void)
|
||||
void startup_simulation(uint64_t seed_)
|
||||
{
|
||||
seed = seed_;
|
||||
if (seed == 0)
|
||||
seed = 1;
|
||||
|
||||
num_processes = 0;
|
||||
current_process = NULL;
|
||||
}
|
||||
|
||||
uint64_t simulation_random_number(void)
|
||||
{
|
||||
uint64_t x = seed;
|
||||
x ^= x << 13;
|
||||
x ^= x >> 7;
|
||||
x ^= x << 17;
|
||||
seed = x;
|
||||
return x;
|
||||
}
|
||||
|
||||
int spawn_simulated_process(char *args)
|
||||
{
|
||||
if (num_processes == MAX_PROCESSES)
|
||||
@@ -332,15 +348,12 @@ int spawn_simulated_process(char *args)
|
||||
|
||||
switch (process->type) {
|
||||
case PROCESS_TYPE_METADATA_SERVER:
|
||||
printf("metadata_server_init\n");
|
||||
num_polled = metadata_server_init(&process->metadata_server, argc, argv, contexts, polled, &timeout);
|
||||
break;
|
||||
case PROCESS_TYPE_CHUNK_SERVER:
|
||||
printf("chunk_server_init\n");
|
||||
num_polled = chunk_server_init(&process->chunk_server, argc, argv, contexts, polled, &timeout);
|
||||
break;
|
||||
case PROCESS_TYPE_CLIENT:
|
||||
printf("simulation_client_init\n");
|
||||
num_polled = simulation_client_init(&process->simulation_client, argc, argv, contexts, polled, &timeout);
|
||||
break;
|
||||
default:
|
||||
@@ -658,7 +671,6 @@ void update_simulation(void)
|
||||
int timeout = -1;
|
||||
switch (current_process->type) {
|
||||
case PROCESS_TYPE_METADATA_SERVER:
|
||||
printf("metadata_server_step\n");
|
||||
num_polled = metadata_server_step(
|
||||
¤t_process->metadata_server,
|
||||
contexts,
|
||||
@@ -668,7 +680,6 @@ void update_simulation(void)
|
||||
);
|
||||
break;
|
||||
case PROCESS_TYPE_CHUNK_SERVER:
|
||||
printf("chunk_server_step\n");
|
||||
num_polled = chunk_server_step(
|
||||
¤t_process->chunk_server,
|
||||
contexts,
|
||||
@@ -678,7 +689,6 @@ void update_simulation(void)
|
||||
);
|
||||
break;
|
||||
case PROCESS_TYPE_CLIENT:
|
||||
//printf("simulation_client_step\n");
|
||||
num_polled = simulation_client_step(
|
||||
¤t_process->simulation_client,
|
||||
contexts,
|
||||
@@ -720,21 +730,8 @@ void update_simulation(void)
|
||||
|
||||
case CONNECTION_DELAYED:
|
||||
{
|
||||
switch (desc->connect_address.type) {
|
||||
char ip_str[INET_ADDRSTRLEN];
|
||||
case DESC_ADDR_IPV4:
|
||||
inet_ntop(AF_INET, &desc->connect_address.ipv4.sin_addr, ip_str, sizeof(ip_str));
|
||||
printf("Resolving connect %s:%d\n", ip_str, ntohs(desc->connect_address.ipv4.sin_port));
|
||||
break;
|
||||
case DESC_ADDR_IPV6:
|
||||
inet_ntop(AF_INET6, &desc->connect_address.ipv6.sin6_addr, ip_str, sizeof(ip_str));
|
||||
printf("Resolving connect %s:%d\n", ip_str, ntohs(desc->connect_address.ipv6.sin6_port));
|
||||
break;
|
||||
}
|
||||
|
||||
DescriptorHandle peer_handle;
|
||||
if (!find_peer_by_address(desc->connect_address, &peer_handle)) {
|
||||
printf("connect failed (line %d)\n", __LINE__); // TODO
|
||||
desc->revents |= POLLOUT;
|
||||
desc->connection_state = CONNECTION_FAILED;
|
||||
desc->connect_errno = EHOSTUNREACH; // TODO: This only works on Linux, not Windows
|
||||
@@ -744,15 +741,12 @@ void update_simulation(void)
|
||||
|
||||
DescriptorHandle self_handle = { processes[i], j, desc->generation };
|
||||
if (!accept_queue_push(&peer->accept_queue, self_handle)) {
|
||||
printf("connect failed (line %d)\n", __LINE__); // TODO
|
||||
desc->revents |= POLLOUT;
|
||||
desc->connection_state = CONNECTION_FAILED;
|
||||
desc->connect_errno = ECONNREFUSED; // TODO: This only works on Linux, not Windows
|
||||
break;
|
||||
}
|
||||
|
||||
printf("connect succeded\n"); // TODO
|
||||
|
||||
peer->revents |= POLLIN;
|
||||
|
||||
desc->connection_state = CONNECTION_QUEUED;
|
||||
|
||||
+32
-28
@@ -9,6 +9,7 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <direct.h> // _mkdir
|
||||
#include <bcrypt.h>
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
@@ -23,6 +24,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/random.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define SOCKET int
|
||||
@@ -32,10 +34,11 @@
|
||||
|
||||
#ifdef BUILD_TEST
|
||||
|
||||
void startup_simulation(void);
|
||||
int spawn_simulated_process(char *args);
|
||||
void update_simulation(void);
|
||||
void cleanup_simulation(void);
|
||||
void startup_simulation(uint64_t seed_);
|
||||
int spawn_simulated_process(char *args);
|
||||
void update_simulation(void);
|
||||
void cleanup_simulation(void);
|
||||
uint64_t simulation_random_number(void);
|
||||
|
||||
void* mock_malloc(size_t len);
|
||||
void* mock_realloc(void *ptr, size_t len);
|
||||
@@ -53,31 +56,31 @@ int mock_send(SOCKET fd, void *src, int len, int flags);
|
||||
int mock_connect(SOCKET fd, void *addr, size_t addr_len);
|
||||
|
||||
#ifdef _WIN32
|
||||
int mock_closesocket(SOCKET fd);
|
||||
HANDLE mock_CreateFileW(WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
BOOL mock_CloseHandle(HANDLE handle);
|
||||
BOOL mock_LockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh);
|
||||
BOOL mock_UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh);
|
||||
BOOL mock_FlushFileBuffers(HANDLE handle);
|
||||
BOOL mock_ReadFile(HANDLE handle, char *dst, DWORD len, DWORD *num, OVERLAPPED *ov);
|
||||
BOOL mock_WriteFile(HANDLE handle, char *src, DWORD len, DWORD *num, OVERLAPPED *ov);
|
||||
BOOL mock_GetFileSizeEx(HANDLE handle, LARGE_INTEGER *buf);
|
||||
BOOL mock_QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);
|
||||
BOOL mock_QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
|
||||
char* mock__fullpath(char *path, char *dst, int cap);
|
||||
int mock__mkdir(char *path);
|
||||
int mock_closesocket(SOCKET fd);
|
||||
HANDLE mock_CreateFileW(WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
BOOL mock_CloseHandle(HANDLE handle);
|
||||
BOOL mock_LockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh);
|
||||
BOOL mock_UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh);
|
||||
BOOL mock_FlushFileBuffers(HANDLE handle);
|
||||
BOOL mock_ReadFile(HANDLE handle, char *dst, DWORD len, DWORD *num, OVERLAPPED *ov);
|
||||
BOOL mock_WriteFile(HANDLE handle, char *src, DWORD len, DWORD *num, OVERLAPPED *ov);
|
||||
BOOL mock_GetFileSizeEx(HANDLE handle, LARGE_INTEGER *buf);
|
||||
BOOL mock_QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);
|
||||
BOOL mock_QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
|
||||
char* mock__fullpath(char *path, char *dst, int cap);
|
||||
int mock__mkdir(char *path);
|
||||
#else
|
||||
int mock_clock_gettime(clockid_t clockid, struct timespec *tp);
|
||||
int mock_open(char *path, int flags, int mode);
|
||||
int mock_close(int fd);
|
||||
int mock_flock(int fd, int op);
|
||||
int mock_fsync(int fd);
|
||||
int mock_read(int fd, char *dst, int len);
|
||||
int mock_write(int fd, char *src, int len);
|
||||
int mock_fstat(int fd, struct stat *buf);
|
||||
int mock_mkstemp(char *path);
|
||||
char* mock_realpath(char *path, char *dst);
|
||||
int mock_mkdir(char *path, mode_t mode);
|
||||
int mock_clock_gettime(clockid_t clockid, struct timespec *tp);
|
||||
int mock_open(char *path, int flags, int mode);
|
||||
int mock_close(int fd);
|
||||
int mock_flock(int fd, int op);
|
||||
int mock_fsync(int fd);
|
||||
int mock_read(int fd, char *dst, int len);
|
||||
int mock_write(int fd, char *src, int len);
|
||||
int mock_fstat(int fd, struct stat *buf);
|
||||
int mock_mkstemp(char *path);
|
||||
char* mock_realpath(char *path, char *dst);
|
||||
int mock_mkdir(char *path, mode_t mode);
|
||||
#endif
|
||||
|
||||
// Common
|
||||
@@ -123,6 +126,7 @@ int mock_mkdir(char *path, mode_t mode);
|
||||
#define sys_mkstemp mock_mkstemp
|
||||
#define sys_realpath mock_realpath
|
||||
#define sys_clock_gettime mock_clock_gettime
|
||||
#define sys_getrandom mock_getrandom
|
||||
|
||||
#else
|
||||
|
||||
|
||||
Reference in New Issue
Block a user