def causal(self, cmds): if cmds.request == 1: # write request coming from primary/master newKV = cmds.data.split(" ::: ") if len(newKV) == 2: self.causalDB[newKV[0]] = newKV[1] self.writeTimestamp = max(self.writeTimestamp, cmds.l_Clock) toMaster = build_msg.build(self.ip, cmds.consis, cmds.request, 1, cmds.data, cmds.l_Clock, cmds.rID) self.start_connections( self.master_ip, toMaster.SerializeToString( )) # not even sure master needs to see this elif cmds.request == 2: # read request coming from causalClient if self.writeTimestamp > cmds.ma_Timestamp: # if we have seen the relevant write, we can reply if cmds.data in self.causalDB: toMaster = build_msg.build(self.ip, cmds.consis, cmds.request, 1, self.causalDB[cmds.data], cmds.l_Clock, cmds.rID) else: toMaster = build_msg.build(self.ip, cmds.consis, cmds.request, 0, 'Key not found', cmds.l_Clock, cmds.rID) else: # returning something here would break causal consistency toMaster = build_msg.build(self.ip, cmds.consis, cmds.request, 0, 'Try get request later', cmds.l_Clock, cmds.rID) self.start_connections(self.master_ip, toMaster.SerializeToString())
def eventual(self, cmds): pass toMaster = msg_pb2.Message() if cmds.rID in self.requests.keys(): # Do nothing if replica has already seen request pass else: # Handle set request if cmds.request == 1: newKV = cmds.data.split(" ::: ") if len(newKV) == 2: self.allConsisDB[newKV[0]] = newKV[1] self.eventualDB[newKV[0]] = newKV[1] # If msg from master, # then it is the first replica to see it, and we should send a response if cmds.ip == config.MASTER_IP: toMaster = build_msg.build(self.ip, cmds.consis, cmds.request, cmds.ack, cmds.data, cmds.l_Clock, cmds.rID) # Send to other replicas if for ip in self.replicaRoster: if ip == self.ip: pass else: toReplica = build_msg.build( self.ip, cmds.consis, cmds.request, cmds.ack, cmds.data, cmds.l_Clock, cmds.rID) self.start_connections( ip, toReplica.SerializeToString()) # Add the request to the requests dictionary self.requests[cmds.rID] = cmds.ip else: toMaster = build_msg.build(self.ip, cmds.consis, cmds.request, 0, cmds.data, cmds.l_Clock, cmds.rID) # Handle get request elif cmds.request == 2: if cmds.data in self.eventualDB: pass toMaster = build_msg.build(self.ip, cmds.consis, cmds.request, 1, self.eventualDB[cmds.data], self.l_clock, cmds.rID) else: toMaster = build_msg.build(self.ip, cmds.consis, cmds.request, 0, 'Get Failure', self.l_clock, cmds.rID) # Send off to master self.start_connections(self.master_ip, toMaster.SerializeToString())
def run(self): #override node run method self.lsock.bind((self.ip, config.PORT)) self.lsock.listen() self.node_log.write('listening on' + str((self.ip, config.PORT))) self.lsock.setblocking(False) self.sel.register(self.lsock, selectors.EVENT_READ, data=None) for message in messages: #self.l_clock += 1 print(self.role + ' sent a request!') msg = build_msg.build(self.ip, message[0], message[1], 1, message[2], self.l_clock) self.start_connections(self.master_ip, msg.SerializeToString()) #time.sleep(0.1) print('Client is running') try: while True: events = self.sel.select(timeout=None) for key, mask in events: if key.data is None: self.accept_wrapper(key.fileobj) else: self.service_connection(key, mask) except KeyboardInterrupt: print("caught keyboard interrupt, node exiting") self.node_log.write('Logical clock:' + str(self.l_clock)) self.node_log.output_log() finally: self.sel.close()
def run(self): #override node run method self.lsock.bind((self.ip, config.PORT)) self.lsock.listen() self.node_log.write('listening on' + str((self.ip, config.PORT))) self.lsock.setblocking(False) self.sel.register(self.lsock, selectors.EVENT_READ, data=None) #msg = msg_pb2.Message() msg = build_msg.build(self.ip, 0, 0, 0, 'hey there Im up', self.l_clock) self.node_log.write('\n Data outbound: \n') self.node_log.write(str(msg)) self.start_connections(self.master_ip, msg.SerializeToString()) print('im running!') #print('my l clock is : ' + str(self.l_clock)) try: while True: events = self.sel.select(timeout=None) for key, mask in events: if key.data is None: self.accept_wrapper(key.fileobj) else: self.service_connection(key, mask) except KeyboardInterrupt: print("caught keyboard interrupt, node exiting") self.node_log.write('Logical clock:' + str(self.l_clock)) self.node_log.write('Outstanding requests:' + '\n') for req in self.requests: if (isinstance(self.requests[req], PriorityQueue)): self.node_log.write('\n' + str(req) + ': ' + str(self.requests[req].queue)) else: self.node_log.write('\n' + str(req) + ': ' + str(self.requests[req])) self.node_log.write('processed requests:' + '\n') for req in self.processed_reqs: if (isinstance(self.processed_reqs[req], PriorityQueue)): self.node_log.write('\n' + str(req) + ': ' + str(self.processed_reqs[req].queue)) else: self.node_log.write('\n' + str(req) + ': ' + str(self.processed_reqs[req].queue)) self.node_log.write("\nLinearPQ: " + str(self.linearPQ.queue)) self.node_log.write("\nSeqPQ: " + str(self.seqPQ.queue)) self.node_log.write("\nAll consistencies DB : " + str(self.allConsisDB)) self.node_log.write("Linearized consistency DB : " + str(self.linearDB)) self.node_log.write("Sequential consistency DB : " + str(self.sequentialDB)) self.node_log.write("Causal consistency DB : " + str(self.causalDB)) self.node_log.write("Eventual consistency DB : " + str(self.eventualDB)) self.node_log.output_log() finally: self.sel.close()
def run(self): #override node run method self.lsock.bind((self.ip, config.PORT)) self.lsock.listen() self.node_log.write('listening on' + str((self.ip, config.PORT))) self.lsock.setblocking(False) self.sel.register(self.lsock, selectors.EVENT_READ, data=None) for message in messages: # if read message, calculate minimum acceptable timestamp if message[1] == 2: if message[2] in self.writes: wt = self.writes[message[2]] else: wt = 0 ma_Timestamp = max(wt, self.read_time) msg = build_msg.build(self.ip, 3, message[1], 1, message[2], self.l_clock, ma_Timestamp=ma_Timestamp) else: msg = build_msg.build(self.ip, 3, message[1], 1, message[2], self.l_clock) self.start_connections(self.master_ip, msg.SerializeToString()) #time.sleep(0.1) print('Client is running') try: while True: events = self.sel.select(timeout=None) for key, mask in events: if key.data is None: self.accept_wrapper(key.fileobj) else: self.service_connection(key, mask) except KeyboardInterrupt: print("caught keyboard interrupt, node exiting") self.node_log.write('Logical clock:' + str(self.l_clock)) self.node_log.output_log() finally: self.sel.close()
def tob(self, cmds): msgQ = PriorityQueue() outb = msg_pb2.Message() #check if request is in the dict if (cmds.rID in self.requests.keys()): # this is an acknowledgement message #add to request's msgQ msgQ = self.requests[cmds.rID] msgQ.put((msgQ.queue[0][0] + cmds.l_Clock, cmds)) #update requests dict self.requests[cmds.rID] = msgQ else: #this is a command message #update local requests dict if (cmds.ip == self.master_ip): outb = build_msg.build(self.ip, cmds.consis, cmds.request, 1, cmds.data, self.l_clock, cmds.rID) #msgQ.put((self.l_clock, outb)) self.requests[cmds.rID] = msgQ if (cmds.consis == 1): # add to linearPQ self.linearPQ.put((self.l_clock, cmds.rID, cmds)) else: # add to seq self.seqPQ.put((self.l_clock, cmds.rID, cmds)) self.broadcast(outb) return 0 else: # handle replica message msgQ.put((cmds.l_Clock, cmds)) self.requests[cmds.rID] = msgQ if (cmds.consis == 1): # add to linearPQ self.linearPQ.put((cmds.l_Clock, cmds.rID, cmds)) else: # add to seq self.seqPQ.put((cmds.l_Clock, cmds.rID, cmds)) self.broadcast(cmds)
def broadcast(self, cmds): #logging where we are with our requests ''' for req in self.requests: if(isinstance(self.requests[req], PriorityQueue)): self.node_log.write('\n' + str(req) + ': ' + str(self.requests[req].queue)) else: self.node_log.write('\n' + str(req) + ': ' + str(self.requests[req])) self.node_log.write('processed requests:' + '\n') for req in self.processed_reqs: if(isinstance(self.processed_reqs[req], PriorityQueue)): self.node_log.write('\n' + str(req) + ': ' + str(self.processed_reqs[req].queue)) else: self.node_log.write('\n' + str(req) + ': ' + str(self.processed_reqs[req].queue)) ''' # Check the queues if we have any broadcasting to do # if linear if (cmds.consis == 1): #prevent empty queue if (len(self.linearPQ.queue) == 0): self.node_log.write('**Lin Queue is Empty ****!!!!') return 0 rID = self.linearPQ.queue[0][1] orig_msg = self.linearPQ.queue[0][2] msgQ = self.requests[rID] top_msg = msg_pb2.Message() outb = msg_pb2.Message() #self.node_log.write('\n' + 'message q: \n' + str(msgQ.queue)) for msg in msgQ.queue: if (msg[1].ip == self.ip and len(msgQ.queue) < 3): #we have already sent a message return 0 # are we the originator of the next queued broadcast if (len(msgQ.queue) == 0): outb = build_msg.build(self.ip, orig_msg.consis, orig_msg.request, 1, orig_msg.data, self.linearPQ.queue[0][0], orig_msg.rID) #update msgQ and requests msgQ.put((self.linearPQ.queue[0][0], outb)) self.requests[rID] = msgQ # Broadcast to all for ip in self.replicaRoster: if ip == self.ip: pass else: self.start_connections(ip, outb.SerializeToString()) self.broadcast(cmds) return 0 top_msg = msgQ.queue[0][1] # all acks are in and we are originator if (len(msgQ.queue) == len(self.replicaRoster)): #remove first element self.linearPQ.get() #if set perform operation if (top_msg.request == 1): newKV = top_msg.data.split(" ::: ") if (len(newKV) == 2): self.node_log.write('\n' + 'processing: ' + str(newKV) + '\n') self.allConsisDB[newKV[0]] = newKV[1] self.linearDB[newKV[0]] = newKV[1] outb = build_msg.build(self.ip, 1, 1, 1, 'Set successful', self.l_clock, rID) else: outb = build_msg.build(self.ip, 1, 1, 0, 'Set failure', self.l_clock, rID) else: # perform get if (top_msg.data in self.linearDB): outb = build_msg.build(self.ip, orig_msg.consis, orig_msg.request, 1, self.linearDB[orig_msg.data], self.l_clock, orig_msg.rID) else: outb = build_msg.build(self.ip, orig_msg.consis, orig_msg.request, 0, 'Get Failure', self.l_clock, orig_msg.rID) #if we are originator send to master if (top_msg.ip == self.ip): self.start_connections(self.master_ip, outb.SerializeToString()) #move request to processed_reqs self.processed_reqs[rID] = self.requests.pop(rID) #call broadcast again to check if we need to do anything self.broadcast(cmds) else: #These should all be requests that we are not originators on #check if we need to broadcast ack #if(len(msgQ.queue) == 1): # Broadcast to all for ip in self.replicaRoster: if ip == self.ip: pass else: outb = build_msg.build(self.ip, top_msg.consis, top_msg.request, top_msg.ack, 'acknowledge ' + top_msg.data, self.l_clock, top_msg.rID) #update msg queue and send ack self.start_connections(ip, outb.SerializeToString()) clock = 0 clock = self.l_clock + self.linearPQ.queue[0][0] msgQ.put((clock, outb)) self.requests[rID] = msgQ self.broadcast(cmds) else: #sequential tob if (len(self.seqPQ.queue) == 0): self.node_log.write('**Seq Queue is Empty ****!!!!') return 0 rID = self.seqPQ.queue[0][1] orig_msg = self.seqPQ.queue[0][2] msgQ = self.requests[rID] top_msg = msg_pb2.Message() outb = msg_pb2.Message() if (orig_msg.request == 2): #If the next message in the queue is a get, just do it if (top_msg.data in self.sequentialDB): outb = build_msg.build(self.ip, orig_msg.consis, orig_msg.request, 1, self.sequentialDB[orig_msg.data], self.l_clock, orig_msg.rID) else: outb = build_msg.build(self.ip, orig_msg.consis, orig_msg.request, 0, 'Get Failure', self.l_clock, orig_msg.rID) #Remove from queue, send to master, then broadcast again fillQueue = PriorityQueue() fillQueue.put((rID, orig_msg)) self.seqPQ.get() self.requests.pop(rID) # remove from requests registry self.processed_reqs[rID] = fillQueue self.start_connections(self.master_ip, outb.SerializeToString()) self.broadcast(cmds) else: #self.node_log.write('\n' + 'message q: \n' + str(msgQ.queue)) for msg in msgQ.queue: if (msg[1].ip == self.ip and len(msgQ.queue) < 3): #we have already sent a message return 0 # are we the originator of the next queued broadcast if (len(msgQ.queue) == 0): outb = build_msg.build(self.ip, orig_msg.consis, orig_msg.request, 1, orig_msg.data, self.seqPQ.queue[0][0], orig_msg.rID) #update msgQ and requests msgQ.put((self.seqPQ.queue[0][0], outb)) self.requests[rID] = msgQ # Broadcast to all for ip in self.replicaRoster: if ip == self.ip: pass else: self.start_connections(ip, outb.SerializeToString()) self.broadcast(cmds) return 0 top_msg = msgQ.queue[0][1] # all acks are in and we are originator if (len(msgQ.queue) == len(self.replicaRoster)): #remove first element self.seqPQ.get() #if set perform operation newKV = top_msg.data.split(" ::: ") if (len(newKV) == 2): self.node_log.write('\n' + 'processing: ' + str(newKV) + '\n') self.allConsisDB[newKV[0]] = newKV[1] self.sequentialDB[newKV[0]] = newKV[1] outb = build_msg.build(self.ip, 1, 1, 1, 'Set successful', self.l_clock, rID) else: outb = build_msg.build(self.ip, 1, 1, 0, 'Set failure', self.l_clock, rID) #if we are originator send to master if (top_msg.ip == self.ip): self.start_connections(self.master_ip, outb.SerializeToString()) #move request to processed_reqs self.processed_reqs[rID] = self.requests.pop(rID) #call broadcast again to check if we need to do anything self.broadcast(cmds) else: #These should all be requests that we are not originators on #check if we need to broadcast ack #if(len(msgQ.queue) == 1): # Broadcast to all for ip in self.replicaRoster: if ip == self.ip: pass else: outb = build_msg.build( self.ip, top_msg.consis, top_msg.request, top_msg.ack, 'acknowledge ' + top_msg.data, self.l_clock, top_msg.rID) #update msg queue and send ack self.start_connections(ip, outb.SerializeToString()) clock = 0 clock = self.l_clock + self.seqPQ.queue[0][0] msgQ.put((clock, outb)) self.requests[rID] = msgQ self.broadcast(cmds)
def handle_message(self, cmds): #test message recv_ip = cmds.ip #TODO handle all possible incoming messages ### Handle Client message if recv_ip not in self.replicaRoster: if (cmds.request > 2): # TODO send error message to client 'faulty request' pass elif ( cmds.consis == 3 and cmds.request == 1 ): # causal consistency + write request -> lazy propagation -- send to all replicas self.currentRID += 1 #self.requests[self.currentRID] = (cmds, time.time(), 0, 0) for r in self.replicaRoster: toReplica = build_msg.build(self.ip, cmds.consis, cmds.request, cmds.ack, cmds.data, self.l_clock, self.currentRID) self.start_connections(r, toReplica.SerializeToString()) ## also, send a message back to client. It will update it's clock # self.processed_reqs[cmds.rID] = (curr_req[0], curr_req[1], curr_time, proc_time) toClient = build_msg.build(self.ip, cmds.consis, cmds.request, cmds.ack, cmds.data, self.l_clock, self.currentRID) #self.processed_reqs[cmds.rID] = self.requests.pop(cmds.rID) self.start_connections(cmds.ip, toClient.SerializeToString()) else: self.currentRID += 1 # (rID, [orig_Message, timestamp recv, timestamp processed, total time elapsed]) self.requests[self.currentRID] = (cmds, time.time(), 0, 0) #Message to send to replica toReplica = build_msg.build(self.ip, cmds.consis, cmds.request, cmds.ack, cmds.data, self.l_clock, self.currentRID, cmds.ma_Timestamp) #send to random? replica. self.start_connections( self.replicaRoster[random.randrange( 0, len(self.replicaRoster))], toReplica.SerializeToString()) #time.sleep(0.5) ### Handle Replica message else: if cmds.rID != 0 and cmds.consis == 3 and cmds.request != 1: # if it's a write, we don't need to do anything toClient = build_msg.build(self.ip, cmds.consis, cmds.request, cmds.ack, cmds.data, cmds.l_Clock, cmds.rID) try: client = self.requests[cmds.rID][0].ip self.processed_reqs[cmds.rID] = self.requests.pop(cmds.rID) # calculate current time stats curr_req = self.processed_reqs[cmds.rID] curr_time = time.time() proc_time = curr_time - curr_req[1] #update processed_reqs self.processed_reqs[cmds.rID] = (curr_req[0], curr_req[1], curr_time, proc_time) #finalize request by sending to client #print('sent read confirm to client') self.start_connections(client, toClient.SerializeToString()) except: print("an error occured in causal with cmd : " + str(cmds)) elif cmds.rID != 0 and cmds.consis != 3: if cmds.ack == 1: #Answer a successful request to client toClient = build_msg.build(self.ip, cmds.consis, cmds.request, cmds.ack, cmds.data, self.l_clock, cmds.rID) elif cmds.ack == 0: #Answer failure of Request to client pass toClient = build_msg.build(self.ip, cmds.consis, cmds.request, cmds.ack, 'REQUEST FAILURE', self.l_clock, cmds.rID) try: client = self.requests[cmds.rID][0].ip self.processed_reqs[cmds.rID] = self.requests.pop(cmds.rID) # calculate current time stats curr_req = self.processed_reqs[cmds.rID] curr_time = time.time() proc_time = curr_time - curr_req[1] #update processed_reqs self.processed_reqs[cmds.rID] = (curr_req[0], curr_req[1], curr_time, proc_time) #finalize request by sending to client self.start_connections(client, toClient.SerializeToString()) except: print("an error occured with cmd : " + str(cmds))