Example #1
0
    def leave(self, pred_node, succ_node):
        # First update successor of our predecessor
        # create a client for this operation
        client = Simple_Client(self.host, self.port)
        # the insert request is like lookup
        msg = "UPDATE_SUCC|{0}|{1}|{2}".format(
            succ_node.hash, succ_node.host, succ_node.port)
        # the server at succ is contacted, response is the pred node of our
        # node
        response = client.attempt_to_connect(
            pred_node.host, pred_node.port, msg)
        # the server returned the predecessor
        if response == "":
            print("NO INSERT RESPONSE ERROR!")
            exit(0)

        # Next, update predecessor of our successor
        msg = "UPDATE_PRED|{0}|{1}|{2}".format(
            pred_node.hash, pred_node.host, pred_node.port)
        # the server at succ is contacted, response is the pred node of our
        # node
        response = client.attempt_to_connect(
            succ_node.host, succ_node.port, msg)
        # the server returned the successor
        if response == "":
            print("NO INSERT RESPONSE ERROR!")
            exit(0)

        # Okay
        return "OK"
Example #2
0
    def insert(self, hash_code, succ_node):
        # create a client for this operation
        client = Simple_Client(self.host, self.port)
        # the insert request is like lookup
        msg = "INSERT|{0}|{1}|{2}".format(hash_code, self.host, self.port)

        # the server at succ is contacted, response is the pred node of our
        # node
        response = client.attempt_to_connect(
            succ_node.host, succ_node.port, msg)
        # the server returned the predecessor
        if response == "":
            print("NO INSERT RESPONSE ERROR!")
            exit(0)
        # the response should be a string of strings, separated by ':', but
        # there is no type checking, sorry
        # the response contained the pred node after the coord in the network
        # was complete
        pred_hash, pred_host, pred_port_str = response.split(':')
        # pred_port_str was sent as a string and now is converted to an int
        pred_port = int(pred_port_str)
        # we create a remote node for this pred
        pred_node = NetNode(pred_host, (int(pred_port)))
        # then we stop and return the remote node
        return pred_node
Example #3
0
    def insert(self, hash_code, succ_node):
        # create a client for this operation
        client = Simple_Client(self.host, self.port)
        # the insert request is like lookup
        msg = "INSERT|{0}|{1}|{2}".format(hash_code, self.host, self.port)

        # the server at succ is contacted, response is the pred node of our
        # node
        response = client.attempt_to_connect(succ_node.host, succ_node.port,
                                             msg)
        # the server returned the predecessor
        if response == "":
            print("NO INSERT RESPONSE ERROR!")
            exit(0)
        # the response should be a string of strings, separated by ':', but
        # there is no type checking, sorry
        # the response contained the pred node after the coord in the network
        # was complete
        pred_hash, pred_host, pred_port_str = response.split(':')
        # pred_port_str was sent as a string and now is converted to an int
        pred_port = int(pred_port_str)
        # we create a remote node for this pred
        pred_node = NetNode(pred_host, (int(pred_port)))
        # then we stop and return the remote node
        return pred_node
Example #4
0
 def deleteFromNet(self, key):
     # we need a client to talk to the peer head
     client = Simple_Client(self.host, self.port)
     # put a header so the app_support server knows what to do with the data string
     msg = "DELETE|" + key
     # send the data and return
     return client.connect_send__receive_close(self.host, self.port, msg)
Example #5
0
 def locateHash(self, hash):
     # we need a client to talk to the peer head
     client = Simple_Client(self.host, self.port)
     msg = "LOOKUP|" + hash
     # send the data and return
     response = client.connect_send__receive_close(self.host, self.port, msg)
     return response
Example #6
0
    def leave(self, pred_node, succ_node):
        # First update successor of our predecessor
        # create a client for this operation
        client = Simple_Client(self.host, self.port)
        # the insert request is like lookup
        msg = "UPDATE_SUCC|{0}|{1}|{2}".format(succ_node.hash, succ_node.host,
                                               succ_node.port)
        # the server at succ is contacted, response is the pred node of our
        # node
        response = client.attempt_to_connect(pred_node.host, pred_node.port,
                                             msg)
        # the server returned the predecessor
        if response == "":
            print("NO INSERT RESPONSE ERROR!")
            exit(0)

        # Next, update predecessor of our successor
        msg = "UPDATE_PRED|{0}|{1}|{2}".format(pred_node.hash, pred_node.host,
                                               pred_node.port)
        # the server at succ is contacted, response is the pred node of our
        # node
        response = client.attempt_to_connect(succ_node.host, succ_node.port,
                                             msg)
        # the server returned the successor
        if response == "":
            print("NO INSERT RESPONSE ERROR!")
            exit(0)

        # Okay
        return "OK"
