MFS的python连接

学习MFS有一段时间了, 分享下个人实现的python客户端连接MFS

<!-- lang: python -->
class MFSApi(object):
def __init__(self, host, port, mountfolder):
    self.mountfolder=mountfolder if mountfolder.endswith('/') else mountfolder+'/'
    self.mountfolder=self.mountfolder if self.mountfolder.startswith('/') else '/'+self.mountfolder 
    self.masterconn=socket.socket()
    self.masterconn.connect((host,port))
    leng=len(self.mountfolder)+1
    mysend(self.masterconn,struct.pack(">LL64sBHBBL1sL%ss"%leng, CLTOMA_FUSE_REGISTER, 64+13+1+leng, 
                                     FUSE_REGISTER_BLOB_ACL, REGISTER_NEWSESSION, 1, 6, 26, 1, "/", leng, self.mountfolder+"\0"))
    header = myrecv(self.masterconn,8)
    cmd,size = struct.unpack(">LL",header)
    data=myrecv(self.masterconn,size)
    if cmd != MATOCL_FUSE_REGISTER or size != 25:
        self.masterconn.close()
        raise RuntimeError("Register to masterserver(%s:%s) failed" % (host, port))
    self.versmaj,self.versmid,self.versmin,self.sessionid,self.sesflags,self.rootuid,self.rootgid,self.mapalluid,self.mapallgid=struct.unpack(">HBBLBLLLL", data)
    crc_generate_main_tables()
    
def statfs(self):
    mysend(self.masterconn,struct.pack(">LLL", CLTOMA_FUSE_STATFS, 4, 1))
    header = myrecv(self.masterconn,8)
    cmd,size = struct.unpack(">LL",header)
    data=myrecv(self.masterconn,size)
    if cmd != MATOCL_FUSE_STATFS or size != 40:
        raise IOError("Error while getting statfs")
    _,totalspace,availspace,trashspace,reservedspace,inodes=struct.unpack(">LQQQQL", data)
    return {'totalspace':totalspace,
            'availspace':availspace,
            'trashspace':trashspace,
            'reservedspace':reservedspace,
            'inodes':inodes}

def _transfer2attr(self, data):
    _type,mode,uid,gid,atime,mtime,ctime,nlink,length=struct.unpack(">BHLLLLLLQ", data)
    return {'type':_type,
            'mode':mode,
            'uid':uid,
            'gid':gid,
            'atime':atime,
            'mtime':mtime,
            'ctime':ctime,
            'nlink':nlink,
            'length':length}

def _lookup(self, inode, fname):
    leng=len(fname)
    mysend(self.masterconn, struct.pack(">LLLLB%ssLL"%leng, CLTOMA_FUSE_LOOKUP, 17+leng,
                                      1, inode, leng, fname, self.rootuid, self.rootgid))
    header = myrecv(self.masterconn,8)
    cmd,size = struct.unpack(">LL",header)
    data=myrecv(self.masterconn,size)
    if cmd != MATOCL_FUSE_LOOKUP or size != 43:
        raise IOError("Error while lookingup of file name: '%s'" % fname)
    _,newinode=struct.unpack(">LL", data[:8])
    return {'inode':newinode,
            'attr':data[8:]}

def ls(self, fpath):
    result=self.ll(fpath)
    subnames=[]
    for sub in result:
        subnames.append(sub['name'])
    return subnames

