// Handle the create message coming at its correct destinations void MP2Node::processCreate(Message incoming_msg) { // Call the server local function to insert key and value into its local hash table according to replica type. bool success_status = createKeyValue(incoming_msg.key, incoming_msg.value, incoming_msg.replica); int _trans_id = incoming_msg.transID; // get trans_id from the incoming message Address to_addr(incoming_msg.fromAddr); // get the coordinator address from where this message came if (_trans_id < 0) //if stablization came with trans_id = -1. This is special type of message that comes when ring repair work is going on. So, don't send its reply return; Message *msg = new Message(_trans_id, getMemberNode()->addr, REPLY, success_status); emulNet->ENsend(&getMemberNode()->addr, &to_addr, msg->toString()); // send reply message back to the coordinator // if the local create operation returned success then log server success otherwise log failure. if (success_status) log->logCreateSuccess(&getMemberNode()->addr, false, _trans_id, incoming_msg.key, incoming_msg.value); else log->logCreateFail(&getMemberNode()->addr, false, _trans_id, incoming_msg.key, incoming_msg.value); // free the message variable. free(msg); }
/** * FUNCTION NAME: checkMessages * * DESCRIPTION: This function is the message handler of this node. * This function does the following: * 1) Pops messages from the queue * 2) Handles the messages according to message types */ void MP2Node::checkMessages() { /* * Implement this. Parts of it are already implemented */ char * data; int size; /* * Declare your local variables here */ // dequeue all messages and handle them while ( !memberNode->mp2q.empty() ) { /* * Pop a message from the queue */ data = (char *)memberNode->mp2q.front().elt; size = memberNode->mp2q.front().size; memberNode->mp2q.pop(); string msg_string(data, data + size); /* * Handle the message types here */ Message recv_msg = Message(msg_string); bool success; switch (recv_msg.type) { case CREATE: { success = createKeyValue(recv_msg.key, recv_msg.value, recv_msg.replica); if (success) log->logCreateSuccess(&memberNode->addr, false, recv_msg.transID, recv_msg.key, recv_msg.value); else log->logCreateFail(&memberNode->addr, false, recv_msg.transID, recv_msg.key, recv_msg.value); //send reply Message send_msg = Message(recv_msg.transID, memberNode->addr, REPLY, success); emulNet->ENsend(&memberNode->addr, &recv_msg.fromAddr, send_msg.toString()); break; } case UPDATE: { success = updateKeyValue(recv_msg.key, recv_msg.value, recv_msg.replica); if (success) log->logUpdateSuccess(&memberNode->addr, false, recv_msg.transID, recv_msg.key, recv_msg.value); else log->logUpdateFail(&memberNode->addr, false, recv_msg.transID, recv_msg.key, recv_msg.value); //send reply Message send_msg = Message(recv_msg.transID, memberNode->addr, REPLY, success); emulNet->ENsend(&memberNode->addr, &recv_msg.fromAddr, send_msg.toString()); break; } case READ: { string ret = readKey(recv_msg.key); if ("" != ret) log->logReadSuccess(&memberNode->addr, false, recv_msg.transID, recv_msg.key, ret); else log->logReadFail(&memberNode->addr, false, recv_msg.transID, recv_msg.key); //send read reply Message send_msg = Message(recv_msg.transID, memberNode->addr, ret); emulNet->ENsend(&memberNode->addr, &recv_msg.fromAddr, send_msg.toString()); break; } case DELETE: { success = deletekey(recv_msg.key); if (success) log->logDeleteSuccess(&memberNode->addr, false, recv_msg.transID, recv_msg.key); else log->logDeleteFail(&memberNode->addr, false, recv_msg.transID, recv_msg.key); //send reply Message send_msg = Message(recv_msg.transID, memberNode->addr, REPLY, success); emulNet->ENsend(&memberNode->addr, &recv_msg.fromAddr, send_msg.toString()); break; } case REPLY: { for (list<Transaction>::iterator it = buff.begin(); it != buff.end(); ++it) { if (it->transID_ == recv_msg.transID) { if (it->isStart()) it->startCount(); if (recv_msg.success) { it->increCount(); } break; } } break; } case READREPLY: { for (list<ReadTransaction>::iterator it = buffRead.begin(); it != buffRead.end(); ++it) { if (it->transID_ == recv_msg.transID) { if (it->isStart()) { it->startCount(); } if (recv_msg.value != "") { it->increCount(); it->pushValue(recv_msg.value); break; } } } break; } } } /* * This function should also ensure all READ and UPDATE operation * get QUORUM replies */ for (list<ReadTransaction>::iterator it = buffRead.begin(); it != buffRead.end(); ) { if (it->count_ == -1) { it++; } else if (it->count_ >= QUORUM) { //case READ int max = 0; string ret; for (auto i = it->values_.begin(); i != it->values_.end(); ++i) { if (i->second > max) ret = i->first; //TODO for two euqal max //else if (i->second == max) { // log->logReadFail(&memberNode->addr, true, it->transID_, it->key_); //} } log->logReadSuccess(&memberNode->addr, true, it->transID_, it->key_, ret); it = buffRead.erase(it); } else { //if (it->count_ < QUORUM) //case READ log->logReadFail(&memberNode->addr, true, it->transID_, it->key_); it = buffRead.erase(it); } } for (list<Transaction>::iterator it = buff.begin(); it != buff.end(); ) { if (it->count_ == -1) { it++; } else if (it->count_ >= QUORUM) { switch (it->type_) { case CREATE: log->logCreateSuccess(&memberNode->addr, true, it->transID_, it->key_, it->value_); break; case UPDATE: log->logUpdateSuccess(&memberNode->addr, true, it->transID_, it->key_, it->value_); break; case DELETE: log->logDeleteSuccess(&memberNode->addr, true, it->transID_, it->key_); break; default: //error break; } it = buff.erase(it); } else { //if (it->count_ < QUORUM) switch (it->type_) { case CREATE: log->logCreateFail(&memberNode->addr, true, it->transID_, it->key_, it->value_); break; case UPDATE: log->logUpdateFail(&memberNode->addr, true, it->transID_, it->key_, it->value_); break; case DELETE: log->logDeleteFail(&memberNode->addr, true, it->transID_, it->key_); break; default: //error break; } it = buff.erase(it); } } }