Example #7
0
 def findPeer(self):
     # we need a client to talk to the peer head
     client = Simple_Client(self.host, self.port)
     msg = "FIND_PEER|" + self.host
     # send the data and return
     response = client.connect_send__receive_close(self.host, self.port, msg)
     return response
Example #8
0
 def joinNetwork(self):
     # we need a client to talk to the peer head
     client = Simple_Client(self.host, self.port)
     msg = "JOIN_NETWORK|"
     # send the data and return
     response = client.connect_send__receive_close(self.host, self.port, msg)
     return response
Example #9
0
 def DumpPeerData(self):
     # we need a client to talk to the peer head
     client = Simple_Client(self.host, self.port)
     msg = "DUMP_PEER_DATA|"
     # send the data and return
     response = client.connect_send__receive_close(self.host, self.port, msg)
     return response
Example #10
0
 def readFromNet(self, key):
     # we need a client to talk to the peer head
     client = Simple_Client(self.host, self.port)
     # put a header so the app_support server knows what to do with the data
     # string
     msg = "READ_DATA|{0}".format(key)
     # send the data and return
     return client.connect_send__receive_close(self.host, self.port, msg)
Example #11
0
 def writeToNet(self, value):
     # we need a client to talk to the peer head
     client = Simple_Client(self.host, self.port)
     # put a header so the app_support server knows what to do with the data string
     d_item = DataItem(value)
     msg = "WRITE_DATA|" + d_item.key + "|" + d_item.value
     # send the data and return
     client.connect_send__receive_close(self.host, self.port, msg)
     return d_item.key
Example #12
0
 def hasListener(self):
     response = ""
     client = Simple_Client(self.host, self.port)
     try:
         response = client.connect_send__receive_close(self.host, self.port, "PING|")
     except:
         return False
     if response == "OK":
         return True
     return False
Example #13
0
    def getNeighbors(self, mode):
        # we need a client to talk to the peer head
        client = Simple_Client(self.host, self.port)
        if mode == "FULL":
            msg = "GET_NET_STAT|FULL"
        else:
            msg = "GET_NET_STAT|CSV"

        # send the data and return
        return client.connect_send__receive_close(self.host, self.port, msg)
Example #14
0
    def getNeighbors(self, mode):
        # we need a client to talk to the peer head
        client = Simple_Client(self.host, self.port)
        if mode == "FULL":
            msg = "GET_NET_STAT|FULL"
        else:
            msg = "GET_NET_STAT|CSV"

        # send the data and return
        response = client.connect_send__receive_close(self.host, self.port, msg)
        return response
Example #15
0
    def read(self, key, succ_node):
        # create a client for this operation
        client = Simple_Client(self.host, self.port)
        # the insert request is like lookup
        msg = "READ_DATA" + "|" + key + "|" + self.host + "|" + str(self.port)

        # the server at succ is contacted, response is the okay
        response = client.attempt_to_connect(succ_node.host, succ_node.port, msg)
        # the server returned the predecessor
        if response == "":
            return ("NO READ RESPONSE ERROR!")
        if response == " ":
            return None
        return response
Example #16
0
    def read(self, key, succ_node):
        # create a client for this operation
        client = Simple_Client(self.host, self.port)
        # the insert request is like lookup
        msg = "READ_DATA|{0}|{1}|{2}".format(key, self.host, self.port)

        # the server at succ is contacted, response is the okay
        response = client.attempt_to_connect(succ_node.host, succ_node.port,
                                             msg)
        # the server returned the predecessor
        if response == "":
            return ("NO READ RESPONSE ERROR!")
        if response == " ":
            return None
        return response