def ll(self, fpath):
    if fpath == '/': fpath='.'
    _fpath=fpath if fpath.startswith('/') else '/'+fpath
    nlist=_fpath.split('/')[1:]
    if not nlist[-1]: nlist=nlist[0:-1]
    inode=1
    attr_v={}
    for name in nlist:
        value=self._lookup(inode, name)
        inode=value['inode']
        attr_v=self._transfer2attr(value['attr'])
    subnames=[{'inode':inode,
               'type':attr_v['type'],
               'name':nlist[-1],
               'uid':attr_v['uid'],
               'gid':attr_v['gid'],
               'atime':attr_v['atime'],
               'mtime':attr_v['mtime'],
               'ctime':attr_v['ctime'],
               'length':attr_v['length']}]
    if attr_v['type'] == ord('d'):
        mysend(self.masterconn,struct.pack(">LLLLLLB", CLTOMA_FUSE_GETDIR, 17,
                                         1, inode, self.rootuid, self.rootgid, 1))
        header = myrecv(self.masterconn,8)
        cmd,size = struct.unpack(">LL",header)
        data=myrecv(self.masterconn,size)
        if cmd != MATOCL_FUSE_GETDIR:
            raise IOError("Error while getting dir of inode(%s)" % inode)
        readed=4+83
        subnames=[]
        while readed < size:
            nlen=struct.unpack('>B', data[readed])[0]
            readed+=1
            name=data[readed:readed+nlen]
            readed+=nlen
            node=struct.unpack('>L', data[readed:readed+4])[0]
            readed+=4
            attr_v=self._transfer2attr(data[readed:readed+35])
            readed+=35
            subnames.append({'inode':node,
                             'type':attr_v['type'],
                             'name':name,
                             'uid':attr_v['uid'],
                             'gid':attr_v['gid'],
                             'atime':attr_v['atime'],
                             'mtime':attr_v['mtime'],
                             'ctime':attr_v['ctime'],
                             'length':attr_v['length']})
    return subnames

def mkdir(self, fpath):
    if fpath in ['/', '.', '..'] or fpath.endswith('/'):
        raise ValueError("Invalid path: '%s'" % fpath)
    _fpath=fpath if fpath.startswith('/') else '/'+fpath
    nlist=_fpath.split('/')[1:]
    fname=nlist[-1]
    nlist=nlist[:-1]
    inode=1
    attr_v={}
    if not nlist: nlist.append('.')
    for name in nlist:
        value=self._lookup(inode, name)
        inode=value['inode']
        attr_v=self._transfer2attr(value['attr'])
        
    if attr_v['type'] != ord('d'):
        raise IOError("[Errno 20] Not a directory: '/%s'" % '/'.join(nlist))
    
    nleng=len(fname)
    mysend(self.masterconn,struct.pack(">LLLLB%ssHLL"%nleng, CLTOMA_FUSE_MKDIR, 19+nleng,
                                     1, inode, nleng, fname, 0666, self.rootuid, self.rootgid))
    header = myrecv(self.masterconn,8)
    cmd,size = struct.unpack(">LL",header)
    data=myrecv(self.masterconn,size)
    if cmd != MATOCL_FUSE_MKDIR or size != 43:
        raise IOError("Error while mkdir of path: '%s'" % fpath)
    _,newinode=struct.unpack(">LL", data[:8])
    dirinfo=self._transfer2attr(data[8:])
    dirinfo['inode']=newinode
    return dirinfo  
    
def rmdir(self, fpath):
    if fpath in ['/', '.', '..'] or fpath.endswith('/'):
        raise ValueError("Invalid path: '%s'" % fpath)
    _fpath=fpath if fpath.startswith('/') else '/'+fpath
    nlist=_fpath.split('/')[1:]
    fname=nlist[-1]
    nlist=nlist[:-1]
    inode=1
    attr_v={}
    if not nlist: nlist.append('.')
    for name in nlist:
        value=self._lookup(inode, name)
        inode=value['inode']
        attr_v=self._transfer2attr(value['attr'])
        
    if attr_v['type'] != ord('d'):
        raise IOError("[Errno 20] Not a directory: '/%s'" % '/'.join(nlist))
    
    nleng=len(fname)
    mysend(self.masterconn,struct.pack(">LLLLB%ssLL"%nleng, CLTOMA_FUSE_RMDIR, 17+nleng,
                                     1, inode, nleng, fname, self.rootuid, self.rootgid))
    header = myrecv(self.masterconn,8)
    cmd,size = struct.unpack(">LL",header)
    data=myrecv(self.masterconn,size)
    if cmd != MATOCL_FUSE_RMDIR or size != 5:
        raise IOError("Error while rmdir of path: '%s'" % fpath)
    _,status=struct.unpack('>LB', data)
    if status:
        raise IOError("Failed while rmdir of path: '%s'" % fpath)

