make Readdir and Readdirnames work

+ fix registerWithParent function
+ fix unRegisterWithParent and use it in Remove and RemoveAll
+ fix findParent function
+ add lock free versions of Mkdir and Open for the use during register and unregistering with parent, so that these changes happen atomical
This commit is contained in:
Martin Bertschler 2015-10-17 12:58:11 +02:00
parent 6ced24dbe1
commit 3de0cfae06
1 changed files with 64 additions and 36 deletions

View File

@ -16,6 +16,7 @@ package afero
import ( import (
"errors" "errors"
"fmt" "fmt"
"log"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
@ -80,56 +81,67 @@ func (m *MemMapFs) Create(name string) (File, error) {
m.lock() m.lock()
file := MemFileCreate(name) file := MemFileCreate(name)
m.getData()[name] = file m.getData()[name] = file
m.registerWithParent(file)
m.unlock() m.unlock()
m.registerDirs(file)
return file, nil return file, nil
} }
func (m *MemMapFs) registerDirs(f File) { func (m *MemMapFs) unRegisterWithParent(fileName string) {
var x = f.Name() f, err := m.lockfreeOpen(fileName)
for x != "/" { if err != nil {
f := m.registerWithParent(f) if os.IsNotExist(err) {
if f == nil { log.Println("Open err:", err)
break
} }
x = f.Name() return
} }
}
func (m *MemMapFs) unRegisterWithParent(f File) File {
parent := m.findParent(f) parent := m.findParent(f)
pmem := parent.(*InMemoryFile) pmem := parent.(*InMemoryFile)
pmem.memDir.Remove(f) pmem.memDir.Remove(f)
return parent
} }
func (m *MemMapFs) findParent(f File) File { func (m *MemMapFs) findParent(f File) File {
dirs, _ := path.Split(f.Name()) pdir, _ := path.Split(f.Name())
if len(dirs) > 1 { pdir = path.Clean(pdir)
_, parent := path.Split(path.Clean(dirs)) pfile, err := m.lockfreeOpen(pdir)
if len(parent) > 0 {
pfile, err := m.Open(parent)
if err != nil { if err != nil {
return pfile
}
}
}
return nil return nil
}
return pfile
} }
func (m *MemMapFs) registerWithParent(f File) File { func (m *MemMapFs) registerWithParent(f File) {
if f == nil { if f == nil {
return nil return
} }
var err error
parent := m.findParent(f) parent := m.findParent(f)
if parent != nil { if parent == nil {
pdir := filepath.Dir(path.Clean(f.Name()))
err = m.lockfreeMkdir(pdir, 0777)
if err != nil {
log.Println("Mkdir error:", err)
return
}
parent, err = m.lockfreeOpen(pdir)
if err != nil {
log.Println("Open after Mkdir error:", err)
return
}
}
pmem := parent.(*InMemoryFile) pmem := parent.(*InMemoryFile)
pmem.memDir.Add(f) pmem.memDir.Add(f)
}
func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error {
_, ok := m.getData()[name]
if ok {
return ErrFileExists
} else { } else {
pdir := filepath.Dir(path.Clean(f.Name())) item := &InMemoryFile{name: name, memDir: &MemDirMap{}, dir: true}
m.Mkdir(pdir, 0777) m.getData()[name] = item
m.registerWithParent(item)
} }
return parent return nil
} }
func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error { func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
@ -142,8 +154,8 @@ func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
m.lock() m.lock()
item := &InMemoryFile{name: name, memDir: &MemDirMap{}, dir: true} item := &InMemoryFile{name: name, memDir: &MemDirMap{}, dir: true}
m.getData()[name] = item m.getData()[name] = item
m.registerWithParent(item)
m.unlock() m.unlock()
m.registerDirs(item)
} }
return nil return nil
} }
@ -168,6 +180,19 @@ func (m *MemMapFs) Open(name string) (File, error) {
} }
} }
func (m *MemMapFs) lockfreeOpen(name string) (File, error) {
f, ok := m.getData()[name]
ff, ok := f.(*InMemoryFile)
if ok {
ff.Open()
}
if ok {
return f, nil
} else {
return nil, ErrFileNotFound
}
}
func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
return m.Open(name) return m.Open(name)
} }
@ -177,6 +202,7 @@ func (m *MemMapFs) Remove(name string) error {
defer m.unlock() defer m.unlock()
if _, ok := m.getData()[name]; ok { if _, ok := m.getData()[name]; ok {
m.unRegisterWithParent(name)
delete(m.getData(), name) delete(m.getData(), name)
} else { } else {
return &os.PathError{"remove", name, os.ErrNotExist} return &os.PathError{"remove", name, os.ErrNotExist}
@ -187,10 +213,12 @@ func (m *MemMapFs) Remove(name string) error {
func (m *MemMapFs) RemoveAll(path string) error { func (m *MemMapFs) RemoveAll(path string) error {
m.rlock() m.rlock()
defer m.runlock() defer m.runlock()
for p, _ := range m.getData() { for p, _ := range m.getData() {
if strings.HasPrefix(p, path) { if strings.HasPrefix(p, path) {
m.runlock() m.runlock()
m.lock() m.lock()
m.unRegisterWithParent(p)
delete(m.getData(), p) delete(m.getData(), p)
m.unlock() m.unlock()
m.rlock() m.rlock()