forked from mirror/afero
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:
parent
6ced24dbe1
commit
3de0cfae06
86
memmap.go
86
memmap.go
|
@ -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 nil
|
||||||
|
}
|
||||||
return pfile
|
return pfile
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
} else {
|
|
||||||
pdir := filepath.Dir(path.Clean(f.Name()))
|
|
||||||
m.Mkdir(pdir, 0777)
|
|
||||||
}
|
}
|
||||||
return parent
|
|
||||||
|
func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error {
|
||||||
|
_, ok := m.getData()[name]
|
||||||
|
if ok {
|
||||||
|
return ErrFileExists
|
||||||
|
} else {
|
||||||
|
item := &InMemoryFile{name: name, memDir: &MemDirMap{}, dir: true}
|
||||||
|
m.getData()[name] = item
|
||||||
|
m.registerWithParent(item)
|
||||||
|
}
|
||||||
|
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()
|
||||||
|
|
Loading…
Reference in New Issue