def process(self,data):
        global fs
        
        print "Client wants to know about %s" % data.path
        

        file = self.fs.get_file(path=data.path)

        
        #if there is no such file tell the client so
        if not file:
            self.net.write(self.pb.build(packet_types.FS_ERR_PATH_NOT_FOUND, data))
            return None

        data = packet_builder.Data(params={'oid':file.oid,'path':file.path,'num_blocks':len(file.blocks),'version':file.version,'size':file.size,'file_type':file.type,'parent':file.parent,'block_size':file.block_size})        
    
        if file.type == 0:
            children = []
            
            for child in self.fs.get_children(file.oid):
                    data_child = packet_builder.Data(params={'oid':child.oid,'path':child.path,'num_blocks':len(child.blocks),'version':child.version,'size':child.size,'file_type':child.type,'parent':child.parent,'block_size':child.block_size})                    
                    children.append(data_child)
            
            data.children = children
        
        #print data
        self.net.write(self.pb.build(packet_types.FS_FILE_INFO, data))
    def process(self,data):
        global fs
        #client wants a file
        print "Client wants to delete %s" % (data.path)
        

        file = self.fs.get_file(path=data.path)

        
        #if there is no such file tell the client so
        if not file:
            data = packet_builder.Data()
            self.net.write(self.pb.build(packet_types.FS_ERR_PATH_NOT_FOUND, data))
            return None
            
        #get current replicas of this file

        reps = self.fs.get_replicas(file.oid)

        
        #if the file is currently in use, tell the client so
        file_has_locks = self.app.serverList.file_has_locks(file.oid)
        
        if not file_has_locks:
            data = packet_builder.Data(params={'oid':file.oid,'version':file.version})
            self.net.write(self.pb.build(packet_types.FS_ERR_LOCK_DENIED,data))
            return None
        
        #delete everything we have on that file

        self.fs.delete_file(file.oid)


        #tell the client the file is gone
        
        data = packet_builder.Data(params={'oid':file.oid})
        self.net.write(self.pb.build(packet_types.FS_DELETE_DONE,data))
        self.net.close()


        if reps:
            #get a list of ip & ports of online servers that have such replica
            servers = map(self.app.serverList.get_server, reps.replicas.keys())
            
            for server in servers:
                try:
                    
                    print "Trying %s..." % str(server)
                    
                    out = network_services.NetworkTransport()
                    out.open(server[0],server[1])
                    out.write(self.pb.build(packet_types.FS_DELETE_OID,data))
                    out.close()
                except Exception,e:
                    print e
    def process(self, data):
        data = self.pb.extract_stream(self.fp)
        #if we are done then don't process any more incoming sync packets
        if data.type == packet_types.CHK_DONE:
            print "Sync done"
            return None
    
        oid = data.oid
        block_id = data.block_id

        block = self.fs.get_block(oid,block_id)

        #if the block has been deleted, tell the data server to delete the block too
        if not block:
            print "Block deleted"
            data = packet_builder.Data(params={'oid':oid,'block_id':block_id})
            try:
                out = network_services.NetworkTransport()
                out.open(self.serverip,self.serverport)
                out.write(self.pb.build(packet_types.FS_DELETE_BLOCK,data))
                out.close()
                
            except Exception,e:
                print e


                self.app.serverList.remove_address(self.serverip,self.serverport)
                return None
Exemple #4
0
    def replicate_block(self,
                        oid,
                        block_id,
                        version,
                        original_serverid,
                        force=False):

        block = self.fs_db.get_block(oid, block_id)
        reps = self.fs_db.get_block_replicas(oid, block_id)

        #make sure the block we are replicating is the most current version
        if block.version != version:
            print "This version has expired! (%s) %s" % (version, block)
            return

        #replicate the file
        done = False

        while 1:
            if len(reps.replicas.keys()) > self.cfg.REPLICAS and not force:
                return None

            #see if we need to do any more replicas
            rep = self.serverList.select_new_replica_server(reps.replicas)
            server = self.serverList.get_server(original_serverid)

            if rep:
                #            print "REPLICATE FILE: server: %s replica %s" % (server, rep)
                try:
                    (ip, port, serverid) = rep
                    data = packet_builder.Data(
                        params={
                            'oid': oid,
                            'block_id': block_id,
                            'version': version,
                            'serverid': original_serverid,
                            'ip': server[0],
                            'port': server[1]
                        })
                    net = network_services.NetworkTransport()
                    net.open(ip, port)
                    net.write(
                        self.pb.build(packet_types.FS_REPLICATE_BLOCK, data))
                    net.close()
                    done = True
                except network_services.NetworkError, e:
                    print "OOOOOOOOOOO: %s" % e.value
                    #if the dataserver didn't work remove it from the active server list
                    self.serverList.remove(serverid)
                    print e
                    os._exit(1)

            if done or not rep:
                break
    def process(self,data):
