Beispiel #1
0
    def sendAllFiles(self, data) :
        """ Data = [ operation, idPredeccessor, id] """

        idPredeccessor = Bin(data[1].decode())
        id = Bin(data[2].decode())
        idPredeccessor = Bin(idPredeccessor.sumKBit(0))
        l = ['a']

        if idPredeccessor > id:

            self.filesManager.listkeys(idPredeccessor.getHex(), 'F' * (self.k // 4), l)
            self.filesManager.listkeys('0' * (self.k // 4), id.getHex(), l)
        else:
            self.filesManager.listkeys(idPredeccessor.getHex(), id.getHex(), l)
        l = [i.encode() for i in l]
        print("lista" , l)
        self.listen.send_multipart(l)
Beispiel #2
0
class Server:

    context = zmq.Context()
    listen = context.socket(zmq.REP)
    next = context.socket(zmq.REQ)
    

    def __init__(self, id, IPListen, portListen, IPNext, portNext, bootstrap, k = 160):

        self.folder = Folder(id =portListen)
        self.filesManager = Trie()    

        self.IPListen = IPListen
        self.portListen = portListen
        self.IPNext = IPNext
        self.portNext = portNext
        self.k = k

        self.numElements = Bin(hex((2**k)-1)[2:])

        self.id = Bin(id)#aca va entrar la mac, debe crear una funcion que cuadre la mac como sha1
        print("my id:", self.id.getHex())

        self.listen.bind(tcp + self.IPListen + ":" + self.portListen)

        self.idPredecessor = None
        self.idSuccessor = None


        #query of disponible operations in the server's
        self.operation = {"updatePredecessor": self.updatePredecessor, 
                            "idIsInMySuccesor": self.idIsInMySuccesor,
                            "idIsInMyInterval": self.idIsInMyInterval,
                            "getSuccessor": self.getSuccessor,
                            "getServerID": self.getServerID,
                            "changeTheSuccessorInformation": self.changeTheSuccessorInformation,
                            "upload": self.upload,
                            "download": self.download,
                            "existsFileNow": self.existsFileNow,
                            "sendAllFiles": self.sendAllFiles }

        print("Server IP:", self.IPListen + ":" + self.portListen)

        if bootstrap:

            self.bootstrap()
            self.run()
        else :
            
            #self.find()
            self.addServerToChord()
            self.run()


    def idIsInMyInterval(self,data):
        """recive data with id hex wanted, return 1 if the id is in my interval, else return 0"""
        ans = None
        num = Bin(data[1].decode())

        if self.idPredecessor < self.id:

            ans = self.idPredecessor < num <= self.id
        
        else:
            #el id del predecesor es mayor que mi id
            ans = self.idPredecessor < num <= self.numElements or Bin("0") <= num <= self.id

        ans = str(int(ans))
        self.listen.send(ans.encode())


    def idIsInMySuccesor(self, data):
        """
            recive data with id hex wanted, return 1 if the id is in the succesor interval, else return 0
        """
        ans = None
        num = Bin(data[1].decode())
        
        #print("id:", self.id)
        #print("idSuccessor:", self.idSuccessor)
        #print("numero que busco", num)
        if self.idSuccessor > self.id :
            #print("por el if")
            ans = (self.id < num <= self.idSuccessor)

        else :
            #print("por el else")
            ans = (self.id < num <= self.numElements or Bin("0") <= num <= self.idSuccessor) # convertir esto como un string hexadecimal

        ans = str(int(ans))
        self.listen.send(ans.encode())

    def getSuccessor(self, data):

        self.listen.send_multipart([self.IPNext.encode(),self.portNext.encode()])
        #cuando exista finger table hay que hacer un get succesor para cliente como para 
        #servidor, este sera el del servidor

    def bootstrap(self):

        self.next.connect(tcp + self.IPNext + ":" + self.portNext)
        self.next.send_multipart([b"updatePredecessor", self.id.getHex().encode()])

        data = self.listen.recv_multipart()
        self.operation[data[0].decode()](data)

        self.idSuccessor = Bin(self.idPredecessor.getHex())
        
        self.next.recv()

    def updatePredecessor(self, data):
        """the predecessor tell me who is him, his id"""
        
        self.idPredecessor = Bin(data[1].decode())
        print("New Predecessor :", self.idPredecessor)
        self.listen.send(b"OK")
        

    def find(self):

        """find the ip and port of the server that contain my id, i am his new predeccessor"""
        while True:

            ip_port = tcp + self.IPNext + ":" + self.portNext
            print("Search ubication in:", ip_port)

            self.next.connect(ip_port)

            self.next.send_multipart([b"idIsInMySuccesor", self.id.getHex().encode()])#my id is in the next of my next
            ifind = int(self.next.recv().decode())

            self.next.send_multipart([b"getSuccessor"])#i get the ip of the next
            res = self.next.recv_multipart()
                    
            if ifind:
                
                #print(res)
                return (res[0].decode() , res[1].decode())#ip_port for my ubication

            else:
                print("Move to:", res[0].decode() + ":" + res[1].decode())
                self.IPNext = res[0].decode()
                self.portNext = res[1].decode()
                self.next.disconnect(ip_port)

    def getServerID(self, data):
        """return the id server"""

        self.listen.send(self.id.getHex().encode())

    def changeTheSuccessorInformation(self, data):
        
        ip = data[1].decode()
        port = data[2].decode()
        ids = data[3].decode()

        self.next.disconnect(tcp + self.IPNext + ":" + self.portNext)
        self.IPNext = ip
        self.portNext = port
        self.idSuccessor = Bin(ids)
        self.next.connect(tcp + self.IPNext + ":" + self.portNext)

        self.listen.send(b'Update the successor')

    def addServerToChord(self):
        """Add in the middel to two server in the chord
            TODO 
            send all files in the new successor server and me    
        """
        #init the socket listen, that is in the __init__


        ipNewSuccessor, portNewSuccessor = self.find()
        #send to my predecessor my ip, port and id
        self.next.send_multipart([b'changeTheSuccessorInformation', self.IPListen.encode(), self.portListen.encode(), self.id.getHex().encode()])
        print(self.next.recv().decode())

        #get id of my predeccessor
        self.next.send_multipart([b'getServerID'])
        idp = self.next.recv().decode()
        self.next.disconnect(tcp + self.IPNext + ":" + self.portNext)
        print("id new predeccessor:", idp)
        self.idPredecessor = Bin(idp)

        #connect to my successor
        self.IPNext = ipNewSuccessor
        self.portNext = portNewSuccessor
        print("my successor is:", tcp + self.IPNext + ":" + self.portNext)
        self.next.connect(tcp + self.IPNext + ":" + self.portNext)
        self.next.send_multipart([b'getServerID'])
        ids = self.next.recv().decode()
        self.idSuccessor = Bin(ids)

        #tell to successor the id of his new predecessor
        self.next.send_multipart([b"updatePredecessor", self.id.getHex().encode()])
        print("update successor id",self.next.recv())

        #tell to succesor that send me hash of the my files
        msj = [b"sendAllFiles", self.idPredecessor.getHex().encode(), self.id.getHex().encode()]
        self.next.send_multipart(msj)
        filesHash = self.next.recv_multipart()
        filesHash = filesHash[1:]
        
        for fh in filesHash:
            print("Recovery files from another server")
            path = self.folder.getpath(fh.decode())
            msj = [b'download', fh]
            self.next.send_multipart(msj)
            byte = self.next.recv()
            self.filesManager.insert(fh.decode())
            with open(path, 'ab') as f :
                f.write(byte)

        #tell to all servers to update the finger table

    def sendAllFiles(self, data) :
        """ Data = [ operation, idPredeccessor, id] """

        idPredeccessor = Bin(data[1].decode())
        id = Bin(data[2].decode())
        idPredeccessor = Bin(idPredeccessor.sumKBit(0))
        l = ['a']

        if idPredeccessor > id:

            self.filesManager.listkeys(idPredeccessor.getHex(), 'F' * (self.k // 4), l)
            self.filesManager.listkeys('0' * (self.k // 4), id.getHex(), l)
        else:
            self.filesManager.listkeys(idPredeccessor.getHex(), id.getHex(), l)
        l = [i.encode() for i in l]
        print("lista" , l)
        self.listen.send_multipart(l)


    def existsFileNow(self, data):

        shaname = data[1].decode()
        res = self.filesManager.search(shaname)
        if(res):

            self.listen.send(b'1')
        
        else:

            self.listen.send(b'0')

    def upload(self, data):
        """data = [operation, sha, bytestosave] """

        shaname = data[1].decode()

        self.filesManager.insert(shaname)

        path = self.folder.getpath(shaname)
        print("save into server:", path)
        with open(path, "ab") as f:
            f.write(data[2])

        msj = "Chunk saved in " + self.id.getHex()
        self.listen.send(msj.encode())

    def download(self, data):
        """data = [operation, sha] """
        
        shaname = data[1].decode()
        path = self.folder.getpath(shaname)
        print("send form server:", path)

        with open(path, "rb") as f:
            byte = f.read()
            self.listen.send(byte)


    

    def run(self):

        print("Server is running")
        while True:

            msj = self.listen.recv_multipart()
            print(msj[0].decode())
            self.operation[msj[0].decode()](msj)