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.

100 lines
3.8 KiB

11 months ago
11 months ago
11 months ago
  1. package broker
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/seaweedfs/seaweedfs/weed/glog"
  6. "github.com/seaweedfs/seaweedfs/weed/mq/pub_balancer"
  7. "github.com/seaweedfs/seaweedfs/weed/mq/topic"
  8. "github.com/seaweedfs/seaweedfs/weed/pb"
  9. "github.com/seaweedfs/seaweedfs/weed/pb/mq_pb"
  10. "sync"
  11. )
  12. // AssignTopicPartitions Runs on the assigned broker, to execute the topic partition assignment
  13. func (b *MessageQueueBroker) AssignTopicPartitions(c context.Context, request *mq_pb.AssignTopicPartitionsRequest) (*mq_pb.AssignTopicPartitionsResponse, error) {
  14. ret := &mq_pb.AssignTopicPartitionsResponse{}
  15. self := pb.ServerAddress(fmt.Sprintf("%s:%d", b.option.Ip, b.option.Port))
  16. // drain existing topic partition subscriptions
  17. for _, assignment := range request.BrokerPartitionAssignments {
  18. t := topic.FromPbTopic(request.Topic)
  19. partition := topic.FromPbPartition(assignment.Partition)
  20. b.accessLock.Lock()
  21. if request.IsDraining {
  22. // TODO drain existing topic partition subscriptions
  23. b.localTopicManager.RemoveTopicPartition(t, partition)
  24. } else {
  25. var localPartition *topic.LocalPartition
  26. if localPartition = b.localTopicManager.GetTopicPartition(t, partition); localPartition == nil {
  27. localPartition = topic.FromPbBrokerPartitionAssignment(self, partition, assignment, b.genLogFlushFunc(t, assignment.Partition), b.genLogOnDiskReadFunc(t, assignment.Partition))
  28. b.localTopicManager.AddTopicPartition(t, localPartition)
  29. }
  30. }
  31. b.accessLock.Unlock()
  32. }
  33. // if is leader, notify the followers to drain existing topic partition subscriptions
  34. if request.IsLeader {
  35. for _, brokerPartition := range request.BrokerPartitionAssignments {
  36. for _, follower := range brokerPartition.FollowerBrokers {
  37. err := pb.WithBrokerGrpcClient(false, follower, b.grpcDialOption, func(client mq_pb.SeaweedMessagingClient) error {
  38. _, err := client.AssignTopicPartitions(context.Background(), request)
  39. return err
  40. })
  41. if err != nil {
  42. return ret, err
  43. }
  44. }
  45. }
  46. }
  47. glog.V(0).Infof("AssignTopicPartitions: topic %s partition assignments: %v", request.Topic, request.BrokerPartitionAssignments)
  48. return ret, nil
  49. }
  50. // called by broker leader to drain existing partitions.
  51. // new/updated partitions will be detected by broker from the filer
  52. func (b *MessageQueueBroker) assignTopicPartitionsToBrokers(ctx context.Context, t *mq_pb.Topic, assignments []*mq_pb.BrokerPartitionAssignment, isAdd bool) error {
  53. // notify the brokers to create the topic partitions in parallel
  54. var wg sync.WaitGroup
  55. for _, bpa := range assignments {
  56. wg.Add(1)
  57. go func(bpa *mq_pb.BrokerPartitionAssignment) {
  58. defer wg.Done()
  59. if doCreateErr := b.withBrokerClient(false, pb.ServerAddress(bpa.LeaderBroker), func(client mq_pb.SeaweedMessagingClient) error {
  60. _, doCreateErr := client.AssignTopicPartitions(ctx, &mq_pb.AssignTopicPartitionsRequest{
  61. Topic: t,
  62. BrokerPartitionAssignments: []*mq_pb.BrokerPartitionAssignment{
  63. {
  64. Partition: bpa.Partition,
  65. },
  66. },
  67. IsLeader: true,
  68. IsDraining: !isAdd,
  69. })
  70. if doCreateErr != nil {
  71. if !isAdd {
  72. return fmt.Errorf("drain topic %s %v on %s: %v", t, bpa.LeaderBroker, bpa.Partition, doCreateErr)
  73. } else {
  74. return fmt.Errorf("create topic %s %v on %s: %v", t, bpa.LeaderBroker, bpa.Partition, doCreateErr)
  75. }
  76. }
  77. brokerStats, found := b.Balancer.Brokers.Get(bpa.LeaderBroker)
  78. if !found {
  79. brokerStats = pub_balancer.NewBrokerStats()
  80. if !b.Balancer.Brokers.SetIfAbsent(bpa.LeaderBroker, brokerStats) {
  81. brokerStats, _ = b.Balancer.Brokers.Get(bpa.LeaderBroker)
  82. }
  83. }
  84. brokerStats.RegisterAssignment(t, bpa.Partition, isAdd)
  85. return nil
  86. }); doCreateErr != nil {
  87. glog.Errorf("create topic %s partition %+v on %s: %v", t, bpa.Partition, bpa.LeaderBroker, doCreateErr)
  88. }
  89. }(bpa)
  90. }
  91. wg.Wait()
  92. return nil
  93. }