Implement synchronization protocol from PROTOCOL.txt
Updated both client.c and metadata_server.c to match the protocol specification in misc/PROTOCOL.txt: Client-to-Server Messages: - Added expect_gen field to DELETE, LIST, READ, and WRITE messages - Removed old_hash and chunk_size from WRITE message chunks Server-to-Client Responses: - Added generation counter to CREATE_SUCCESS response - Added generation counter to LIST_SUCCESS response - Fixed LIST_SUCCESS field order (gen, truncated, item_count) - Added generation counter to READ_SUCCESS response - Added generation counter to WRITE_SUCCESS response All changes compile successfully and pass valgrind memory checks.
This commit is contained in:
+58
-13
@@ -617,11 +617,13 @@ ToastyHandle toasty_begin_delete(ToastyFS *toasty, ToastyString path)
|
||||
opidx = -1;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
uint16_t tmp = path.len;
|
||||
uint16_t path_len = path.len;
|
||||
uint64_t expect_gen = 0; // 0 means skip generation check
|
||||
|
||||
MessageWriter writer;
|
||||
metadata_server_request_start(toasty, &writer, MESSAGE_TYPE_DELETE);
|
||||
message_write(&writer, &tmp, sizeof(tmp));
|
||||
message_write(&writer, &expect_gen, sizeof(expect_gen));
|
||||
message_write(&writer, &path_len, sizeof(path_len));
|
||||
message_write(&writer, path.ptr, path.len);
|
||||
if (metadata_server_request_end(toasty, &writer, opidx, 0) < 0) {
|
||||
free_operation(toasty, opidx);
|
||||
@@ -659,11 +661,13 @@ ToastyHandle toasty_begin_list(ToastyFS *toasty, ToastyString path)
|
||||
opidx = -1;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
uint16_t tmp = path.len;
|
||||
uint16_t path_len = path.len;
|
||||
uint64_t expect_gen = 0; // 0 means skip generation check
|
||||
|
||||
MessageWriter writer;
|
||||
metadata_server_request_start(toasty, &writer, MESSAGE_TYPE_LIST);
|
||||
message_write(&writer, &tmp, sizeof(tmp));
|
||||
message_write(&writer, &expect_gen, sizeof(expect_gen));
|
||||
message_write(&writer, &path_len, sizeof(path_len));
|
||||
message_write(&writer, path.ptr, path.len);
|
||||
if (metadata_server_request_end(toasty, &writer, opidx, 0) < 0) {
|
||||
free_operation(toasty, opidx);
|
||||
@@ -687,9 +691,11 @@ static int send_read_message(ToastyFS *toasty, int opidx, int tag, ToastyString
|
||||
if (path.len > UINT16_MAX)
|
||||
return -1;
|
||||
uint16_t path_len = path.len;
|
||||
uint64_t expect_gen = 0; // 0 means skip generation check
|
||||
|
||||
MessageWriter writer;
|
||||
metadata_server_request_start(toasty, &writer, MESSAGE_TYPE_READ);
|
||||
message_write(&writer, &expect_gen, sizeof(expect_gen));
|
||||
message_write(&writer, &path_len, sizeof(path_len));
|
||||
message_write(&writer, path.ptr, path.len);
|
||||
message_write(&writer, &offset, sizeof(offset));
|
||||
@@ -813,6 +819,13 @@ static void process_event_for_create(ToastyFS *toasty,
|
||||
return;
|
||||
}
|
||||
|
||||
// Read generation counter
|
||||
uint64_t gen;
|
||||
if (!binary_read(&reader, &gen, sizeof(gen))) {
|
||||
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_CREATE_ERROR, .user=toasty->operations[opidx].user };
|
||||
return;
|
||||
}
|
||||
|
||||
// Check there is nothing else to read
|
||||
if (binary_read(&reader, NULL, 1)) {
|
||||
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_CREATE_ERROR, .user=toasty->operations[opidx].user };
|
||||
@@ -901,19 +914,26 @@ static void process_event_for_list(ToastyFS *toasty,
|
||||
return;
|
||||
}
|
||||
|
||||
// Read and validate the list data
|
||||
uint32_t item_count;
|
||||
if (!binary_read(&reader, &item_count, sizeof(item_count))) {
|
||||
// Read generation counter
|
||||
uint64_t gen;
|
||||
if (!binary_read(&reader, &gen, sizeof(gen))) {
|
||||
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_LIST_ERROR, .user=toasty->operations[opidx].user };
|
||||
return;
|
||||
}
|
||||
|
||||
// Read and validate the list data
|
||||
uint8_t truncated;
|
||||
if (!binary_read(&reader, &truncated, sizeof(truncated))) {
|
||||
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_LIST_ERROR, .user=toasty->operations[opidx].user };
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t item_count;
|
||||
if (!binary_read(&reader, &item_count, sizeof(item_count))) {
|
||||
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_LIST_ERROR, .user=toasty->operations[opidx].user };
|
||||
return;
|
||||
}
|
||||
|
||||
ToastyListingEntry *entities = sys_malloc(item_count * sizeof(ToastyListingEntry));
|
||||
if (entities == NULL) {
|
||||
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_LIST_ERROR, .user=toasty->operations[opidx].user };
|
||||
@@ -1000,6 +1020,13 @@ static void process_event_for_read(ToastyFS *toasty,
|
||||
return;
|
||||
}
|
||||
|
||||
// Read generation counter
|
||||
uint64_t gen;
|
||||
if (!binary_read(&reader, &gen, sizeof(gen))) {
|
||||
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_READ_ERROR, .user=toasty->operations[opidx].user };
|
||||
return;
|
||||
}
|
||||
|
||||
// Read chunk size
|
||||
uint32_t chunk_size;
|
||||
if (!binary_read(&reader, &chunk_size, sizeof(chunk_size))) {
|
||||
@@ -1429,6 +1456,13 @@ static void process_event_for_write(ToastyFS *toasty,
|
||||
return;
|
||||
}
|
||||
|
||||
// Read generation counter
|
||||
uint64_t gen;
|
||||
if (!binary_read(&reader, &gen, sizeof(gen))) {
|
||||
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t chunk_size;
|
||||
if (!binary_read(&reader, &chunk_size, sizeof(chunk_size))) {
|
||||
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||
@@ -1436,6 +1470,12 @@ static void process_event_for_write(ToastyFS *toasty,
|
||||
}
|
||||
toasty->operations[opidx].chunk_size = chunk_size;
|
||||
|
||||
// Skip file_length field that comes after chunk_size
|
||||
if (!binary_read(&reader, NULL, sizeof(uint32_t))) {
|
||||
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t num_hashes;
|
||||
if (!binary_read(&reader, &num_hashes, sizeof(num_hashes))) {
|
||||
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||
@@ -1921,21 +1961,19 @@ static void process_event_for_write(ToastyFS *toasty,
|
||||
assert(0); // TODO
|
||||
}
|
||||
uint16_t path_len = path.len;
|
||||
uint64_t expect_gen = 0; // 0 means skip generation check - but per protocol, WRITE can't use 0
|
||||
|
||||
uint32_t num_chunks = num_upload_results;
|
||||
uint32_t chunk_size = toasty->operations[opidx].chunk_size;
|
||||
|
||||
message_write(&writer, &expect_gen, sizeof(expect_gen));
|
||||
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));
|
||||
message_write(&writer, &num_chunks, sizeof(num_chunks));
|
||||
message_write(&writer, &chunk_size, sizeof(chunk_size));
|
||||
|
||||
for (int i = 0; i < num_upload_results; i++) {
|
||||
|
||||
// TODO: newly create chunks don't have an old hash
|
||||
message_write(&writer, &upload_results[i].old_hash, sizeof(upload_results[i].old_hash));
|
||||
message_write(&writer, &upload_results[i].new_hash, sizeof(upload_results[i].new_hash));
|
||||
|
||||
uint32_t tmp = upload_results[i].num_locations;
|
||||
@@ -1984,12 +2022,19 @@ static void process_event_for_write(ToastyFS *toasty,
|
||||
return;
|
||||
}
|
||||
|
||||
if (binary_read(&reader, NULL, 1)) {
|
||||
if (type != MESSAGE_TYPE_WRITE_SUCCESS) {
|
||||
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||
return;
|
||||
}
|
||||
|
||||
if (type != MESSAGE_TYPE_WRITE_SUCCESS) {
|
||||
// Read generation counter
|
||||
uint64_t gen;
|
||||
if (!binary_read(&reader, &gen, sizeof(gen))) {
|
||||
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||
return;
|
||||
}
|
||||
|
||||
if (binary_read(&reader, NULL, 1)) {
|
||||
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user