diff --git a/samples/cachingfs/caching_fs.go b/samples/cachingfs/caching_fs.go index ffe1d61..7c48931 100644 --- a/samples/cachingfs/caching_fs.go +++ b/samples/cachingfs/caching_fs.go @@ -15,14 +15,20 @@ package cachingfs import ( - "sync" "time" "github.com/jacobsa/fuse" "github.com/jacobsa/fuse/fuseutil" + "github.com/jacobsa/gcloud/syncutil" "golang.org/x/net/context" ) +const ( + // Sizes of the files according to the file system. + FooSize = 123 + BarSize = 456 +) + // A file system with a fixed structure that looks like this: // // foo @@ -64,32 +70,60 @@ type CachingFS interface { func NewCachingFS( lookupEntryTimeout time.Duration, getattrTimeout time.Duration) (fs CachingFS, err error) { - fs = &cachingFS{ - inodeIDBase: fuse.RootInodeID + 1, - mtime: time.Now(), + cfs := &cachingFS{ + fooID: ((fuse.RootInodeID + 1 + numInodes - 1) / numInodes) + fooOffset, + mtime: time.Now(), } + cfs.mu = syncutil.NewInvariantMutex(cfs.checkInvariants) + + fs = cfs return } +const ( + // Inode IDs are issued such that "foo" always receives an ID that is + // congruent to fooOffset modulo numInodes, etc. + fooOffset = iota + dirOffset + barOffset + numInodes +) + type cachingFS struct { fuseutil.NotImplementedFileSystem - mu sync.Mutex + mu syncutil.InvariantMutex + // The current ID of foo. + // + // INVARIANT: FooID() > fuse.RootInodeID + // INVARIANT: DirID() > fuse.RootInodeID + // INVARIANT: BarID() > fuse.RootInodeID + // + // INVARIANT: FooID() % numInodes == fooOffset + // INVARIANT: DirID() % numInodes == dirOffset + // INVARIANT: BarID() % numInodes == barOffset + // // GUARDED_BY(mu) - inodeIDBase fuse.InodeID + fooID fuse.InodeID // GUARDED_BY(mu) mtime time.Time } -// LOCKS_EXCLUDED(fs.mu) -func (fs *cachingFS) RenumberInodes(base fuse.InodeID) { - fs.mu.Lock() - defer fs.mu.Unlock() +func (fs *cachingFS) checkInvariants() - fs.inodeIDBase = base -} +// LOCKS_EXCLUDED(fs.mu) +func (fs *cachingFS) FooID() fuse.InodeID + +// LOCKS_EXCLUDED(fs.mu) +func (fs *cachingFS) DirID() fuse.InodeID + +// LOCKS_EXCLUDED(fs.mu) +func (fs *cachingFS) BarID() fuse.InodeID + +// LOCKS_EXCLUDED(fs.mu) +func (fs *cachingFS) RenumberInodes() // LOCKS_EXCLUDED(fs.mu) func (fs *cachingFS) SetMtime(mtime time.Time) {