Exemple #1
0
    def visit_SNLeaveRequest(self, message):
        LOGGER.log(logging.DEBUG, "[DGB] SNLeaveRequest - Process")
        payload_msg = SNLeaveReply(self, self.__local_node)
        route_msg = RouteDirect(payload_msg, message.leaving_node)
        self.__local_node.route_internal(route_msg)

        self.__local_node.neighbourhood.remove_neighbour(message.leaving_node)
Exemple #2
0
    def visit_STJoinReply(self, message):
        ## running on the newborn node, if the welcoming node can welcome us.
        print("0_0 visit_STJoinReply, phase=", str(message.phase))
        if (self.debugging & 2):
            import pdb
            pdb.set_trace()

        if (message.phase == STJoinReply.STATE_PROPOSE):
            self.__local_node.sign("join proposition received " +
                                   str(message.contact_node))
            if (self.is_busy(message)):
                # The local node is already busy with another joining node.
                join_error = STJoinError(
                    message,
                    "Contacted node already busy with a join activity")
                self.__local_node.sign("joining and busy!?")
                route_msg = RouteDirect(join_error, message.joining_node)
                self.__local_node.route_internal(route_msg)

            else:
                self.set_busy(message)
                print("0_0 adding data in the local store ...")
                self.__local_node.sign("inserting into local store")
                # Set data received from contact node.
                self.__local_node.partition_id = message.partition_id
                self.__local_node.cpe = message.cpe
                for data in message.data:
                    self.__local_node.data_store.add(data[0], data[1])
                # Send a reply to the contact node.
                self.__join_msg = STJoinRequest(self.__local_node,
                                                STJoinRequest.STATE_ACCEPT)
                self.__local_node.sign("accepting proposition")
                route_msg = RouteDirect(self.__join_msg, message.contact_node)
                self.__local_node.route_internal(route_msg)

        elif (message.phase == STJoinReply.STATE_CONFIRM):
            self.set_busy(False)
            print("0_0 connected, hopefully.")
            self.__local_node.status = "connected through " + str(
                message.contact_node)

        else:
            join_error = STJoinError(message, "Unrecognized join request.")

            route_msg = RouteDirect(join_error, message.joining_node)
            self.__local_node.route_internal(route_msg)
Exemple #3
0
    def ping_half_ring(node, half_ring, ring_level):
        """Send ping to all neighbours (telling them this node is alive)."""
        neighbours = half_ring.get_neighbours()
        for neighbour in neighbours:
            LOGGER.debug("[DBG] Send a Ping to: " + neighbour.__repr__())

            payload_msg = SNPingMessage(node, ring_level)
            route_msg = RouteDirect(payload_msg, neighbour)
            node.route_internal(route_msg)
Exemple #4
0
 def lookupData(self, message):
     """ expect message ISA LookupRequest """
     print(message, " has reached ", self.__local_node)
     if (self.debugging):
         import pdb
         pdb.set_trace()
     values = self.__local_node.data_store.get(message.key)
     reply = LookupReply(values, message.nonce)
     reply.trace = message.trace
     reply.trace.append("reading data at %s" % self.__local_node.pname)
     route = RouteDirect(reply, message.originator)
     self.__local_node.route_internal(route)
Exemple #5
0
    def _arrived_at_nearest_node(self, message):
        """Process a JoinRequest arrived at the nearest node."""
        assert message.state == SNJoinRequest.ROUTING

        # The nearest node's neighbour contains new neighbours for joining node.
        neighbours = self.__local_node.neighbourhood.get_ring(
            0).get_all_unique_neighbours()

        # Send a reply to the joining node.
        payload_msg = SNJoinReply(message, neighbours)
        route_msg = RouteDirect(payload_msg, message.joining_node)
        self.__local_node.route_internal(route_msg)
Exemple #6
0
    def compute_partition_id(self, message, side_join, next_node):
        ln = self.__local_node
        partition_id = 0
        if (next_node != ln and next_node.cpe.k == 0):
            ln.sign("%s isn't ready to welcome a new node" % next_node.pname)
            next_node.queue(RouteDirect(message, ln))
            request = RouteDirect(SNPingRequest(ln, 0), next_node)
            ln.route_internal(request)
            raise RoutingDeferred("compute_partition_id")

        # we need to cancel cross-wrap generation of partitionID so that the
        # rightmost node on the tree is the one with highest PID, leftmost node
        # is the one with lowest PID and PID monotonously increases in-between.
        if next_node.partition_id < ln.partition_id and side_join == Direction.RIGHT:
            ln.sign("RIGHT wrap detected with %s" % next_node.pname)
            next_node = ln
        if next_node.partition_id > ln.partition_id and side_join == Direction.LEFT:
            ln.sign("LEFT wrap detected with %s" % next_node.pname)
            next_node = ln

        if (next_node != ln):
            ln.sign("computing partition for joining node %f<?<%f" %
                    (ln.partition_id, next_node.partition_id))
            partition_id = PartitionID.gen_btw(ln.partition_id,
                                               next_node.partition_id)
        else:
            assert next_node == ln
            if (side_join == Direction.RIGHT):
                ln.sign("computing partition for joining node %f<?" %
                        (ln.partition_id))
                partition_id = PartitionID.gen_aft(ln.partition_id)
            else:
                assert side_join == Direction.LEFT
                ln.sign("computing partition for joining ?<%f" %
                        ln.partition_id)
                partition_id = PartitionID.gen_bef(ln.partition_id)

        assert partition_id != ln.partition_id and partition_id != next_node.partition_id
        return partition_id