#        print "FS_MODIFY_DONE: %s" % data
        
        serverid = data.serverid
        
        #release lock
        self.app.serverList.release_lock(data.oid,data.block_id,data.version)
        
        #update info in the database

        file = self.fs.get_file(oid=data.oid)
        block = self.fs.get_block(data.oid,data.block_id)

        #if the versions differ, tell the dataserver it has an invalid version
        if int(block.version) != int(data.version):
            print "Server has a different version %s != %s" % (int(file.version),int(data.version))
            data = packet_builder.Data(params={'oid':file.oid,'block_id':block.block_id,'version':file.version})
            self.net.write(self.pb.build(packet_types.FS_ERR_INCORRECT_VERSION,data))
            return None
        
        #increment the file version and update our records
        block.version += 1
        block.block_size = data.block_size
        block.size = data.block_size
        file.set_block(block)

        #add the block to the database
        self.fs.add_block(block, data.serverid)

        #tell the dataserver the new version
        data = packet_builder.Data(params={'oid':file.oid, 'block_id':block.block_id, 'version':block.version})
 #       print "Sending FS_MODIFY_ACK: %s" % data
        self.net.write(self.pb.build(packet_types.FS_MODIFY_ACK,data))
        ds_reply = self.pb.extract_stream(self.net.sock)

        if ds_reply.type == packet_types.FS_VERSION_UPDATED:
            self.app.update_file_replicas(block.oid, block.block_id, block.version, serverid)
        


        return None
    def process(self,data):
        print "Server %s wants a lock on oid %s:%s" % (data.serverid, data.oid, data.block_id)

        #check if the file is locked
        block_lock_success = self.app.serverList.add_lock(data.oid,data.block_id, data.version, data.serverid)

        data = packet_builder.Data(params={'oid':data.oid,'block_id':data.block_id,'version':data.version})

        
        #the file is locked so tell the client better luck next time
        if not block_lock_success:
            self.net.write(self.pb.build(packet_types.FS_ERR_LOCK_DENIED,data))
        else:
            self.net.write(self.pb.build(packet_types.FS_LOCK_OK,data))

        return None
Exemple #7
0
    def update_file_replicas(self, oid, block_id, version, original_serverid):
        """Updates all replicas of oid, where the new version is in original_serverid"""

        reps = self.fs_db.get_block_replicas(oid, block_id)
        server = self.serverList.get_server(original_serverid)

        if not server:
            return

        reps_done = 0

        for rep in reps.replicas.keys():
            dest = self.serverList.get_server(rep)

            #        print version
            #        print reps.replicas[rep]
            #        print dest

            if not dest or reps.replicas[rep] >= version:
                continue

            try:
                print "UPDATE REPLICA: server: %s replica %s" % (server, dest)
                data = packet_builder.Data(
                    params={
                        'oid': oid,
                        'block_id': block_id,
                        'version': version,
                        'serverid': original_serverid,
                        'ip': server[0],
                        'port': server[1]
                    })

                net = network_services.NetworkTransport()
                net.open(dest[0], dest[1])
                net.write(self.pb.build(packet_types.FS_REPLICATE_BLOCK, data))
                net.close()
                reps_done += 1

            except network_services.NetworkError, e:
                print "OOOOOOOOOOO: %s" % e.value

                #if the dataserver didn't work remove it from the active server list
                self.serverList.remove(str(rep))
    def process(self, data):
        #        print "Request to delete block: (%s,%s) " % (data.oid, data.block_id)

        oid = data.oid
        block_id = data.block_id
        version = self.fs.get(oid, block_id)

        #if we have the block, delete it from the database and the file system
        if version:
            file = os.path.join(self.app.get_storage_path(oid, block_id),
                                '__%s' % oid)
            self.fs.delete(oid, block_id)
            if os.path.exists(file):
                os.unlink(file)

        #confirm the block delete
        data = packet_builder.Data(params={'oid': oid, 'block_id': block_id})
        self.net.write(self.pb.build(packet_types.FS_DELETE_DONE, data))

        return None
    def process(self,data):
        global fs
        
        #a dataserver is telling us that it successfully stored a replica of a file object
