You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
3.0 KiB

7 years ago
7 years ago
  1. package filesys
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "path"
  7. "sync"
  8. "bazil.org/fuse/fs"
  9. "bazil.org/fuse"
  10. "github.com/chrislusf/seaweedfs/weed/filer"
  11. "github.com/chrislusf/seaweedfs/weed/glog"
  12. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  13. "time"
  14. )
  15. type Dir struct {
  16. Path string
  17. NodeMap map[string]fs.Node
  18. NodeMapLock sync.Mutex
  19. wfs *WFS
  20. }
  21. func (dir *Dir) Attr(context context.Context, attr *fuse.Attr) error {
  22. attr.Mode = os.ModeDir | 0777
  23. return nil
  24. }
  25. func (dir *Dir) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fs.Node, error) {
  26. dir.NodeMapLock.Lock()
  27. defer dir.NodeMapLock.Unlock()
  28. fmt.Printf("mkdir %+v\n", req)
  29. node := &Dir{Path: path.Join(dir.Path, req.Name), wfs: dir.wfs}
  30. dir.NodeMap[req.Name] = node
  31. return node, nil
  32. }
  33. func (dir *Dir) Lookup(ctx context.Context, name string) (node fs.Node, err error) {
  34. dir.NodeMapLock.Lock()
  35. defer dir.NodeMapLock.Unlock()
  36. if dir.NodeMap == nil {
  37. dir.NodeMap = make(map[string]fs.Node)
  38. }
  39. if node, ok := dir.NodeMap[name]; ok {
  40. return node, nil
  41. }
  42. var entry *filer_pb.Entry
  43. err = dir.wfs.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {
  44. request := &filer_pb.LookupDirectoryEntryRequest{
  45. Directory: dir.Path,
  46. Name: name,
  47. }
  48. glog.V(1).Infof("lookup directory entry: %v", request)
  49. resp, err := client.LookupDirectoryEntry(ctx, request)
  50. if err != nil {
  51. return err
  52. }
  53. entry = resp.Entry
  54. return nil
  55. })
  56. if entry != nil {
  57. if entry.IsDirectory {
  58. node = &Dir{Path: path.Join(dir.Path, name), wfs: dir.wfs}
  59. } else {
  60. node = &File{FileId: filer.FileId(entry.FileId), Name: name, dir: dir, wfs: dir.wfs}
  61. }
  62. dir.NodeMap[name] = node
  63. return node, nil
  64. }
  65. return nil, err
  66. }
  67. func (dir *Dir) ReadDirAll(ctx context.Context) (ret []fuse.Dirent, err error) {
  68. err = dir.wfs.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {
  69. request := &filer_pb.ListEntriesRequest{
  70. Directory: dir.Path,
  71. }
  72. glog.V(1).Infof("read directory: %v", request)
  73. resp, err := client.ListEntries(ctx, request)
  74. if err != nil {
  75. return err
  76. }
  77. for _, entry := range resp.Entries {
  78. if entry.IsDirectory {
  79. dirent := fuse.Dirent{Name: entry.Name, Type: fuse.DT_Dir}
  80. ret = append(ret, dirent)
  81. } else {
  82. dirent := fuse.Dirent{Name: entry.Name, Type: fuse.DT_File}
  83. ret = append(ret, dirent)
  84. dir.wfs.listDirectoryEntriesCache.Set(dir.Path+"/"+entry.Name, entry.Attributes, 3*time.Second)
  85. }
  86. }
  87. return nil
  88. })
  89. return ret, err
  90. }
  91. func (dir *Dir) Remove(ctx context.Context, req *fuse.RemoveRequest) error {
  92. dir.NodeMapLock.Lock()
  93. defer dir.NodeMapLock.Unlock()
  94. return dir.wfs.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {
  95. request := &filer_pb.DeleteEntryRequest{
  96. Directory: dir.Path,
  97. Name: req.Name,
  98. IsDirectory: req.Dir,
  99. }
  100. glog.V(1).Infof("remove directory entry: %v", request)
  101. _, err := client.DeleteEntry(ctx, request)
  102. if err != nil {
  103. return err
  104. }
  105. delete(dir.NodeMap, req.Name)
  106. return nil
  107. })
  108. }