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.

90 lines
2.6 KiB

  1. package command
  2. import (
  3. "fmt"
  4. "github.com/chrislusf/seaweedfs/weed/operation"
  5. "github.com/chrislusf/seaweedfs/weed/storage"
  6. )
  7. var (
  8. s BackupOptions
  9. )
  10. type BackupOptions struct {
  11. master *string
  12. collection *string
  13. dir *string
  14. volumeId *int
  15. }
  16. func init() {
  17. cmdBackup.Run = runBackup // break init cycle
  18. s.master = cmdBackup.Flag.String("server", "localhost:9333", "SeaweedFS master location")
  19. s.collection = cmdBackup.Flag.String("collection", "", "collection name")
  20. s.dir = cmdBackup.Flag.String("dir", ".", "directory to store volume data files")
  21. s.volumeId = cmdBackup.Flag.Int("volumeId", -1, "a volume id. The volume .dat and .idx files should already exist in the dir.")
  22. }
  23. var cmdBackup = &Command{
  24. UsageLine: "backup -dir=. -volumeId=234 -server=localhost:9333",
  25. Short: "incrementally backup a volume to local folder",
  26. Long: `Incrementally backup volume data.
  27. It is expected that you use this inside a script, to loop through
  28. all possible volume ids that needs to be backup to local folder.
  29. The volume id does not need to exist locally or even remotely.
  30. This will help to backup future new volumes.
  31. Usually backing up is just copying the .dat (and .idx) files.
  32. But it's tricky to incremententally copy the differences.
  33. The complexity comes when there are multiple addition, deletion and compaction.
  34. This tool will handle them correctly and efficiently, avoiding unnecessary data transporation.
  35. `,
  36. }
  37. func runBackup(cmd *Command, args []string) bool {
  38. if *s.volumeId == -1 {
  39. return false
  40. }
  41. vid := storage.VolumeId(*s.volumeId)
  42. // find volume location, replication, ttl info
  43. lookup, err := operation.Lookup(*s.master, vid.String())
  44. if err != nil {
  45. fmt.Printf("Error looking up volume %d: %v\n", vid, err)
  46. return true
  47. }
  48. volumeServer := lookup.Locations[0].Url
  49. stats, err := operation.GetVolumeSyncStatus(volumeServer, vid.String())
  50. if err != nil {
  51. fmt.Printf("Error get volume %d status: %v\n", vid, err)
  52. return true
  53. }
  54. ttl, err := storage.ReadTTL(stats.Ttl)
  55. if err != nil {
  56. fmt.Printf("Error get volume %d ttl %s: %v\n", vid, stats.Ttl, err)
  57. return true
  58. }
  59. replication, err := storage.NewReplicaPlacementFromString(stats.Replication)
  60. if err != nil {
  61. fmt.Printf("Error get volume %d replication %s : %v\n", vid, stats.Replication, err)
  62. return true
  63. }
  64. v, err := storage.NewVolume(*s.dir, *s.collection, vid, storage.NeedleMapInMemory, replication, ttl, 0)
  65. if err != nil {
  66. fmt.Printf("Error creating or reading from volume %d: %v\n", vid, err)
  67. return true
  68. }
  69. if err := v.Synchronize(volumeServer); err != nil {
  70. fmt.Printf("Error synchronizing volume %d: %v\n", vid, err)
  71. return true
  72. }
  73. return true
  74. }