Example #17
0
    def write(self, key, value, succ_node):
        # create a client for this operation
        client = Simple_Client(self.host, self.port)
        # the insert request is like lookup
        msg = "WRITE_DATA" + "|" + key + "|" + value + "|" + self.host + "|" + str(
            self.port)

        # the server at succ is contacted, response is the okay
        response = client.attempt_to_connect(succ_node.host, succ_node.port,
                                             msg)
        # the server returned the predecessor
        if response == "":
            return ("NO READ RESPONSE ERROR!")
        if response == "OK":
            return True
        return False
Example #18
0
    def write(self, key, value, succ_node):
        # create a client for this operation
        client = Simple_Client(self.host, self.port)
        # the insert request is like lookup
        msg = "WRITE_DATA|{0}|{1}|{2}|{3}".format(
            key, value, self.host, self.port)

        # the server at succ is contacted, response is the okay
        response = client.attempt_to_connect(
            succ_node.host, succ_node.port, msg)
        # the server returned the predecessor
        if response == "":
            return ("NO READ RESPONSE ERROR!")
        if response == "OK":
            return True
        return False
Example #19
0
    def find_peer(self, target_host, min_port, port_range):
        # the concept is to start at a random port, loop around until we get to a host that will respond
        max_port = min_port + port_range      # find the max range
        random_offset = 0 # = random.randint(min_port, self.port) # choose a random port in range
        # create a client for this operation
        client = Simple_Client(self.host, self.port)

        # instruct the client to 'broadcast' and loop through all peer addresses
        response = client.iterative_broadcast(target_host, min_port, random_offset, port_range, "FIND_PEER")
        if response == "":
            return (NetNode("None",0))
        # the response should be a tuple, separated by ':', but there is no type checking, sorry
        r_host, r_port = response.split(':')
        # we create a remote node for this
        r_node = NetNode(r_host, (int(r_port)))
        # then we stop and return the remote node
        return r_node
Example #20
0
    def find_peer(self, target_host, min_port, port_range):
        # the concept is to start at a random port, loop around until we get to a host that will respond
        max_port = min_port + port_range  # find the max range
        random_offset = 0  # = random.randint(min_port, self.port) # choose a random port in range
        # create a client for this operation
        client = Simple_Client(self.host, self.port)

        # instruct the client to 'broadcast' and loop through all peer addresses
        response = client.iterative_broadcast(target_host, min_port,
                                              random_offset, port_range,
                                              "FIND_PEER")
        if response == "":
            return (NetNode("None", 0))
        # the response should be a tuple, separated by ':', but there is no type checking, sorry
        r_host, r_port = response.split(':')
        # we create a remote node for this
        r_node = NetNode(r_host, (int(r_port)))
        # then we stop and return the remote node
        return r_node
Example #21
0
    def lookup(self, hash_code, net_node):
        # create a client for this operation
        client = Simple_Client(self.host, self.port)
        # the lookup request is always the same
        msg = "LOOKUP|{0}|{1}|{2}".format(hash_code, self.host, self.port)

        succ_node = NetNode("None", 0)

        # since this implementation of lookup is iterative, so we need to keep
        # track of the nodes we've queried the last hash inits as the code we
        # are looking for, but is updated as the last node we checked
        last_hash = hash_code
        # our successor's hash inits as the entry node of the lookup
        succ_hash = net_node.hash
        succ_host = net_node.host
        succ_port = net_node.port
        # if the pred and succ hashes ever are equal, it means that the node we
        # are going to check next is the same node as the one we just checked,
        # which means we are done searching
        while not (last_hash == succ_hash):
            # the server at succ is contacted, response is the succ node to the
            # hash
            response = client.attempt_to_connect(succ_host, succ_port, msg)
            # print ("Lookup:" + response)
            # since we just checked succ, we can copy that info to last_hash
            last_hash = succ_hash
            # the response should be a few strings, separated by ':', but there
            # is no type checking, sorry
            if not response == "":
                # the response contained the next node to check, so it is
                # assigned to the current successor
                succ_hash, succ_host, succ_port_str = response.split(':')
                # succ_port_str was sent as a string and now is converted to an
                # int
                succ_port = int(succ_port_str)
            else:
                return("NO LOOKUP RESPONSE ERROR!")

        # we create a remote node for this succ
        succ_node = NetNode(succ_host, (int(succ_port)))
        # the server returned self or its succ, if it returned self, then we
        # will exit the loop and return
        return succ_node
