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.

213 lines
5.1 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package cluster
  2. import (
  3. "github.com/chrislusf/seaweedfs/weed/pb"
  4. "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
  5. "math"
  6. "sync"
  7. "time"
  8. )
  9. const (
  10. MasterType = "master"
  11. FilerType = "filer"
  12. BrokerType = "broker"
  13. )
  14. type ClusterNode struct {
  15. Address pb.ServerAddress
  16. Version string
  17. counter int
  18. createdTs time.Time
  19. }
  20. type Leaders struct {
  21. leaders [3]pb.ServerAddress
  22. }
  23. type Cluster struct {
  24. filers map[pb.ServerAddress]*ClusterNode
  25. filersLock sync.RWMutex
  26. filerLeaders *Leaders
  27. }
  28. func NewCluster() *Cluster {
  29. return &Cluster{
  30. filers: make(map[pb.ServerAddress]*ClusterNode),
  31. filerLeaders: &Leaders{},
  32. }
  33. }
  34. func (cluster *Cluster) AddClusterNode(nodeType string, address pb.ServerAddress, version string) []*master_pb.KeepConnectedResponse {
  35. switch nodeType {
  36. case FilerType:
  37. cluster.filersLock.Lock()
  38. defer cluster.filersLock.Unlock()
  39. if existingNode, found := cluster.filers[address]; found {
  40. existingNode.counter++
  41. return nil
  42. }
  43. cluster.filers[address] = &ClusterNode{
  44. Address: address,
  45. Version: version,
  46. counter: 1,
  47. createdTs: time.Now(),
  48. }
  49. return cluster.ensureFilerLeaders(true, nodeType, address)
  50. case MasterType:
  51. }
  52. return nil
  53. }
  54. func (cluster *Cluster) RemoveClusterNode(nodeType string, address pb.ServerAddress) []*master_pb.KeepConnectedResponse {
  55. switch nodeType {
  56. case FilerType:
  57. cluster.filersLock.Lock()
  58. defer cluster.filersLock.Unlock()
  59. if existingNode, found := cluster.filers[address]; !found {
  60. return nil
  61. } else {
  62. existingNode.counter--
  63. if existingNode.counter <= 0 {
  64. delete(cluster.filers, address)
  65. return cluster.ensureFilerLeaders(false, nodeType, address)
  66. }
  67. }
  68. case MasterType:
  69. }
  70. return nil
  71. }
  72. func (cluster *Cluster) ListClusterNode(nodeType string) (nodes []*ClusterNode) {
  73. switch nodeType {
  74. case FilerType:
  75. cluster.filersLock.RLock()
  76. defer cluster.filersLock.RUnlock()
  77. for _, node := range cluster.filers {
  78. nodes = append(nodes, node)
  79. }
  80. case MasterType:
  81. }
  82. return
  83. }
  84. func (cluster *Cluster) IsOneLeader(address pb.ServerAddress) bool {
  85. return cluster.filerLeaders.isOneLeader(address)
  86. }
  87. func (cluster *Cluster) ensureFilerLeaders(isAdd bool, nodeType string, address pb.ServerAddress) (result []*master_pb.KeepConnectedResponse) {
  88. if isAdd {
  89. if cluster.filerLeaders.addLeaderIfVacant(address) {
  90. // has added the address as one leader
  91. result = append(result, &master_pb.KeepConnectedResponse{
  92. ClusterNodeUpdate: &master_pb.ClusterNodeUpdate{
  93. NodeType: nodeType,
  94. Address: string(address),
  95. IsLeader: true,
  96. IsAdd: true,
  97. },
  98. })
  99. } else {
  100. result = append(result, &master_pb.KeepConnectedResponse{
  101. ClusterNodeUpdate: &master_pb.ClusterNodeUpdate{
  102. NodeType: nodeType,
  103. Address: string(address),
  104. IsLeader: false,
  105. IsAdd: true,
  106. },
  107. })
  108. }
  109. } else {
  110. if cluster.filerLeaders.removeLeaderIfExists(address) {
  111. result = append(result, &master_pb.KeepConnectedResponse{
  112. ClusterNodeUpdate: &master_pb.ClusterNodeUpdate{
  113. NodeType: nodeType,
  114. Address: string(address),
  115. IsLeader: true,
  116. IsAdd: false,
  117. },
  118. })
  119. // pick the freshest one, since it is less likely to go away
  120. var shortestDuration int64 = math.MaxInt64
  121. now := time.Now()
  122. var candidateAddress pb.ServerAddress
  123. for _, node := range cluster.filers {
  124. if cluster.filerLeaders.isOneLeader(node.Address) {
  125. continue
  126. }
  127. duration := now.Sub(node.createdTs).Nanoseconds()
  128. if duration < shortestDuration {
  129. shortestDuration = duration
  130. candidateAddress = node.Address
  131. }
  132. }
  133. if candidateAddress != "" {
  134. cluster.filerLeaders.addLeaderIfVacant(candidateAddress)
  135. // added a new leader
  136. result = append(result, &master_pb.KeepConnectedResponse{
  137. ClusterNodeUpdate: &master_pb.ClusterNodeUpdate{
  138. NodeType: nodeType,
  139. Address: string(candidateAddress),
  140. IsLeader: true,
  141. IsAdd: true,
  142. },
  143. })
  144. }
  145. } else {
  146. result = append(result, &master_pb.KeepConnectedResponse{
  147. ClusterNodeUpdate: &master_pb.ClusterNodeUpdate{
  148. NodeType: nodeType,
  149. Address: string(address),
  150. IsLeader: false,
  151. IsAdd: false,
  152. },
  153. })
  154. }
  155. }
  156. return
  157. }
  158. func (leaders *Leaders) addLeaderIfVacant(address pb.ServerAddress) (hasChanged bool) {
  159. if leaders.isOneLeader(address) {
  160. return
  161. }
  162. for i := 0; i < len(leaders.leaders); i++ {
  163. if leaders.leaders[i] == "" {
  164. leaders.leaders[i] = address
  165. hasChanged = true
  166. return
  167. }
  168. }
  169. return
  170. }
  171. func (leaders *Leaders) removeLeaderIfExists(address pb.ServerAddress) (hasChanged bool) {
  172. if !leaders.isOneLeader(address) {
  173. return
  174. }
  175. for i := 0; i < len(leaders.leaders); i++ {
  176. if leaders.leaders[i] == address {
  177. leaders.leaders[i] = ""
  178. hasChanged = true
  179. return
  180. }
  181. }
  182. return
  183. }
  184. func (leaders *Leaders) isOneLeader(address pb.ServerAddress) bool {
  185. for i := 0; i < len(leaders.leaders); i++ {
  186. if leaders.leaders[i] == address {
  187. return true
  188. }
  189. }
  190. return false
  191. }
  192. func (leaders *Leaders) GetLeaders() (addresses []pb.ServerAddress) {
  193. for i := 0; i < len(leaders.leaders); i++ {
  194. if leaders.leaders[i] != "" {
  195. addresses = append(addresses, leaders.leaders[i])
  196. }
  197. }
  198. return
  199. }