fix Readdir behaviour for n > 0, fix RemoveAll
diff --git a/fs_test.go b/fs_test.go index 301fc13..99ab330 100644 --- a/fs_test.go +++ b/fs_test.go
@@ -16,6 +16,7 @@ import ( "bytes" + "fmt" "io" "io/ioutil" "os" @@ -288,6 +289,20 @@ } f.WriteString("Testfile 2 content") f.Close() + + f, err = fs.Create(filepath.Join(testSubDir, "testfile3")) + if err != nil { + t.Fatal(err) + } + f.WriteString("Testfile 3 content") + f.Close() + + f, err = fs.Create(filepath.Join(testSubDir, "testfile4")) + if err != nil { + t.Fatal(err) + } + f.WriteString("Testfile 4 content") + f.Close() } } @@ -315,7 +330,81 @@ } } +func TestReaddirSimple(t *testing.T) { + for _, fs := range Fss { + root, err := fs.Open(testDir) + if err != nil { + t.Fatal(err) + } + rootInfo, err := root.Readdir(1) + if err != nil { + t.Log(myFileInfo(rootInfo)) + t.Error(err) + } + rootInfo, err = root.Readdir(5) + if err != io.EOF { + t.Log(myFileInfo(rootInfo)) + t.Error(err) + } + + sub, err := fs.Open(testSubDir) + if err != nil { + t.Fatal(err) + } + subInfo, err := sub.Readdir(5) + if err != nil { + t.Log(myFileInfo(subInfo)) + t.Error(err) + } + } +} + func TestReaddir(t *testing.T) { + for num := 0; num < 6; num++ { + outputs := make([]string, len(Fss)) + for i, fs := range Fss { + root, err := fs.Open(testSubDir) + if err != nil { + t.Fatal(err) + } + for j := 0; j < 6; j++ { + info, err := root.Readdir(num) + outputs[i] += fmt.Sprintf("%v Error: %v\n", myFileInfo(info), err) + } + } + + fail := false + for i, o := range outputs { + if i == 0 { + continue + } + if o != outputs[i-1] { + fail = true + break + } + } + if fail { + t.Log("Readdir outputs not equal for Readdir(", num, ")") + for i, o := range outputs { + t.Log(Fss[i].Name()) + t.Log(o) + } + t.Fail() + } + } +} + +type myFileInfo []os.FileInfo + +func (m myFileInfo) String() string { + out := "Fileinfos:\n" + for _, e := range m { + out += " " + e.Name() + "\n" + } + return out +} + +func TestReaddirAll(t *testing.T) { defer removeTestDir(t) for _, fs := range Fss { root, err := fs.Open(testDir) @@ -389,12 +478,12 @@ } func removeTestDir(t *testing.T) { - // for _, fs := range Fss { - // err := fs.RemoveAll(testDir) - // if err != nil { - // t.Fatal(err) - // } - // } + for _, fs := range Fss { + err := fs.RemoveAll(testDir) + if err != nil { + t.Fatal(err) + } + } } func newFile(testName string, fs Fs, t *testing.T) (f File) {
diff --git a/memfile.go b/memfile.go index 505b4f1..90a5ae0 100644 --- a/memfile.go +++ b/memfile.go
@@ -35,14 +35,15 @@ type InMemoryFile struct { sync.Mutex - at int64 - name string - data []byte - memDir MemDir - dir bool - closed bool - mode os.FileMode - modtime time.Time + at int64 + name string + data []byte + memDir MemDir + dir bool + closed bool + mode os.FileMode + modtime time.Time + readDirCount int64 } func MemFileCreate(name string) *InMemoryFile { @@ -51,6 +52,7 @@ func (f *InMemoryFile) Open() error { atomic.StoreInt64(&f.at, 0) + atomic.StoreInt64(&f.readDirCount, 0) f.Lock() f.closed = false f.Unlock() @@ -58,7 +60,6 @@ } func (f *InMemoryFile) Close() error { - atomic.StoreInt64(&f.at, 0) f.Lock() f.closed = true f.Unlock() @@ -74,29 +75,31 @@ } func (f *InMemoryFile) Readdir(count int) (res []os.FileInfo, err error) { - files := f.memDir.Files() - limit := len(files) + var outLength int64 - if len(files) == 0 { - return - } - + f.Lock() + files := f.memDir.Files()[f.readDirCount:] if count > 0 { - limit = count + if len(files) < count { + outLength = int64(len(files)) + } else { + outLength = int64(count) + } + if len(files) == 0 { + err = io.EOF + } + } else { + outLength = int64(len(files)) + } + f.readDirCount += outLength + f.Unlock() + + res = make([]os.FileInfo, outLength) + for i := range res { + res[i], _ = files[i].Stat() } - if len(files) < limit { - err = io.EOF - } - - res = make([]os.FileInfo, f.memDir.Len()) - - i := 0 - for _, file := range f.memDir.Files() { - res[i], _ = file.Stat() - i++ - } - return res, nil + return res, err } func (f *InMemoryFile) Readdirnames(n int) (names []string, err error) {
diff --git a/memmap.go b/memmap.go index c7b132c..5020e4c 100644 --- a/memmap.go +++ b/memmap.go
@@ -20,6 +20,7 @@ "os" "path" "path/filepath" + "sort" "strings" "sync" "time" @@ -65,9 +66,17 @@ for _, f := range m { files = append(files, f) } + sort.Sort(filesSorter(files)) return files } +type filesSorter []File + +// implement sort.Interface for []File +func (s filesSorter) Len() int { return len(s) } +func (s filesSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s filesSorter) Less(i, j int) bool { return s[i].Name() < s[j].Name() } + func (m MemDirMap) Names() (names []string) { for x := range m { names = append(names, x) @@ -95,6 +104,9 @@ return } parent := m.findParent(f) + if parent == nil { + log.Fatal("parent of ", f.Name(), " is nil") + } pmem := parent.(*InMemoryFile) pmem.memDir.Remove(f) } @@ -113,11 +125,10 @@ if f == nil { return } - var err error parent := m.findParent(f) if parent == nil { pdir := filepath.Dir(path.Clean(f.Name())) - err = m.lockfreeMkdir(pdir, 0777) + err := m.lockfreeMkdir(pdir, 0777) if err != nil { log.Println("Mkdir error:", err) return @@ -211,6 +222,10 @@ } func (m *MemMapFs) RemoveAll(path string) error { + m.lock() + m.unRegisterWithParent(path) + m.unlock() + m.rlock() defer m.runlock() @@ -218,7 +233,6 @@ if strings.HasPrefix(p, path) { m.runlock() m.lock() - m.unRegisterWithParent(p) delete(m.getData(), p) m.unlock() m.rlock()