def checker(self): # If item is ready to be delivered go ahead. # And then check if the limbo item can be delivered. # Else add it to the limbo queue # And ask for the missing elements # Lets go! while True: try: item = json.loads(self.q_rcv.get()) except ValueError: logging.debug("JSON Couldn't load the message!") continue else: #print(item) msg_type = item['type'] # reassemble the vc if needed if msg_type == 'DATA_2ALL' or msg_type == 'DATA_P2P' or msg_type == 'recovery': aux = VectorClock(static=True, max_entries=item['vc']['max_entries'], key=item['vc']['key']) aux.vc = item['vc']['vc'] item['vc'] = aux self.d_stats['last_vc_seen'] = item['vc'] if msg_type == 'recovery': self.d_stats['count_recovery'] += 1 self.d_stats['count_received'] += 1 logging.debug("[stats] (R, " + str(item['src_id']) + ", " + str(self.src_id) + ", " + str(item['vc'].vc[item['src_id']]) + ")") # Lets check if message is in the rer_worker waiting list # if its there we remove it and continue as normal. if self.inRER(item): del self.rer[(item['vc'].vc[item['src_id']], item['src_id'])] self.d_stats['tvop'] += 1 # if the message is duplicated, means that it should already be delivered or in limbo if not self.duplicate(item['vc']): # Its ugly but we can check it here. for , A1, A2, A3 cases. if msg_type == 'recovery': logging.debug( "I'm in receovery!( I know... its not funny)") if self.vc.vc[item['src_id']] >= item['vc'].vc[ item['src_id']]: self.d_stats['count_fp'] += 1 if self.vc.happened_before(item['vc']): # item can be delivered. self.vc.inc(item['vc'].key) self.q_deliv.put(item['msg']) #logging.debug("[stats] (D, " + str(item['src_id']) + ", " + str(self.src_id) + ", " + str(item['vc'].vc[item['src_id']]) + ")") if msg_type == 'recovery': # the message has been recovered. with the recovery logging.debug( "[stats] (DR, " + str(item['src_id']) + ", " + str(self.src_id) + ", " + str(item['vc'].vc[item['src_id']]) + ")") else: logging.debug( "[stats] (D, " + str(item['src_id']) + ", " + str(self.src_id) + ", " + str(item['vc'].vc[item['src_id']]) + ")") # Now Check if limbo stuff can be delivered. mark_for_deletion = list() len_i = len(self.l_limbo) for i in range(len_i): item = self.l_limbo[i] if self.vc.happened_before(item['vc']): self.vc.inc(item['vc'].key) self.q_deliv.put(item['msg']) logging.debug( "[stats] (D, " + str(item['src_id']) + ", " + str(self.src_id) + ", " + str(item['vc'].vc[item['src_id']]) + ")") # its been delivered, so leave the limbo #del self.l_limbo[i] mark_for_deletion.append(i) else: # ask again self.check_missing(item) for i in reversed(mark_for_deletion): del self.l_limbo[i] else: #it couldnt be delivered, so add to limbo and ask for missing msgs self.l_limbo.append(item) self.d_stats["count_limbo"] += 1 self.check_missing(item) else: if msg_type == 'recovery': self.d_stats['count_fp'] += 1 elif msg_type == 'DATA_2ALL' or msg_type == 'DATA_P2P': self.d_stats['count_A3'] += 1 # It was a duplicate but... you can check if something can be delivered. # Check in the limbo self.check_limbo() elif msg_type == 'ack': # What do we want to do with ack?? self.d_stats['count_ack'] += 1 elif msg_type == 'missing': # We send what they want. missing_msg = self.log[item['num']] self.snd.recovery(dst_id=item['src_id'], str_msg=missing_msg['msg'], vc=missing_msg['vc']) self.d_stats['count_missing'] += 1 elif msg_type == 'nack': # Something went wrong with the AR. self.d_stats['count_nack'] += 1 elif msg_type == 'debug': print(item['msg']) elif msg_type == 'ack_bj': # We update the membership dict with what was sent. self.d_stats['membership'] = item['msg'] # If dst_id exists but the address has changed, then we are screwed. for dst_id, address in self.d_stats['membership'].items(): if not dst_id == self.src_id: if not dst_id in self.d_stats['ms_conns']: # We have to create the connection to this address. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) sock.connect((address, int(self.d_stats['config'] ['default']['ServerPort']))) self.d_stats['ms_conns'][dst_id] = sock v_fileno = list() v_id = list() for dst_id, conn in self.d_stats['ms_conns'].items(): v_fileno.append(conn.fileno()) v_id.append(dst_id) self.d_stats['ms_fileno'] = v_fileno self.d_stats['ms_fileno_id'] = v_id self.q_rcv.task_done()