def compute_cpe_and_data(self, message, side_join): """Compute the CPE of the joining node.""" ln = self.__local_node side_local = Direction.get_opposite(side_join) # Create the CPE. data_store = ln.data_store [cut_dimension, cut_value, data_left, data_right] = data_store.get_partition_value(ln.cpe) # Create the CPE for the joining node. join_node = InternalNode(side_join, cut_dimension, cut_value) join_cpe = copy.deepcopy(ln.cpe) join_cpe.add_node(join_node) # Create the CPE for the local node. local_node = InternalNode(side_local, cut_dimension, cut_value) local_cpe = copy.deepcopy(ln.cpe) local_cpe.add_node(local_node) print("NEW CPE:: ", local_cpe) # Split the data. if (side_join == Direction.LEFT): join_value = data_left local_value = data_right else: assert side_join == Direction.RIGHT join_value = data_right local_value = data_left return join_cpe, join_value, local_cpe, local_value
def compute_cpe_and_data(self, message, side_join): """Compute the CPE of the joining node.""" ln=self.__local_node side_local = Direction.get_opposite(side_join) # Create the CPE. data_store = ln.data_store [cut_dimension, cut_value, data_left, data_right] = data_store.get_partition_value(ln.cpe) # Create the CPE for the joining node. join_node = InternalNode(side_join, cut_dimension, cut_value) join_cpe = copy.deepcopy(ln.cpe) join_cpe.add_node(join_node) # Create the CPE for the local node. local_node = InternalNode(side_local, cut_dimension, cut_value) local_cpe = copy.deepcopy(ln.cpe) local_cpe.add_node(local_node) print("NEW CPE:: ", local_cpe) # Split the data. if(side_join == Direction.LEFT): join_value = data_left local_value = data_right else: assert side_join == Direction.RIGHT join_value = data_right local_value = data_left return join_cpe, join_value, local_cpe, local_value
def which_side_space(self, space_part, forking=False): """ Indicates to which side of the node belongs the 'space_part'. 'Left' means one of the internal nodes would have to be followed to the left instead so that the desired part is reached. """ nb_here = 0 here, left, right = False, False, False for inode in self.__internal_nodes: if(not space_part.exists(inode.dimension)): if (not forking): raise CPEMissingDimension( "Mandatory dimension %s isn't defined in %s"% (repr(inode.dimension),repr(space_part)), inode.dimension) else: # no clue, a split is required. # - here? is still undefined: further inodes could invalidate it. # - left? or right? will be set depending on our own direction # on the offending inode. (l,r) = Direction.get_directions(Direction.get_opposite(inode.direction)) left |=l ; right |=r nb_here+=1 else: try: m_range = space_part.get_component(inode.dimension) if(inode.is_here(m_range)): nb_here += 1 left |= inode.is_more_on_the_left(m_range) right |= inode.is_more_on_the_right(m_range) else: # The range is managed by the opposite side. @test1171706 # 0_0 opposite_side = Direction.get_opposite(inode.dimension.direction) opposite_side = Direction.get_opposite(inode.direction) left |= (opposite_side == Direction.LEFT) right |= (opposite_side == Direction.RIGHT) break # you need all the dimensions to say 'it's here' so that it's actually here. except: raise ValueError("Component %s of %s is of unknown type: %s"%( repr(inode.dimension),repr(space_part),repr(m_range))) here |= (nb_here == len(self.__internal_nodes)) assert True == left | here | right, "The request coudn't be oriented." return [left, here, right]
def test_bare_bones(self): left, right = Direction.get_directions(Direction.LEFT) assert left, "Direction.get_directions(Direction.LEFT)" assert not right, "Direction.get_directions(Direction.LEFT)" left, right = Direction.get_directions(Direction.RIGHT) assert not left, "Direction.get_directions(R)" assert right, "Direction.get_directions(R)" assert Direction.get_opposite(Direction.LEFT) == Direction.RIGHT assert Direction.get_opposite(Direction.RIGHT) == Direction.LEFT assert RouterReflect.check_position_partition_tree( Direction.LEFT,None,.2,.7), "isn't it on the left ?" assert RouterReflect.check_position_partition_tree( Direction.RIGHT,None,.7,.2), "isn't it on the right ?" print("#0 : directions tests passed") return True
def test_bare_bones(self): left, right = Direction.get_directions(Direction.LEFT) assert left, "Direction.get_directions(Direction.LEFT)" assert not right, "Direction.get_directions(Direction.LEFT)" left, right = Direction.get_directions(Direction.RIGHT) assert not left, "Direction.get_directions(R)" assert right, "Direction.get_directions(R)" assert Direction.get_opposite(Direction.LEFT) == Direction.RIGHT assert Direction.get_opposite(Direction.RIGHT) == Direction.LEFT assert RouterReflect.check_position_partition_tree( Direction.LEFT, None, .2, .7), "isn't it on the left ?" assert RouterReflect.check_position_partition_tree( Direction.RIGHT, None, .7, .2), "isn't it on the right ?" print("#0 : directions tests passed") return True
def test_ring(self): j=0 nd=[] for n,i in (("g3",45),("jt",71),("na",53),("se",42),("sw",59),("xk",19)): nd+=[self.createNode(n,"127.0.0.1%i"%j)] nd[j].numeric_id=i j=j+1 import copy from equation import InternalNode from util import Direction import pdb; pdb.set_trace() cut_dim=("a","b","a","x","c") cut_val=("girl","soft","cute","c","face") from localevent import Router for i in (1, 0, 4, 2): nb = nd[3].neighbourhood side=Router.by_name_get_direction(nd[3].name_id,nd[i].name_id) nextn = nb.get_neighbour(side,0) othern= nb.get_neighbour(not side,0) wrapf = nb.can_wrap(side) wrapb = nb.can_wrap(not side) assert( NodeID.lies_between_direction(side,nd[3].name_id,nd[i].name_id,nextn.name_id,wrapf) or NodeID.lies_between_direction(not side,nd[3].name_id,nd[i].name_id,othern.name_id,wrapb) ) if (not NodeID.lies_between_direction(side,nd[3].name_id,nd[i].name_id,nextn.name_id, wrapf)): print("need to reverse side %s-%s-%s!"%(nd[3].name_id,nd[i].name_id,nextn.name_id)) side=not side nextn=othern print("next on %s is %s"%("LEFT" if side else "RIGHT",repr(nextn))) nb.add_neighbour(0,nd[i]) if (nd[i].numeric_id>=32): nb.add_neighbour(1,nd[i]) if (nd[i].numeric_id<48): nb.add_neighbour(2,nd[i]) if (nd[i].numeric_id>40): nb.add_neighbour(3,nd[i]) if (nd[i].numeric_id<44): nb.add_neighbour(4,nd[i]) if (nd[i].numeric_id>=42): nb.add_neighbour(5,nd[i]) new_side_join = side new_side_local= Direction.get_opposite(new_side_join) njnode=InternalNode(new_side_join,cut_dim[i],cut_val[i]) njcpe =copy.deepcopy(nd[3].cpe) njcpe.add_node(njnode) print("%s gets CPE %s"%(nd[i].pname,njcpe)) nlnode=InternalNode(new_side_local,cut_dim[i],cut_val[i]) nlcpe =copy.deepcopy(nd[3].cpe) nlcpe.add_node(nlnode) print("%s gets CPE %s"%(nd[3].pname,nlcpe)) nd[i].cpe=njcpe nd[3].cpe=nlcpe
def test_ring(self): j = 0 nd = [] for n, i in (("g3", 45), ("jt", 71), ("na", 53), ("se", 42), ("sw", 59), ("xk", 19)): nd += [self.createNode(n, "127.0.0.1%i" % j)] nd[j].numeric_id = i j = j + 1 import copy from equation import InternalNode from util import Direction import pdb pdb.set_trace() cut_dim = ("a", "b", "a", "x", "c") cut_val = ("girl", "soft", "cute", "c", "face") from localevent import Router for i in (1, 0, 4, 2): nb = nd[3].neighbourhood side = Router.by_name_get_direction(nd[3].name_id, nd[i].name_id) nextn = nb.get_neighbour(side, 0) othern = nb.get_neighbour(not side, 0) wrapf = nb.can_wrap(side) wrapb = nb.can_wrap(not side) assert (NodeID.lies_between_direction( side, nd[3].name_id, nd[i].name_id, nextn.name_id, wrapf) or NodeID.lies_between_direction( not side, nd[3].name_id, nd[i].name_id, othern.name_id, wrapb)) if (not NodeID.lies_between_direction( side, nd[3].name_id, nd[i].name_id, nextn.name_id, wrapf)): print("need to reverse side %s-%s-%s!" % (nd[3].name_id, nd[i].name_id, nextn.name_id)) side = not side nextn = othern print("next on %s is %s" % ("LEFT" if side else "RIGHT", repr(nextn))) nb.add_neighbour(0, nd[i]) if (nd[i].numeric_id >= 32): nb.add_neighbour(1, nd[i]) if (nd[i].numeric_id < 48): nb.add_neighbour(2, nd[i]) if (nd[i].numeric_id > 40): nb.add_neighbour(3, nd[i]) if (nd[i].numeric_id < 44): nb.add_neighbour(4, nd[i]) if (nd[i].numeric_id >= 42): nb.add_neighbour(5, nd[i]) new_side_join = side new_side_local = Direction.get_opposite(new_side_join) njnode = InternalNode(new_side_join, cut_dim[i], cut_val[i]) njcpe = copy.deepcopy(nd[3].cpe) njcpe.add_node(njnode) print("%s gets CPE %s" % (nd[i].pname, njcpe)) nlnode = InternalNode(new_side_local, cut_dim[i], cut_val[i]) nlcpe = copy.deepcopy(nd[3].cpe) nlcpe.add_node(nlnode) print("%s gets CPE %s" % (nd[3].pname, nlcpe)) nd[i].cpe = njcpe nd[3].cpe = nlcpe
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