Exemplo n.º 1
0
    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()