Example #22
0
    def lookup(self, hash_code, net_node):
        # create a client for this operation
        client = Simple_Client(self.host, self.port)
        # the lookup request is always the same
        msg = "LOOKUP|{0}|{1}|{2}".format(hash_code, self.host, self.port)

        succ_node = NetNode("None", 0)

        # since this implementation of lookup is iterative, so we need to keep
        # track of the nodes we've queried the last hash inits as the code we
        # are looking for, but is updated as the last node we checked
        last_hash = hash_code
        # our successor's hash inits as the entry node of the lookup
        succ_hash = net_node.hash
        succ_host = net_node.host
        succ_port = net_node.port
        # if the pred and succ hashes ever are equal, it means that the node we
        # are going to check next is the same node as the one we just checked,
        # which means we are done searching
        while not (last_hash == succ_hash):
            # the server at succ is contacted, response is the succ node to the
            # hash
            response = client.attempt_to_connect(succ_host, succ_port, msg)
            # print ("Lookup:" + response)
            # since we just checked succ, we can copy that info to last_hash
            last_hash = succ_hash
            # the response should be a few strings, separated by ':', but there
            # is no type checking, sorry
            if not response == "":
                # the response contained the next node to check, so it is
                # assigned to the current successor
                succ_hash, succ_host, succ_port_str = response.split(':')
                # succ_port_str was sent as a string and now is converted to an
                # int
                succ_port = int(succ_port_str)
            else:
                return ("NO LOOKUP RESPONSE ERROR!")

        # we create a remote node for this succ
        succ_node = NetNode(succ_host, (int(succ_port)))
        # the server returned self or its succ, if it returned self, then we
        # will exit the loop and return
        return succ_node
Example #23
0
 def networkSize(self):
     # we need a client to talk to the peer head
     client = Simple_Client(self.host, self.port)
     msg = "NETWORK_SIZE|"
     # send the data and return
     return client.connect_send__receive_close(self.host, self.port, msg)
Example #24
0
 def leaveNetwork(self):
     # we need a client to talk to the peer head
     client = Simple_Client(self.host, self.port)
     msg = "LEAVE_NETWORK|"
     # send the data and return
     return client.connect_send__receive_close(self.host, self.port, msg)
