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.

137 lines
3.6 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
5 years ago
6 years ago
6 years ago
  1. package wdclient
  2. import (
  3. "context"
  4. "fmt"
  5. "math/rand"
  6. "time"
  7. "github.com/chrislusf/seaweedfs/weed/glog"
  8. "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
  9. "github.com/chrislusf/seaweedfs/weed/util"
  10. "google.golang.org/grpc"
  11. )
  12. type MasterClient struct {
  13. name string
  14. currentMaster string
  15. masters []string
  16. grpcDialOption grpc.DialOption
  17. vidMap
  18. }
  19. func NewMasterClient(grpcDialOption grpc.DialOption, clientName string, masters []string) *MasterClient {
  20. return &MasterClient{
  21. name: clientName,
  22. masters: masters,
  23. grpcDialOption: grpcDialOption,
  24. vidMap: newVidMap(),
  25. }
  26. }
  27. func (mc *MasterClient) GetMaster() string {
  28. return mc.currentMaster
  29. }
  30. func (mc *MasterClient) WaitUntilConnected() {
  31. for mc.currentMaster == "" {
  32. time.Sleep(time.Duration(rand.Int31n(200)) * time.Millisecond)
  33. }
  34. }
  35. func (mc *MasterClient) KeepConnectedToMaster() {
  36. glog.V(1).Infof("%s bootstraps with masters %v", mc.name, mc.masters)
  37. for {
  38. mc.tryAllMasters()
  39. time.Sleep(time.Second)
  40. }
  41. }
  42. func (mc *MasterClient) tryAllMasters() {
  43. nextHintedLeader := ""
  44. for _, master := range mc.masters {
  45. nextHintedLeader = mc.tryConnectToMaster(master)
  46. for nextHintedLeader != "" {
  47. nextHintedLeader = mc.tryConnectToMaster(nextHintedLeader)
  48. }
  49. mc.currentMaster = ""
  50. mc.vidMap = newVidMap()
  51. }
  52. }
  53. func (mc *MasterClient) tryConnectToMaster(master string) (nextHintedLeader string) {
  54. glog.V(1).Infof("%s Connecting to master %v", mc.name, master)
  55. gprcErr := withMasterClient(master, mc.grpcDialOption, func(client master_pb.SeaweedClient) error {
  56. stream, err := client.KeepConnected(context.Background())
  57. if err != nil {
  58. glog.V(0).Infof("%s failed to keep connected to %s: %v", mc.name, master, err)
  59. return err
  60. }
  61. if err = stream.Send(&master_pb.KeepConnectedRequest{Name: mc.name}); err != nil {
  62. glog.V(0).Infof("%s failed to send to %s: %v", mc.name, master, err)
  63. return err
  64. }
  65. glog.V(1).Infof("%s Connected to %v", mc.name, master)
  66. mc.currentMaster = master
  67. for {
  68. volumeLocation, err := stream.Recv()
  69. if err != nil {
  70. glog.V(0).Infof("%s failed to receive from %s: %v", mc.name, master, err)
  71. return err
  72. }
  73. // maybe the leader is changed
  74. if volumeLocation.Leader != "" {
  75. glog.V(0).Infof("redirected to leader %v", volumeLocation.Leader)
  76. nextHintedLeader = volumeLocation.Leader
  77. return nil
  78. }
  79. // process new volume location
  80. loc := Location{
  81. Url: volumeLocation.Url,
  82. PublicUrl: volumeLocation.PublicUrl,
  83. }
  84. for _, newVid := range volumeLocation.NewVids {
  85. glog.V(1).Infof("%s: %s adds volume %d", mc.name, loc.Url, newVid)
  86. mc.addLocation(newVid, loc)
  87. }
  88. for _, deletedVid := range volumeLocation.DeletedVids {
  89. glog.V(1).Infof("%s: %s removes volume %d", mc.name, loc.Url, deletedVid)
  90. mc.deleteLocation(deletedVid, loc)
  91. }
  92. }
  93. })
  94. if gprcErr != nil {
  95. glog.V(0).Infof("%s failed to connect with master %v: %v", mc.name, master, gprcErr)
  96. }
  97. return
  98. }
  99. func withMasterClient(master string, grpcDialOption grpc.DialOption, fn func(client master_pb.SeaweedClient) error) error {
  100. masterGrpcAddress, parseErr := util.ParseServerToGrpcAddress(master)
  101. if parseErr != nil {
  102. return fmt.Errorf("failed to parse master grpc %v: %v", master, parseErr)
  103. }
  104. return util.WithCachedGrpcClient(func(grpcConnection *grpc.ClientConn) error {
  105. client := master_pb.NewSeaweedClient(grpcConnection)
  106. return fn(client)
  107. }, masterGrpcAddress, grpcDialOption)
  108. }
  109. func (mc *MasterClient) WithClient(fn func(client master_pb.SeaweedClient) error) error {
  110. return withMasterClient(mc.currentMaster, mc.grpcDialOption, func(client master_pb.SeaweedClient) error {
  111. return fn(client)
  112. })
  113. }