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.

133 lines
3.4 KiB

6 years ago
  1. package command
  2. import (
  3. "github.com/chrislusf/seaweedfs/weed/filer2"
  4. "github.com/chrislusf/seaweedfs/weed/glog"
  5. "github.com/chrislusf/seaweedfs/weed/server"
  6. "github.com/spf13/viper"
  7. )
  8. func init() {
  9. cmdFilerExport.Run = runFilerExport // break init cycle
  10. }
  11. var cmdFilerExport = &Command{
  12. UsageLine: "filer.export -sourceStore=mysql -targetStroe=cassandra",
  13. Short: "export meta data in filer store",
  14. Long: `Iterate the file tree and export all metadata out
  15. Both source and target store:
  16. * should be a store name already specified in filer.toml
  17. * do not need to be enabled state
  18. If target store is empty, only the directory tree will be listed.
  19. `,
  20. }
  21. var (
  22. // filerExportOutputFile = cmdFilerExport.Flag.String("output", "", "the output file. If empty, only list out the directory tree")
  23. filerExportSourceStore = cmdFilerExport.Flag.String("sourceStore", "", "the source store name in filer.toml")
  24. filerExportTargetStore = cmdFilerExport.Flag.String("targetStore", "", "the target store name in filer.toml")
  25. dirListLimit = cmdFilerExport.Flag.Int("dirListLimit", 100000, "limit directory list size")
  26. )
  27. type statistics struct {
  28. directoryCount int
  29. fileCount int
  30. }
  31. func runFilerExport(cmd *Command, args []string) bool {
  32. weed_server.LoadConfiguration("filer", true)
  33. config := viper.GetViper()
  34. var sourceStore, targetStore filer2.FilerStore
  35. for _, store := range filer2.Stores {
  36. if store.GetName() == *filerExportSourceStore {
  37. viperSub := config.Sub(store.GetName())
  38. if err := store.Initialize(viperSub); err != nil {
  39. glog.Fatalf("Failed to initialize store for %s: %+v",
  40. store.GetName(), err)
  41. } else {
  42. sourceStore = store
  43. }
  44. break
  45. }
  46. }
  47. for _, store := range filer2.Stores {
  48. if store.GetName() == *filerExportTargetStore {
  49. viperSub := config.Sub(store.GetName())
  50. if err := store.Initialize(viperSub); err != nil {
  51. glog.Fatalf("Failed to initialize store for %s: %+v",
  52. store.GetName(), err)
  53. } else {
  54. targetStore = store
  55. }
  56. break
  57. }
  58. }
  59. if sourceStore == nil {
  60. glog.Errorf("Failed to find source store %s", *filerExportSourceStore)
  61. println("existing data sources are:")
  62. for _, store := range filer2.Stores {
  63. println(" " + store.GetName())
  64. }
  65. return false
  66. }
  67. stat := statistics{}
  68. var fn func(level int, entry *filer2.Entry) error
  69. if targetStore == nil {
  70. fn = printout
  71. } else {
  72. fn = func(level int, entry *filer2.Entry) error {
  73. return targetStore.InsertEntry(entry)
  74. }
  75. }
  76. doTraverse(&stat, sourceStore, filer2.FullPath("/"), 0, fn)
  77. glog.Infof("processed %d directories, %d files", stat.directoryCount, stat.fileCount)
  78. return true
  79. }
  80. func doTraverse(stat *statistics, filerStore filer2.FilerStore, parentPath filer2.FullPath, level int, fn func(level int, entry *filer2.Entry) error) {
  81. limit := *dirListLimit
  82. lastEntryName := ""
  83. for {
  84. entries, err := filerStore.ListDirectoryEntries(parentPath, lastEntryName, false, limit)
  85. if err != nil {
  86. break
  87. }
  88. for _, entry := range entries {
  89. if fnErr := fn(level, entry); fnErr != nil {
  90. glog.Errorf("failed to process entry: %s", entry.FullPath)
  91. }
  92. if entry.IsDirectory() {
  93. stat.directoryCount++
  94. doTraverse(stat, filerStore, entry.FullPath, level+1, fn)
  95. } else {
  96. stat.fileCount++
  97. }
  98. }
  99. if len(entries) < limit {
  100. break
  101. }
  102. }
  103. }
  104. func printout(level int, entry *filer2.Entry) error {
  105. for i := 0; i < level; i++ {
  106. print(" ")
  107. }
  108. println(entry.FullPath.Name())
  109. return nil
  110. }