extern "C" void write_response_handler (WriteChunkResponse *write_response) { printf ("~~~~~~~~~ Write Response id: %d", write_response->id); if (replace_request_exists(write_response->id)) { printf("(BARISTA) Processing replacement...\n"); return; } assert (write_request_exists (write_response->id)); struct write_request request = write_request_lookups[write_response->id]; printf ("(BARISTA) Processing write response for file %d.\n", active_write_requests[request].info.file_id); // If this is a primary chunk response if (write_response->id == request.request_id) { active_write_requests[request].info.chunks_received++; active_write_requests[request].count += write_response->count; } // Replica response else { active_write_requests[request].replica_info.chunks_received++; } check_write_complete(write_response->id); }
extern "C" void write_file (int fd, const void *buf, size_t count, struct client client) { struct file_instance inst; struct decafs_file_stat stat; uint32_t stripe_id, num_chunks = 0, num_replica_chunks = 0; uint32_t chunks_written, replica_chunks_written; int file_offset, stripe_offset, bytes_written = 0, write_size = 0; uint32_t request_id = get_new_request_id(); uint32_t replica_request_id = get_new_request_id(); struct write_request request = {request_id, replica_request_id}; assert (fd > 0); inst = get_file_info((uint32_t)fd); printf ("\n(BARISTA) Write request (%d bytes) from file %d\n", (int)count, (int)inst.file_id); // If the client does not have permission to write, return an error if (has_exclusive_lock (client, inst.file_id) <= 0) { if (send_write_result (client, 0, FILE_NOT_OPEN_FOR_WRITE) < 0) { printf ("\tWrite result could not reach client.\n"); } return; } if (decafs_file_stat (inst.file_id, &stat, client) < 0) { if (send_write_result (client, 0, UNABLE_TO_STAT_FILE) < 0) { printf ("\tWrite result could not reach client.\n"); } return; } if ((file_offset = get_file_cursor (fd)) < 0) { if (send_write_result (client, 0, FILE_NOT_OPEN_FOR_WRITE) < 0) { printf ("\tWrite result could not reach client.\n"); } return; } // If we are requesting 0 bytes, return 0 bytes written if (count == 0) { if (send_write_result (client, 0, 0) < 0) { printf ("\tWrite result could not reach client.\n"); } return; } // Save the request id write_request_lookups[request_id] = request; write_request_lookups[replica_request_id] = request; active_write_requests[request] = write_request_info (client, inst.file_id, fd); // TODO: make some assertion about max write size here get_first_stripe (&stripe_id, &stripe_offset, stat.stripe_size, file_offset); while (bytes_written < (int)count) { if (count - bytes_written > stat.stripe_size - stripe_offset) { write_size = stat.stripe_size - stripe_offset; } else { write_size = count - bytes_written; } printf ("\t(request: (%d,%d)) sending stripe %d for processing (%d bytes)\n", request_id, replica_request_id, stripe_id, write_size); // TODO: add pathname here, get from persistent meta chunks_written = 0; replica_chunks_written = 0; process_write_stripe (request_id, replica_request_id, &chunks_written, &replica_chunks_written, inst.file_id, (char *)"", stripe_id, stat.stripe_size, stat.chunk_size, (uint8_t *)buf + bytes_written, stripe_offset, write_size); num_chunks += chunks_written; num_replica_chunks += replica_chunks_written; // TODO (?): Move the file size update and cursor to check_write_complete() update_file_size (inst.file_id, write_size, client); set_file_cursor (fd, get_file_cursor (fd) + write_size, client); stripe_offset = 0; bytes_written += write_size; ++stripe_id; } assert (write_request_exists (request_id)); active_write_requests[request].info.chunks_expected = num_chunks; active_write_requests[request].replica_info.chunks_expected = num_replica_chunks; check_write_complete(request_id); }
int main(int argc, char* argv[]) { int active, w, write_complete, loss, sr, ss, target_num, num, received_len, from_ip, last_ack, timeout_limit; char* target_name; struct sockaddr_in my_addr, received_addr; fd_set mask, reset_mask; struct timeval timeout; FILE* fp; data_packet* received; ack_packet* ret; received_len = sizeof(received_addr); write_complete = 0; active = 0; if (argc < 2){ printf("Useage: server <loss>\n"); exit(0); } loss = atoi(argv[1]); sr = socket(AF_INET, SOCK_DGRAM, 0); if (sr < 0){ printf("SR Error\n"); exit(1); } my_addr.sin_family = AF_INET; my_addr.sin_addr.s_addr = htonl(INADDR_ANY); my_addr.sin_port = htons(PORT); if ( bind(sr, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0){ printf("SR Bind error\n"); exit(1); } ss = socket(AF_INET, SOCK_DGRAM, 0); if (ss < 0){ printf("SS error\n"); exit(1); } printf("sockets initialized.\n"); fp = fopen("received", "w"); last_ack = -1; ret = malloc(sizeof(ack_packet)); //for ack response if (ret == NULL){ printf("malloc error\n"); exit(1); } FD_ZERO( &reset_mask); FD_SET( sr, &reset_mask); sendto_dbg_init(loss); timeout.tv_sec = 0; timeout.tv_usec = 1000; for(;;) { mask = reset_mask; num = select( FD_SETSIZE, &mask, NULL, NULL, &timeout); if (num > 0 && FD_ISSET(sr, &mask)) { //we receive a packet from client timeout_limit = 0; active = 1; received = malloc(sizeof(data_packet)); recvfrom(sr, (char*)received, sizeof(data_packet), 0, (struct sockaddr*)&received_addr , &received_len); received_addr.sin_port = htons(PORT); if (received->index == last_ack+1){ //next chunck, write direct to file check_write_complete(fwrite(received->payload, 1, received->payload_len, fp), received, fp); last_ack++; } else if (received->index > last_ack+1) //chunk out of order, store in queue push(received); while(get_size() > 0 && peek()->index == last_ack+1) { //try to empty the queue data_packet * tmp = pop(); check_write_complete(fwrite(tmp->payload, 1, tmp->payload_len, fp), received, fp); last_ack++; } ret->index = last_ack; //send ack sendto_dbg(ss, (char*)ret, sizeof(ret), 0, (struct sockaddr*)&received_addr, sizeof(received_addr)); } else { if (active == 1) sendto_dbg(ss, (char*)ret, sizeof(ret), 0, (struct sockaddr*)&received_addr, sizeof(received_addr)); } } }