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.

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