from dht_common import SIZE_OF_HASH, SIZE_OF_IP_ADDRESS, SIZE_OF_KEY, SIZE_OF_SIGNATURE, SIZE_OF_TIMESTAMP from base_node import Base_Node class RCP_Quorum(Base_Node): def __init__(self, quorumID, documentSize, numNodes, numItems=0, table=[]): Base_Node.__init__(self, quorumID, documentSize, numItems, table) self.numNodes = numNodes self.nodeNumRounds = [0 for i in range(self.numNodes)] self.nodeNumMessagesSent = [0 for i in range(self.numNodes)] self.nodeNumMessagesRecv = [0 for i in range(self.numNodes)] self.nodeNumBytesSent = [0 for i in range(self.numNodes)] self.nodeNumBytesRecv = [0 for i in range(self.numNodes)] self.nodeLastNumRounds = [0 for i in range(self.numNodes)] self.nodeLastNumMessagesSent = [0 for i in range(self.numNodes)] self.nodeLastNumMessagesRecv = [0 for i in range(self.numNodes)] self.nodeLastNumBytesSent = [0 for i in range(self.numNodes)] self.nodeLastNumBytesRecv = [0 for i in range(self.numNodes)] def insert(self, numKeys, numSignatures): self.numItems += 1 # Asker's ID sizeOfRequest = SIZE_OF_HASH # timestamp sizeOfRequest += SIZE_OF_TIMESTAMP # keys in request sizeOfRequest += SIZE_OF_KEY * numKeys # signatures in request sizeOfRequest += SIZE_OF_SIGNATURE * numSignatures # actual document sent sizeOfRequest += self.documentSize # signature over whole thing sizeOfRequest += SIZE_OF_SIGNATURE sizeOfResponse = SIZE_OF_HASH + SIZE_OF_SIGNATURE map(lambda x: x+1, self.nodeNumRounds) map(lambda x: x+1, self.nodeNumMessagesSent) map(lambda x: x+1, self.nodeNumMessagesRecv) map(lambda x: x+sizeOfResponse, self.nodeNumBytesSent) map(lambda x: x+sizeOfRequest, self.nodeNumBytesRecv) # This is simulating some extra stuff (signing) so that the correct size is recorded def retrieve(self, whichNode, numKeys, numSignatures): # Asker's ID sizeOfRequest = SIZE_OF_HASH # timestamp sizeOfRequest += SIZE_OF_TIMESTAMP # keys in request sizeOfRequest += SIZE_OF_KEY * numKeys # signatures in request sizeOfRequest += SIZE_OF_SIGNATURE * numSignatures # actual hash requested sizeOfRequest += SIZE_OF_HASH # signature over whole thing sizeOfRequest += SIZE_OF_SIGNATURE sizeOfResponse = self.documentSize + SIZE_OF_SIGNATURE self.nodeNumRounds[whichNode] += 1 self.nodeNumMessagesSent[whichNode] += 1 self.nodeNumMessagesRecv[whichNode] += 1 self.nodeNumBytesSent[whichNode] += sizeOfResponse self.nodeNumBytesRecv[whichNode] += sizeOfRequest def get_finger_table_val(self, whichNode, searchID, numKeys, numSignatures): retval = Base_Node.get_finger_table_val(self, searchID) # key of previous group sizeOfResponse = SIZE_OF_KEY # next groups ID/routing information sizeOfResponse += SIZE_OF_IP_ADDRESS * self.numNodes + SIZE_OF_HASH # key of next group sizeOfResponse += SIZE_OF_KEY # sign the whole thing sizeOfResponse += SIZE_OF_SIGNATURE # Asker's ID sizeOfRequest = SIZE_OF_HASH # timestamp sizeOfRequest += SIZE_OF_TIMESTAMP # Keys in request sizeOfRequest += SIZE_OF_KEY * numKeys # signatures in request sizeOfRequest += SIZE_OF_SIGNATURE * numSignatures # ID being searched for sizeOfRequest += SIZE_OF_HASH self.nodeNumRounds[whichNode] += 1 self.nodeNumMessagesSent[whichNode] += 1 self.nodeNumMessagesRecv[whichNode] += 1 self.nodeNumBytesSent[whichNode] += sizeOfResponse self.nodeNumBytesRecv[whichNode] += sizeOfRequest return retval def get_first_auth(self, whichNode): # Asker's ID sizeOfRequest = SIZE_OF_HASH # timestamp sizeOfRequest += SIZE_OF_TIMESTAMP # response is just the whole thing signed sizeOfResponse = sizeOfRequest + SIZE_OF_SIGNATURE self.nodeNumRounds[whichNode] += 1 self.nodeNumMessagesSent[whichNode] += 1 self.nodeNumMessagesRecv[whichNode] += 1 self.nodeNumBytesSent[whichNode] += sizeOfResponse self.nodeNumBytesRecv[whichNode] += sizeOfRequest return None def get_num_nodes(self): return self.numNodes def get_num_rounds(self, whichNode): self.nodeLastNumRounds[whichNode] = self.nodeNumRounds[whichNode] return self.nodeNumRounds[whichNode] def get_recent_num_rounds(self, whichNode): retval = self.nodeNumRounds[whichNode] - self.nodeLastNumRounds[whichNode] self.nodeLastNumRounds[whichNode] = self.nodeNumRounds[whichNode] return retval def get_num_messages_sent(self, whichNode): self.nodeLastNumMessagesSent[whichNode] = self.nodeNumMessagesSent[whichNode] return self.nodeNumMessagesSent[whichNode] def get_recent_num_messages_sent(self, whichNode): retval = self.nodeNumMessagesSent[whichNode] - self.nodeLastNumMessagesSent[whichNode] self.nodeLastNumMessagesSent[whichNode] = self.nodeNumMessagesSent[whichNode] return retval def get_num_messages_recv(self, whichNode): self.nodeLastNumMessagesRecv[whichNode] = self.nodeNumMessagesRecv[whichNode] return self.nodeNumMessagesRecv[whichNode] def get_recent_num_messages_recv(self, whichNode): retval = self.nodeNumMessagesRecv[whichNode] - self.nodeLastNumMessagesRecv[whichNode] self.nodeLastNumMessagesRecv[whichNode] = self.nodeNumMessagesRecv[whichNode] return retval def get_num_bytes_sent(self, whichNode): self.nodeLastNumBytesSent[whichNode] = self.nodeNumBytesSent[whichNode] return self.nodeNumBytesSent[whichNode] def get_recent_num_bytes_sent(self, whichNode): retval = self.nodeNumBytesSent[whichNode] - self.nodeLastNumBytesSent[whichNode] self.nodeLastNumBytesSent[whichNode] = self.nodeNumBytesSent[whichNode] return retval def get_num_bytes_recv(self, whichNode): self.nodeLastNumBytesRecv[whichNode] = self.nodeNumBytesRecv[whichNode] return self.nodeNumBytesRecv[whichNode] def get_recent_num_bytes_recv(self, whichNode): retval = self.nodeNumBytesRecv[whichNode] - self.nodeLastNumBytesRecv[whichNode] self.nodeLastNumBytesRecv[whichNode] = self.nodeNumBytesRecv[whichNode] return retval # TODO: Add unit tests for size calculations # TODO: Add unit test to make sure finger_table_val is still firing correctly? if __name__ == "__main__": SIZE_OF_DOCUMENTS_IN_TEST = 1024 NUM_NODES_PER_QUORUM_IN_TEST = 10 test = RCP_Quorum(0, SIZE_OF_DOCUMENTS_IN_TEST, NUM_NODES_PER_QUORUM_IN_TEST) randomNode = 0 [test.insert() for x in range(NUM_NODES_PER_QUORUM_IN_TEST)] [test.retrieve(randomNode) for x in range(NUM_NODES_PER_QUORUM_IN_TEST)] print("Insert and retrieval on node 0 fires correctly.") [test.retrieve(x) for x in range(NUM_NODES_PER_QUORUM_IN_TEST)] print("Retrieval fires on all nodes correctly.")