class MooseFS(object): def __init__(self, host='mfsmaster', port=9421): self.host = host self.mc = MasterConn(host, port) self.inode_cache = {} def _lookup(self, parent, name): cache = self.inode_cache.setdefault(parent, {}) info = cache.get(name) if info is not None: return info info, err = self.mc.lookup(parent, name) if info is not None: cache[name] = info return info def lookup(self, path, followSymlink=True): parent = MFS_ROOT_INODE info = None ps = path.split('/') for i, n in enumerate(ps): if not n: continue info = self._lookup(parent, n) if not info: return if info.is_symlink() and followSymlink: target = self.mc.readlink(info.inode) if not target.startswith('/'): target = os.path.join('/'.join(ps[:i]), target) return self.lookup(target, True) parent = info.inode if info is None and parent == MFS_ROOT_INODE: info = self.mc.getattr(parent) return info def open(self, path): info = self.lookup(path) if not info: raise Exception("not found") return File(info.inode, path, info, self.host) def listdir(self, path): info = self.lookup(path) if not info: raise Exception("not found") files = self.mc.getdirplus(info.inode) for i in files.values(): self.inode_cache.setdefault(info.inode, {})[i.name] = i return files def close(self): self.mc.close()
class MooseFS(object): def __init__(self, host='mfsmaster', port=9421, mountpoint='/mfs'): self.host = host self.mountpoint = mountpoint self.mc = MasterConn(host, port) self.symlink_cache = {} def _lookup(self, parent, name): return self.mc.lookup(parent, name)[0] def readlink(self, inode): target = self.symlink_cache.get(inode) if target is None: target = self.mc.readlink(inode) self.symlink_cache[inode] = target return target def lookup(self, path, followSymlink=True): parent = MFS_ROOT_INODE info = None ps = path.split('/') for i, n in enumerate(ps): if not n: continue info = self._lookup(parent, n) if not info: return while info.is_symlink() and followSymlink: target = self.readlink(info.inode) if not target.startswith('/'): target = os.path.join('/'.join(ps[:i]), target) info = self.lookup(target, followSymlink) elif target.startswith(self.mountpoint): info = self.lookup(target[len(self.mountpoint):], followSymlink) else: raise CrossSystemSymlink(path, os.path.join(target, *ps[i+1:])) parent = info.inode if info is None and parent == MFS_ROOT_INODE: info = self.mc.getattr(parent) return info def open(self, path): info = self.lookup(path) if not info: raise Exception("not found") return File(info.inode, path, info, self.host) def listdir(self, path): info = self.lookup(path) if not info: raise Exception("not found") return self.mc.getdirplus(info.inode) def walk(self, path, followlinks=False): ds = [path] while ds: root = ds.pop() cs = self.listdir(root) dirs, files = [], [] for name, info in cs.iteritems(): if name in '..': continue while followlinks and info and info.type == TYPE_SYMLINK: target = self.readlink(info.inode) if target.startswith('/'): if not target.startswith(self.mountpoint): if os.path.exists(target): if os.path.isdir(target): dirs.append(target) else: files.append(target) info = None # ignore broken symlink break else: target = target[len(self.mountpoint):] # use relative path for internal symlinks name = ('../' * len(filter(None, root.split('/')))) + target else: name = target target = os.path.join(root, target) info = self.lookup(target) if info: if info.type == TYPE_DIRECTORY: if name not in dirs: dirs.append(name) elif info.type == TYPE_FILE: if name not in files: files.append(name) yield root, dirs, files for d in sorted(dirs, reverse=True): if not d.startswith('/'): # skip external links ds.append(os.path.join(root, d)) def close(self): self.mc.terminate()
class MooseFS(object): def __init__(self, host='mfsmaster', port=9421, mountpoint='/mfs'): self.host = host self.mountpoint = mountpoint self.mc = MasterConn(host, port) self.inode_cache = {} self.symlink_cache = {} def _lookup(self, parent, name): cache = self.inode_cache.get(parent) if cache is None: cache = self.mc.getdirplus(parent) self.inode_cache[parent] = cache return cache.get(name) def readlink(self, inode): target = self.symlink_cache.get(inode) if target is None: target = self.mc.readlink(inode) self.symlink_cache[inode] = target return target def lookup(self, path, followSymlink=True): parent = MFS_ROOT_INODE info = None ps = path.split('/') for i, n in enumerate(ps): if not n: continue info = self._lookup(parent, n) if not info: return while info.is_symlink() and followSymlink: target = self.readlink(info.inode) if not target.startswith('/'): target = os.path.join('/'.join(ps[:i]), target) info = self.lookup(target, followSymlink) elif target.startswith(self.mountpoint): info = self.lookup(target[len(self.mountpoint):], followSymlink) else: raise CrossSystemSymlink(path, os.path.join(target, *ps[i + 1:])) parent = info.inode if info is None and parent == MFS_ROOT_INODE: info = self.mc.getattr(parent) return info def open(self, path): info = self.lookup(path) if not info: raise Exception("not found") return File(info.inode, path, info, self.host) def listdir(self, path): info = self.lookup(path) if not info: raise Exception("not found") files = self.inode_cache.get(info.inode) if files is None: files = self.mc.getdirplus(info.inode) self.inode_cache[info.inode] = files return files def walk(self, path, followlinks=False): ds = [path] while ds: root = ds.pop() cs = self.listdir(root) dirs, files = [], [] for name, info in cs.iteritems(): if name in '..': continue while followlinks and info and info.type == TYPE_SYMLINK: target = self.readlink(info.inode) if target.startswith('/'): if not target.startswith(self.mountpoint): if os.path.exists(target): if os.path.isdir(target): dirs.append(target) else: files.append(target) info = None # ignore broken symlink break else: target = target[len(self.mountpoint):] # use relative path for internal symlinks name = ('../' * len(filter( None, root.split('/')))) + target else: name = target target = os.path.join(root, target) info = self.lookup(target) if info: if info.type == TYPE_DIRECTORY: if name not in dirs: dirs.append(name) elif info.type == TYPE_FILE: if name not in files: files.append(name) yield root, dirs, files for d in sorted(dirs, reverse=True): if not d.startswith('/'): # skip external links ds.append(os.path.join(root, d)) def close(self): self.mc.close()