Example #25
0
    def performAction(self, msg):
        m = msg.split('|')

        if (m[0] == "FIND_PEER"):
            # return this nodes info, easily done
            return self.host + ":" + str(self.port)

        if (m[0] == "LOOKUP"):
            # lookup()
            code = m[1]  # hash_code being sent as a lookup
            host = m[2]  # host of the requester
            port = int(m[3])  # port of the requester

            mine = self.head.node.hash  # my hashed ID
            succ = self.head.router.succ.hash  # my succ's hashed ID
            pred = self.head.router.pred.hash  # my pred's hashed ID

            # 4 ways that the lookup returns my node (SELF RESPONSES INDICATE Completion)
            # 1: if pred = mine = succ: (one node network)
            if (pred == mine) and (mine == succ):
                # send succ(hash_code) = mine ID back to client
                return "{0}:{1}:{2}".format(mine, self.host, str(self.port))
            # 2: if pred < hash_code and hash_code <= self and pred < self:
            # (no boundary check, if my node is the last, but not the first)
            if (pred < code) and (code <= mine) and (pred < mine):
                # send succ(hash_code) = mine ID back to client
                return "{0}:{1}:{2}".format(mine, self.host, str(self.port))
            # 3: if pred < hash_code and hash_code > self and pred > self:
            # (pred is last node before flip, id first after, hash is before the flip)
            if (pred < code) and (code > mine) and (pred > mine):
                # send succ(hash_code) = mine ID back to client
                return "{0}:{1}:{2}".format(mine, self.host, str(self.port))
            # 4: if pred > hash_code and hash_code <= self and pred > self:
            # (pred is last node before flip, id first after, hash is after the flip)
            if (pred > code) and (code <= mine) and (pred > mine):
                # send succ(hash_code) = mine ID back to client
                return "{0}:{1}:{2}".format(mine, self.host, str(self.port))

            # ALL OTHER CASES Return the successor (which implicitly indicates non completion)
            # Alternate implementations could have server call lookup on successor (recursive)
            # But this implementation returns the succ for the client to do
            # next lookup (iterative)

            return "{0}:{1}:{2}".format(succ, self.head.router.succ.host,
                                        str(self.head.router.succ.port))

        if (m[0] == "INSERT"):
            # insert()
            new_pred_code = m[1]  # hash_code being sent in insert
            new_pred_host = m[2]  # host of the requester
            new_pred_port = int(m[3])  # port of the requester
            # we need to save the old pred info in case we overwrite the object
            old_pred_code = self.head.router.pred.hash
            old_pred_host = self.head.router.pred.host
            old_pred_port = self.head.router.pred.port
            # creating the new predecessor object from the message
            new_pred = NetNode(new_pred_host, new_pred_port)

            # if this is a new network, set all to the new node, return self
            # info
            if ((old_pred_code == self.head.node.hash) and
                    (self.head.router.succ.hash == self.head.node.hash)):
                self.head.router.setPred(new_pred)
                self.head.router.setSucc(new_pred)
                self.head.router.setEntry(new_pred)
                return "{0}:{1}:{2}".format(old_pred_code, old_pred_host,
                                            str(old_pred_port))

            # INSERT is the 1st of 3 messages, the 2nd is sent to the pred
            # we need a temp client for that
            temp_client = Simple_Client(self.host, self.port)
            # craft a message for the old_pred server to update its successor
            # to the new pred
            msg = "UPDATE_SUCC" + "|" + new_pred_code + \
                "|" + new_pred_host + "|" + str(new_pred_port)

            # connect to the current predecessor to update pointer to succ
            response = temp_client.attempt_to_connect(
                old_pred_host, old_pred_port, msg)
            # if the response was "UPDATED_SUCC_OK" then we set the new_pred
            # and return the old one
            if(response == "UPDATED_SUCC_OK"):
                # update the new predecessor
                self.head.router.setPred(new_pred)
                # return info on the old predecessor
                return "{0}:{1}:{2}".format(old_pred_code, old_pred_host,
                                            str(old_pred_port))
            # else:
            return ""

        if (m[0] == "UPDATE_PRED"):
            # update_succ()
            # hash_code being sent in update_pred is that of the new pred
            code = m[1]
            host = m[2]  # host of the new pred
            port = int(m[3])  # port of the new pred
            # creating the new successor object from the message
            new_pred = NetNode(host, port)
            # updating the app_support node
            self.head.router.setPred(new_pred)
            # no error checking yet
            return "UPDATED_PRED_OK"

        if (m[0] == "UPDATE_SUCC"):
            # update_succ()
            # hash_code being sent in update_succ is that of the new succ
            code = m[1]
            host = m[2]  # host of the new succ
            port = int(m[3])  # port of the new succ
            # creating the new successor object from the message
            new_succ = NetNode(host, port)
            # updating the app_support node
            self.head.router.setSucc(new_succ)
            # no error checking yet
            return "UPDATED_SUCC_OK"

        if (m[0] == "WRITE_DATA"):
            # write()
            key = m[1]  # hash_code being sent in write
            value = m[2]
            host = m[3]  # host of the requester
            port = int(m[4])  # port of the requester

            self.head.data.write(key, value)
            return "OK"

            # Implement these handlers
        if (m[0] == "READ_DATA"):
            key = m[1]
            return self.head.data.read(key)

        # not using this, just write("0")
        if (m[0] == "DELETE_DATA"):
            return "{0}{1} Reading Data...".format(self.host, str(self.port))

        return "CMD NOT FOUND"
