diff --git a/mem/dir.go b/mem/dir.go index 0767dc9..79cba7a 100644 --- a/mem/dir.go +++ b/mem/dir.go @@ -20,3 +20,18 @@ type Dir interface { Add(File) Remove(File) } + +func RemoveFromMemDir(dir *File, f *File) { + dir.memDir.Remove(*f) +} + +func AddToMemDir(dir *File, f *File) { + dir.memDir.Add(*f) +} + +func InitializeDir(d *File) { + if d.memDir == nil { + d.dir = true + d.memDir = &DirMap{} + } +} diff --git a/mem/file.go b/mem/file.go index 692077a..33093f5 100644 --- a/mem/file.go +++ b/mem/file.go @@ -26,24 +26,45 @@ import ( import "time" +const FilePathSeparator = string(filepath.Separator) + type File struct { // atomic requires 64-bit alignment for struct field access at int64 readDirCount int64 - FileName string - MemDir Dir - Dir bool - Mode os.FileMode - Modtime time.Time - sync.Mutex - closed bool - data []byte + name string + data []byte + memDir Dir + dir bool + closed bool + mode os.FileMode + modtime time.Time } -func Create(name string) *File { - return &File{FileName: name, Mode: os.ModeTemporary, Modtime: time.Now()} +func CreateFile(name string) *File { + return &File{name: name, mode: os.ModeTemporary, modtime: time.Now()} +} + +func CreateDir(name string) *File { + return &File{name: name, memDir: &DirMap{}, dir: true} +} + +func ChangeFileName(f *File, newname string) { + f.name = newname +} + +func SetMode(f *File, mode os.FileMode) { + f.mode = mode +} + +func SetModTime(f *File, mtime time.Time) { + f.modtime = mtime +} + +func GetFileInfo(f *File) *FileInfo { + return &FileInfo{file: f} } func (f *File) Open() error { @@ -63,7 +84,7 @@ func (f *File) Close() error { } func (f *File) Name() string { - return f.FileName + return f.name } func (f *File) Stat() (os.FileInfo, error) { @@ -78,7 +99,7 @@ func (f *File) Readdir(count int) (res []os.FileInfo, err error) { var outLength int64 f.Lock() - files := f.MemDir.Files()[f.readDirCount:] + files := f.memDir.Files()[f.readDirCount:] if count > 0 { if len(files) < count { outLength = int64(len(files)) @@ -198,27 +219,27 @@ func (f *File) WriteString(s string) (ret int, err error) { } func (f *File) Info() *FileInfo { - return &FileInfo{File: f} + return &FileInfo{file: f} } type FileInfo struct { - File *File + file *File } // Implements os.FileInfo func (s *FileInfo) Name() string { - _, name := filepath.Split(s.File.Name()) + _, name := filepath.Split(s.file.Name()) return name } -func (s *FileInfo) Mode() os.FileMode { return s.File.Mode } -func (s *FileInfo) ModTime() time.Time { return s.File.Modtime } -func (s *FileInfo) IsDir() bool { return s.File.Dir } +func (s *FileInfo) Mode() os.FileMode { return s.file.mode } +func (s *FileInfo) ModTime() time.Time { return s.file.modtime } +func (s *FileInfo) IsDir() bool { return s.file.dir } func (s *FileInfo) Sys() interface{} { return nil } func (s *FileInfo) Size() int64 { if s.IsDir() { return int64(42) } - return int64(len(s.File.data)) + return int64(len(s.file.data)) } var ( diff --git a/memmap.go b/memmap.go index 327aea1..3a5a918 100644 --- a/memmap.go +++ b/memmap.go @@ -48,7 +48,7 @@ func (m *MemMapFs) getData() map[string]File { // Root should always exist, right? // TODO: what about windows? - m.data[FilePathSeparator] = &mem.File{FileName: FilePathSeparator, MemDir: &mem.DirMap{}, Dir: true} + m.data[FilePathSeparator] = mem.CreateDir(FilePathSeparator) } return m.data } @@ -66,7 +66,7 @@ func (MemMapFs) Name() string { return "MemMapFS" } func (m *MemMapFs) Create(name string) (File, error) { name = normalizePath(name) m.lock() - file := mem.Create(name) + file := mem.CreateFile(name) m.getData()[name] = file m.registerWithParent(file) m.unlock() @@ -86,7 +86,8 @@ func (m *MemMapFs) unRegisterWithParent(fileName string) { log.Fatal("parent of ", f.Name(), " is nil") } pmem := parent.(*mem.File) - pmem.MemDir.Remove(*f.(*mem.File)) + fmem := f.(*mem.File) + mem.RemoveFromMemDir(pmem, fmem) } func (m *MemMapFs) findParent(f File) File { @@ -118,17 +119,14 @@ func (m *MemMapFs) registerWithParent(f File) { } } pmem := parent.(*mem.File) + fmem := f.(*mem.File) // TODO(mbertschler): memDir is only nil when it was not made with Mkdir // or lockfreeMkdir. In this case the parent is also not a real directory. // This currently only happens for the file ".". // This is a quick hack to make the library usable with relative paths. - if pmem.MemDir == nil { - pmem.Dir = true - pmem.MemDir = &mem.DirMap{} - } - - pmem.MemDir.Add(*f.(*mem.File)) + mem.InitializeDir(pmem) + mem.AddToMemDir(pmem, fmem) } func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error { @@ -144,7 +142,7 @@ func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error { return err } } else { - item := &mem.File{FileName: name, MemDir: &mem.DirMap{}, Dir: true} + item := mem.CreateDir(name) m.getData()[name] = item m.registerWithParent(item) } @@ -168,7 +166,7 @@ func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error { } } else { m.lock() - item := &mem.File{FileName: name, MemDir: &mem.DirMap{}, Dir: true} + item := mem.CreateDir(name) m.getData()[name] = item m.registerWithParent(item) m.unlock() @@ -305,7 +303,7 @@ func (m *MemMapFs) Rename(oldname, newname string) error { m.unRegisterWithParent(oldname) file := m.getData()[oldname].(*mem.File) delete(m.getData(), oldname) - file.FileName = newname + mem.ChangeFileName(file, newname) m.getData()[newname] = file m.registerWithParent(file) m.unlock() @@ -324,7 +322,8 @@ func (m *MemMapFs) Stat(name string) (os.FileInfo, error) { if err != nil { return nil, err } - return &mem.FileInfo{File: f.(*mem.File)}, nil + fi := mem.GetFileInfo(f.(*mem.File)) + return fi, nil } func (m *MemMapFs) Chmod(name string, mode os.FileMode) error { @@ -337,7 +336,7 @@ func (m *MemMapFs) Chmod(name string, mode os.FileMode) error { ff, ok := f.(*mem.File) if ok { m.lock() - ff.Mode = mode + mem.SetMode(ff, mode) m.unlock() } else { return errors.New("Unable to Chmod Memory File") @@ -355,7 +354,7 @@ func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error ff, ok := f.(*mem.File) if ok { m.lock() - ff.Modtime = mtime + mem.SetModTime(ff, mtime) m.unlock() } else { return errors.New("Unable to Chtime Memory File")