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.

102 lines
2.8 KiB

2 years ago
12 months ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
2 years ago
2 years ago
  1. package lock_manager
  2. import (
  3. "fmt"
  4. "github.com/seaweedfs/seaweedfs/weed/glog"
  5. "github.com/seaweedfs/seaweedfs/weed/pb"
  6. "time"
  7. )
  8. const RenewInterval = time.Second * 3
  9. const LiveLockTTL = time.Second * 7
  10. var NoLockServerError = fmt.Errorf("no lock server found")
  11. type DistributedLockManager struct {
  12. lockManager *LockManager
  13. LockRing *LockRing
  14. Host pb.ServerAddress
  15. }
  16. func NewDistributedLockManager(host pb.ServerAddress) *DistributedLockManager {
  17. return &DistributedLockManager{
  18. lockManager: NewLockManager(),
  19. LockRing: NewLockRing(time.Second * 5),
  20. Host: host,
  21. }
  22. }
  23. func (dlm *DistributedLockManager) LockWithTimeout(key string, expiredAtNs int64, token string, owner string) (lockOwner string, renewToken string, movedTo pb.ServerAddress, err error) {
  24. movedTo, err = dlm.findLockOwningFiler(key)
  25. if err != nil {
  26. return
  27. }
  28. if movedTo != dlm.Host {
  29. return
  30. }
  31. lockOwner, renewToken, err = dlm.lockManager.Lock(key, expiredAtNs, token, owner)
  32. return
  33. }
  34. func (dlm *DistributedLockManager) findLockOwningFiler(key string) (movedTo pb.ServerAddress, err error) {
  35. servers := dlm.LockRing.GetSnapshot()
  36. if servers == nil {
  37. err = NoLockServerError
  38. return
  39. }
  40. movedTo = hashKeyToServer(key, servers)
  41. return
  42. }
  43. func (dlm *DistributedLockManager) FindLockOwner(key string) (owner string, movedTo pb.ServerAddress, err error) {
  44. movedTo, err = dlm.findLockOwningFiler(key)
  45. if err != nil {
  46. return
  47. }
  48. if movedTo != dlm.Host {
  49. glog.V(0).Infof("lock %s not on current %s but on %s", key, dlm.Host, movedTo)
  50. return
  51. }
  52. owner, err = dlm.lockManager.GetLockOwner(key)
  53. return
  54. }
  55. func (dlm *DistributedLockManager) Unlock(key string, token string) (movedTo pb.ServerAddress, err error) {
  56. servers := dlm.LockRing.GetSnapshot()
  57. if servers == nil {
  58. err = NoLockServerError
  59. return
  60. }
  61. server := hashKeyToServer(key, servers)
  62. if server != dlm.Host {
  63. movedTo = server
  64. return
  65. }
  66. _, err = dlm.lockManager.Unlock(key, token)
  67. return
  68. }
  69. // InsertLock is used to insert a lock to a server unconditionally
  70. // It is used when a server is down and the lock is moved to another server
  71. func (dlm *DistributedLockManager) InsertLock(key string, expiredAtNs int64, token string, owner string) {
  72. dlm.lockManager.InsertLock(key, expiredAtNs, token, owner)
  73. }
  74. func (dlm *DistributedLockManager) SelectNotOwnedLocks(servers []pb.ServerAddress) (locks []*Lock) {
  75. return dlm.lockManager.SelectLocks(func(key string) bool {
  76. server := hashKeyToServer(key, servers)
  77. return server != dlm.Host
  78. })
  79. }
  80. func (dlm *DistributedLockManager) CalculateTargetServer(key string, servers []pb.ServerAddress) pb.ServerAddress {
  81. return hashKeyToServer(key, servers)
  82. }
  83. func (dlm *DistributedLockManager) IsLocal(key string) bool {
  84. servers := dlm.LockRing.GetSnapshot()
  85. if len(servers) <= 1 {
  86. return true
  87. }
  88. return hashKeyToServer(key, servers) == dlm.Host
  89. }