directory_read.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. package mount
  2. import (
  3. "context"
  4. "github.com/chrislusf/seaweedfs/weed/filer"
  5. "github.com/chrislusf/seaweedfs/weed/glog"
  6. "github.com/chrislusf/seaweedfs/weed/mount/meta_cache"
  7. "github.com/chrislusf/seaweedfs/weed/util"
  8. "github.com/hanwen/go-fuse/v2/fs"
  9. "github.com/hanwen/go-fuse/v2/fuse"
  10. "math"
  11. "os"
  12. "syscall"
  13. )
  14. var _ = fs.NodeReaddirer(&Directory{})
  15. var _ = fs.NodeGetattrer(&Directory{})
  16. func (dir *Directory) Getattr(ctx context.Context, fh fs.FileHandle, out *fuse.AttrOut) syscall.Errno {
  17. out.Mode = 0755
  18. return 0
  19. }
  20. func (dir *Directory) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
  21. dirPath := util.FullPath(dir.FullPath())
  22. glog.V(4).Infof("Readdir %s", dirPath)
  23. sourceChan := make(chan fuse.DirEntry, 64)
  24. stream := newDirectoryListStream(sourceChan)
  25. processEachEntryFn := func(entry *filer.Entry, isLast bool) {
  26. sourceChan <- fuse.DirEntry{
  27. Mode: uint32(entry.Mode),
  28. Name: entry.Name(),
  29. Ino: dirPath.Child(entry.Name()).AsInode(os.ModeDir),
  30. }
  31. }
  32. if err := meta_cache.EnsureVisited(dir.wfs.metaCache, dir.wfs, dirPath); err != nil {
  33. glog.Errorf("dir ReadDirAll %s: %v", dirPath, err)
  34. return nil, fs.ToErrno(os.ErrInvalid)
  35. }
  36. go func() {
  37. dir.wfs.metaCache.ListDirectoryEntries(context.Background(), dirPath, "", false, int64(math.MaxInt32), func(entry *filer.Entry) bool {
  38. processEachEntryFn(entry, false)
  39. return true
  40. })
  41. close(sourceChan)
  42. }()
  43. return stream, fs.OK
  44. }
  45. var _ = fs.DirStream(&DirectoryListStream{})
  46. type DirectoryListStream struct {
  47. next fuse.DirEntry
  48. sourceChan chan fuse.DirEntry
  49. isStarted bool
  50. hasNext bool
  51. }
  52. func newDirectoryListStream(ch chan fuse.DirEntry) *DirectoryListStream {
  53. return &DirectoryListStream{
  54. sourceChan: ch,
  55. }
  56. }
  57. func (i *DirectoryListStream) HasNext() bool {
  58. if !i.isStarted {
  59. i.next, i.hasNext = <-i.sourceChan
  60. i.isStarted = true
  61. }
  62. return i.hasNext
  63. }
  64. func (i *DirectoryListStream) Next() (fuse.DirEntry, syscall.Errno) {
  65. t := i.next
  66. i.next, i.hasNext = <-i.sourceChan
  67. return t, fs.OK
  68. }
  69. func (i *DirectoryListStream) Close() {
  70. }