int add_transaction_metadata(int tx_id, int local, int tx_run_number, SERVER_lp_state_type * pointer) { if (!get_transaction_metadata(tx_id, pointer)) { int hash_table_bucket = active_transaction_table_hash_function(tx_id); transaction_metadata * new_transaction_metadata = (transaction_metadata *) malloc(sizeof(transaction_metadata)); new_transaction_metadata->tx_id = tx_id; new_transaction_metadata->local = local; new_transaction_metadata->executed_operations = 0; new_transaction_metadata->current_tx_run_number = tx_run_number; new_transaction_metadata->is_blocked = 0; new_transaction_metadata->expected_response_counter = 0; new_transaction_metadata->next = NULL; new_transaction_metadata->write_set = NULL; new_transaction_metadata->read_set = NULL; if (pointer->cc_metadata->active_transaction[hash_table_bucket] == NULL) { pointer->cc_metadata->active_transaction[hash_table_bucket] = new_transaction_metadata; return 1; } else { transaction_metadata * tmd = (transaction_metadata *) pointer->cc_metadata->active_transaction[hash_table_bucket]; while (tmd->next != NULL) { if (tmd->tx_id == tx_id) { return -1; } tmd = tmd->next; } tmd->next = new_transaction_metadata; return 1; } } return 1; }
static int add_data_to_write_set(int tx_id, int client_id, SERVER_lp_state_type * pointer, int object_key_id) { data_set_entry * entry = (data_set_entry *) malloc(sizeof(data_set_entry)); entry->object_key_id = object_key_id; entry->next = NULL; transaction_metadata * transaction = get_transaction_metadata(tx_id, pointer); if (transaction == NULL) { printf("ERROR: no transaction found with id %d (from client id %d)\n", tx_id, client_id); return -1; } if (transaction->write_set == NULL) { transaction->write_set = entry; return 1; } data_set_entry * current_entry = transaction->write_set; while (current_entry->next != NULL) { if (current_entry->object_key_id == object_key_id) { return 0; } current_entry = current_entry->next; } current_entry->next = entry; return 1; }
//send prepare messages to other servers void send_final_commit_messages(state_type *state, event_content_type * event_content, time_type now) { int s; // Get the server configuration from simulation state SERVER_lp_state_type *pointer = &state->type.server_state; transaction_metadata *transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction == NULL) { printf("ERROR: no transaction fouded with id %d (from cliendt %d)\n", event_content->applicative_content.tx_id, event_content->applicative_content.client_id); exit(-1); } for (s = state->num_clients; s < state->num_clients + state->num_servers; s++) { int a_server_founded = 0; data_set_entry *entry = transaction->write_set; while (entry != NULL && !a_server_founded) { if (pointer->configuration.concurrency_control_type == PRIMARY_OWNER_CTL_2PL) { if (is_primary(entry->object_key_id, s, state->num_servers, state->num_clients)) a_server_founded = 1; } else { if (is_owner(entry->object_key_id, s, state->num_servers, state->num_clients, state->object_replication_degree)) a_server_founded = 1; } entry = entry->next; } if (s != event_content->applicative_content.server_id && a_server_founded) { event_content_type new_event_content; memcpy(&new_event_content, event_content, sizeof(event_content_type)); new_event_content.applicative_content.op_type = TX_DISTRIBUTED_FINAL_COMMIT; new_event_content.destination_object_id = s; new_event_content.applicative_content.write_set = transaction->write_set; transaction->expected_prepare_response_counter++; server_send_final_commit_message(state, &new_event_content, now); if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: TX_DISTRIBUTED_FINAL_COMMIT sent at time %f to server %i\n", event_content->applicative_content.server_id, now, s); } } }
//send final abort messages to other servers void send_final_abort_messages(state_type *state, event_content_type * event_content, time_type now) { int s; // Get the server configuration from simulation state SERVER_lp_state_type *pointer = &state->type.server_state; transaction_metadata *transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction == NULL) { printf("ERROR: no transaction found with id %d (from client id %d)\n", event_content->applicative_content.tx_id, event_content->applicative_content.client_id); exit(-1); } for (s = state->num_clients; s < state->num_clients + state->num_servers; s++) { // send a message to other servers containing at least an entry of the transaction write set int an_entry_founded = 0; data_set_entry *entry = transaction->write_set; while (entry != NULL && !an_entry_founded) { if (pointer->configuration.concurrency_control_type == PRIMARY_OWNER_CTL_2PL) { if (is_primary(entry->object_key_id, s, state->num_servers, state->num_clients)) an_entry_founded = 1; } else { if (is_owner(entry->object_key_id, s, state->num_servers, state->num_clients, state->object_replication_degree)) an_entry_founded = 1; } entry = entry->next; } if (s != event_content->applicative_content.server_id && an_entry_founded) { event_content->applicative_content.op_type = TX_REMOTE_ABORT; event_content->destination_object_id = s; event_content->applicative_content.write_set = transaction->write_set; transaction->expected_prepare_response_counter++; server_send_message(state, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: TX_REMOTE_ABORT sent at time %f to server %i\n", event_content->applicative_content.server_id, now, s); } } }
static void abort_local_tx(event_content_type * event_content, state_type *state, double now) { SERVER_lp_state_type *pointer = &state->type.server_state; //Remove all events of transaction remove_event_of_tx(pointer->cc_metadata->event_queue, event_content->applicative_content.tx_id); transaction_metadata *transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction == NULL) { printf("ERROR: no transaction found with id %d (from client id %d)\n", event_content->applicative_content.tx_id, event_content->applicative_content.client_id); exit(-1); } remove_tx_locks(transaction->tx_id, transaction->write_set, state, now); }
int acquire_a_local_lock(state_type *state, time_type timeout, int timeout_event_type, event_content_type *event_content, double now) { SERVER_lp_state_type *pointer = &state->type.server_state; if (pointer->configuration.cc_verbose) printf("cc%d - oggetto %d per la transizione %i da lockare\n", pointer->server_id, event_content->applicative_content.object_key_id, event_content->applicative_content.tx_id); //check lock... if (pointer->cc_metadata->locks[event_content->applicative_content.object_key_id] == -1) { //not locked pointer->cc_metadata->lock_retry_num = 0; //acquire lock pointer->cc_metadata->locks[event_content->applicative_content.object_key_id] = event_content->applicative_content.tx_id; if (pointer->configuration.cc_verbose) printf("cc%d - oggetto %d per la transizione %i lockato al tempo %f \n", pointer->server_id, event_content->applicative_content.object_key_id, event_content->applicative_content.tx_id, now); return 1; } else if (pointer->cc_metadata->locks[event_content->applicative_content.object_key_id] == event_content->applicative_content.tx_id) { // already locked by me return 1; } else { //already locked by another transaction pointer->cc_metadata->lock_retry_num++; //check deadlocks (if enabled) if (pointer->configuration.deadlock_detection_enabled && check_deadlock(event_content, pointer)) { return -1; } //add the timeout event event_content_type new_event_content; memcpy(&new_event_content, event_content, sizeof(event_content_type)); ScheduleNewEvent(pointer->server_id, now + timeout, timeout_event_type, &new_event_content, sizeof(event_content_type)); //enqueue event memcpy(&new_event_content, event_content, sizeof(event_content_type)); new_event_content.applicative_content.object_key_id = event_content->applicative_content.object_key_id; enqueue_event(pointer, &new_event_content); transaction_metadata *transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction == NULL) { if (pointer->configuration.cc_verbose) { printf("cc%d - la tx %i non è locale\n", pointer->server_id, event_content->applicative_content.tx_id); printf("cc%d - prepare of tx %i added in the waiting event queue %f due to a lock on object :%d tx:%i\n", pointer->server_id, event_content->applicative_content.tx_id, now, event_content->applicative_content.object_key_id, new_event_content.applicative_content.tx_id); } return 0; } else { transaction->is_blocked = 1; if (pointer->configuration.cc_verbose) printf("cc%d - tx %i is waiting at time %f due to a lock lock on object :%d tx:%i\n", pointer->server_id, event_content->applicative_content.tx_id, now, event_content->applicative_content.object_key_id, new_event_content.applicative_content.tx_id); return 0; } } }
static void reschedule_event(state_type *state, double now, int object_key_id) { SERVER_lp_state_type *pointer = &state->type.server_state; event_content_type *event_content = NULL; do { event_content = get_next_event_waiting_for_object_key(state, CC_QUEUE, object_key_id); if (event_content != NULL) { transaction_metadata *transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction != NULL) transaction->is_blocked = 0; ScheduleNewEvent(pointer->server_id, now, DELIVER_MESSAGE, event_content, sizeof(event_content_type)); if (pointer->configuration.cc_verbose) printf("cc - Funzione reschedule_event: reinviato evento %d (op %d della txn %d) a server %d al tempo %f\n", event_content->applicative_content.op_type, event_content->applicative_content.op_number, event_content->applicative_content.tx_id, event_content->applicative_content.server_id, now); remove_event_of_tx(pointer->cc_metadata->event_queue, event_content->applicative_content.tx_id); } } while (event_content != NULL); }
static int add_data_to_read_set(int tx_id, int client_id, SERVER_lp_state_type * pointer, int object_key_id) { data_set_entry * entry = (data_set_entry *) malloc(sizeof(data_set_entry)); entry->object_key_id = object_key_id; entry->next = NULL; transaction_metadata * transaction = get_transaction_metadata(tx_id, pointer); if (transaction == NULL) { printf("ERRORE (add_data_to_read_set): Nessun active transaction con id %d del client %d presente\n", tx_id, client_id); return -1; } if (transaction->read_set == NULL) { transaction->read_set = entry; return 1; } data_set_entry * current_entry = transaction->read_set; while (current_entry->next != NULL) { if (current_entry->object_key_id == object_key_id) { return 0; } current_entry = current_entry->next; } current_entry->next = entry; return 1; }
//main concurrency control function: return 0 if the event is enqueued, 1 if the accessing object is locked, -1 if transaction must be aborted int CC_control(event_content_type * event_content, state_type *state, time_type now) { SERVER_lp_state_type *pointer = &state->type.server_state; if (pointer == NULL || event_content == NULL) return -1; switch (event_content->applicative_content.op_type) { case TX_BEGIN: if (pointer->configuration.cc_verbose) printf("\tcc%d - TX_BEGIN\n", pointer->server_id); return 1; break; case TX_GET: if (pointer->configuration.cc_verbose) printf("\tcc%d - TX_GET per tx %i\n", pointer->server_id, event_content->applicative_content.tx_id); int return_from_add_data_to_read_set = add_data_to_read_set(event_content->applicative_content.tx_id, event_content->applicative_content.client_id, pointer, event_content->applicative_content.object_key_id); if (return_from_add_data_to_read_set == -1) { abort_local_tx(event_content, state, now); if (pointer->configuration.cc_verbose) printf("\tcc%d - ERROR while adding object %i in the read-set of transaction %d from client %d\n", pointer->server_id, event_content->applicative_content.object_key_id, event_content->applicative_content.tx_id, event_content->applicative_content.client_id); return -1; } else { if (return_from_add_data_to_read_set == 0 && pointer->configuration.cc_verbose) printf("\tcc%d - object %d is already in the read-set of transaction %d from client %d\n", pointer->server_id, event_content->applicative_content.object_key_id, event_content->applicative_content.tx_id, event_content->applicative_content.client_id); else if (pointer->configuration.cc_verbose) printf("\tcc%d - object %d added to the read-set of transaction tx %d\n", pointer->server_id, event_content->applicative_content.object_key_id, event_content->applicative_content.tx_id); } return 1; break; case TX_PUT: if (pointer->configuration.cc_verbose) printf("\tcc%d - TX_PUT per tx %i\n", pointer->server_id, event_content->applicative_content.tx_id); //add data to write-set add_data_to_write_set(event_content->applicative_content.tx_id, event_content->applicative_content.client_id, pointer, event_content->applicative_content.object_key_id); if (pointer->configuration.concurrency_control_type == ETL_2PL && is_owner(event_content->applicative_content.object_key_id, pointer->server_id, state->num_servers, state->num_clients, state->object_replication_degree)) { return acquire_a_local_lock(state, pointer->configuration.locking_timeout, TX_LOCAL_TIMEOUT, event_content, now); } return 1; break; case TX_PREPARE: if (pointer->configuration.cc_verbose) printf("\tcc%d - TX_PREPARE per tx %i\n", pointer->server_id, event_content->applicative_content.tx_id); data_set_entry *dataset = event_content->applicative_content.write_set; int result = acquire_local_locks(state, dataset, pointer->configuration.locking_timeout, TX_PREPARE_TIMEOUT, event_content, now); if (result == -1) abort_local_tx(event_content, state, now); return result; break; case TX_COMMIT: if (pointer->configuration.cc_verbose) printf("\tcc%d - TX_COMMIT per tx %i\n", pointer->server_id, event_content->applicative_content.tx_id); if (pointer->configuration.concurrency_control_type == CTL_2PL || pointer->configuration.concurrency_control_type == PRIMARY_OWNER_CTL_2PL) { transaction_metadata *transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction == NULL) { printf("ERROR: no transaction found with id %d (from client id %d)\n", event_content->applicative_content.tx_id, event_content->applicative_content.client_id); exit(-1); } data_set_entry *dataset = transaction->write_set; int result = acquire_local_locks(state, dataset, pointer->configuration.locking_timeout, TX_LOCAL_TIMEOUT, event_content, now); if (result == -1) abort_local_tx(event_content, state, now); return result; } else return 1; break; case TX_FINAL_LOCAL_COMMIT: if (pointer->configuration.cc_verbose) printf("\tcc%d - TX_FINAL_LOCAL_COMMIT per tx %i\n", pointer->server_id, event_content->applicative_content.tx_id); transaction_metadata *transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction == NULL) { printf("ERROR: no transaction found with id %d (from client id %d)\n", event_content->applicative_content.tx_id, event_content->applicative_content.client_id); exit(-1); } dataset = transaction->write_set; remove_tx_locks(event_content->applicative_content.tx_id, dataset, state, now); //} else return 1; break; case TX_FINAL_REMOTE_COMMIT: if (pointer->configuration.cc_verbose) printf("\tcc%d - TX_FINAL_REMOTE_COMMIT per tx %i\n", pointer->server_id, event_content->applicative_content.tx_id); remove_tx_locks(event_content->applicative_content.tx_id, event_content->applicative_content.write_set, state, now); return 1; break; case TX_LOCAL_ABORT: if (pointer->configuration.cc_verbose) printf("\tcc%d - TX_ABORT per tx %i\n", pointer->server_id, event_content->applicative_content.tx_id); abort_local_tx(event_content, state, now); return -1; break; case TX_REMOTE_ABORT: if (pointer->configuration.cc_verbose) printf("\tcc%d - TX_ABORT per tx %i\n", pointer->server_id, event_content->applicative_content.tx_id); abort_remote_tx(event_content, state, now); return -1; break; default: printf("ERRORE: evento %i non catturato\n", event_content->applicative_content.op_type); break; } printf("ERROR: case not managed\n"); exit(-1); }
int acquire_local_locks(state_type *state, data_set_entry *data_set, time_type timeout, int timeout_event_type, event_content_type *event_content, double now) { SERVER_lp_state_type *pointer = &state->type.server_state; data_set_entry *entry = data_set; if (entry == NULL) { if (pointer->configuration.cc_verbose) printf("cc%d - write set of transaction %d is empty\n", pointer->server_id, event_content->applicative_content.tx_id); return 1; } while (entry != NULL) { int need_to_lock = 0; if (pointer->configuration.concurrency_control_type == ETL_2PL || pointer->configuration.concurrency_control_type == CTL_2PL) need_to_lock = is_owner(entry->object_key_id, pointer->server_id, state->num_servers, state->num_clients, state->object_replication_degree); else if (pointer->configuration.concurrency_control_type == PRIMARY_OWNER_CTL_2PL) need_to_lock = is_primary(entry->object_key_id, pointer->server_id, state->num_servers, state->num_clients); if (need_to_lock) { if (pointer->configuration.cc_verbose) printf("cc%d - object %d for transaction %i to be locked\n", pointer->server_id, entry->object_key_id, event_content->applicative_content.tx_id); //check lock... if (pointer->cc_metadata->locks[entry->object_key_id] == -1) { //not locked pointer->cc_metadata->lock_retry_num = 0; //acquire lock pointer->cc_metadata->locks[entry->object_key_id] = event_content->applicative_content.tx_id; if (pointer->configuration.cc_verbose) printf("cc%d - pbject %d for transaction %i locked at time %f \n", pointer->server_id, entry->object_key_id, event_content->applicative_content.tx_id, now); } else if (pointer->cc_metadata->locks[entry->object_key_id] == event_content->applicative_content.tx_id) { // already locked by me // go to the next entry } else { //already locked by another transaction pointer->cc_metadata->lock_retry_num++; //check deadlock (if enabled) if (pointer->configuration.deadlock_detection_enabled && check_deadlock(event_content, pointer)) { return -1; } //add the timeout event event_content_type new_event_content; memcpy(&new_event_content, event_content, sizeof(event_content_type)); ScheduleNewEvent(pointer->server_id, now + timeout, timeout_event_type, &new_event_content, sizeof(event_content_type)); //enqueue transaction memcpy(&new_event_content, event_content, sizeof(event_content_type)); new_event_content.applicative_content.object_key_id = entry->object_key_id; enqueue_event(pointer, &new_event_content); transaction_metadata *transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction == NULL) { if (pointer->configuration.cc_verbose) { printf("cc%d - transaction %i is not local\n", pointer->server_id, event_content->applicative_content.tx_id); printf("cc%d - prepare of tx %i added in the waiting event queue %f due to a lock on object %d tx:%i\n", pointer->server_id, event_content->applicative_content.tx_id, now, entry->object_key_id, new_event_content.applicative_content.tx_id); } return 0; } else { transaction->is_blocked = 1; if (pointer->configuration.cc_verbose) printf("cc%d - transaction %i is waiting at time %f due to a lock on object%d tx:%i\n", pointer->server_id, event_content->applicative_content.tx_id, now, entry->object_key_id, new_event_content.applicative_content.tx_id); return 0; } } } entry = entry->next; } return 1; }
//function per il processamento degli eventi da parte del server void process_message(int me, time_type now, event_content_type * event_content, state_type *state) { // Get the server configuration from simulation state SERVER_lp_state_type *pointer = &state->type.server_state; transaction_metadata * transaction; // check operation type switch (event_content->applicative_content.op_type) { case TX_BEGIN: if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received TX_BEGIN at time %f for transaction %d run number %i\n", me, now, event_content->applicative_content.tx_id, event_content->applicative_content.tx_run_number); //add transaction metadata to active_transaction list int ret = add_transaction_metadata(event_content->applicative_content.tx_id, 1, event_content->applicative_content.tx_run_number, state); int cc_response = CC_control(event_content, state, now); if (cc_response == 1) { event_content->applicative_content.op_type = CPU_TX_BEGIN; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_TX_BEGIN added to CPU at time %f\n", me, now); } else if (cc_response == -1) { event_content->applicative_content.op_type = CPU_TX_LOCAL_ABORT; remove_transaction_metadata(event_content->applicative_content.tx_id, pointer); add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_TX_LOCAL_ABORT added to CPU at time %f\n", me, now); } transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); break; case TX_GET: //get received from a client if (is_in_write_set(event_content->applicative_content.tx_id, event_content->applicative_content.object_key_id, state)) { event_content->applicative_content.op_type = CPU_TX_LOCAL_GET; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_LOCAL_TX_GET added to CPU at time %f\n", me, now); break; } if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received TX_GET at time %f\n", me, now); //am I the owner of the key? if (is_owner(event_content->applicative_content.object_key_id, me, state->num_servers, state->num_clients, state->object_replication_degree)) { //..yes, call the concurrency control int cc_response = CC_control(event_content, state, now); if (cc_response == 1) { //operation allowed event_content->applicative_content.op_type = CPU_TX_LOCAL_GET; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_LOCAL_TX_GET added to CPU at time %f\n", me, now); } else if (cc_response == -1) { //operation not allowed, transaction has to be aborted if (pointer->configuration.server_verbose) printf("S%d - Server_ProcessEvent: operation aborted by the concurrency control at time %f\n", me, now); event_content->applicative_content.op_type = CPU_TX_LOCAL_ABORT; remove_transaction_metadata(event_content->applicative_content.tx_id, pointer); add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_TX_LOCAL_ABORT added to CPU at time %f\n", me, now); } } else { transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); //..no (I'not the owner), TX_GET has to be sent to remote server(s) event_content->applicative_content.op_type = CPU_TX_SEND_REMOTE_GET; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_SEND_REMOTE_TX_GET added to CPU at time %f\n", me, now); } break; case TX_REMOTE_GET: //get received from a server if (pointer->configuration.server_verbose) printf("S%d - Server_ProcessEvent: TX_REMOTE_GET received from server %i for operation %i of transaction %i at time %f\n", me, pointer->server_id, event_content->applicative_content.op_number, event_content->applicative_content.tx_id, now); if (event_content->applicative_content.tx_id==9 && event_content->applicative_content.op_number==6) fflush(stdout); cc_response = CC_control(event_content, state, now); if (cc_response == 1) { event_content->applicative_content.op_type = CPU_TX_LOCAL_GET_FROM_REMOTE; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_LOCAL_TX_GET_FROM_REMOTE added to CPU at time %f\n", me, now); } break; case TX_REMOTE_GET_RETURN: //get response received from a server if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received TX_REMOTE_GET_RETURN from server %i for operation %i tx %i run number %i at time %f\n", me, event_content->origin_object_id, event_content->applicative_content.op_number, event_content->applicative_content.tx_id, event_content->applicative_content.tx_run_number, now); if (event_content->applicative_content.tx_id == 9 && event_content->applicative_content.op_number == 6) fflush(stdout); transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction!=NULL && event_content->applicative_content.op_number - 1 == transaction->executed_operations && transaction->current_tx_run_number == event_content->applicative_content.tx_run_number) { transaction->executed_operations++; int cc_response = CC_control(event_content, state, now); if (cc_response == 1) { event_content->applicative_content.op_type = CPU_TX_REMOTE_GET_RETURN; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_REMOTE_TX_GET_RETURN added to CPU at time %f\n", me, now); } else if (cc_response == -1) { event_content->applicative_content.op_type = CPU_TX_LOCAL_ABORT; remove_transaction_metadata(event_content->applicative_content.tx_id, pointer); add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_TX_LOCAL_ABORT added to CPU at time %f\n", me, now); } } break; case TX_PUT: //put received from a client if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received TX_PUT (txn %i, op: %i) at time %f\n", me, event_content->applicative_content.tx_id, event_content->applicative_content.op_number, now); //call the concurrency control cc_response = CC_control(event_content, state, now); if (cc_response == 1) { //operation allowed event_content->applicative_content.op_type = CPU_TX_LOCAL_PUT; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_LOCAL_TX_PUT added to CPU at time %f\n", me, now); } else if (cc_response == -1) { //operation not not allowed, transaction has to be aborted event_content->applicative_content.op_type = CPU_TX_LOCAL_ABORT; remove_transaction_metadata(event_content->applicative_content.tx_id, pointer); add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_TX_LOCAL_ABORT added to CPU at time %f\n", me, now); } break; case TX_UPDATE: //data update update received from a primary owner server if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received UPDATE at time %f \n", me, now); event_content->applicative_content.op_type = CPU_TX_UPDATE; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_UPDATE added to CPU at time %f\n", me, now); break; case TX_COMMIT: // commit request received from a client if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received TX_COMMIT for transaction %i run number %i at time %f \n", me, event_content->applicative_content.tx_id, event_content->applicative_content.tx_run_number, now); cc_response = CC_control(event_content, state, now); if (cc_response == 1) { //operation allowed transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction == NULL ) { printf("ERROR: no transaction found with id %d (from client id %d)\n", event_content->applicative_content.tx_id, event_content->applicative_content.client_id); exit(-1); } event_content->applicative_content.op_type = CPU_PREPARE; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_PREPARE for transaction %i added to CPU at time %f\n", me, event_content->applicative_content.tx_id, now); } else if (cc_response == -1) { ////operation not allowed, transaction has to be aborted if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: operazione abortita dal Controllore di Concorrenza at time %f\n", me, now); event_content->applicative_content.op_type = CPU_TX_LOCAL_ABORT; remove_transaction_metadata(event_content->applicative_content.tx_id, pointer); add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_TX_LOCAL_ABORT added to CPU at time %f\n", me, now); } break; case TX_PREPARE: //prepare request received from a coordinator server ret = add_transaction_metadata(event_content->applicative_content.tx_id, 0, event_content->applicative_content.tx_run_number, state); if (ret == -1 && pointer->configuration.cc_verbose) printf("[cc%d] Error while adding transaction %i to transaction metadata list\n", pointer->server_id, event_content->applicative_content.tx_id); if (pointer->configuration.server_verbose) printf(" S%d - function Server_ProcessEvent: received TX_PREPARE for transaction %i run number %i at time %f \n", me, event_content->applicative_content.tx_id, event_content->applicative_content.tx_run_number, now); int CC_response = CC_control(event_content, state, now); if (CC_response == 1) { event_content->applicative_content.op_type = CPU_TX_LOCAL_PREPARE_SUCCESSED; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_TX_LOCAL_PREPARE_SUCCESSED added to CPU at time %f\n", me, now); } else if (CC_response == -1) { event_content->applicative_content.op_type = CPU_TX_LOCAL_PREPARE_FAILED; add_processing_request(pointer, event_content, now); remove_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (pointer->configuration.server_verbose) printf("S%d - CPU_TX_LOCAL_PREPARE_FAILED added to CPU at time %f\n", me, now); } break; case TX_PREPARE_SUCCEEDED: // received from a remote participant server if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received TX_PREPARE_SUCCEEDED for transaction %i run number %i at time %f \n", me, event_content->applicative_content.tx_id, event_content->applicative_content.tx_run_number, now); transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); // decrement expected response counter if (transaction != NULL && transaction->current_tx_run_number == event_content->applicative_content.tx_run_number) { transaction->expected_prepare_response_counter--; CC_control(event_content, state, now); if (transaction->expected_prepare_response_counter == 0) { //all expected prepare messages have been succesfully received, transaction can commit event_content->applicative_content.op_type = CPU_TX_DISTRIBUTED_FINAL_COMMIT; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_DISTRIBUTED_FINAL_TX_COMMIT to cpu of transaction %i at time %f\n", me, event_content->applicative_content.tx_id, now); } } break; case TX_PREPARE_FAILED: // received from a remote participant server if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received TX_PREPARE_FAILED for transaction %i at time %f\n", me, event_content->applicative_content.tx_id, now); event_content->applicative_content.op_type = CPU_TX_PREPARE_FAILED; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_TX_PREPARE_FAILED added to CPU at time %f\n", me, now); break; case TX_DISTRIBUTED_FINAL_COMMIT: //received from a remote coordinator server if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received TX_DISTRIBUTED_FINAL_COMMIT for transaction %i at time %f \n", me, event_content->applicative_content.tx_id, now); event_content->applicative_content.op_type = CPU_TX_LOCAL_FINAL_COMMIT; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_LOCAL_TX_FINAL_COMMIT for transaction %i added to CPU at time %f\n", me, event_content->applicative_content.tx_id, now); break; case TX_REMOTE_ABORT: // received from a remote coordinator server if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received TX_REMOTE_ABORT at time %f for transaction %d\n", me, now, event_content->applicative_content.tx_id); event_content->applicative_content.op_type = CPU_TX_REMOTE_ABORT; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_TX_REMOTE_ABORT added to CPU at time %f\n", me, now); break; default: printf("ERRORE: event type %i not managed\n", event_content->applicative_content.op_type); break; } }
void SERVER_ProcessEvent(unsigned int me, time_type now, int event_type, event_content_type *event_content, unsigned int size, state_type *state) { // get the server configuration from simulation state SERVER_lp_state_type *pointer = &state->type.server_state; transaction_metadata *transaction; switch (event_type) { // Configuration has just been stored case INIT: if (pointer->configuration.server_verbose) { printf("S%d - function Server_ProcessEvent: received SHARE_CONF\n", me); } if (me>state->num_clients+state->num_servers) break; pointer->server_id = me; pointer->stored_values = 0; pointer->last_net_iterarrival_tx_time=0; pointer->average_net_interarrival_tx_time=0; concurrency_control_init(state); cpu_init(pointer); break; case CPU_TX_LOCAL_GET: //return from cpu in case of local get if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received READ_LOCAL_VALUE_RET_CPU at time %f\n", me, now); transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction == NULL) { printf("ERROR: no transaction found with id %d (from client id %d)\n", event_content->applicative_content.tx_id, event_content->applicative_content.client_id); exit(-1); } transaction->executed_operations++; event_content_type new_event_content; memcpy(&new_event_content, event_content, sizeof(event_content_type)); new_event_content.applicative_content.object_key_id = event_content->applicative_content.object_key_id; new_event_content.destination_object_id = event_content->applicative_content.client_id; new_event_content.applicative_content.op_type = TX_GET_RETURN; server_send_message(state, &new_event_content, now); break; case CPU_TX_LOCAL_PUT: //return from cpu in case of local put if (pointer->configuration.server_verbose) printf("- function Server_ProcessEvent: received WRITE_VALUE_RET_CPU at time %f\n", now); transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction == NULL) { printf("ERROR: no transaction found with id %d (from client id %d)\n", event_content->applicative_content.tx_id, event_content->applicative_content.client_id); exit(-1); } transaction->executed_operations++; memcpy(&new_event_content, event_content, sizeof(event_content_type)); new_event_content.applicative_content.server_id = pointer->server_id; new_event_content.applicative_content.op_type = TX_PUT_RETURN; new_event_content.destination_object_id = event_content->applicative_content.client_id; server_send_message(state, &new_event_content, now); if (pointer->configuration.server_verbose) printf("- function Server_ProcessEvent: sent DELIVER_PUT_RETURN to NET at time %f\n", now); break; case CPU_TX_REMOTE_GET_RETURN: //return from cpu in case of remote get if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: CPU_REMOTE_TX_GET_RETURN received for tx %i run number %i at time %f\n", me, event_content->applicative_content.tx_id, event_content->applicative_content.tx_run_number, now); // check if a remote get response has already arrived transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction == NULL) { break; } memcpy(&new_event_content, event_content, sizeof(event_content_type)); new_event_content.applicative_content.object_key_id = event_content->applicative_content.object_key_id; new_event_content.destination_object_id = new_event_content.applicative_content.client_id; new_event_content.applicative_content.op_type = TX_GET_RETURN; server_send_message(state, &new_event_content, now); break; case CPU_PREPARE: //return from cpu in case of prepare transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); transaction->expected_prepare_response_counter = 0; //stats for cubist //printf("\n%f",pointer->average_net_interarrival_tx_time); pointer->average_net_interarrival_tx_time=0.95*pointer->average_net_interarrival_tx_time+0.05*(now-pointer->last_net_iterarrival_tx_time); pointer->last_net_iterarrival_tx_time=now; if(transaction->write_set != NULL){ //send prepare messages to other servers send_prepare_messages(state, transaction, event_content, now); } // check whether not to wait for other server response if (transaction->expected_prepare_response_counter == 0) { // can immediately commit if (pointer->configuration.server_verbose) printf("S%d - la tx %i ha solo write locali\n", me, event_content->applicative_content.tx_id); event_content->applicative_content.op_type = CPU_TX_DISTRIBUTED_FINAL_COMMIT; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_DISTRIBUTED_FINAL_TX_COMMIT to cpu for transaction %i at time %f\n", me, event_content->applicative_content.tx_id, now); } break; case CPU_TX_LOCAL_PREPARE_SUCCESSED: //return from cpu in case of local prepare memcpy(&new_event_content, event_content, sizeof(event_content_type)); new_event_content.applicative_content.op_type = TX_PREPARE_SUCCEEDED; new_event_content.destination_object_id = new_event_content.applicative_content.server_id; server_send_prepare_response_message(state, &new_event_content, now); if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: sent TX_PREPARE_SUCCEEDED for transaction %i run number %i at time %f to server %i\n", me, event_content->applicative_content.tx_id, event_content->applicative_content.tx_run_number, now, new_event_content.applicative_content.server_id); break; case CPU_TX_LOCAL_PREPARE_FAILED: memcpy(&new_event_content, event_content, sizeof(event_content_type)); new_event_content.applicative_content.op_type = TX_PREPARE_FAILED; new_event_content.destination_object_id = new_event_content.applicative_content.server_id; server_send_prepare_response_message(state, &new_event_content, now); if (pointer->configuration.server_verbose) printf(" S%d - function Server_ProcessEvent: sent TX_PREPARE_FAILED for transaction %i at time %f to server %i\n", me, event_content->applicative_content.tx_id, now, new_event_content.applicative_content.server_id); break; case CPU_TX_PREPARE_FAILED: if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received CPU_PREPARE_FAILED for transaction %i at time %f \n", me, event_content->applicative_content.tx_id, now); // transaction must abort transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction != NULL && transaction->current_tx_run_number == event_content->applicative_content.tx_run_number) { abort_distributed_transaction(state, transaction, event_content, now); remove_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: transazione abortita at time %f\n", me, now); //reply to client event_content->destination_object_id = event_content->applicative_content.client_id; event_content->applicative_content.op_type = TX_EXECUTION_EXCEPTION; server_send_message(state, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - sent TX_EXECUTION_EXCEPTION for transaction %i to client %i at time %f\n", me, event_content->applicative_content.tx_id, event_content->applicative_content.client_id, now); } break; case CPU_TX_DISTRIBUTED_FINAL_COMMIT: if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received CPU_DISTRIBUTED_FINAL_TX_COMMIT at time %f for transaction %i\n", me, now, event_content->applicative_content.tx_id); transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if(transaction->write_set != NULL){ commit_distributed_transaction(state, transaction, event_content, now); } remove_transaction_metadata(event_content->applicative_content.tx_id, pointer); //reply to client memcpy(&new_event_content, event_content, sizeof(event_content_type)); new_event_content.applicative_content.op_type = TX_COMMIT_RESPONSE; new_event_content.destination_object_id = new_event_content.applicative_content.client_id; server_send_message(state, &new_event_content, now); break; case CPU_TX_LOCAL_FINAL_COMMIT: if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received CPU_LOCAL_TX_FINAL_COMMIT at time %f for transaction %i\n", me, now, event_content->applicative_content.tx_id); commit_remote_transaction(state, event_content, now); break; case TX_LOCAL_TIMEOUT: // timeout for a local transaction if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received TX_LOCAL_TIMEOUT at time %f for transaction %d\n", me, now, event_content->applicative_content.tx_id); transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction != NULL && transaction->current_tx_run_number == event_content->applicative_content.tx_run_number && transaction->is_blocked) { event_content->applicative_content.op_type = TX_LOCAL_ABORT; CC_control(event_content, state, now); if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: transaction aborted at time %f\n", me, now); event_content->applicative_content.op_type = CPU_TX_LOCAL_ABORT; remove_transaction_metadata(event_content->applicative_content.tx_id, pointer); add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_TX_LOCAL_ABORT added to CPU at time %f\n", me, now); } break; case TX_PREPARE_TIMEOUT: // timeout for a prepare of a remote transaction if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received TX_PREPARE_TIMEOUT at time %f for transaction %d run number %i \n", me, now, event_content->applicative_content.tx_id, event_content->applicative_content.tx_run_number); // remove waiting event of transaction transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (transaction != NULL && transaction->current_tx_run_number == event_content->applicative_content.tx_run_number && transaction->is_blocked) { event_content->applicative_content.op_type = TX_PREPARE_ABORT; CC_control(event_content, state, now); if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: prepare of %i transaction aborted at time %f\n", me, event_content->applicative_content.tx_id, now); remove_transaction_metadata(event_content->applicative_content.tx_id, pointer); //reply to server memcpy(&new_event_content, event_content, sizeof(event_content_type)); new_event_content.destination_object_id = event_content->applicative_content.server_id; new_event_content.applicative_content.op_type = TX_PREPARE_FAILED; server_send_message(state, &new_event_content, now); if (pointer->configuration.server_verbose) printf("S%d - Server_ProcessEvent: transaction %i aborted at time %f per LOCK_TIMEOUT\n", me, event_content->applicative_content.tx_id, now); event_content->applicative_content.op_type = CPU_TX_REMOTE_ABORT; add_processing_request(pointer, event_content, now); if (pointer->configuration.server_verbose) printf("S%d - CPU_TX_REMOTE_ABORT added to CPU at time %f\n", me, now); } break; case CPU_TX_BEGIN: //return from cpu in case of begin if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received TX_BEGIN_RET_CPU at time %f\n", me, now); memcpy(&new_event_content, event_content, sizeof(event_content_type)); new_event_content.destination_object_id = event_content->applicative_content.client_id; new_event_content.applicative_content.op_type = TX_BEGIN_RETURN; server_send_message(state, &new_event_content, now); transaction = get_transaction_metadata(event_content->applicative_content.tx_id, pointer); if (pointer->configuration.server_verbose) printf("S%d - Server_ProcessEvent: TX_BEGIN_RETURN sent at time %f\n", me, now); break; case CPU_TX_LOCAL_ABORT: //return from cpu in case of local transaction abort if (pointer->configuration.server_verbose) printf("S%d - tx %i run number %i aborted at time %f\n", me, event_content->applicative_content.tx_id, event_content->applicative_content.tx_run_number, now); memcpy(&new_event_content, event_content, sizeof(event_content_type)); //reply to client new_event_content.destination_object_id = event_content->applicative_content.client_id; new_event_content.applicative_content.op_type = TX_EXECUTION_EXCEPTION; server_send_message(state, &new_event_content, now); if (pointer->configuration.server_verbose) printf("S%d - TX_EXECUTION_EXCEPTION of transaction %i sent to client %i at time %f\n", me, event_content->applicative_content.tx_id, event_content->applicative_content.client_id, now); break; case CPU_TX_REMOTE_ABORT: //return from cpu in case of remote transaction abort abort_remote_transaction(state, event_content, now); break; case CPU_TX_LOCAL_GET_FROM_REMOTE: //return from cpu in case of local get from a remote transaction //send get response to the server if (pointer->configuration.server_verbose) printf("S%d - function Server_ProcessEvent: received CPU_LOCAL_TX_GET_FROM_REMOTE at time %f\n", me, now); memcpy(&new_event_content, event_content, sizeof(event_content_type)); new_event_content.destination_object_id = event_content->applicative_content.server_id; new_event_content.applicative_content.op_type = TX_REMOTE_GET_RETURN; server_send_message(state, &new_event_content, now); if (pointer->configuration.server_verbose) printf("S%d - TX_REMOTE_GET_RETURN sent to NET for tx %i run number %i at time %f\n", me, event_content->applicative_content.tx_id, event_content->applicative_content.tx_run_number, now); break; case CPU_TX_SEND_REMOTE_GET: //return from cpu in case of response to a remote get request if (pointer->configuration.server_verbose) printf("S%d - CPU_SEND_REMOTE_TX_GET received at time %f\n", me, now); send_remote_tx_get(state, event_content, now); break; case CPU_PROCESSING_REQUEST_EXECUTED: //notify a request completion to cpu cpu_request_executed(pointer, now); break; case DELIVER_MESSAGE: // a message from network has been received... process_message(me, now, event_content, state); break; default: printf("ERROR: event type %i not managed\n", event_type); exit(-1); break; } }