2022-02-11 11:09:30 +00:00
|
|
|
package mount
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"github.com/chrislusf/seaweedfs/weed/filer"
|
|
|
|
"github.com/chrislusf/seaweedfs/weed/glog"
|
2022-02-14 09:09:31 +00:00
|
|
|
"github.com/chrislusf/seaweedfs/weed/mount/meta_cache"
|
2022-02-11 11:09:30 +00:00
|
|
|
"github.com/chrislusf/seaweedfs/weed/util"
|
|
|
|
"github.com/hanwen/go-fuse/v2/fs"
|
|
|
|
"github.com/hanwen/go-fuse/v2/fuse"
|
|
|
|
"math"
|
|
|
|
"os"
|
|
|
|
"syscall"
|
|
|
|
)
|
|
|
|
|
|
|
|
var _ = fs.NodeReaddirer(&Directory{})
|
|
|
|
var _ = fs.NodeGetattrer(&Directory{})
|
|
|
|
|
|
|
|
func (dir *Directory) Getattr(ctx context.Context, fh fs.FileHandle, out *fuse.AttrOut) syscall.Errno {
|
|
|
|
out.Mode = 0755
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (dir *Directory) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
|
|
|
|
|
|
|
|
dirPath := util.FullPath(dir.FullPath())
|
|
|
|
glog.V(4).Infof("Readdir %s", dirPath)
|
|
|
|
|
|
|
|
sourceChan := make(chan fuse.DirEntry, 64)
|
|
|
|
|
|
|
|
stream := newDirectoryListStream(sourceChan)
|
|
|
|
|
|
|
|
processEachEntryFn := func(entry *filer.Entry, isLast bool) {
|
|
|
|
sourceChan <- fuse.DirEntry{
|
|
|
|
Mode: uint32(entry.Mode),
|
|
|
|
Name: entry.Name(),
|
|
|
|
Ino: dirPath.Child(entry.Name()).AsInode(os.ModeDir),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := meta_cache.EnsureVisited(dir.wfs.metaCache, dir.wfs, dirPath); err != nil {
|
|
|
|
glog.Errorf("dir ReadDirAll %s: %v", dirPath, err)
|
|
|
|
return nil, fs.ToErrno(os.ErrInvalid)
|
|
|
|
}
|
|
|
|
go func() {
|
|
|
|
dir.wfs.metaCache.ListDirectoryEntries(context.Background(), dirPath, "", false, int64(math.MaxInt32), func(entry *filer.Entry) bool {
|
|
|
|
processEachEntryFn(entry, false)
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
close(sourceChan)
|
|
|
|
}()
|
|
|
|
|
|
|
|
return stream, fs.OK
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ = fs.DirStream(&DirectoryListStream{})
|
|
|
|
|
|
|
|
type DirectoryListStream struct {
|
|
|
|
next fuse.DirEntry
|
|
|
|
sourceChan chan fuse.DirEntry
|
|
|
|
isStarted bool
|
|
|
|
hasNext bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func newDirectoryListStream(ch chan fuse.DirEntry) *DirectoryListStream {
|
|
|
|
return &DirectoryListStream{
|
|
|
|
sourceChan: ch,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *DirectoryListStream) HasNext() bool {
|
|
|
|
if !i.isStarted {
|
|
|
|
i.next, i.hasNext = <-i.sourceChan
|
|
|
|
i.isStarted = true
|
|
|
|
}
|
|
|
|
return i.hasNext
|
|
|
|
}
|
|
|
|
func (i *DirectoryListStream) Next() (fuse.DirEntry, syscall.Errno) {
|
|
|
|
t := i.next
|
|
|
|
i.next, i.hasNext = <-i.sourceChan
|
|
|
|
return t, fs.OK
|
|
|
|
}
|
|
|
|
func (i *DirectoryListStream) Close() {
|
|
|
|
}
|