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.

110 lines
3.4 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
6 years ago
6 years ago
6 years ago
  1. package command
  2. import (
  3. "strings"
  4. "github.com/chrislusf/seaweedfs/weed/glog"
  5. "github.com/chrislusf/seaweedfs/weed/replication"
  6. "github.com/chrislusf/seaweedfs/weed/replication/sink"
  7. _ "github.com/chrislusf/seaweedfs/weed/replication/sink/azuresink"
  8. _ "github.com/chrislusf/seaweedfs/weed/replication/sink/b2sink"
  9. _ "github.com/chrislusf/seaweedfs/weed/replication/sink/filersink"
  10. _ "github.com/chrislusf/seaweedfs/weed/replication/sink/gcssink"
  11. _ "github.com/chrislusf/seaweedfs/weed/replication/sink/s3sink"
  12. "github.com/chrislusf/seaweedfs/weed/server"
  13. "github.com/spf13/viper"
  14. )
  15. func init() {
  16. cmdFilerReplicate.Run = runFilerReplicate // break init cycle
  17. }
  18. var cmdFilerReplicate = &Command{
  19. UsageLine: "filer.replicate",
  20. Short: "replicate file changes to another destination",
  21. Long: `replicate file changes to another destination
  22. filer.replicate listens on filer notifications. If any file is updated, it will fetch the updated content,
  23. and write to the other destination.
  24. Run "weed scaffold -config replication" to generate a replication.toml file and customize the parameters.
  25. `,
  26. }
  27. func runFilerReplicate(cmd *Command, args []string) bool {
  28. weed_server.LoadConfiguration("replication", true)
  29. config := viper.GetViper()
  30. var notificationInput replication.NotificationInput
  31. for _, input := range replication.NotificationInputs {
  32. if config.GetBool("notification." + input.GetName() + ".enabled") {
  33. viperSub := config.Sub("notification." + input.GetName())
  34. if err := input.Initialize(viperSub); err != nil {
  35. glog.Fatalf("Failed to initialize notification input for %s: %+v",
  36. input.GetName(), err)
  37. }
  38. glog.V(0).Infof("Configure notification input to %s", input.GetName())
  39. notificationInput = input
  40. break
  41. }
  42. }
  43. // avoid recursive replication
  44. if config.GetBool("notification.source.filer.enabled") && config.GetBool("notification.sink.filer.enabled") {
  45. sourceConfig, sinkConfig := config.Sub("source.filer"), config.Sub("sink.filer")
  46. if sourceConfig.GetString("grpcAddress") == sinkConfig.GetString("grpcAddress") {
  47. fromDir := sourceConfig.GetString("directory")
  48. toDir := sinkConfig.GetString("directory")
  49. if strings.HasPrefix(toDir, fromDir) {
  50. glog.Fatalf("recursive replication! source directory %s includes the sink directory %s", fromDir, toDir)
  51. }
  52. }
  53. }
  54. var dataSink sink.ReplicationSink
  55. for _, sk := range sink.Sinks {
  56. if config.GetBool("sink." + sk.GetName() + ".enabled") {
  57. viperSub := config.Sub("sink." + sk.GetName())
  58. if err := sk.Initialize(viperSub); err != nil {
  59. glog.Fatalf("Failed to initialize sink for %s: %+v",
  60. sk.GetName(), err)
  61. }
  62. glog.V(0).Infof("Configure sink to %s", sk.GetName())
  63. dataSink = sk
  64. break
  65. }
  66. }
  67. if dataSink == nil {
  68. println("no data sink configured:")
  69. for _, sk := range sink.Sinks {
  70. println(" " + sk.GetName())
  71. }
  72. return true
  73. }
  74. replicator := replication.NewReplicator(config.Sub("source.filer"), dataSink)
  75. for {
  76. key, m, err := notificationInput.ReceiveMessage()
  77. if err != nil {
  78. glog.Errorf("receive %s: %+v", key, err)
  79. continue
  80. }
  81. if m.OldEntry != nil && m.NewEntry == nil {
  82. glog.V(1).Infof("delete: %s", key)
  83. } else if m.OldEntry == nil && m.NewEntry != nil {
  84. glog.V(1).Infof(" add: %s", key)
  85. } else {
  86. glog.V(1).Infof("modify: %s", key)
  87. }
  88. if err = replicator.Replicate(key, m); err != nil {
  89. glog.Errorf("replicate %s: %+v", key, err)
  90. }
  91. }
  92. return true
  93. }