def mv(self, oldfpath, newfpath):
    if oldfpath in ['/', '.', '..'] or oldfpath.endswith('/'):
        raise ValueError("Invalid source path: '%s'" % oldfpath)
    if newfpath in ['/', '.', '..'] or newfpath.endswith('/'):
        raise ValueError("Invalid destination path: '%s'" % newfpath)
    
    def _parse_node_info(fpath):
        _fpath=fpath if fpath.startswith('/') else '/'+fpath
        nlist=_fpath.split('/')[1:]
        fname=nlist[-1]
        nlist=nlist[:-1]
        inode=1
        if not nlist: nlist.append('.')
        for name in nlist:
            value=self._lookup(inode, name)
            inode=value['inode']
        return inode, fname
    
    oldnode_info=_parse_node_info(oldfpath)
    newnode_info=_parse_node_info(newfpath)
    oldinode=oldnode_info[0]
    oldfname=oldnode_info[1]
    oldnleng=len(oldfname)
    newinode=newnode_info[0]
    newfname=newnode_info[1]
    newnleng=len(newfname)
    
    # old file not exist or new file exist
    if not self._lookup(oldinode, oldfname):
        raise IOError("The source file is not exist, path: '%s'" % oldfpath)
    if self._lookup(newinode, newfname):
        raise IOError("The destination file is exist, path: '%s'" % newfpath)
    
    mysend(self.masterconn,struct.pack(">LLLLB%ssLB%ssLL"%(oldnleng, newnleng), CLTOMA_FUSE_RENAME, 22+oldnleng+newnleng,
                                     1, oldinode, oldnleng, oldfname, newinode, newnleng, newfname, self.rootuid, self.rootgid))
    header = myrecv(self.masterconn,8)
    cmd,size = struct.unpack(">LL",header)
    data=myrecv(self.masterconn,size)
    if cmd != MATOCL_FUSE_RENAME or size != 43:
        raise IOError("Error while moving file from '%s' to '%s'" % (oldfpath, newfpath))
    _,newinode=struct.unpack(">LL", data[:8])
    nodeinfo=self._transfer2attr(data[8:])
    nodeinfo['inode']=newinode
    return nodeinfo  

def unlink(self, fpath):
    if fpath in ['/', '.', '..'] or fpath.endswith('/'):
        raise ValueError("Invalid path: '%s'" % fpath)
    _fpath=fpath if fpath.startswith('/') else '/'+fpath
    nlist=_fpath.split('/')[1:]
    fname=nlist[-1]
    nlist=nlist[:-1]
    inode=1
    attr_v={}
    if not nlist: nlist.append('.')
    for name in nlist:
        value=self._lookup(inode, name)
        inode=value['inode']
        attr_v=self._transfer2attr(value['attr'])
        
    if attr_v['type'] != ord('d'):
        raise IOError("[Errno 20] Not a directory: '/%s'" % '/'.join(nlist))
    
    nleng=len(fname)
    mysend(self.masterconn,struct.pack(">LLLLB%ssLL"%nleng, CLTOMA_FUSE_UNLINK, 17+nleng,
                                     1, inode, nleng, fname, self.rootuid, self.rootgid))
    header = myrecv(self.masterconn,8)
    cmd,size = struct.unpack(">LL",header)
    data=myrecv(self.masterconn,size)
    if cmd != MATOCL_FUSE_UNLINK or size != 5:
        raise IOError("Error while unlink file '%s'" % fpath)
    _,status=struct.unpack('>LB', data)
    if status:
        raise IOError("Failed while unlink file: '%s'" % fpath)

