fusetoys

various hacky fuse filesystem utilities
git clone https://a3nm.net/git/fusetoys/
Log | Files | Refs | README

commit bad803f5d352e0cd2f16716f53e47994276331d3
parent 9dba92ddf907baf0b09acfb252b5fe4ae2a1c755
Author: Antoine Amarilli <a3nm@a3nm.net>
Date:   Sat, 29 Dec 2012 00:19:16 +0100

CacheFS inherits from MetaCacheFS

Diffstat:
TODO | 1-
cachefs.py | 77+++++++++++++++++------------------------------------------------------------
2 files changed, 17 insertions(+), 61 deletions(-)

diff --git a/TODO b/TODO @@ -1,4 +1,3 @@ - fail more gracefully for missing endpoints - partial reads, or bufferize as much as needed - don't cache for a small read -- cachefs inherits from loopfs or from metacachefs diff --git a/cachefs.py b/cachefs.py @@ -12,6 +12,7 @@ import pickle import time import heapq from threading import Lock +from metacachefs import MetaCacheFS DB = ".cache.db" @@ -48,7 +49,7 @@ class Cache: self.heap = [] self.files = {} self.path = path - self.discover() + # TODO self.discover() @property def freeSize(self): @@ -96,9 +97,9 @@ class Cache: return f -class CacheFS(fuse.Fuse): +class CacheFS(MetaCacheFS): def __init__(self, *args, **kw): - fuse.Fuse.__init__(self, *args, **kw) + MetaCacheFS.__init__(self, *args, **kw) self.rwlock = Lock() self.cache = None @@ -115,9 +116,9 @@ class CacheFS(fuse.Fuse): type='int', help="maximal size of cache") def fsinit(self): + MetaCacheFS.fsinit(self) + options = self.cmdline[0] - args = self.cmdline[1] - self.sourceRoot = args[0] self.cacheRoot = options.cache self.db = options.db self.size = options.size @@ -140,9 +141,6 @@ class CacheFS(fuse.Fuse): with open(self.db, 'wb+') as f: pickle.dump(self.cache, f) - def sourcePath(self, path): - return os.path.join(self.sourceRoot, path[1:]) - def cachePath(self, path): return os.path.join(self.cacheRoot, path[1:]) @@ -194,54 +192,32 @@ class CacheFS(fuse.Fuse): return self.sourcePath(path) # create folder hierarchy head, tail = os.path.split(self.cachePath(path)) + print "will create folders" try: os.makedirs(head) except OSError as exc: # Python >2.5 if exc.errno == errno.EEXIST and os.path.isdir(head): pass else: raise + print "will copy %s to %s" % (self.sourcePath(path), self.cachePath(path)) shutil.copy2(self.sourcePath(path), self.cachePath(path)) self.cache.addFile(path[1:]) return self.cachePath(path) - def access(self, path, mode): - if not os.access(self.sourcePath(path), mode): - return -errno.EACCES - def chmod(self, path, mode): wasCached = self.isCached(path) - retval = os.chmod(self.sourcePath(path), mode) + retval = super(CacheFS, self).chmod(path, mode) if wasCached: os.chmod(self.cachePath(path), mode) # ignore errors return retval def chown(self, path, mode): wasCached = self.isCached(path) - retval = os.chown(self.sourcePath(path), mode) + retval = super(CacheFS, self).chown(path, mode) if wasCached: os.chown(self.cachePath(path), mode) # ignore errors return retval - def create(self, path, flags, mode): - return os.open(self.sourcePath(path), os.O_WRONLY | os.O_CREAT, mode) - - def getattr(self, path): - return os.lstat(self.sourcePath(path)) - - def link(self, target, source): - os.link(self.sourcePath(source), self.sourcePath(target)) - - def mkdir(self, path, mode): - return os.mkdir(self.sourcePath(path), mode) - - def mknod(self, path, mode, rdev): - return os.mknod(self.sourcePath(path), mode, rdev) - - def open(self, path, flags): - #print("will call open %s %s" % (self.prepare(path), flags)) - #return os.open(self.prepare(path), flags) - return 0 - def read(self, path, size, offset): f = self.prepare(path) with self.rwlock: @@ -251,30 +227,14 @@ class CacheFS(fuse.Fuse): os.close(fh) return x - def readdir(self, path, offset): - path = self.sourcePath(path) - myIno = os.lstat(path).st_ino - yield fuse.Direntry('.', ino=myIno) - parentIno = os.lstat(os.path.join(path, "..")).st_ino - yield fuse.Direntry('..', ino=parentIno) - for name in os.listdir(path): - ino = os.lstat(os.path.join(path, name)).st_ino - yield fuse.Direntry(name, ino=ino) - - def readlink(self, path): - return os.readlink(self.sourcePath(path)) - def rename(self, old, new): wasCached = self.isCached(old) - retval = os.rename(self.sourcePath(old), self.sourcePath(new)) + retval = super(CacheFS, self).rename(old, new) if wasCached: self.cache.moveFile(old[1:], new[1:]) os.rename(self.cachePath(old), self.cachePath(new)) return retval - def rmdir(self, path): - return os.rmdir(self.sourcePath(path)) - def statfs(self): stv = os.statvfs(self.cacheRoot) stv = Stat(**dict((key, getattr(stv, key)) for key in ["f_bavail", @@ -285,24 +245,23 @@ class CacheFS(fuse.Fuse): stv.f_blocks = self.cache.maxSize/stv.f_bsize return stv - def symlink(self, target, source): - return os.symlink(self.sourcePath(source), self.sourcePath(target)) - def doTruncate(self, path, length): with open(path, 'r+') as f: f.truncate(length) - def truncate(self, path, length, fh=None): + def truncate(self, path, length): wasCached = self.isCached(path) + retval = super(CacheFS, self).truncate(path, length) self.doTruncate(self.sourcePath(path), length) if wasCached: self.cache.currentSize -= self.cache.files[path[1:]].size self.doTruncate(self.cachePath(path), length) self.cache.currentSize += self.cache.files[path[1:]].size + return retval def unlink(self, path): wasCached = self.isCached(path) - retval = os.unlink(self.sourcePath(path)) + retval = super(CacheFS, self).unlink(path) if wasCached: self.cache.deleteFile(path[1:]) os.unlink(self.cachePath(path)) @@ -311,7 +270,7 @@ class CacheFS(fuse.Fuse): def utimens(self, path, ts_acc, ts_mod): wasCached = self.isCached(path) times = (ts_acc.tv_sec, ts_mod.tv_sec) - retval = os.utime(self.sourcePath(path), times) + retval = super(CacheFS, self).utimens(path, ts_acc, ts_mod) if wasCached: os.utime(self.cachePath(path), times) return retval @@ -327,7 +286,7 @@ class CacheFS(fuse.Fuse): def write(self, path, data, offset): wasCached = self.isCached(path) print "writing to a %s file" % ("cached" if wasCached else "non-cached") - retval = self.doWrite(self.sourcePath(path), data, offset) + retval = super(CacheFS, self).write(path, data, offset) if retval > 0 and wasCached: self.makeRoom(len(data)) self.cache.currentSize -= self.cache.files[path[1:]].size @@ -336,8 +295,6 @@ class CacheFS(fuse.Fuse): return retval - - if __name__ == "__main__": cachefs = CacheFS() fuse_opts = cachefs.parse(['-o', 'fsname=cachefs'] + sys.argv[1:])