Exemple #7
0
    def visit_SNJoinReply(self, message):
        ln = self.__local_node
        ng = ln.neighbourhood

        LOGGER.log(logging.DEBUG, "[DBG] SNJoinReply - Process")
        if (self.debugging & 4):
            import pdb
            pdb.set_trace()

        ng.sign("repair(%s)" % repr(message))
        NeighbourhoodNet.repair_level(ln, ng, 0, message.neightbours)

        # The contact node for SkipTree is the left or right neighbour.
        node_left = ng.get_neighbour(Direction.LEFT, 0)
        node_right = ng.get_neighbour(Direction.RIGHT, 0)

        psl = ln.name_id.get_longest_prefix_length(node_left.name_id)
        psr = ln.name_id.get_longest_prefix_length(node_right.name_id)
        # Launch the SkipTree joining.
        payload_msg = STJoinRequest(ln, STJoinRequest.STATE_ASK)
        payload_msg.sign(
            "%s joint SN. Candidates for ST are %s:%f or %s:%f" %
            (ln.name_id, node_left.name_id, psl, node_right.name_id, psr))

        # decide which neighbour we will join.
        print("0_0 %s@%f -vs- %s@%f" % (node_left, psl, node_right, psr))
        contact_node = node_left
        if (ng.can_wrap(Direction.LEFT)):
            contact_node = node_right
        elif (psl < psr and not ng.can_wrap(Direction.RIGHT)):
            contact_node = node_right
        ln.sign("joint the skipnet")
        payload_msg.sign("prefered %s" % contact_node.name_id)
        print("0_0 joining the skiptree : %s->%s", ln.name_id,
              contact_node.name_id)
        route_msg = RouteDirect(payload_msg, contact_node)
        ln.route_internal(route_msg)
Exemple #8
0
    def by_cpe_get_next_hop_forking(self, lnode, message):
        self.__lastcall = ['bycpe+f']
        dest = []
        left, here, right = lnode.cpe.which_side_space(message.space_part,
                                                       True)
        if (here):
            # NOTE: it cannot be 'naked' message, but must be a clone with
            #   search range that has been 'constraint' to stick here.
            newmsg = copy.copy(message)
            newmsg.trace = copy.copy(message.trace)
            newmsg.limit = PidRange(lnode.partition_id, lnode.partition_id)
            dest.append((lnode, newmsg))

        # create 'directions', that identifies sub-rings to be scanned
        #   and the sub-range of PartitionID that should be taken into account.

        message.sign(
            "routing %s%s with %s" %
            ('L' if left else '', 'R' if right else '', repr(message.limit)))

        directions = list()
        if (left):
            r = message.limit.restrict(Direction.RIGHT, lnode.partition_id)
            directions.append((Direction.LEFT, r, 'L'))

        if (right):
            r = message.limit.restrict(Direction.LEFT, lnode.partition_id)
            directions.append((Direction.RIGHT, r, 'R'))

        self.__lastcall.append("scanning rings @%s: %s" %
                               (lnode.partition_id, repr(directions)))
        part = message.space_part
        neighbourhood = lnode.neighbourhood
        lastpid, lastngh = None, None

        # (point) routing guideline:
        #   for a message that must be sent in direction D, we look for
        #   the farthest neighbour that would not reverse the travelling
        #   direction.

        # (range) routing guideline:
        #   you send a copy to N[i] if region between N[i] and N[i+1] inter-
        #   sects the region you're searching for.

        for dirx, prange, pd in directions:
            for height in range(neighbourhood.nb_ring - 1, -1, -1):
                if height > 0 and neighbourhood.size(dirx, height) < 2:
                    continue  # this ring is empty or has a single node.
                ngh = neighbourhood.get_neighbour(dirx, height)
                pid = ngh.partition_id
                if lastngh != None and ngh.name_id == lastngh.name_id:
                    continue  # we just checked this neighbour
                lastngh = ngh
                self.__lastcall.append("%s (%i, %s)" %
                                       (ngh.pname, height, repr(dirx)))
                if (ngh.cpe.k == 0):
                    ngh.queue(message)
                    reply = RouteDirect(SNPingRequest(lnode, height), ngh)
                    self.__lastcall.append(
                        "requesting routing table complement at %s" % ngh)
                    return [(ngh, reply)]
                    # todo: rate-limit to avoid redundant PING requests.

                epid = prange.includes_pid(
                    pid)  # effective pid = pid+{-1,0,+1}
                if (epid != None):
                    left, here, right = ngh.cpe.which_side_space(part, True)
                    if (here or RouterReflect.__goes_forward(
                            dirx, left, right)):
                        self.__lastcall.append(
                            "%s is %s compared to %s" %
                            (part, 'here' if here else 'forw', repr(ngh.cpe)))
                        newmsg = copy.copy(message)
                        newmsg.sign("routed to %s at h=%i" %
                                    (ngh.pname, height))
                        newmsg.limit = prange.restrict(
                            Direction.get_opposite(dirx), epid)
                        dest.append((ngh, newmsg))
                    else:
                        self.__lastcall.append(
                            "ignored w/ %s, %s, %s - %s" %
                            (repr(left), repr(here), repr(right),
                             'L' if dirx == Direction.LEFT else 'R'))
                    lastpid = pid
                    prange = prange.restrict(dirx, epid)
                    # ^ messages that will be generated after this one will not be allowed
                    #   to forward beyond the 'current position'.
                    if (not RouterReflect.__goes_backward(dirx, left, right)):
                        break
                else:
                    self.__lastcall.append("%f out of partition range %s" %
                                           (pid, repr(prange)))