def open(self, fpath, mode):
    outer_self = self
    class _MFSFile(object):
        def __init__(self, fpath, mode):
            if mode not in ['r', 'rw', 'w', 'wr']:
                raise ValueError("mode string must begin with one of 'r', 'w', not '%s'" % mode)
            self.fpath=fpath if fpath.startswith('/') else '/'+fpath
            nlist=self.fpath.split('/')[1:]
            self.fname=nlist[-1]
            self.parent_foldernlist=nlist[:-1]
            if not self.parent_foldernlist: self.parent_foldernlist.append('.')
            
            # open or create
            _ = self.__open() if mode[0] == 'r' else self.__create()
            
            self.readonly=True if mode=='r' else False
            self.writeonly=True if mode=='w' else False
            self.fleng=0
            self.offset=0
            self.chunksock=-1
            self.chunkindx=-1
            self.chunkid=-1
        
        def __open(self):
            inode=1
            attr_v={}
            for name in self.parent_foldernlist:
                value=outer_self._lookup(inode, name)
                if not value:
                    raise IOError("[Errno 2] No such file or directory: '%s'" % self.fpath)
                inode=value['inode']
                attr_v=outer_self._transfer2attr(value['attr'])
                
            if attr_v['type'] != ord('d'):
                raise IOError("[Errno 20] Not a directory: '%s'" % self.fpath)
            
            value=outer_self._lookup(inode, self.fname)
            if not value:
                raise IOError("[Errno 2] No such file or directory: '%s'" % self.fpath)
            inode=value['inode']
            attr_v=outer_self._transfer2attr(value['attr'])
            if attr_v['type'] != ord('f'):
                raise IOError("[Errno 2] No such file or directory: '%s'" % self.fpath)
            
            self.inode=inode
            
        
        def __create(self):
            inode=1
            attr_v={}
            for name in self.parent_foldernlist:
                value=outer_self._lookup(inode, name)
                if not value:
                    raise IOError("[Errno 2] No such file or directory: '%s'" % self.fpath)
                inode=value['inode']
                attr_v=outer_self._transfer2attr(value['attr'])
                
            if attr_v['type'] != ord('d'):
                raise IOError("[Errno 20] Not a directory: '%s'" % self.fpath)
            
            value=outer_self._lookup(inode, self.fname)
            if value:
                attr_v=outer_self._transfer2attr(value['attr'])
                if attr_v['type'] == ord('d'):
                    raise IOError("[Errno 21] Is a directory: '%s'" % self.fpath)
                
                # exist file, delete 
                nleng=len(self.fname)
                mysend(outer_self.masterconn,struct.pack(">LLLLB%ssLL"%nleng, CLTOMA_FUSE_UNLINK, 17+nleng,
                                                 1, inode, nleng, self.fname, outer_self.rootuid, outer_self.rootgid))
                header = myrecv(outer_self.masterconn,8)
                cmd,size = struct.unpack(">LL",header)
                data=myrecv(outer_self.masterconn,size)
                if cmd != MATOCL_FUSE_UNLINK or size != 5:
                    raise IOError("Error while delete the exist file for overwriting of file: '%s'" % self.fpath)
                _,status=struct.unpack('>LB', data)
                if status:
                    raise IOError("Failed while delete the exist file for overwriting of file: '%s'" % self.fpath)
            
            # create a new file with new inode
            nleng=len(self.fname)
            mysend(outer_self.masterconn,struct.pack(">LLLLB%ssBHLLL"%nleng, CLTOMA_FUSE_MKNOD, 24+nleng,
                                             1, inode, nleng, self.fname, ord('f'), 0666, outer_self.rootuid, outer_self.rootgid, 0))
            header = myrecv(outer_self.masterconn,8)
            cmd,size = struct.unpack(">LL",header)
            data=myrecv(outer_self.masterconn,size)
            if cmd != MATOCL_FUSE_MKNOD or size != 43:
                raise IOError("Failed while creating a new file: '%s'" % self.fpath)
            
            _,newinode=struct.unpack(">LL", data[:8])
            self.inode = newinode
            
        def __reset_chunksock(self):
            if self.chunksock != -1:
                self.chunksock.close()
                self.chunksock = -1
        
        def __read_chunk_loc(self):
            self.__reset_chunksock()
            mysend(outer_self.masterconn,struct.pack(">LLLLL", CLTOMA_FUSE_READ_CHUNK, 12,
                                     1, self.inode, self.chunkindx))
            header = myrecv(outer_self.masterconn,8)
            cmd,size = struct.unpack(">LL",header)
            data=myrecv(outer_self.masterconn,size)
            if cmd != MATOCL_FUSE_READ_CHUNK:
                raise IOError("There is error while reading chunk locations from masterserver of file: '%s'" % self.fpath)
            if size-24 <= 0 or (size-24) % 6 != 0:
                raise IOError("There is no chunkservers for reading of file: '%s'" % self.fpath)
            
            _, self.fleng, self.chunkid, self.version=struct.unpack(">LQQL", data[:24])
            loc_size=(size-24)/6
            self.chunksock=socket.socket()
            readed=24 + 6 * (random.randint(0, loc_size) % loc_size)
            chunkip=data[readed:readed+4]
            self.chunkport=struct.unpack(">H", data[readed+4:readed+6])[0]
            self.chunkhost=socket.inet_ntoa(chunkip)
            retried=0
            while(retried<3):
                try:
                    self.chunksock.connect((self.chunkhost, self.chunkport))
                    break
                except socket.error:
                    retried+=1
            if retried == 3:
                self.__reset_chunksock()
                raise IOError("Can not connect to chunk(%s:%s) after 3 times' retried for file: '%s'" 
                              % (self.chunkhost, self.chunkport, self.fpath))
        
        def __read_chunk_data(self, chunkoffset, chunksize):
            mysend(self.chunksock,struct.pack(">LLQLLL", CLTOCS_READ, 20,
                                     self.chunkid, self.version, chunkoffset, chunksize))
            chunkdata=''
            while True:
                header = myrecv(self.chunksock,8)
                cmd,size = struct.unpack(">LL",header)
                data=myrecv(self.chunksock,size)
                if cmd == CSTOCL_READ_STATUS:
                    if size==9:
                        chunkid, status=struct.unpack(">QB", data)
                        if self.chunkid == chunkid and not status: 
                            return chunkdata
                    raise IOError("Error read_status while reading data from chunk(%s:%s) for file: '%s'" 
                                  % (self.chunkhost, self.chunkport, self.fpath))
                elif cmd == CSTOCL_READ_DATA:
                    if size < 20:
                        raise IOError("Error read_data(size<20) while reading data from chunk(%s:%s) for file: '%s'" 
                                      % (self.chunkhost, self.chunkport, self.fpath))
                    chunkid, blocknum, blockoffset, blocksize, blockcrc=struct.unpack(">QHHLL", data[:20])
                    blockdata=data[20:]
                    breq = MFSBLOCKSIZE - blockoffset
                    if chunksize < breq: breq=chunksize
                    
                    if self.chunkid != chunkid \
                        or size != 20+blocksize \
                        or not blocksize \
                        or blocknum != chunkoffset>>MFSBLOCKBITS \
                        or blockoffset != chunkoffset&MFSBLOCKMASK \
                        or blocksize != breq:
                        raise IOError("Error read_data(required not match) while reading data from chunk(%s:%s) for file: '%s'" 
                                      % (self.chunkhost, self.chunkport, self.fpath))
                    if blockcrc != mycrc32(0,blockdata,blocksize):
                        raise IOError("Error read_data(crc error) while reading data from chunk(%s:%s) for file: '%s'" 
                                      % (self.chunkhost, self.chunkport, self.fpath))
                    chunkoffset+=blocksize
                    chunksize-=blocksize
                    chunkdata+=blockdata
                else:
                    raise IOError("Error unknown command(%s) while reading data from chunk(%s:%s) for file: '%s'" 
                                  % (cmd, self.chunkhost, self.chunkport, self.fpath))
            #fail
            self.__reset_chunksock()
            
        def read(self, bufsize=1<<MFSBLOCKBITS):
            if self.writeonly:
                raise IOError("File not open for reading of file: '%s'" % self.fpath)

            data=''
            if self.offset>=self.fleng and self.fleng:
                # the end of file
                return data
            
            readed=0
            while readed<bufsize:
                chunkindx = (self.offset>>MFSCHUNKBITS) 
                if self.chunksock == -1 or self.chunkindx != chunkindx:
                    self.chunkindx=chunkindx
                    self.__read_chunk_loc()
                bufsize=bufsize if self.offset+bufsize<self.fleng else self.fleng-self.offset
                if not bufsize:
                    # empty file
                    break
                
                chunkoffset = self.offset & MFSCHUNKMASK
                if chunkoffset+bufsize > MFSCHUNKSIZE:
                    chunksize = MFSCHUNKSIZE-chunkoffset
                else:
                    chunksize=bufsize
                    
                chunkdata=self.__read_chunk_data(chunkoffset, chunksize)
                
                self.offset+=chunksize
                readed+=chunksize
                data+=chunkdata
            
            self.chunkindx=-1
            return data
            
        def seek(self, pos):
            self.offset=pos
            
        def close(self):
            '''
            Not Implement
            '''
        
        def __write_chunk_locs(self):
            self.__reset_chunksock()
            mysend(outer_self.masterconn,struct.pack(">LLLLL", CLTOMA_FUSE_WRITE_CHUNK, 12,
                                     1, self.inode, self.chunkindx))
            header = myrecv(outer_self.masterconn,8)
            cmd,size = struct.unpack(">LL",header)
            data=myrecv(outer_self.masterconn,size)
            if cmd != MATOCL_FUSE_WRITE_CHUNK or size-24 <= 0 or (size-24) % 6 != 0:
                raise IOError("Error while getting writing chunk for file: '%s'" % self.fpath)
            
            _, self.fleng, self.chunkid, self.version=struct.unpack(">LQQL", data[:24])
            self.chunksock=socket.socket()
            chunkip=data[24:28]
            self.chunkport=struct.unpack(">H", data[28:30])[0]
            self.chunkhost=socket.inet_ntoa(chunkip)
            retried=0
            while(retried<3):
                try:
                    self.chunksock.connect((self.chunkhost, self.chunkport))
                    break
                except socket.error:
                    retried+=1
            if retried == 3:
                self.__reset_chunksock()
                raise IOError("Can not connect to chunk(%s:%s) after 3 times' retried for file: '%s'" 
                              % (self.chunkhost, self.chunkport, self.fpath))
            
            # return other locations
            return data[30:]
        
        def __write_chunk_end(self):
            self.fleng = max(self.offset, self.fleng)
            mysend(outer_self.masterconn,struct.pack(">LLLQLQ", CLTOMA_FUSE_WRITE_CHUNK_END, 24,
                                     1, self.chunkid, self.inode, self.fleng))
            header = myrecv(outer_self.masterconn,8)
            cmd,size = struct.unpack(">LL",header)
            data=myrecv(outer_self.masterconn,size)
            if cmd != MATOCL_FUSE_WRITE_CHUNK_END or size != 5:
                raise IOError("Error while write chunk end of chunkid(%s) for file: '%s'" 
                              % (self.chunkid, self.fpath))
            
            _, status=struct.unpack(">LB", data)
            if status:
                raise IOError("Error response bad status(%s) while write chunk end of chunkid(%s) for file: '%s'" 
                              % (status, self.chunkid, self.fpath))
            
        def __write_block_data(self, blocknum, blockoffset, blocksize, blockdata, other_locs):
            mysend(self.chunksock, struct.pack(">LLQL", CLTOCS_WRITE, 12+len(other_locs),
                                               self.chunkid, self.version)+other_locs)
            header = myrecv(self.chunksock,8)
            cmd,size = struct.unpack(">LL",header)
            data=myrecv(self.chunksock,size)
            if cmd != CSTOCL_WRITE_STATUS and size != 13:
                raise IOError("Error while writing block initialize for file: '%s'" % self.fpath)
            chunkid, _, status=struct.unpack(">QLB", data)
            if self.chunkid != chunkid: 
                raise IOError("Error response not required while writing block initialize"
                              "chunkid(%s:%s) for file: '%s'" 
                              % (self.chunkid, chunkid, self.fpath))
            if status:
                raise IOError("Error response bad status(%s) while writing block initialize for file: '%s'"
                              % (status, self.fpath))
                
            writeid=blocknum+1
            crc=mycrc32(0, blockdata, blocksize)
            mysend(self.chunksock, struct.pack(">LLQLHHLL", CLTOCS_WRITE_DATA, 24+blocksize,
                                               self.chunkid, writeid, blocknum, blockoffset, blocksize, crc))
            mysend(self.chunksock, blockdata)
            
            header = myrecv(self.chunksock,8)
            cmd,size = struct.unpack(">LL",header)
            data=myrecv(self.chunksock,size)
            if cmd != CSTOCL_WRITE_STATUS and size != 13:
                raise IOError("Error while writing block data with blocknum: %s, "
                              "blockoffset: %s, blocksize: %s for file: '%s'" 
                              % (blocknum, blockoffset, blocksize, self.fpath))
            chunkid, reswriteid, status=struct.unpack(">QLB", data)
            if self.chunkid != chunkid or writeid != reswriteid: 
                raise IOError("Error response not required while writing block data with blocknum: %s, "
                              "blockoffset: %s, blocksize: %s, chunkid(%s:%s), chunkindex:(%s:%s) for file: '%s'" 
                              % (blocknum, blockoffset, blocksize, self.chunkid, chunkid, writeid, reswriteid, self.fpath))
            if status:
                raise IOError("Error response bad status(%s) while writing block data with blocknum: %s, "
                              "blockoffset: %s, blocksize: %s for file: '%s'" 
                              % (status, blocknum, blockoffset, blocksize, self.fpath))
            
        def write(self, data):
            if self.readonly:
                raise IOError("File not open for writing of file: '%s'" % self.fpath)
            
            size=len(data)
            chunkindx = self.offset >> MFSCHUNKBITS
            blocknum = (self.offset&MFSCHUNKMASK) >> MFSBLOCKBITS
            blockoffset = self.offset&MFSBLOCKMASK
            writed_pos=0
            other_locs=''
            while writed_pos < size:
                if self.chunkindx == -1 or self.chunkindx != chunkindx:
                    if self.chunkindx != -1:
                        self.__write_chunk_end()
                    self.chunkindx=chunkindx
                    other_locs=self.__write_chunk_locs()
                
                remain_size=size-writed_pos
                blocksize=min(MFSBLOCKSIZE-blockoffset, remain_size)
                blockdata=data[writed_pos : writed_pos+blocksize]
                
                self.__write_block_data(blocknum, blockoffset, blocksize, blockdata, other_locs)
                
                if remain_size > MFSBLOCKSIZE-blockoffset:
                    blockoffset = 0
                    blocknum += 1
                    if blocknum == 1024:
                        blocknum = 0
                        chunkindx+=1
                        
                writed_pos += blocksize
                self.offset += blocksize
            
            self.__reset_chunksock()
            self.__write_chunk_end()
            self.chunkindx=-1
                
    if fpath in ['/', '.', '..'] or fpath.endswith('/'):
        raise ValueError("Invalid path: '%s'" % fpath)
    return _MFSFile(fpath, mode)

