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.

181 lines
3.8 KiB

2 years ago
10 months ago
2 years ago
2 years ago
2 years ago
2 years ago
10 months ago
2 years ago
10 months ago
2 years ago
10 months ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. package lock_manager
  2. import (
  3. "github.com/seaweedfs/seaweedfs/weed/glog"
  4. "github.com/seaweedfs/seaweedfs/weed/pb"
  5. "github.com/seaweedfs/seaweedfs/weed/util"
  6. "sort"
  7. "sync"
  8. "time"
  9. )
  10. type LockRingSnapshot struct {
  11. servers []pb.ServerAddress
  12. ts time.Time
  13. }
  14. type LockRing struct {
  15. sync.RWMutex
  16. snapshots []*LockRingSnapshot
  17. candidateServers map[pb.ServerAddress]struct{}
  18. lastUpdateTime time.Time
  19. lastCompactTime time.Time
  20. snapshotInterval time.Duration
  21. onTakeSnapshot func(snapshot []pb.ServerAddress)
  22. }
  23. func NewLockRing(snapshotInterval time.Duration) *LockRing {
  24. return &LockRing{
  25. snapshotInterval: snapshotInterval,
  26. candidateServers: make(map[pb.ServerAddress]struct{}),
  27. }
  28. }
  29. func (r *LockRing) SetTakeSnapshotCallback(onTakeSnapshot func(snapshot []pb.ServerAddress)) {
  30. r.Lock()
  31. defer r.Unlock()
  32. r.onTakeSnapshot = onTakeSnapshot
  33. }
  34. // AddServer adds a server to the ring
  35. // if the previous snapshot passed the snapshot interval, create a new snapshot
  36. func (r *LockRing) AddServer(server pb.ServerAddress) {
  37. glog.V(0).Infof("add server %v", server)
  38. r.Lock()
  39. if _, found := r.candidateServers[server]; found {
  40. glog.V(0).Infof("add server: already exists %v", server)
  41. r.Unlock()
  42. return
  43. }
  44. r.lastUpdateTime = time.Now()
  45. r.candidateServers[server] = struct{}{}
  46. r.Unlock()
  47. r.takeSnapshotWithDelayedCompaction()
  48. }
  49. func (r *LockRing) RemoveServer(server pb.ServerAddress) {
  50. glog.V(0).Infof("remove server %v", server)
  51. r.Lock()
  52. if _, found := r.candidateServers[server]; !found {
  53. r.Unlock()
  54. return
  55. }
  56. r.lastUpdateTime = time.Now()
  57. delete(r.candidateServers, server)
  58. r.Unlock()
  59. r.takeSnapshotWithDelayedCompaction()
  60. }
  61. func (r *LockRing) SetSnapshot(servers []pb.ServerAddress) {
  62. sort.Slice(servers, func(i, j int) bool {
  63. return servers[i] < servers[j]
  64. })
  65. r.Lock()
  66. r.lastUpdateTime = time.Now()
  67. r.Unlock()
  68. r.addOneSnapshot(servers)
  69. go func() {
  70. <-time.After(r.snapshotInterval)
  71. r.compactSnapshots()
  72. }()
  73. }
  74. func (r *LockRing) takeSnapshotWithDelayedCompaction() {
  75. r.doTakeSnapshot()
  76. go func() {
  77. <-time.After(r.snapshotInterval)
  78. r.compactSnapshots()
  79. }()
  80. }
  81. func (r *LockRing) doTakeSnapshot() {
  82. servers := r.getSortedServers()
  83. r.addOneSnapshot(servers)
  84. }
  85. func (r *LockRing) addOneSnapshot(servers []pb.ServerAddress) {
  86. r.Lock()
  87. defer r.Unlock()
  88. ts := time.Now()
  89. t := &LockRingSnapshot{
  90. servers: servers,
  91. ts: ts,
  92. }
  93. r.snapshots = append(r.snapshots, t)
  94. for i := len(r.snapshots) - 2; i >= 0; i-- {
  95. r.snapshots[i+1] = r.snapshots[i]
  96. }
  97. r.snapshots[0] = t
  98. if r.onTakeSnapshot != nil {
  99. r.onTakeSnapshot(t.servers)
  100. }
  101. }
  102. func (r *LockRing) compactSnapshots() {
  103. r.Lock()
  104. defer r.Unlock()
  105. if r.lastCompactTime.After(r.lastUpdateTime) {
  106. return
  107. }
  108. ts := time.Now()
  109. // remove old snapshots
  110. recentSnapshotIndex := 1
  111. for ; recentSnapshotIndex < len(r.snapshots); recentSnapshotIndex++ {
  112. if ts.Sub(r.snapshots[recentSnapshotIndex].ts) > r.snapshotInterval {
  113. break
  114. }
  115. }
  116. // keep the one that has been running for a while
  117. if recentSnapshotIndex+1 <= len(r.snapshots) {
  118. r.snapshots = r.snapshots[:recentSnapshotIndex+1]
  119. }
  120. r.lastCompactTime = ts
  121. }
  122. func (r *LockRing) getSortedServers() []pb.ServerAddress {
  123. sortedServers := make([]pb.ServerAddress, 0, len(r.candidateServers))
  124. for server := range r.candidateServers {
  125. sortedServers = append(sortedServers, server)
  126. }
  127. sort.Slice(sortedServers, func(i, j int) bool {
  128. return sortedServers[i] < sortedServers[j]
  129. })
  130. return sortedServers
  131. }
  132. func (r *LockRing) GetSnapshot() (servers []pb.ServerAddress) {
  133. r.RLock()
  134. defer r.RUnlock()
  135. if len(r.snapshots) == 0 {
  136. return
  137. }
  138. return r.snapshots[0].servers
  139. }
  140. func hashKeyToServer(key string, servers []pb.ServerAddress) pb.ServerAddress {
  141. if len(servers) == 0 {
  142. return ""
  143. }
  144. x := util.HashStringToLong(key)
  145. if x < 0 {
  146. x = -x
  147. }
  148. x = x % int64(len(servers))
  149. return servers[x]
  150. }