From c03718ca7b5c13483766c84fcbb6cdb41ea254e1 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Fri, 27 Feb 2015 16:30:22 +1100 Subject: [PATCH] Started on an in-memory file system. --- samples/mem_fs.go | 92 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 samples/mem_fs.go diff --git a/samples/mem_fs.go b/samples/mem_fs.go new file mode 100644 index 0000000..7e0af09 --- /dev/null +++ b/samples/mem_fs.go @@ -0,0 +1,92 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// Author: jacobsa@google.com (Aaron Jacobs) + +package samples + +import ( + "sync" + + "github.com/jacobsa/fuse" + "github.com/jacobsa/fuse/fuseutil" + "github.com/jacobsa/gcloud/syncutil" + "github.com/jacobsa/gcsfuse/timeutil" +) + +// Create a file system that stores data and metadata in memory. +func NewMemFS( + clock timeutil.Clock) fuse.FileSystem + +type memFS struct { + fuseutil.NotImplementedFileSystem + + ///////////////////////// + // Dependencies + ///////////////////////// + + clock timeutil.Clock + + ///////////////////////// + // Mutable state + ///////////////////////// + + mu syncutil.InvariantMutex + + // The next inode to issue. + // + // INVARIANT: nextInode > 0 + nextInode fuse.InodeID // GUARDED_BY(mu) + + // A map from inode number to file or directory with that inode. + // + // INVARIANT: inodeIndex[fuse.RootInodeID != nil + // INVARIANT: For all keys k, k > 0 + // INVARIANT: For all keys k, k < nextInode + // INVARIANT: For all keys k, inodeIndex[k] is *memFile or *memDir + // INVARIANT: For all keys k, inodeIndex[k].inode == k + // INVARIANT: For all dirs d, all of d's children are in the map. + inodeIndex map[fuse.InodeID]interface{} // GUARDED_BY(mu) +} + +type memFile struct { + ///////////////////////// + // Constant data + ///////////////////////// + + inode fuse.InodeID + + ///////////////////////// + // Mutable state + ///////////////////////// + + mu sync.RWMutex + + // The current contents of the file. + contents []byte // GUARDED_BY(mu) +} + +// TODO(jacobsa): Add a test that various WriteAt calls with a real on-disk +// file to verify what the behavior should be here, particularly when starting +// a write well beyond EOF. Leave the test around for documentation purposes. +func (f *memFile) WriteAt(p []byte, off int64) (n int, err error) + +type memDir struct { + ///////////////////////// + // Constant data + ///////////////////////// + + inode fuse.InodeID + + ///////////////////////// + // Mutable state + ///////////////////////// + + mu syncutil.InvariantMutex + + // The contents of the directory. An entry with inode zero is unused. + // + // This array can never be shortened, nor can its elements be moved, because + // we use its indices for Dirent.Offset, which is exposed to the user who + // might be calling readdir in a loop while concurrently modifying the + // directory. Unused entries can, however, be reused. + entries []fuseutil.Dirent +}