Example #26
0
    def performAction(self, msg):
        m = msg.split('|')

        if (m[0] == "FIND_PEER"):
            #return this nodes info, easily done
            return self.host + ":" + str(self.port)

        if (m[0] == "LOOKUP"):
            #lookup()
            code = m[1]  #hash_code being sent as a lookup
            host = m[2]  #host of the requester
            port = int(m[3])  #port of the requester

            mine = self.head.node.hash  #my hashed ID
            succ = self.head.router.succ.hash  # my succ's hashed ID
            pred = self.head.router.pred.hash  # my pred's hashed ID

            # 4 ways that the lookup returns my node (SELF RESPONSES INDICATE Completion)
            # 1: if pred = mine = succ: (one node network)
            if (pred == mine) and (mine == succ):
                #send succ(hash_code) = mine ID back to client
                return (mine + ":" + self.host + ":" + str(self.port))
            # 2: if pred < hash_code and hash_code <= self and pred < self:
            # (no boundary check, if my node is the last, but not the first)
            if (pred < code) and (code <= mine) and (pred < mine):
                #send succ(hash_code) = mine ID back to client
                return (mine + ":" + self.host + ":" + str(self.port))
            # 3: if pred < hash_code and hash_code > self and pred > self:
            # (pred is last node before flip, id first after, hash is before the flip)
            if (pred < code) and (code > mine) and (pred > mine):
                #send succ(hash_code) = mine ID back to client
                return (mine + ":" + self.host + ":" + str(self.port))
            # 4: if pred > hash_code and hash_code <= self and pred > self:
            # (pred is last node before flip, id first after, hash is after the flip)
            if (pred > code) and (code <= mine) and (pred > mine):
                #send succ(hash_code) = mine ID back to client
                return (mine + ":" + self.host + ":" + str(self.port))

            # ALL OTHER CASES Return the successor (which implicitly indicates non completion)
            # Alternate implementations could have server call lookup on successor (recursive)
            # But this implementation returns the succ for the client to do next lookup (iterative)

            return (succ + ":" + self.head.router.succ.host + ":" +
                    str(self.head.router.succ.port))

        if (m[0] == "INSERT"):
            #insert()
            code = m[1]  #hash_code being sent in insert
            host = m[2]  #host of the requester
            port = int(m[3])  #port of the requester
            # we need to save the old pred info in case we overwrite the object
            old_pred_code = self.head.router.pred.hash
            old_pred_host = self.head.router.pred.host
            old_pred_port = self.head.router.pred.port
            #creating the new predecessor object from the message
            new_pred = NetNode(host, port)

            #if this is a new network, set all to the new node, return self info
            if ((old_pred_code == self.head.node.hash)
                    and (self.head.router.succ.hash == self.head.node.hash)):
                self.head.router.setPred(new_pred)
                self.head.router.setSucc(new_pred)
                self.head.router.setEntry(new_pred)
                return (old_pred_code + ":" + old_pred_host + ":" +
                        str(old_pred_port))

            #INSERT is the 1st of 3 messages, the 2nd is sent to the pred
            # we need a temp client for that
            temp_client = Simple_Client(self.host, self.port)
            # craft a message for the old_pred server to update its successor to the new pred
            msg = "UPDATE_SUCC" + "|" + code + "|" + host + "|" + str(port)

            # connect to the current predecessor to update pointer to succ
            response = temp_client.attempt_to_connect(old_pred_host,
                                                      old_pred_port, msg)
            # if the response was "UPDATED_SUCC_OK" then we set the new_pred and return the old one
            if (response == "UPDATED_SUCC_OK"):
                # update the new predecessor
                self.head.router.setPred(new_pred)
                # return info on the old predecessor
                return (old_pred_code + ":" + old_pred_host + ":" +
                        str(old_pred_port))
            #else:
            return ""

        if (m[0] == "UPDATE_SUCC"):
            #update_succ()
            code = m[
                1]  #hash_code being sent in update_succ is that of the new succ
            host = m[2]  #host of the new succ
            port = int(m[3])  #port of the new succ
            #creating the new successor object from the message
            new_succ = NetNode(host, port)
            #updating the app_support node
            self.head.router.setSucc(new_succ)
            #no error checking yet
            return "UPDATED_SUCC_OK"

        if (m[0] == "WRITE_DATA"):
            #write()
            key = m[1]  #hash_code being sent in write
            value = m[2]
            host = m[3]  #host of the requester
            port = int(m[4])  #port of the requester

            self.head.data.write(key, value)
            return "OK"

#Implement these handlers
        if (m[0] == "READ_DATA"):
            key = m[1]
            return self.head.data.read(key)

        #not using this, just write("0")
        if (m[0] == "DELETE_DATA"):
            return self.host + str(self.port) + " Reading Data..."

        return "CMD NOT FOUND"