#        print "%s now has oid %s, block %s (version %s)" % (data.serverid, data.oid, data.block_id, data.version)
        
#        mon.log(1,data.oid,data.serverid, ver=data.version)
        
        serverid = data.serverid
        
        
        #update the new file info with version & length
        oid = data.oid
        block_id = data.block_id
        

        block = self.fs.get_block(oid, block_id)

        
        
        if not block:
            block = FSBlock(0,0,0,0,0)
            block.oid = data.oid
            block.block_id = data.block_id

        block.offset = data.offset
        block.version = data.version
        block.size = data.length
        
        #add the block to the database

        self.fs.add_block(block, data.serverid)
        
        #tell dataserver the block has been stored
        data = packet_builder.Data()
#        print "Sending ACK: %s" % data
        self.net.write(self.pb.build(packet_types.ACK,data))
        
        self.app.replicate_block(block.oid, block.block_id, block.version, serverid)
    def process(self, data):

        try:
            #open the file, read the data from the network and store it in the filesystem
            fout = open(
                os.path.join(
                    self.app.get_storage_path(self.oid, self.block_id),
                    '__%s__%s' % (self.oid, self.block_id)), "wb")

            #            print "Trying to read %s bytes" % self.length
            remaining = self.length
            buf_size = 60000
            l = 0

            while remaining > 0:
                if buf_size > remaining:
                    buf_size = remaining

                buf = self.net.read_buffered(buf_size)
                fout.write(buf)

                l += len(buf)
                remaining -= len(buf)

            fout.close()

            data = packet_builder.Data(
                params={
                    'oid': self.oid,
                    'block_id': self.block_id,
                    'length': l,
                    'version': self.version,
                    'serverid': self.cfg.SERVER_ID,
                    'offset': self.file_offset
                })

            #store the replica information in the data server's local database
            self.fs.add(self.oid, self.block_id, self.version)

            #tell metadata server we have the file now
            mds = network_services.NetworkTransport()
            mds.open(self.cfg.CURR_MD_IP, self.cfg.CURR_MD_PORT)
            mds.write(self.pb.build(packet_types.FS_BLOCK_STORED, data))
            mds_reply = self.pb.extract_stream(mds.sock)
            mds.close()

            #            print 'MDSERVER REPLY: %s' % mds_reply
            if mds_reply.type == packet_types.ACK:
                #tell client everything went ok
                self.net.write(
                    self.pb.build(packet_types.FS_BLOCK_STORED, data))

            return STATE_STORE_BLOCK_INFO()

        except socket.timeout:
            print "Socket timed out. File transfer failed for %s:%s." % (
                self.oid, self.block_id)
            self.rollback(fout)
            #TODO: tell metadata that the client crashed on this operation
            return None
        except IOError:
            print "Error while creating file __%s__%s." % (self.oid,
                                                           self.block_id)
            data = Data()
            data.oid = self.oid
            data.block_id = self.block_id
            #Notify client there was an error creating this file
            self.net.write(pb.build(packet_types.FS_ERR_STORE, data))
            return None
    def process(self, data):
        try:
            #open the file, read the data from the network and store it in the filesystem
            if self.offset == -1:
                fout = open(
                    os.path.join(
                        self.app.get_storage_path(self.oid, self.block_id),
                        '__%s__%s' % (self.oid, self.block_id)), "ab+")
            else:
                fout = open(
                    os.path.join(
                        self.app.get_storage_path(self.oid, self.block_id),
                        '__%s__%s' % (self.oid, self.block_id)), "r+w")
                fout.seek(self.offset)


