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.

119 lines
2.8 KiB

7 years ago
6 years ago
  1. package filesys
  2. import (
  3. "bazil.org/fuse"
  4. "bazil.org/fuse/fs"
  5. "context"
  6. "math"
  7. "path/filepath"
  8. "github.com/chrislusf/seaweedfs/weed/glog"
  9. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  10. )
  11. func (dir *Dir) Rename(ctx context.Context, req *fuse.RenameRequest, newDirectory fs.Node) error {
  12. newDir := newDirectory.(*Dir)
  13. return dir.wfs.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {
  14. // find existing entry
  15. request := &filer_pb.LookupDirectoryEntryRequest{
  16. Directory: dir.Path,
  17. Name: req.OldName,
  18. }
  19. glog.V(4).Infof("find existing directory entry: %v", request)
  20. resp, err := client.LookupDirectoryEntry(ctx, request)
  21. if err != nil {
  22. glog.V(0).Infof("renaming find %s/%s: %v", dir.Path, req.OldName, err)
  23. return fuse.ENOENT
  24. }
  25. entry := resp.Entry
  26. glog.V(4).Infof("found existing directory entry resp: %+v", resp)
  27. return moveEntry(ctx, client, dir.Path, entry, newDir.Path, req.NewName)
  28. })
  29. }
  30. func moveEntry(ctx context.Context, client filer_pb.SeaweedFilerClient, oldParent string, entry *filer_pb.Entry, newParent, newName string) error {
  31. if entry.IsDirectory {
  32. currentDirPath := filepath.Join(oldParent, entry.Name)
  33. lastFileName := ""
  34. includeLastFile := false
  35. limit := math.MaxInt32
  36. for limit > 0 {
  37. request := &filer_pb.ListEntriesRequest{
  38. Directory: currentDirPath,
  39. StartFromFileName: lastFileName,
  40. InclusiveStartFrom: includeLastFile,
  41. Limit: 1024,
  42. }
  43. glog.V(4).Infof("read directory: %v", request)
  44. resp, err := client.ListEntries(ctx, request)
  45. if err != nil {
  46. glog.V(0).Infof("list %s: %v", oldParent, err)
  47. return fuse.EIO
  48. }
  49. if len(resp.Entries) == 0 {
  50. break
  51. }
  52. for _, item := range resp.Entries {
  53. lastFileName = item.Name
  54. err := moveEntry(ctx, client, currentDirPath, item, filepath.Join(newParent, newName), item.Name)
  55. if err != nil {
  56. return err
  57. }
  58. limit--
  59. }
  60. if len(resp.Entries) < 1024 {
  61. break
  62. }
  63. }
  64. }
  65. // add to new directory
  66. {
  67. request := &filer_pb.CreateEntryRequest{
  68. Directory: newParent,
  69. Entry: &filer_pb.Entry{
  70. Name: newName,
  71. IsDirectory: entry.IsDirectory,
  72. Attributes: entry.Attributes,
  73. Chunks: entry.Chunks,
  74. },
  75. }
  76. glog.V(1).Infof("create new entry: %v", request)
  77. if _, err := client.CreateEntry(ctx, request); err != nil {
  78. glog.V(0).Infof("renaming create %s/%s: %v", newParent, newName, err)
  79. return fuse.EIO
  80. }
  81. }
  82. // delete old entry
  83. {
  84. request := &filer_pb.DeleteEntryRequest{
  85. Directory: oldParent,
  86. Name: entry.Name,
  87. IsDeleteData: false,
  88. }
  89. glog.V(1).Infof("remove old entry: %v", request)
  90. _, err := client.DeleteEntry(ctx, request)
  91. if err != nil {
  92. glog.V(0).Infof("renaming delete %s/%s: %v", oldParent, entry.Name, err)
  93. return fuse.EIO
  94. }
  95. }
  96. return nil
  97. }