def allexports(self):
    mysend(self.masterconn,struct.pack(">LL", CLTOMA_EXPORTS_INFO, 0))
    header = myrecv(self.masterconn,8)
    cmd,size = struct.unpack(">LL",header)
    data=myrecv(self.masterconn,size)
    if cmd != MATOCL_EXPORTS_INFO:
        raise IOError("Error while getting all exports")
    servers = []
    pos = 0
    while pos<size:
        fip1,fip2,fip3,fip4,tip1,tip2,tip3,tip4,pleng = struct.unpack(">BBBBBBBBL",data[pos:pos+12])
        pos+=12
        path = data[pos:pos+pleng]
        pos+=pleng
        v1,v2,v3,exportflags,sesflags,rootuid,rootgid,mapalluid,mapallgid = struct.unpack(">HBBBBLLLL",data[pos:pos+22])
        pos+=22
        servers.append({'version':'%d.%d.%d' % (v1,v2,v3),
                        'fromip':'%d.%d.%d.%d' % (fip1,fip2,fip3,fip4),
                        'toip':'%d.%d.%d.%d' % (tip1,tip2,tip3,tip4),
                        'path':path,
                        'exportflags':exportflags,
                        'sesflags':sesflags,
                        'rootuid':rootuid,
                        'rootgid':rootgid,
                        'mapalluid':mapalluid,
                        'mapallgid':mapallgid
                        })
    return servers
        
def __del__(self):
    self.metaconn.close()

转载于:https://my.oschina.net/yzhoumaoy/blog/84783

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值