// 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);
}
示例#2
0
/**
 * 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);
		}
	}
}