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.

121 lines
3.0 KiB

  1. package shell
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/chrislusf/seaweedfs/weed/filer2"
  6. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  7. "github.com/chrislusf/seaweedfs/weed/util"
  8. "google.golang.org/grpc"
  9. "io"
  10. "strings"
  11. )
  12. func init() {
  13. commands = append(commands, &commandFsDu{})
  14. }
  15. type commandFsDu struct {
  16. }
  17. func (c *commandFsDu) Name() string {
  18. return "fs.du"
  19. }
  20. func (c *commandFsDu) Help() string {
  21. return `show disk usage
  22. fs.du http://<filer_server>:<port>/dir
  23. fs.du http://<filer_server>:<port>/dir/file_name
  24. fs.du http://<filer_server>:<port>/dir/file_prefix
  25. `
  26. }
  27. func (c *commandFsDu) Do(args []string, commandEnv *commandEnv, writer io.Writer) (err error) {
  28. filerServer, filerPort, path, err := commandEnv.parseUrl(args[0])
  29. if err != nil {
  30. return err
  31. }
  32. dir, name := filer2.FullPath(path).DirAndName()
  33. if strings.HasSuffix(path, "/") {
  34. if path == "/" {
  35. dir, name = "/", ""
  36. } else {
  37. dir, name = path[0 : len(path)-1], ""
  38. }
  39. }
  40. ctx := context.Background()
  41. return commandEnv.withFilerClient(ctx, filerServer, filerPort, func(client filer_pb.SeaweedFilerClient) error {
  42. _, _, err = paginateDirectory(ctx, writer, client, dir, name, 1000)
  43. return err
  44. })
  45. }
  46. func paginateDirectory(ctx context.Context, writer io.Writer, client filer_pb.SeaweedFilerClient, dir, name string, paginateSize int) (blockCount uint64, byteCount uint64, err error) {
  47. paginatedCount := -1
  48. startFromFileName := ""
  49. for paginatedCount == -1 || paginatedCount == paginateSize {
  50. resp, listErr := client.ListEntries(ctx, &filer_pb.ListEntriesRequest{
  51. Directory: dir,
  52. Prefix: name,
  53. StartFromFileName: startFromFileName,
  54. InclusiveStartFrom: false,
  55. Limit: uint32(paginateSize),
  56. })
  57. if listErr != nil {
  58. err = listErr
  59. return
  60. }
  61. paginatedCount = len(resp.Entries)
  62. for _, entry := range resp.Entries {
  63. if entry.IsDirectory {
  64. subDir := fmt.Sprintf("%s/%s", dir, entry.Name)
  65. if dir == "/" {
  66. subDir = "/" + entry.Name
  67. }
  68. numBlock, numByte, err := paginateDirectory(ctx, writer, client, subDir, "", paginateSize)
  69. if err == nil {
  70. blockCount += numBlock
  71. byteCount += numByte
  72. }
  73. } else {
  74. blockCount += uint64(len(entry.Chunks))
  75. byteCount += filer2.TotalSize(entry.Chunks)
  76. }
  77. startFromFileName = entry.Name
  78. if name != "" && !entry.IsDirectory {
  79. fmt.Fprintf(writer, "block:%4d\tbyte:%10d\t%s/%s\n", blockCount, byteCount, dir, name)
  80. }
  81. }
  82. }
  83. if name == "" {
  84. fmt.Fprintf(writer, "block:%4d\tbyte:%10d\t%s\n", blockCount, byteCount, dir)
  85. }
  86. return
  87. }
  88. func (env *commandEnv) withFilerClient(ctx context.Context, filerServer string, filerPort int64, fn func(filer_pb.SeaweedFilerClient) error) error {
  89. filerGrpcAddress := fmt.Sprintf("%s:%d", filerServer, filerPort+10000)
  90. return util.WithCachedGrpcClient(ctx, func(grpcConnection *grpc.ClientConn) error {
  91. client := filer_pb.NewSeaweedFilerClient(grpcConnection)
  92. return fn(client)
  93. }, filerGrpcAddress, env.option.GrpcDialOption)
  94. }