#        print("0_0 %s : %i"%(repr(message),len(dest)))
# ^it's a bad idea to do a per-message report to the MCP. Use your
#  'personal log' for that. Otherwise, you're forcing the MCP to do
#  a poll with period approaching msg_rate x buffer_size or your
#  own node will stall, waiting for room to appear in STDOUT buffer.
        return dest
Exemple #9
0
 def visit_IdentityRequest(self, message):
     find_neighbour = IdentityReply(self.__local_node)
     route_msg = RouteDirect(find_neighbour, message.contact_node)
     self.__local_node.route_internal(route_msg)
Exemple #10
0
 def visit_SNPingRequest(self, message):
     reply = SNPingMessage(self.__local_node, message.ring_level)
     reply = RouteDirect(reply, message.source)
     LOGGER.debug("[DBG] %s -> %s" % (message, reply))
     self.__local_node.route_internal(reply)
Exemple #11
0
    def visit_STJoinRequest(self, message):
        # runs in the welcoming node, upon Join Request message.
        print("0_0 visit_STJoinRequest, phase=", str(message.phase))
        if (self.debugging & 1):
            import pdb
            pdb.set_trace()
        ln = self.__local_node

        if (message.phase == STJoinRequest.STATE_ASK):
            # A new node would like to join the network.

            if (self.is_busy(message)):
                # The local node is already busy with another joining node.
                join_error = STJoinError(
                    message,
                    "Contacted node already busy with a join activity")
                ln.sign("sending error message " + join_error)
                route_msg = RouteDirect(join_error, message.joining_node)
                ln.route_internal(route_msg)

            else:
                # Compute a proposition for the joining node and sent it.
                self.set_busy(message)
                ln.status = "welcoming %s" % repr(message.joining_node.name_id)

                join_side, next_node = self.decide_side_join(message)
                ln.sign("next on %s is %s" %
                        ("LEFT" if join_side else "RIGHT", repr(next_node)))

                join_partition_id = self.compute_partition_id(
                    message, join_side, next_node)
                ln.sign("assigned pid=%f" % join_partition_id)

                join_cpe, join_data, self.__new_local_cpe, self.__new_local_data =\
                          self.compute_cpe_and_data(message,join_side)

                jm = self.__join_msg = STJoinReply(ln,
                                                   STJoinReply.STATE_PROPOSE)
                jm.partition_id = join_partition_id
                jm.cpe = join_cpe
                jm.data = join_data

                route_msg = RouteDirect(jm, message.joining_node)
                ln.sign("sending joinreply (ask phase)")
                # this message is likely to be large. [network::]OutRequestManager
                #  may have a hard time transmitting this.
                ln.route_internal(route_msg)
                ln.sign("sent joinreply (ask phase)")

        elif (message.phase == STJoinRequest.STATE_ACCEPT):
            # blindly setup what the other node's compute_data_and_cpe has defined.
            ln.sign("Update the local node data")
            ln.cpe = self.__new_local_cpe
            ln.data_store = DataStore(self.__new_local_data)

            print("0_0 Data Split accepted")
            local_node_status = ln.status_updater

            ln.sign("'repairing' the neighbourhood table")
            local_node_status.update_status_now()
            self.set_busy(False)
            print("0_0 -- Join process completed. --")

            self.__join_msg = STJoinReply(ln, STJoinReply.STATE_CONFIRM)
            route_msg = RouteDirect(self.__join_msg, message.joining_node)
            ln.sign("sending confirmation message")
            ln.route_internal(route_msg)

        else:
            join_error = STJoinError(message, "Unrecognized join request.")
            ln.sign("sending error message " + join_error)
            route_msg = RouteDirect(join_error, message.joining_node)
            ln.route_internal(route_msg)