Clean up state update logic in chunk server
This commit is contained in:
+62
-53
@@ -4,6 +4,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "basic.h"
|
#include "basic.h"
|
||||||
|
#include "config.h"
|
||||||
#include "sha256.h"
|
#include "sha256.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include "file_system.h"
|
#include "file_system.h"
|
||||||
@@ -204,12 +205,14 @@ static int chunk_store_add(ChunkStore *store, string data)
|
|||||||
return store_chunk(store, data, &dummy);
|
return store_chunk(store, data, &dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chunk_store_remove(ChunkStore *store, SHA256 hash)
|
static int chunk_store_remove(ChunkStore *store, SHA256 hash)
|
||||||
{
|
{
|
||||||
char buf[PATH_MAX];
|
char buf[PATH_MAX];
|
||||||
string path = hash2path(store, hash, buf);
|
string path = hash2path(store, hash, buf);
|
||||||
|
|
||||||
remove_file_or_dir(path);
|
if (remove_file_or_dir(path) < 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool chunk_store_exists(ChunkStore *store, SHA256 hash)
|
static bool chunk_store_exists(ChunkStore *store, SHA256 hash)
|
||||||
@@ -366,8 +369,8 @@ process_metadata_server_state_update(ChunkServer *state, int conn_idx, ByteView
|
|||||||
|
|
||||||
// Check that all items in the add_list are in the chunk directory
|
// Check that all items in the add_list are in the chunk directory
|
||||||
// Any hashes that are missing are added to a missing list
|
// Any hashes that are missing are added to a missing list
|
||||||
SHA256 *missing_list = NULL;
|
SHA256 *missing = NULL;
|
||||||
uint32_t missing_count = 0;
|
uint32_t num_missing = 0;
|
||||||
|
|
||||||
Time current_time = get_current_time();
|
Time current_time = get_current_time();
|
||||||
|
|
||||||
@@ -377,22 +380,16 @@ process_metadata_server_state_update(ChunkServer *state, int conn_idx, ByteView
|
|||||||
|
|
||||||
// Check if chunk exists in the chunk store
|
// Check if chunk exists in the chunk store
|
||||||
if (!chunk_store_exists(&state->store, add_list[i])) {
|
if (!chunk_store_exists(&state->store, add_list[i])) {
|
||||||
|
|
||||||
// Chunk is missing, add to missing list
|
// Chunk is missing, add to missing list
|
||||||
SHA256 *new_missing_list = sys_malloc((missing_count + 1) * sizeof(SHA256));
|
|
||||||
if (new_missing_list == NULL) {
|
|
||||||
sys_free(add_list);
|
|
||||||
sys_free(rem_list);
|
|
||||||
sys_free(missing_list);
|
|
||||||
return send_error(&state->tcp, conn_idx, false, MESSAGE_TYPE_STATE_UPDATE_ERROR, S("Out of memory"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (missing_count > 0) {
|
if (missing == NULL) {
|
||||||
memcpy(new_missing_list, missing_list, missing_count * sizeof(SHA256));
|
missing = sys_malloc(add_count * sizeof(SHA256));
|
||||||
sys_free(missing_list);
|
if (missing == NULL) {
|
||||||
|
assert(0); // TODO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
missing[num_missing++] = add_list[i];
|
||||||
missing_list = new_missing_list;
|
|
||||||
missing_list[missing_count++] = add_list[i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,7 +398,7 @@ process_metadata_server_state_update(ChunkServer *state, int conn_idx, ByteView
|
|||||||
if (removal_list_add(&state->removal_list, rem_list[i], current_time) < 0) {
|
if (removal_list_add(&state->removal_list, rem_list[i], current_time) < 0) {
|
||||||
sys_free(add_list);
|
sys_free(add_list);
|
||||||
sys_free(rem_list);
|
sys_free(rem_list);
|
||||||
sys_free(missing_list);
|
sys_free(missing);
|
||||||
return send_error(&state->tcp, conn_idx, false, MESSAGE_TYPE_STATE_UPDATE_ERROR, S("Out of memory"));
|
return send_error(&state->tcp, conn_idx, false, MESSAGE_TYPE_STATE_UPDATE_ERROR, S("Out of memory"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -410,22 +407,26 @@ process_metadata_server_state_update(ChunkServer *state, int conn_idx, ByteView
|
|||||||
sys_free(rem_list);
|
sys_free(rem_list);
|
||||||
|
|
||||||
// Respond to the metadata server
|
// Respond to the metadata server
|
||||||
if (missing_count == 0) {
|
if (num_missing == 0) {
|
||||||
|
|
||||||
// No missing chunks, send success
|
// No missing chunks, send success
|
||||||
sys_free(missing_list);
|
|
||||||
MessageWriter writer;
|
|
||||||
|
|
||||||
ByteQueue *output = tcp_output_buffer(&state->tcp, conn_idx);
|
ByteQueue *output = tcp_output_buffer(&state->tcp, conn_idx);
|
||||||
message_writer_init(&writer, output, MESSAGE_TYPE_STATE_UPDATE_SUCCESS);
|
assert(output);
|
||||||
|
|
||||||
|
MessageWriter writer;
|
||||||
|
message_writer_init(&writer, output, MESSAGE_TYPE_STATE_UPDATE_SUCCESS);
|
||||||
if (!message_writer_free(&writer))
|
if (!message_writer_free(&writer))
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Some chunks are missing, send error with missing list
|
// Some chunks are missing, send error with missing list
|
||||||
MessageWriter writer;
|
|
||||||
|
|
||||||
ByteQueue *output = tcp_output_buffer(&state->tcp, conn_idx);
|
ByteQueue *output = tcp_output_buffer(&state->tcp, conn_idx);
|
||||||
|
assert(output);
|
||||||
|
|
||||||
|
MessageWriter writer;
|
||||||
message_writer_init(&writer, output, MESSAGE_TYPE_STATE_UPDATE_ERROR);
|
message_writer_init(&writer, output, MESSAGE_TYPE_STATE_UPDATE_ERROR);
|
||||||
|
|
||||||
// Write error message
|
// Write error message
|
||||||
@@ -435,15 +436,17 @@ process_metadata_server_state_update(ChunkServer *state, int conn_idx, ByteView
|
|||||||
message_write(&writer, error_msg.ptr, error_msg.len);
|
message_write(&writer, error_msg.ptr, error_msg.len);
|
||||||
|
|
||||||
// Write missing count and missing hashes
|
// Write missing count and missing hashes
|
||||||
message_write(&writer, &missing_count, sizeof(missing_count));
|
uint32_t tmp = num_missing;
|
||||||
message_write(&writer, missing_list, missing_count * sizeof(SHA256));
|
message_write(&writer, &tmp, sizeof(tmp));
|
||||||
|
message_write(&writer, missing, num_missing * sizeof(SHA256));
|
||||||
|
|
||||||
sys_free(missing_list);
|
sys_free(missing);
|
||||||
|
|
||||||
if (!message_writer_free(&writer))
|
if (!message_writer_free(&writer))
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -849,16 +852,12 @@ process_client_message(ChunkServer *state, int conn_idx, uint16_t type, ByteView
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
start_connecting_to_metadata_server(ChunkServer *state)
|
start_connecting_to_metadata_server(ChunkServer *state)
|
||||||
{
|
{
|
||||||
Time current_time = get_current_time();
|
|
||||||
|
|
||||||
ByteQueue *output;
|
ByteQueue *output;
|
||||||
if (tcp_connect(&state->tcp, state->remote_addr, TAG_METADATA_SERVER, &output) < 0) {
|
if (tcp_connect(&state->tcp, state->remote_addr, TAG_METADATA_SERVER, &output) < 0)
|
||||||
state->disconnect_time = current_time;
|
return -1;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send AUTH message to authenticate with metadata server
|
// Send AUTH message to authenticate with metadata server
|
||||||
MessageWriter writer;
|
MessageWriter writer;
|
||||||
@@ -877,10 +876,9 @@ start_connecting_to_metadata_server(ChunkServer *state)
|
|||||||
uint32_t num_ipv6 = 0;
|
uint32_t num_ipv6 = 0;
|
||||||
message_write(&writer, &num_ipv6, sizeof(num_ipv6));
|
message_write(&writer, &num_ipv6, sizeof(num_ipv6));
|
||||||
|
|
||||||
if (message_writer_free(&writer))
|
if (!message_writer_free(&writer))
|
||||||
state->disconnect_time = INVALID_TIME;
|
return -1;
|
||||||
else
|
return 0;
|
||||||
state->disconnect_time = current_time;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int chunk_server_init(ChunkServer *state, int argc, char **argv, void **contexts, struct pollfd *polled, int *timeout)
|
int chunk_server_init(ChunkServer *state, int argc, char **argv, void **contexts, struct pollfd *polled, int *timeout)
|
||||||
@@ -1056,25 +1054,36 @@ int chunk_server_step(ChunkServer *state, void **contexts, struct pollfd *polled
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: periodically look for chunks that have their hashes messed up and delete them
|
Time deadline = INVALID_TIME;
|
||||||
|
|
||||||
// TODO: Remove items from the remove list that got too old
|
// Remove items from the remove list that got too old
|
||||||
|
for (int i = 0; i < state->removal_list.count; i++) {
|
||||||
|
PendingRemoval *removal = &state->removal_list.items[i];
|
||||||
|
Time removal_time = removal->marked_time + (Time) DELETION_TIMEOUT * 1000000000;
|
||||||
|
if (removal_time < current_time) {
|
||||||
|
if (chunk_store_remove(&state->store, removal->hash) == 0)
|
||||||
|
*removal = state->removal_list.items[--state->removal_list.count];
|
||||||
|
} else {
|
||||||
|
nearest_deadline(&deadline, removal_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: periodically look for chunks that have their hashes messed up and delete them
|
||||||
|
|
||||||
// TODO: periodically start downloads if some are pending and weren't started yet
|
// TODO: periodically start downloads if some are pending and weren't started yet
|
||||||
// start_download_if_necessary(state);
|
// start_download_if_necessary(state);
|
||||||
|
|
||||||
if (state->disconnect_time != INVALID_TIME && (current_time - state->disconnect_time) / 1000000 >= CHUNK_SERVER_RECONNECT_TIME)
|
if (state->disconnect_time != INVALID_TIME) {
|
||||||
start_connecting_to_metadata_server(state);
|
Time reconnect_time = state->disconnect_time + (Time) CHUNK_SERVER_RECONNECT_TIME * 1000000000;
|
||||||
|
if (reconnect_time <= current_time) {
|
||||||
if (state->disconnect_time == INVALID_TIME)
|
state->disconnect_time = INVALID_TIME;
|
||||||
*timeout = -1;
|
if (start_connecting_to_metadata_server(state) < 0)
|
||||||
else {
|
state->disconnect_time = current_time;
|
||||||
int elapsed = current_time - state->disconnect_time;
|
}
|
||||||
int delta_sec = 1;
|
if (state->disconnect_time != INVALID_TIME)
|
||||||
if (elapsed > delta_sec * 1000000000)
|
nearest_deadline(&deadline, reconnect_time);
|
||||||
*timeout = 0;
|
|
||||||
else
|
|
||||||
*timeout = delta_sec * 1000 - elapsed / 1000000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*timeout = deadline_to_timeout(deadline, current_time);
|
||||||
return tcp_register_events(&state->tcp, contexts, polled);
|
return tcp_register_events(&state->tcp, contexts, polled);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -554,6 +554,8 @@ void tinydfs_result_free(TinyDFS_Result *result)
|
|||||||
static void process_event_for_create(TinyDFS *tdfs,
|
static void process_event_for_create(TinyDFS *tdfs,
|
||||||
int opidx, int request_tag, ByteView msg)
|
int opidx, int request_tag, ByteView msg)
|
||||||
{
|
{
|
||||||
|
(void) request_tag;
|
||||||
|
|
||||||
if (msg.len == 0) {
|
if (msg.len == 0) {
|
||||||
tdfs->operations[opidx].result = (TinyDFS_Result) { .type=TINYDFS_RESULT_CREATE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { .type=TINYDFS_RESULT_CREATE_ERROR };
|
||||||
return;
|
return;
|
||||||
@@ -596,6 +598,8 @@ static void process_event_for_create(TinyDFS *tdfs,
|
|||||||
static void process_event_for_delete(TinyDFS *tdfs,
|
static void process_event_for_delete(TinyDFS *tdfs,
|
||||||
int opidx, int request_tag, ByteView msg)
|
int opidx, int request_tag, ByteView msg)
|
||||||
{
|
{
|
||||||
|
(void) request_tag;
|
||||||
|
|
||||||
if (msg.len == 0) {
|
if (msg.len == 0) {
|
||||||
tdfs->operations[opidx].result = (TinyDFS_Result) { .type=TINYDFS_RESULT_DELETE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { .type=TINYDFS_RESULT_DELETE_ERROR };
|
||||||
return;
|
return;
|
||||||
@@ -638,6 +642,8 @@ static void process_event_for_delete(TinyDFS *tdfs,
|
|||||||
static void process_event_for_list(TinyDFS *tdfs,
|
static void process_event_for_list(TinyDFS *tdfs,
|
||||||
int opidx, int request_tag, ByteView msg)
|
int opidx, int request_tag, ByteView msg)
|
||||||
{
|
{
|
||||||
|
(void) request_tag;
|
||||||
|
|
||||||
if (msg.len == 0) {
|
if (msg.len == 0) {
|
||||||
tdfs->operations[opidx].result = (TinyDFS_Result) { .type=TINYDFS_RESULT_LIST_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { .type=TINYDFS_RESULT_LIST_ERROR };
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -12,4 +12,6 @@
|
|||||||
#define SYNC_INTERVAL 10
|
#define SYNC_INTERVAL 10
|
||||||
#define RESPONSE_TIME_LIMIT 90
|
#define RESPONSE_TIME_LIMIT 90
|
||||||
|
|
||||||
|
#define DELETION_TIMEOUT 30
|
||||||
|
|
||||||
#endif // CONFIG_INCLUDED
|
#endif // CONFIG_INCLUDED
|
||||||
|
|||||||
@@ -744,10 +744,10 @@ static int send_state_update(MetadataServer *state, int chunk_server_idx)
|
|||||||
message_write(&writer, &add_count, sizeof(add_count));
|
message_write(&writer, &add_count, sizeof(add_count));
|
||||||
message_write(&writer, &rem_count, sizeof(rem_count));
|
message_write(&writer, &rem_count, sizeof(rem_count));
|
||||||
|
|
||||||
for (int i = 0; i < add_count; i++)
|
for (uint32_t i = 0; i < add_count; i++)
|
||||||
message_write(&writer, &chunk_server->add_list.items[i], sizeof(SHA256));
|
message_write(&writer, &chunk_server->add_list.items[i], sizeof(SHA256));
|
||||||
|
|
||||||
for (int i = 0; i < rem_count; i++)
|
for (uint32_t i = 0; i < rem_count; i++)
|
||||||
message_write(&writer, &chunk_server->rem_list.items[i], sizeof(SHA256));
|
message_write(&writer, &chunk_server->rem_list.items[i], sizeof(SHA256));
|
||||||
|
|
||||||
if (!message_writer_free(&writer))
|
if (!message_writer_free(&writer))
|
||||||
|
|||||||
Reference in New Issue
Block a user