This commit is contained in:
2025-10-27 18:54:49 +01:00
parent 1f4a9956da
commit 3c92b8d343
+105 -73
View File
@@ -2170,8 +2170,7 @@ typedef struct {
int count; int count;
int capacity; int capacity;
SHA256 *items; SHA256 *items;
SHA256 items_hash; } HashList;
} ChunkList;
typedef struct { typedef struct {
@@ -2182,15 +2181,15 @@ typedef struct {
// Chunks held by the chunk server during // Chunks held by the chunk server during
// the last update // the last update
ChunkList old_list; HashList old_list;
// Chunks added to the chunk server since // Chunks added to the chunk server since
// the last update // the last update
ChunkList add_list; HashList add_list;
// Chunks removed from the chunk server // Chunks removed from the chunk server
// since the last update // since the last update
ChunkList rem_list; HashList rem_list;
} ChunkServer; } ChunkServer;
typedef struct { typedef struct {
@@ -2200,46 +2199,46 @@ typedef struct {
ChunkServer chunk_servers[MAX_CHUNK_SERVERS]; ChunkServer chunk_servers[MAX_CHUNK_SERVERS];
} ProgramState; } ProgramState;
static void chunk_list_init(ChunkList *chunk_list) static void hash_list_init(ChunkList *hash_list)
{ {
chunk_list->count = 0; hash_list->count = 0;
chunk_list->capacity = 0; hash_list->capacity = 0;
chunk_list->items = NULL; hash_list->items = NULL;
memset(&chunk_list->items_hash, 0, sizeof(SHA256)); memset(&hash_list->items_hash, 0, sizeof(SHA256));
} }
static void chunk_list_free(ChunkList *chunk_list) static void hash_list_free(ChunkList *hash_list)
{ {
free(chunk_list->items); free(hash_list->items);
} }
static int chunk_list_insert(ChunkList *chunk_list, SHA256 hash) static int hash_list_insert(ChunkList *hash_list, SHA256 hash)
{ {
// Avoid duplicates // Avoid duplicates
for (int i = 0; i < chunk_list->count; i++) for (int i = 0; i < hash_list->count; i++)
if (!memcmp(&chunk_list->items[i], &hash, sizeof(SHA256))) if (!memcmp(&hash_list->items[i], &hash, sizeof(SHA256)))
return 0; // Already present return 0; // Already present
if (chunk_list->count == chunk_list->capacity) { if (hash_list->count == hash_list->capacity) {
int new_capacity = chunk_list->capacity ? chunk_list->capacity * 2 : 16; int new_capacity = hash_list->capacity ? hash_list->capacity * 2 : 16;
SHA256 *new_items = realloc(chunk_list->items, new_capacity * sizeof(SHA256)); SHA256 *new_items = realloc(hash_list->items, new_capacity * sizeof(SHA256));
if (new_items == NULL) if (new_items == NULL)
return -1; return -1;
chunk_list->items = new_items; hash_list->items = new_items;
chunk_list->capacity = new_capacity; hash_list->capacity = new_capacity;
} }
chunk_list->items[chunk_list->count++] = hash; hash_list->items[hash_list->count++] = hash;
return 0; return 0;
} }
static bool chunk_list_contains(ChunkList *chunk_list, SHA256 hash) static bool hash_list_contains(ChunkList *hash_list, SHA256 hash)
{ {
for (int j = 0; j < chunk_list->count; j++) for (int j = 0; j < hash_list->count; j++)
if (!memcmp(&hash, &chunk_list->items[j], sizeof(SHA256))) if (!memcmp(&hash, &hash_list->items[j], sizeof(SHA256)))
return true; return true;
return false; return false;
} }
@@ -2248,48 +2247,76 @@ static void chunk_server_init(ChunkServer *chunk_server)
{ {
chunk_server->auth = false; chunk_server->auth = false;
chunk_server->num_addrs = 0; chunk_server->num_addrs = 0;
chunk_list_init(&chunk_server->old_list); hash_list_init(&chunk_server->old_list);
chunk_list_init(&chunk_server->add_list); hash_list_init(&chunk_server->add_list);
chunk_list_init(&chunk_server->rem_list); hash_list_init(&chunk_server->rem_list);
} }
static void chunk_server_free(ChunkServer *chunk_server) static void chunk_server_free(ChunkServer *chunk_server)
{ {
chunk_list_free(&chunk_server->rem_list); hash_list_free(&chunk_server->rem_list);
chunk_list_free(&chunk_server->add_list); hash_list_free(&chunk_server->add_list);
chunk_list_free(&chunk_server->old_list); hash_list_free(&chunk_server->old_list);
} }
// Look for a chunk server holding a chunk with the static bool chunk_server_contains(ChunkServer *chunk_server, SHA256 hash)
// given hash. If no such chunk server exists, return -1.
static int choose_server_holding_chunk(ProgramState *state, SHA256 hash)
{ {
for (int i = 0; i < state->num_chunk_servers; i++) return hash_list_contains(&chunk_server->old_list, hash)
if (chunk_list_contains(&state->chunk_servers[i].old_list, hash) || || hash_list_contains(&chunk_server->add_list, hash);
chunk_list_contains(&state->chunk_servers[i].add_list, hash))
return i;
return -1;
} }
// Return the index of the chunk server with less static bool chunk_server_load(ChunkServer *chunk_server)
// chunks, or -1 is no chunk servers are available.
static int choose_server_for_write(ProgramState *state)
{ {
if (state->num_chunk_servers == 0) return chunk_server->old_list.count + chunk_server->add_list.count;
return -1; }
int chunk_count = state->chunk_servers[0].old_list.count + state->chunk_servers[0].add_list.count; // Returns all chunk servers holding the given chunk
int server_index = 0; //
// The indices of the chunk servers is stored into "out", but at
for (int i = 1; i < state->num_chunk_servers; i++) { // most "max" indices are written. The return value is the number
int tmp = state->chunk_servers[i].old_list.count + state->chunk_servers[i].add_list.count; // of indices that would be written if "max" were large enough to
if (tmp < chunk_count) { // hold all indices.
chunk_count = tmp; static int
server_index = i; all_chunk_servers_holding_chunk(ProgramState *state, SHA256 hash, int *out, int max)
} {
int num = 0;
for (int i = 0; i < state->num_chunk_servers; i++) {
if (num < max && chunk_server_contains(&state->chunk_servers[i], hash))
out[num] = i;
num++;
} }
return num;
}
return server_index; static int compare_chunk_servers(const void *p1, const void *p2, void *data)
{
int a = *(int*) p1;
int b = *(int*) p2;
ProgramState *state = data;
int l1 = chunk_server_load(&state->chunk_servers[a]);
int l2 = chunk_server_load(&state->chunk_servers[b]);
// TODO
}
// Returns the indices of chunk servers with lowest load in
// the "out" array. The return value is the number of indices
// written, but no more than "max" are written.
static int choose_servers_for_write(ProgramState *state, int *out, int max)
{
int num = state->num_chunk_servers;
int indices[MAX_CHUNK_SERVERS];
for (int i = 0; i < num; i++)
indices[i] = i;
qsort_r(indices, num, sizeof(*indices), compare_chunk_servers, state);
if (max > num) max = num;
for (int i = 0; i < max; i++)
out[i] = indices[i]; // Or maybe the other way around? indices[max - i - 1]?
return num;
} }
static int find_chunk_server_by_addr(ProgramState *state, Address addr) static int find_chunk_server_by_addr(ProgramState *state, Address addr)
@@ -2619,28 +2646,33 @@ process_client_read(ProgramState *state, int conn_idx, ByteView msg)
for (uint32_t i = 0; i < num_hashes; i++) { for (uint32_t i = 0; i < num_hashes; i++) {
// TODO: This should write the address of 3 servers, int num_holders;
// not just 1. int holders[MAX_CHUNK_SERVERS];
int j = choose_server_holding_chunk(state, hashes[i]);
if (j < 0) {
// TODO
}
ChunkServer *chunk_server = &state->chunk_servers[j]; num_holders = all_chunk_servers_holding_chunk(state, hashes[i], holders, MAX_CHUNK_SERVERS);
assert(chunk_server->auth);
assert(chunk_server->num_addrs > 0); if (num_holders > state->replication_factor)
num_holders = state->replication_factor;
message_write(&writer, &hashes[i], sizeof(hashes[i])); message_write(&writer, &hashes[i], sizeof(hashes[i]));
message_write_server_addr(&writer, chunk_server);
uint32_t tmp = num_holders;
message_write(&writer, &tmp, sizeof(tmp));
for (int j = 0; j < num_holders; j++)
message_write_server_addr(&writer, state->chunk_server[holders[j]]);
} }
// TODO: This should write the location of 3 servers, int num_locations;
// not just 1. int locations[MAX_CHUNK_SERVERS];
int write_server_index = choose_server_for_write(state);
if (write_server_index == -1) { num_locations = choose_servers_for_write(state, locations, MAX_CHUNKS_SERVERS);
// TODO
} if (num_locations > state->replication_factor)
message_write_server_addr(&writer, &state->chunk_servers[write_server_index]); nun_locations = state->replication_factor;
for (int j = 0; j < num_locations; j++)
message_write_server_addr(&writer, &state->chunk_servers[locations[j]]);
if (!message_writer_free(&writer)) if (!message_writer_free(&writer))
return -1; return -1;
@@ -2756,7 +2788,7 @@ process_client_write(ProgramState *state, int conn_idx, ByteView msg)
if (j == -1) if (j == -1)
return -1; return -1;
if (!chunk_list_insert(&state->chunk_servers[j].add_list, new_hashes[i])) if (!hash_list_insert(&state->chunk_servers[j].add_list, new_hashes[i]))
return -1; return -1;
} }
@@ -2870,8 +2902,8 @@ process_chunk_server_message(ProgramState *state,
int conn_idx, uint8_t type, ByteView msg) int conn_idx, uint8_t type, ByteView msg)
{ {
switch (type) { switch (type) {
case MESSAGE_TYPE_AUTH : return process_chunk_server_auth(state, conn_idx, msg); case MESSAGE_TYPE_AUTH:
default:break; return process_chunk_server_auth(state, conn_idx, msg);
} }
return -1; return -1;
} }