#            print "Trying to get and write %s bytes at %s" % (self.length, self.offset)
            l = 0
            remaining = self.length
            buf_size = 64000

            while remaining > 0:
                if buf_size > remaining:
                    buf_size = remaining

                buf = self.net.read_buffered(buf_size)
                l += len(buf)
                remaining -= len(buf)
                fout.write(buf)

            fout.close()

            #get the new size of the block
            block_size = os.path.getsize(
                os.path.join(
                    self.app.get_storage_path(self.oid, self.block_id),
                    '__%s__%s' % (self.oid, self.block_id)))

            #            print "Update block: %s:%s" % (self.oid, self.block_id)

            data = packet_builder.Data(
                params={
                    'oid': self.oid,
                    'block_id': self.block_id,
                    'length': l,
                    'version': self.version,
                    'serverid': self.cfg.SERVER_ID,
                    'offset': self.offset,
                    'block_size': block_size
                })

            #tell metadata server we succesfully modified the block
            mds = network_services.NetworkTransport()
            mds.open(self.cfg.CURR_MD_IP, self.cfg.CURR_MD_PORT)
            mds.write(self.pb.build(packet_types.FS_MODIFY_DONE, data))
            mds_reply = self.pb.extract_stream(mds.sock)

            print 'MDSERVER REPLY: %s' % mds_reply
            if mds_reply.type == packet_types.FS_MODIFY_ACK:
                #store the replica information in the data server's local database
                self.fs.add(mds_reply.oid, mds_reply.block_id,
                            mds_reply.version)
                mds.write(
                    self.pb.build(packet_types.FS_VERSION_UPDATED, mds_reply))

                data.version = mds_reply.version
                #tell client everything went ok
                self.net.write(self.pb.build(packet_types.FS_MODIFY_DONE,
                                             data))
            else:
                self.rollback(None)

            mds.close()

            return STATE_STORE_BLOCK_INFO()

        except socket.timeout:
            print "Socket timed out. File transfer failed for %s." % self.oid
            self.rollback(fout)
            return None
        except IOError:
            print "Error while creating file __%s." % self.oid
            data = Data()
            data.oid = self.oid
            #Notify client there was an error creating this file
            self.net.write(pb.build(packet_types.FS_ERR_STORE, data))
            self.rollback(fout)
            return None
    def process(self, data):
        #        print "Request to modify block: %s:%s version %s (%s:%s)" % (self.oid, self.block_id, self.version, self.block_offset, self.length)
        oid = self.oid
        block_id = self.block_id
        stored_version = self.fs.get(oid, block_id)

        #check if we have the file and if not tell the client so
        if not stored_version:
            d = packet_builder.Data(params={
                'oid': oid,
                'block_id': self.block_id,
                'version': self.version
            })
            self.net.write(
                self.pb.build(packet_types.FS_ERR_BLOCK_NOT_FOUND, d))
            return None

        #check if we have the correct version and if not tell the client which version we have
        if int(stored_version) != int(self.version):
            print "We have a different version! (%s vs %s)" % (stored_version,
                                                               data.version)
            d = packet_builder.Data(params={
                'oid': oid,
                'block_id': block_id,
                'version': self.version
            })
            self.net.write(
                self.pb.build(packet_types.FS_ERR_INCORRECT_VERSION, d))
            return None

        #try to get a lock for this block from the metadata server

