Progress
This commit is contained in:
@@ -3825,6 +3825,8 @@ typedef struct {
|
|||||||
char* dst;
|
char* dst;
|
||||||
uint32_t offset_within_chunk;
|
uint32_t offset_within_chunk;
|
||||||
uint32_t length_within_chunk;
|
uint32_t length_within_chunk;
|
||||||
|
Address server_addr; // Chunk server address for this chunk
|
||||||
|
int chunk_server_idx; // Index in tdfs->chunk_servers array
|
||||||
} Range;
|
} Range;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -3900,7 +3902,7 @@ TinyDFS *tinydfs_init(char *addr, uint16_t port)
|
|||||||
addr2.port = port;
|
addr2.port = port;
|
||||||
if (inet_pton(AF_INET, addr, &addr2.ipv4) != 1) {
|
if (inet_pton(AF_INET, addr, &addr2.ipv4) != 1) {
|
||||||
free(tdfs);
|
free(tdfs);
|
||||||
return tdfs;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcp_context_init(&tdfs->tcp);
|
tcp_context_init(&tdfs->tcp);
|
||||||
@@ -3919,7 +3921,7 @@ TinyDFS *tinydfs_init(char *addr, uint16_t port)
|
|||||||
return tdfs;
|
return tdfs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tdfs_free(TinyDFS *tdfs)
|
void tinydfs_free(TinyDFS *tdfs)
|
||||||
{
|
{
|
||||||
tcp_context_free(&tdfs->tcp);
|
tcp_context_free(&tdfs->tcp);
|
||||||
free(tdfs);
|
free(tdfs);
|
||||||
@@ -3937,7 +3939,7 @@ alloc_operation(TinyDFS *tdfs, OperationType type, int off, void *ptr, int len)
|
|||||||
o->ptr = ptr;
|
o->ptr = ptr;
|
||||||
o->off = off;
|
o->off = off;
|
||||||
o->len = len;
|
o->len = len;
|
||||||
o->result = (Result) { TINYDFS_RESULT_EMPTY };
|
o->result = (TinyDFS_Result) { TINYDFS_RESULT_EMPTY };
|
||||||
|
|
||||||
tdfs->num_operations++;
|
tdfs->num_operations++;
|
||||||
return o - tdfs->operations;
|
return o - tdfs->operations;
|
||||||
@@ -3978,6 +3980,63 @@ request_queue_pop(RequestQueue *reqs, Request *req)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get or create connection to a chunk server
|
||||||
|
static int get_chunk_server_connection(TinyDFS *tdfs, Address addr)
|
||||||
|
{
|
||||||
|
// Check if already connected
|
||||||
|
for (int i = 0; i < tdfs->num_chunk_servers; i++) {
|
||||||
|
if (tdfs->chunk_servers[i].used && addr_eql(tdfs->chunk_servers[i].addr, addr)) {
|
||||||
|
int conn_idx = tcp_index_from_tag(&tdfs->tcp, i);
|
||||||
|
if (conn_idx >= 0)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find free slot
|
||||||
|
int idx = -1;
|
||||||
|
for (int i = 0; i < MAX_CHUNK_SERVERS; i++) {
|
||||||
|
if (!tdfs->chunk_servers[i].used) {
|
||||||
|
idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (idx < 0) return -1;
|
||||||
|
|
||||||
|
// Connect
|
||||||
|
if (tcp_connect(&tdfs->tcp, addr, idx, NULL) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Initialize
|
||||||
|
tdfs->chunk_servers[idx].used = true;
|
||||||
|
tdfs->chunk_servers[idx].addr = addr;
|
||||||
|
request_queue_init(&tdfs->chunk_servers[idx].reqs);
|
||||||
|
tdfs->num_chunk_servers++;
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send download request for a chunk
|
||||||
|
static int send_download_chunk(TinyDFS *tdfs, int chunk_server_idx,
|
||||||
|
SHA256 hash, uint32_t offset, uint32_t length, int opidx, int range_idx)
|
||||||
|
{
|
||||||
|
int conn_idx = tcp_index_from_tag(&tdfs->tcp, chunk_server_idx);
|
||||||
|
if (conn_idx < 0) return -1;
|
||||||
|
|
||||||
|
MessageWriter writer;
|
||||||
|
ByteQueue *output = tcp_output_buffer(&tdfs->tcp, conn_idx);
|
||||||
|
message_writer_init(&writer, output, MESSAGE_TYPE_DOWNLOAD_CHUNK);
|
||||||
|
|
||||||
|
message_write(&writer, &hash, sizeof(hash));
|
||||||
|
message_write(&writer, &offset, sizeof(offset));
|
||||||
|
message_write(&writer, &length, sizeof(length));
|
||||||
|
|
||||||
|
if (!message_writer_free(&writer))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
RequestQueue *reqs = &tdfs->chunk_servers[chunk_server_idx].reqs;
|
||||||
|
return request_queue_push(reqs, (Request) { range_idx, opidx });
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
metadata_server_request_start(TinyDFS *tdfs, MessageWriter *writer, uint16_t type)
|
metadata_server_request_start(TinyDFS *tdfs, MessageWriter *writer, uint16_t type)
|
||||||
{
|
{
|
||||||
@@ -4149,7 +4208,7 @@ static void process_event_for_create(TinyDFS *tdfs,
|
|||||||
int opidx, int request_tag, ByteView msg)
|
int opidx, int request_tag, ByteView msg)
|
||||||
{
|
{
|
||||||
if (msg.len == 0) {
|
if (msg.len == 0) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_CREATE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_CREATE_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4157,41 +4216,41 @@ static void process_event_for_create(TinyDFS *tdfs,
|
|||||||
|
|
||||||
// version;
|
// version;
|
||||||
if (!binary_read(&reader, NULL, sizeof(uint16_t))) {
|
if (!binary_read(&reader, NULL, sizeof(uint16_t))) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_CREATE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_CREATE_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
if (!binary_read(&reader, &type, sizeof(type))) {
|
if (!binary_read(&reader, &type, sizeof(type))) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_CREATE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_CREATE_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// length
|
// length
|
||||||
if (!binary_read(&reader, NULL, sizeof(uint32_t))) {
|
if (!binary_read(&reader, NULL, sizeof(uint32_t))) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_CREATE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_CREATE_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != MESSAGE_TYPE_CREATE_SUCCESS) {
|
if (type != MESSAGE_TYPE_CREATE_SUCCESS) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_CREATE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_CREATE_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check there is nothing else to read
|
// Check there is nothing else to read
|
||||||
if (binary_read(&reader, NULL, 1)) {
|
if (binary_read(&reader, NULL, 1)) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_CREATE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_CREATE_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_CREATE_SUCCESS };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_CREATE_SUCCESS };
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
if (msg.len == 0) {
|
if (msg.len == 0) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_DELETE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_DELETE_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4199,41 +4258,41 @@ static void process_event_for_delete(TinyDFS *tdfs,
|
|||||||
|
|
||||||
// version
|
// version
|
||||||
if (!binary_read(&reader, NULL, sizeof(uint16_t))) {
|
if (!binary_read(&reader, NULL, sizeof(uint16_t))) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_DELETE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_DELETE_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
if (!binary_read(&reader, &type, sizeof(type))) {
|
if (!binary_read(&reader, &type, sizeof(type))) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_DELETE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_DELETE_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// length
|
// length
|
||||||
if (!binary_read(&reader, NULL, sizeof(uint32_t))) {
|
if (!binary_read(&reader, NULL, sizeof(uint32_t))) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_DELETE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_DELETE_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != MESSAGE_TYPE_DELETE_SUCCESS) {
|
if (type != MESSAGE_TYPE_DELETE_SUCCESS) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_DELETE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_DELETE_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check there is nothing else to read
|
// Check there is nothing else to read
|
||||||
if (binary_read(&reader, NULL, 1)) {
|
if (binary_read(&reader, NULL, 1)) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_DELETE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_DELETE_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_DELETE_SUCCESS };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_DELETE_SUCCESS };
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
if (msg.len == 0) {
|
if (msg.len == 0) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_LIST_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_LIST_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4241,24 +4300,24 @@ static void process_event_for_list(TinyDFS *tdfs,
|
|||||||
|
|
||||||
// version
|
// version
|
||||||
if (!binary_read(&reader, NULL, sizeof(uint16_t))) {
|
if (!binary_read(&reader, NULL, sizeof(uint16_t))) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_LIST_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_LIST_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
if (!binary_read(&reader, &type, sizeof(type))) {
|
if (!binary_read(&reader, &type, sizeof(type))) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_LIST_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_LIST_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// length
|
// length
|
||||||
if (!binary_read(&reader, NULL, sizeof(uint32_t))) {
|
if (!binary_read(&reader, NULL, sizeof(uint32_t))) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_LIST_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_LIST_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != MESSAGE_TYPE_LIST_SUCCESS) {
|
if (type != MESSAGE_TYPE_LIST_SUCCESS) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_LIST_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_LIST_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4266,177 +4325,291 @@ static void process_event_for_list(TinyDFS *tdfs,
|
|||||||
|
|
||||||
// Check there is nothing else to read
|
// Check there is nothing else to read
|
||||||
if (binary_read(&reader, NULL, 1)) {
|
if (binary_read(&reader, NULL, 1)) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_LIST_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_LIST_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_LIST_SUCCESS };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_LIST_SUCCESS };
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_event_for_read(TinyDFS *tdfs,
|
static void process_event_for_read(TinyDFS *tdfs,
|
||||||
int opidx, int request_tag, ByteView msg)
|
int opidx, int request_tag, ByteView msg)
|
||||||
{
|
{
|
||||||
if (msg.len == 0) {
|
if (msg.len == 0) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_READ_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (request_tag) {
|
if (request_tag == TAG_RETRIEVE_METADATA_FOR_READ) {
|
||||||
|
// Handle metadata response from metadata server
|
||||||
|
BinaryReader reader = { msg.ptr, msg.len, 0 };
|
||||||
|
|
||||||
case TAG_RETRIEVE_METADATA_FOR_READ:
|
// Skip version
|
||||||
{
|
if (!binary_read(&reader, NULL, sizeof(uint16_t))) {
|
||||||
BinaryReader reader = { msg.ptr, msg.len, 0 };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// version
|
// Check message type
|
||||||
if (!binary_read(&reader, NULL, sizeof(uint16_t))) {
|
uint16_t type;
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_READ_ERROR };
|
if (!binary_read(&reader, &type, sizeof(type))) {
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != MESSAGE_TYPE_READ_SUCCESS) {
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip message length
|
||||||
|
if (!binary_read(&reader, NULL, sizeof(uint32_t))) {
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read chunk size
|
||||||
|
uint32_t chunk_size;
|
||||||
|
if (!binary_read(&reader, &chunk_size, sizeof(chunk_size))) {
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate which chunks we need
|
||||||
|
int off = tdfs->operations[opidx].off;
|
||||||
|
int len = tdfs->operations[opidx].len;
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_SUCCESS };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t first_byte = off;
|
||||||
|
uint32_t last_byte = off + len - 1;
|
||||||
|
uint32_t first_chunk = first_byte / chunk_size;
|
||||||
|
uint32_t last_chunk = last_byte / chunk_size;
|
||||||
|
uint32_t num_chunks_needed = last_chunk - first_chunk + 1;
|
||||||
|
|
||||||
|
// Read number of hashes
|
||||||
|
uint32_t num_hashes;
|
||||||
|
if (!binary_read(&reader, &num_hashes, sizeof(num_hashes))) {
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate ranges
|
||||||
|
Range *ranges = malloc(num_chunks_needed * sizeof(Range));
|
||||||
|
if (ranges == NULL) {
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ptr = tdfs->operations[opidx].ptr;
|
||||||
|
int num_ranges_with_data = 0;
|
||||||
|
|
||||||
|
// Parse each chunk's hash and server locations
|
||||||
|
for (uint32_t i = 0; i < num_hashes; i++) {
|
||||||
|
// Read hash
|
||||||
|
SHA256 hash;
|
||||||
|
if (!binary_read(&reader, &hash, sizeof(hash))) {
|
||||||
|
free(ranges);
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t type;
|
// Read number of servers
|
||||||
if (!binary_read(&reader, &type, sizeof(type))) {
|
uint32_t num_servers;
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_READ_ERROR };
|
if (!binary_read(&reader, &num_servers, sizeof(num_servers))) {
|
||||||
|
free(ranges);
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != MESSAGE_TYPE_READ_SUCCESS) {
|
// Parse IPv4 addresses
|
||||||
// TODO
|
uint32_t num_ipv4;
|
||||||
}
|
if (!binary_read(&reader, &num_ipv4, sizeof(num_ipv4))) {
|
||||||
|
free(ranges);
|
||||||
// length
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
if (!binary_read(&reader, NULL, sizeof(uint32_t))) {
|
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_READ_ERROR };
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t chunk_size;
|
Address server_addr = {0};
|
||||||
if (!binary_read(&reader, &chunk_size, sizeof(chunk_size))) {
|
bool found = false;
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_READ_ERROR };
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int off = tdfs->operations[opidx].off;
|
// Get first IPv4 address
|
||||||
int len = tdfs->operations[opidx].len;
|
for (uint32_t j = 0; j < num_ipv4; j++) {
|
||||||
|
IPv4 ipv4;
|
||||||
uint32_t first_byte = off;
|
uint16_t port;
|
||||||
uint32_t last_byte = off + len - 1; // TODO: what if len=0 ?
|
if (!binary_read(&reader, &ipv4, sizeof(ipv4)) ||
|
||||||
|
!binary_read(&reader, &port, sizeof(port))) {
|
||||||
uint32_t first_chunk = first_byte / chunk_size;
|
free(ranges);
|
||||||
uint32_t last_chunk = last_byte / chunk_size;
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
|
return;
|
||||||
uint32_t num_hashes;
|
}
|
||||||
if (!binary_read(&reader, &num_hashes, sizeof(num_hashes))) {
|
if (!found) {
|
||||||
// TODO
|
server_addr.is_ipv4 = true;
|
||||||
}
|
server_addr.ipv4 = ipv4;
|
||||||
|
server_addr.port = port;
|
||||||
Range *ranges = malloc(num_hashes * sizeof(Range));
|
found = true;
|
||||||
if (ranges == NULL) {
|
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_READ_ERROR };
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *ptr = tdfs->operations[opidx].ptr;
|
|
||||||
for (uint32_t i = first_chunk; i <= last_chunk; i++) {
|
|
||||||
|
|
||||||
uint32_t first_byte_within_chunk = 0;
|
|
||||||
uint32_t last_byte_within_chunk = chunk_size-1; // TODO: what if chunk size is 0 ?
|
|
||||||
|
|
||||||
if (i == first_chunk) first_byte_within_chunk = first_byte % chunk_size;
|
|
||||||
if (i == last_chunk) last_byte_within_chunk = last_byte % chunk_size;
|
|
||||||
|
|
||||||
uint32_t length_within_chunk = 1 + last_byte_within_chunk - first_byte_within_chunk;
|
|
||||||
|
|
||||||
if (i - first_chunk < num_hashes) {
|
|
||||||
|
|
||||||
SHA256 hash;
|
|
||||||
if (!binary_read(&reader, &hash, sizeof(hash))) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
ranges[i - first_chunk] = (Range) {
|
|
||||||
.hash = hash,
|
|
||||||
.dst = ptr,
|
|
||||||
.offset_within_chunk = first_byte_within_chunk,
|
|
||||||
.length_within_chunk = length_within_chunk,
|
|
||||||
};
|
|
||||||
|
|
||||||
} else {
|
|
||||||
memset(ptr, 0, length_within_chunk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr += length_within_chunk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check there is nothing else to read
|
// Skip IPv6 addresses
|
||||||
if (binary_read(&reader, NULL, 1)) {
|
uint32_t num_ipv6;
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_LIST_ERROR };
|
if (!binary_read(&reader, &num_ipv6, sizeof(num_ipv6))) {
|
||||||
|
free(ranges);
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (uint32_t j = 0; j < num_ipv6; j++) {
|
||||||
|
if (!binary_read(&reader, NULL, sizeof(IPv6)) ||
|
||||||
|
!binary_read(&reader, NULL, sizeof(uint16_t))) {
|
||||||
|
free(ranges);
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
free(ranges);
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tdfs->operations[opidx].ranges = ranges;
|
// Calculate byte range for this chunk
|
||||||
tdfs->operations[opidx].ranges_head = 0;
|
uint32_t chunk_idx = first_chunk + i;
|
||||||
tdfs->operations[opidx].ranges_count = num_hashes;
|
uint32_t first_in_chunk = (chunk_idx == first_chunk) ? (first_byte % chunk_size) : 0;
|
||||||
tdfs->operations[opidx].num_pending = 0;
|
uint32_t last_in_chunk = (chunk_idx == last_chunk) ? (last_byte % chunk_size) : (chunk_size - 1);
|
||||||
|
uint32_t len_in_chunk = 1 + last_in_chunk - first_in_chunk;
|
||||||
|
|
||||||
// TODO: start N downloads
|
// Fill in range info
|
||||||
|
ranges[i].hash = hash;
|
||||||
|
ranges[i].dst = ptr;
|
||||||
|
ranges[i].offset_within_chunk = first_in_chunk;
|
||||||
|
ranges[i].length_within_chunk = len_in_chunk;
|
||||||
|
ranges[i].server_addr = server_addr;
|
||||||
|
ranges[i].chunk_server_idx = -1;
|
||||||
|
|
||||||
|
ptr += len_in_chunk;
|
||||||
|
num_ranges_with_data++;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
// Fill remaining chunks with zeros (sparse file)
|
||||||
{
|
for (uint32_t i = num_hashes; i < num_chunks_needed; i++) {
|
||||||
BinaryReader reader = { msg.ptr, msg.len, 0 };
|
uint32_t chunk_idx = first_chunk + i;
|
||||||
|
uint32_t first_in_chunk = (chunk_idx == first_chunk) ? (first_byte % chunk_size) : 0;
|
||||||
|
uint32_t last_in_chunk = (chunk_idx == last_chunk) ? (last_byte % chunk_size) : (chunk_size - 1);
|
||||||
|
uint32_t len_in_chunk = 1 + last_in_chunk - first_in_chunk;
|
||||||
|
|
||||||
// version
|
memset(ptr, 0, len_in_chunk);
|
||||||
if (!binary_read(&reader, NULL, sizeof(uint16_t))) {
|
ptr += len_in_chunk;
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_READ_ERROR };
|
}
|
||||||
|
|
||||||
|
// Store range info
|
||||||
|
tdfs->operations[opidx].ranges = ranges;
|
||||||
|
tdfs->operations[opidx].ranges_head = 0;
|
||||||
|
tdfs->operations[opidx].ranges_count = num_ranges_with_data;
|
||||||
|
tdfs->operations[opidx].num_pending = 0;
|
||||||
|
|
||||||
|
// Start first download
|
||||||
|
if (num_ranges_with_data > 0) {
|
||||||
|
Range *r = &ranges[0];
|
||||||
|
int cs_idx = get_chunk_server_connection(tdfs, r->server_addr);
|
||||||
|
if (cs_idx < 0) {
|
||||||
|
free(ranges);
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
r->chunk_server_idx = cs_idx;
|
||||||
|
|
||||||
|
if (send_download_chunk(tdfs, cs_idx, r->hash, r->offset_within_chunk,
|
||||||
|
r->length_within_chunk, opidx, 0) < 0) {
|
||||||
|
free(ranges);
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t type;
|
tdfs->operations[opidx].num_pending = 1;
|
||||||
if (!binary_read(&reader, &type, sizeof(type))) {
|
tdfs->operations[opidx].ranges_head = 1;
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_READ_ERROR };
|
} else {
|
||||||
return;
|
// No chunks to download
|
||||||
}
|
free(ranges);
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_SUCCESS };
|
||||||
|
}
|
||||||
|
|
||||||
if (type != MESSAGE_TYPE_DOWNLOAD_CHUNK_SUCCESS) {
|
} else {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_READ_ERROR };
|
// Handle chunk download response
|
||||||
return;
|
int range_idx = request_tag;
|
||||||
}
|
BinaryReader reader = { msg.ptr, msg.len, 0 };
|
||||||
|
|
||||||
// length
|
// Parse response
|
||||||
if (!binary_read(&reader, NULL, sizeof(uint32_t))) {
|
if (!binary_read(&reader, NULL, sizeof(uint16_t))) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_READ_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t data_len;
|
uint16_t type;
|
||||||
if (!binary_read(&reader, &data_len, sizeof(data_len))) {
|
if (!binary_read(&reader, &type, sizeof(type))) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_READ_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *data = reader.src + reader.cur;
|
if (type != MESSAGE_TYPE_DOWNLOAD_CHUNK_SUCCESS) {
|
||||||
if (!binary_read(&reader, NULL, data_len)) {
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_READ_ERROR };
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Check there is nothing else to read
|
if (!binary_read(&reader, NULL, sizeof(uint32_t))) {
|
||||||
if (binary_read(&reader, NULL, 1)) {
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_LIST_ERROR };
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(tdfs->operations[opidx].ranges[request_tag].dst, data, data_len);
|
uint32_t data_len;
|
||||||
tdfs->operations[opidx].num_pending--;
|
if (!binary_read(&reader, &data_len, sizeof(data_len))) {
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (tdfs->operations[opidx].num_pending == 0) {
|
uint8_t *data = reader.src + reader.cur;
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_READ_SUCCESS };
|
if (!binary_read(&reader, NULL, data_len)) {
|
||||||
} else {
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
// TODO: start operation
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (binary_read(&reader, NULL, 1)) {
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_ERROR };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy data to destination
|
||||||
|
if (range_idx >= 0 && range_idx < tdfs->operations[opidx].ranges_count) {
|
||||||
|
memcpy(tdfs->operations[opidx].ranges[range_idx].dst, data, data_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
tdfs->operations[opidx].num_pending--;
|
||||||
|
|
||||||
|
// Start next download (sequential)
|
||||||
|
int next_idx = tdfs->operations[opidx].ranges_head;
|
||||||
|
if (next_idx < tdfs->operations[opidx].ranges_count) {
|
||||||
|
Range *r = &tdfs->operations[opidx].ranges[next_idx];
|
||||||
|
|
||||||
|
int cs_idx = get_chunk_server_connection(tdfs, r->server_addr);
|
||||||
|
if (cs_idx >= 0) {
|
||||||
|
r->chunk_server_idx = cs_idx;
|
||||||
|
if (send_download_chunk(tdfs, cs_idx, r->hash, r->offset_within_chunk,
|
||||||
|
r->length_within_chunk, opidx, next_idx) == 0) {
|
||||||
|
tdfs->operations[opidx].num_pending++;
|
||||||
|
tdfs->operations[opidx].ranges_head++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
// Check if done
|
||||||
|
if (tdfs->operations[opidx].num_pending == 0) {
|
||||||
|
free(tdfs->operations[opidx].ranges);
|
||||||
|
tdfs->operations[opidx].ranges = NULL;
|
||||||
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_READ_SUCCESS };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4444,7 +4617,7 @@ static void process_event_for_write(TinyDFS *tdfs,
|
|||||||
int opidx, int request_tag, ByteView msg)
|
int opidx, int request_tag, ByteView msg)
|
||||||
{
|
{
|
||||||
if (msg.len == 0) {
|
if (msg.len == 0) {
|
||||||
tdfs->operations[opidx].result = (Result) { TINYDFS_RESULT_WRITE_ERROR };
|
tdfs->operations[opidx].result = (TinyDFS_Result) { TINYDFS_RESULT_WRITE_ERROR };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4472,7 +4645,7 @@ static void process_event(TinyDFS *tdfs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
translate_operation_into_result(TinyDFS *tdfs, int opidx, Result *result)
|
translate_operation_into_result(TinyDFS *tdfs, int opidx, TinyDFS_Result *result)
|
||||||
{
|
{
|
||||||
if (tdfs->operations[opidx].result.type == TINYDFS_RESULT_EMPTY)
|
if (tdfs->operations[opidx].result.type == TINYDFS_RESULT_EMPTY)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -24,16 +24,13 @@ typedef struct {
|
|||||||
TinyDFS_ResultType type;
|
TinyDFS_ResultType type;
|
||||||
} TinyDFS_Result;
|
} TinyDFS_Result;
|
||||||
|
|
||||||
typedef int TinyDFS_Handle;
|
TinyDFS *tinydfs_init(char *addr, uint16_t port);
|
||||||
#define TINYDFS_INVALID ((TinyDFS_Handle) -1)
|
void tinydfs_free(TinyDFS *tdfs);
|
||||||
|
void tinydfs_wait(TinyDFS *tdfs, int opidx, TinyDFS_Result *result, int timeout);
|
||||||
TinyDFS* tinydfs_init(char *addr, uint16_t port);
|
int tinydfs_submit_create (TinyDFS *tdfs, char *path, int path_len, bool is_dir, unsigned int chunk_size);
|
||||||
void tinydfs_free(TinyDFS *tdfs);
|
int tinydfs_submit_delete (TinyDFS *tdfs, char *path, int path_len);
|
||||||
int tinydfs_wait(TinyDFS *tdfs, TinyDFS_Handle handle, TinyDFS_Result *result, int timeout);
|
int tinydfs_submit_list (TinyDFS *tdfs, char *path, int path_len);
|
||||||
TinyDFS_Handle tinydfs_submit_create (TinyDFS *tdfs, char *path, int path_len, bool is_dir, unsigned int chunk_size);
|
int tinydfs_submit_read (TinyDFS *tdfs, char *path, int path_len, int off, void *dst, int len);
|
||||||
TinyDFS_Handle tinydfs_submit_delete (TinyDFS *tdfs, char *path, int path_len);
|
int tinydfs_submit_write (TinyDFS *tdfs, char *path, int path_len, int off, void *src, int len);
|
||||||
TinyDFS_Handle tinydfs_submit_list (TinyDFS *tdfs, char *path, int path_len);
|
|
||||||
TinyDFS_Handle tinydfs_submit_read (TinyDFS *tdfs, char *path, int path_len, void *dst, int len);
|
|
||||||
TinyDFS_Handle tinydfs_submit_write (TinyDFS *tdfs, char *path, int path_len, void *src, int len);
|
|
||||||
|
|
||||||
#endif // TINYDFS_INCLUDED
|
#endif // TINYDFS_INCLUDED
|
||||||
|
|||||||
+5
-5
@@ -7,31 +7,31 @@ int main(void)
|
|||||||
if (tdfs == NULL)
|
if (tdfs == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (tinydfs_submit_create(tdfs, "/my_file_1", -1, false, 1024) == TINYDFS_INVALID) {
|
if (tinydfs_submit_create(tdfs, "/my_file_1", -1, false, 1024) < 0) {
|
||||||
tinydfs_free(tdfs);
|
tinydfs_free(tdfs);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tinydfs_submit_create(tdfs, "/my_file_2", -1, false, 1024) == TINYDFS_INVALID) {
|
if (tinydfs_submit_create(tdfs, "/my_file_2", -1, false, 1024) < 0) {
|
||||||
tinydfs_free(tdfs);
|
tinydfs_free(tdfs);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buff_1[] = "This is file 1";
|
char buff_1[] = "This is file 1";
|
||||||
if (tinydfs_submit_write(tdfs, "/my_file_1", -1, buff_1, sizeof(buff_1)-1) == TINYDFS_INVALID) {
|
if (tinydfs_submit_write(tdfs, "/my_file_1", -1, 0, buff_1, sizeof(buff_1)-1) < 0) {
|
||||||
tinydfs_free(tdfs);
|
tinydfs_free(tdfs);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buff_2[] = "This is file 1";
|
char buff_2[] = "This is file 1";
|
||||||
if (tinydfs_submit_write(tdfs, "/my_file_1", -1, buff_2, sizeof(buff_2)-1) == TINYDFS_INVALID) {
|
if (tinydfs_submit_write(tdfs, "/my_file_1", -1, 0, buff_2, sizeof(buff_2)-1) < 0) {
|
||||||
tinydfs_free(tdfs);
|
tinydfs_free(tdfs);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
TinyDFS_Result result;
|
TinyDFS_Result result;
|
||||||
tinydfs_wait(tdfs, TINYDFS_INVALID, &result, -1);
|
tinydfs_wait(tdfs, -1, &result, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
tinydfs_free(tdfs);
|
tinydfs_free(tdfs);
|
||||||
|
|||||||
Reference in New Issue
Block a user