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.

126 lines
3.7 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. package command
  2. import (
  3. "fmt"
  4. "github.com/chrislusf/seaweedfs/weed/security"
  5. "github.com/chrislusf/seaweedfs/weed/storage/needle"
  6. "github.com/chrislusf/seaweedfs/weed/util"
  7. "github.com/spf13/viper"
  8. "github.com/chrislusf/seaweedfs/weed/operation"
  9. "github.com/chrislusf/seaweedfs/weed/storage"
  10. )
  11. var (
  12. s BackupOptions
  13. )
  14. type BackupOptions struct {
  15. master *string
  16. collection *string
  17. dir *string
  18. volumeId *int
  19. }
  20. func init() {
  21. cmdBackup.Run = runBackup // break init cycle
  22. s.master = cmdBackup.Flag.String("server", "localhost:9333", "SeaweedFS master location")
  23. s.collection = cmdBackup.Flag.String("collection", "", "collection name")
  24. s.dir = cmdBackup.Flag.String("dir", ".", "directory to store volume data files")
  25. s.volumeId = cmdBackup.Flag.Int("volumeId", -1, "a volume id. The volume .dat and .idx files should already exist in the dir.")
  26. }
  27. var cmdBackup = &Command{
  28. UsageLine: "backup -dir=. -volumeId=234 -server=localhost:9333",
  29. Short: "incrementally backup a volume to local folder",
  30. Long: `Incrementally backup volume data.
  31. It is expected that you use this inside a script, to loop through
  32. all possible volume ids that needs to be backup to local folder.
  33. The volume id does not need to exist locally or even remotely.
  34. This will help to backup future new volumes.
  35. Usually backing up is just copying the .dat (and .idx) files.
  36. But it's tricky to incrementally copy the differences.
  37. The complexity comes when there are multiple addition, deletion and compaction.
  38. This tool will handle them correctly and efficiently, avoiding unnecessary data transportation.
  39. `,
  40. }
  41. func runBackup(cmd *Command, args []string) bool {
  42. util.LoadConfiguration("security", false)
  43. grpcDialOption := security.LoadClientTLS(viper.Sub("grpc"), "client")
  44. if *s.volumeId == -1 {
  45. return false
  46. }
  47. vid := needle.VolumeId(*s.volumeId)
  48. // find volume location, replication, ttl info
  49. lookup, err := operation.Lookup(*s.master, vid.String())
  50. if err != nil {
  51. fmt.Printf("Error looking up volume %d: %v\n", vid, err)
  52. return true
  53. }
  54. volumeServer := lookup.Locations[0].Url
  55. stats, err := operation.GetVolumeSyncStatus(volumeServer, grpcDialOption, uint32(vid))
  56. if err != nil {
  57. fmt.Printf("Error get volume %d status: %v\n", vid, err)
  58. return true
  59. }
  60. ttl, err := needle.ReadTTL(stats.Ttl)
  61. if err != nil {
  62. fmt.Printf("Error get volume %d ttl %s: %v\n", vid, stats.Ttl, err)
  63. return true
  64. }
  65. replication, err := storage.NewReplicaPlacementFromString(stats.Replication)
  66. if err != nil {
  67. fmt.Printf("Error get volume %d replication %s : %v\n", vid, stats.Replication, err)
  68. return true
  69. }
  70. v, err := storage.NewVolume(*s.dir, *s.collection, vid, storage.NeedleMapInMemory, replication, ttl, 0)
  71. if err != nil {
  72. fmt.Printf("Error creating or reading from volume %d: %v\n", vid, err)
  73. return true
  74. }
  75. if v.SuperBlock.CompactionRevision < uint16(stats.CompactRevision) {
  76. if err = v.Compact(0, 0); err != nil {
  77. fmt.Printf("Compact Volume before synchronizing %v\n", err)
  78. return true
  79. }
  80. if err = v.CommitCompact(); err != nil {
  81. fmt.Printf("Commit Compact before synchronizing %v\n", err)
  82. return true
  83. }
  84. v.SuperBlock.CompactionRevision = uint16(stats.CompactRevision)
  85. v.DataFile().WriteAt(v.SuperBlock.Bytes(), 0)
  86. }
  87. datSize, _, _ := v.FileStat()
  88. if datSize > stats.TailOffset {
  89. // remove the old data
  90. v.Destroy()
  91. // recreate an empty volume
  92. v, err = storage.NewVolume(*s.dir, *s.collection, vid, storage.NeedleMapInMemory, replication, ttl, 0)
  93. if err != nil {
  94. fmt.Printf("Error creating or reading from volume %d: %v\n", vid, err)
  95. return true
  96. }
  97. }
  98. defer v.Close()
  99. if err := v.IncrementalBackup(volumeServer, grpcDialOption); err != nil {
  100. fmt.Printf("Error synchronizing volume %d: %v\n", vid, err)
  101. return true
  102. }
  103. return true
  104. }