#       print "Getting lock..."
        if not self.app.get_block_lock(self.oid, self.block_id, self.version):
            d = packet_builder.Data(params={
                'oid': oid,
                'block_id': self.block_id,
                'version': self.version
            })
            self.net.write(self.pb.build(packet_types.FS_ERR_LOCK_DENIED, d))
            return None

        #TODO: release locks after each failure

        #get the file length
        try:
            file = os.path.join(self.app.get_storage_path(oid, block_id),
                                '__%s__%s' % (oid, block_id))
            file_size = os.path.getsize(file)
        except OSError:
            #if we didn't find a file tell the client
            d = packet_builder.Data(params={
                'oid': oid,
                'version': self.version
            })
            self.net.write(self.pb.build(packet_types.FS_ERR_OID_NOT_FOUND, d))
            #and update our database
            self.fs.delete(oid)
            return None

        offset = self.block_offset
        #check that if the client is not appending it's not trying to write outside the file bounds
        if offset != -1:
            #          print "Block size: %s, block offset: %s" % (file_size, offset)
            if offset > file_size:
                data = packet_builder.Data(
                    params={
                        'oid': oid,
                        'block_id': self.block_id,
                        'version': self.version,
                        'serverid': self.cfg.SERVER_ID,
                    })
                self.net.write(
                    self.pb.build(packet_types.FS_ERR_BUFFER_OUT_OF_RANGE,
                                  data))
                return None

        return STATE_MODIFY_BLOCK(self.oid, self.block_id, self.block_offset,
                                  self.length, self.version)
    def process(self, data):
        oid = data.oid
        block_id = data.block_id
        version = self.fs.get(oid, block_id)

        #       print "Client wants %s:%s (version %s)" % (oid, block_id, data.version)

        #check if we have the file and if not tell the client so
        if not version:
            print "Block not found: (%s,%s)" % (oid, block_id)
            d = packet_builder.Data(params={
                'oid': oid,
                'block_id': block_id,
                'version': data.version
            })
            self.net.write(
                self.pb.build(packet_types.FS_ERR_BLOCK_NOT_FOUND, d))
            return None

        #check if we have the correct version and if not tell the client which version we have
        if int(version) != int(data.version):
            d = packet_builder.Data(params={
                'oid': oid,
                'block_id': block_id,
                'version': version
            })
            print "Incorrect version: I have (%s) and client wants (%s)" % (
                version, data.version)
            self.net.write(
                self.pb.build(packet_types.FS_ERR_INCORRECT_VERSION, d))
            return None

        #get the file length
        try:
            file = os.path.join(self.app.get_storage_path(oid, block_id),
                                '__%s__%s' % (oid, block_id))
            length = os.path.getsize(file)
        except OSError:
            #if we didn't find a file tell the client
            d = packet_builder.Data(params={
                'oid': oid,
                'block_id': block_id,
                'version': data.version
            })
            self.net.write(
                self.pb.build(packet_types.FS_ERR_BLOCK_NOT_FOUND, d))
            #and update our database
            self.fs.delete(oid)
            return None

        try:
            #confirm the file transfer
            data = packet_builder.Data(
                params={
                    'oid': oid,
                    'block_id': block_id,
                    'version': version,
                    'length': length
                })

            self.net.write(self.pb.build(packet_types.FS_REQUEST_OK, data))

            #send the file!
            f = open(file, 'rb')

            while 1:
                buf = f.read(64000)
                if not buf:
                    break
                self.net.write(buf)

            f.close()

        except socket.timeout:
            print "Socket timed out. File transfer failed for %s:%s." % (
                oid, block_id)
        except IOError:
            print "Something went wrong while reading %s:%s" % (oid, block_id)

        return None
    def process(self, data):
        
        #check if there are any active dataservers where we can store this file
        l = len(self.app.serverList.get())
        
        #if there are none, tell the client
        if not l:
            self.net.write(self.pb.build(packet_types.FS_ERR_NODATASERVERS, None))
            return None
        
        #check if the file already exists
        file = self.fs.get_file(path=data.path)

                
        if file:
            self.net.write(self.pb.build(packet_types.FS_ERR_CREATE, None))
            return None

        type = data.file_type
        version = 1 #this is the first revision of the file
        
        if type == 1: #it's a file
            #set the number of replicas for this file
            desired_replicas = data.replicas
            if not desired_replicas:
                desired_replicas = self.cfg.REPLICAS

            #set the block size for this file
            block_size = data.block_size
            if block_size == 0:
                block_size = self.cfg.BLOCK_SIZE
        elif type == 0: #it's a folder
            block_size = 0
        
        #store the file in our database        
        (path,name) = os.path.split(data.path)
        f = FSObject(0,1,name,0,type,0, block_size)
        
        try:            
            oid = self.fs.insert_file(path,f)
            
        
        # if this exception occurs at this point, it means the file doesn't have one or more parent directories.
        except FileSystemError: 
            
            dirs = []
            tmp = (path,None)
                        
            while 1:                
                tmp = os.path.split(tmp[0])                                            
                dirs.insert(0, tmp)
                if tmp[0] == '/':
                    break            
            
            # lets start trying to create those parent directories!
            print "-----------"            
            print dirs
            print "-----------"
            for i in dirs:
                
                # check if directory already exists
                tmp = i[0] + '/' + i[1]
                if self.fs.get_file(path=tmp):
                    print str(tmp) + " exists. Continue.................................."
                    continue
                
                # create the directory                                
                print str(tmp) + " is being created................"
                x = FSObject(0,1,i[1],0,0,0,0)
                self.fs.insert_file(i[0],x)                
                
            # store the file
            oid = self.fs.insert_file(path,f)

        
        try:
            
            if type == 1: #it's a file
            
                #set the number of replicas for this file
                desired_replicas = data.replicas
                if not desired_replicas:
                    desired_replicas = self.cfg.REPLICAS

                #set the block size for this file
                block_size = data.block_size
                if not block_size:
                    block_size = self.cfg.BLOCK_SIZE
                    
                (ip,port,serverid) = self.app.serverList.select_dataserver(oid)
    
                data = packet_builder.Data(params={'ip':ip,'port':port,'serverid':serverid,'oid':oid,'version':version,'block_size':block_size,'replicas':desired_replicas})
                self.net.write(self.pb.build(packet_types.FS_CREATE_OK, data))
                
                
            else: #it's a folder
            
                desired_replicas = 0 #no replicas for a folder
                block_size = 0
            
                data = packet_builder.Data(params={'oid':oid,'length':0,'version':version,'serverid':0})
                self.net.write(self.pb.build(packet_types.FS_NODE_CREATED,data))
                


        except fs_db.FileSystemError:
            self.net.write(self.pb.build(packet_types.FS_ERR_CREATE, None))
            
        return None
    def process(self,data):
        global fs

        #client wants a file
        print "Client requests %s" % (data.path)
        

        file = self.fs.get_file(path=data.path)

        
        #if there is no such file tell the client so
        if not file:
            data = packet_builder.Data()
            self.net.write(self.pb.build(packet_types.FS_ERR_PATH_NOT_FOUND, data))
            return None
        
        #get the file's blocks and replicas

        blocks = self.fs.get_blocks(file.oid,byte_start=0,byte_end=0)
        replicas = self.fs.get_file_replicas(file.oid)
        
        #get an online dataserver where this file is stored
        block_replicas = self.app.serverList.select_blocks_replicas(file.blocks, replicas)
        
        #if the file size > 0 but there are no online servers that can serve all blocks
        if file.size > 0 and not block_replicas:
            data = packet_builder.Data()
            self.net.write(self.pb.build(packet_types.FS_ERR_NO_REPLICAS,data))
            return None
 
        #tell the client where it can get the file
        data = packet_builder.Data(params={'oid':file.oid,'file_size':file.size, 'version':file.version,'block_size':file.block_size, 'file_type':file.type})


        #build the list of blocks and servers
        data.blocks = []

        for block_id in file.blocks.keys():
            block = packet_builder.Data()
            block.block_id = block_id
            block.version = blocks[block_id].version
            block.block_size = blocks[block_id].size
            block.offset = blocks[block_id].offset
            
            block.ip = block_replicas[block_id][0]
            block.port = block_replicas[block_id][1]
            block.serverid = block_replicas[block_id][2]
            
            data.blocks.append(block)    
        

        #send the client the ok signal and a list of servers where it can get each block
        self.net.write(self.pb.build(packet_types.FS_GET_OK,data))
        
        
#        ds_list_lock.acquire()
#        replicate_further = serverList.oid_used(file.oid)
#        ds_list_lock.release()
        
#        if replicate_further:
#            serverid = get_current_replica_server(file.oid,file.version)
#            replicate_file(file.oid, file.version, serverid,force=True)


        return None