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.

146 lines
3.1 KiB

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