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.

148 lines
4.4 KiB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
1 year ago
  1. package weed_server
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/seaweedfs/seaweedfs/weed/glog"
  6. "github.com/seaweedfs/seaweedfs/weed/pb"
  7. "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
  8. "google.golang.org/grpc/codes"
  9. "google.golang.org/grpc/status"
  10. "time"
  11. )
  12. // DistributedLock is a grpc handler to handle FilerServer's LockRequest
  13. func (fs *FilerServer) DistributedLock(ctx context.Context, req *filer_pb.LockRequest) (resp *filer_pb.LockResponse, err error) {
  14. resp = &filer_pb.LockResponse{}
  15. var movedTo pb.ServerAddress
  16. expiredAtNs := time.Now().Add(time.Duration(req.SecondsToLock) * time.Second).UnixNano()
  17. resp.RenewToken, movedTo, err = fs.filer.Dlm.LockWithTimeout(req.Name, expiredAtNs, req.RenewToken, req.Owner)
  18. glog.V(3).Infof("lock %s %v %v %v, isMoved=%v %v", req.Name, req.SecondsToLock, req.RenewToken, req.Owner, req.IsMoved, movedTo)
  19. if movedTo != "" && movedTo != fs.option.Host && !req.IsMoved {
  20. err = pb.WithFilerClient(false, 0, movedTo, fs.grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
  21. secondResp, err := client.DistributedLock(context.Background(), &filer_pb.LockRequest{
  22. Name: req.Name,
  23. SecondsToLock: req.SecondsToLock,
  24. RenewToken: req.RenewToken,
  25. IsMoved: true,
  26. Owner: req.Owner,
  27. })
  28. if err == nil {
  29. resp.RenewToken = secondResp.RenewToken
  30. } else {
  31. resp.Error = secondResp.Error
  32. }
  33. return err
  34. })
  35. }
  36. if err != nil {
  37. resp.Error = fmt.Sprintf("%v", err)
  38. }
  39. if movedTo != "" {
  40. resp.MovedTo = string(movedTo)
  41. }
  42. return resp, nil
  43. }
  44. // Unlock is a grpc handler to handle FilerServer's UnlockRequest
  45. func (fs *FilerServer) DistributedUnlock(ctx context.Context, req *filer_pb.UnlockRequest) (resp *filer_pb.UnlockResponse, err error) {
  46. resp = &filer_pb.UnlockResponse{}
  47. var movedTo pb.ServerAddress
  48. movedTo, err = fs.filer.Dlm.Unlock(req.Name, req.RenewToken)
  49. if !req.IsMoved && movedTo != "" {
  50. err = pb.WithFilerClient(false, 0, movedTo, fs.grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
  51. secondResp, err := client.DistributedUnlock(context.Background(), &filer_pb.UnlockRequest{
  52. Name: req.Name,
  53. RenewToken: req.RenewToken,
  54. IsMoved: true,
  55. })
  56. resp.Error = secondResp.Error
  57. return err
  58. })
  59. }
  60. if err != nil {
  61. resp.Error = fmt.Sprintf("%v", err)
  62. }
  63. if movedTo != "" {
  64. resp.MovedTo = string(movedTo)
  65. }
  66. return resp, nil
  67. }
  68. func (fs *FilerServer) FindLockOwner(ctx context.Context, req *filer_pb.FindLockOwnerRequest) (*filer_pb.FindLockOwnerResponse, error) {
  69. owner, movedTo, err := fs.filer.Dlm.FindLockOwner(req.Name)
  70. if owner == "" {
  71. glog.V(0).Infof("find lock %s moved to %v: %v", req.Name, movedTo, err)
  72. }
  73. if err != nil {
  74. return nil, status.Error(codes.Internal, err.Error())
  75. }
  76. if !req.IsMoved && movedTo != "" {
  77. err = pb.WithFilerClient(false, 0, movedTo, fs.grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
  78. secondResp, err := client.FindLockOwner(context.Background(), &filer_pb.FindLockOwnerRequest{
  79. Name: req.Name,
  80. IsMoved: true,
  81. })
  82. if err != nil {
  83. return err
  84. }
  85. owner = secondResp.Owner
  86. return nil
  87. })
  88. if err != nil {
  89. return nil, err
  90. }
  91. }
  92. return &filer_pb.FindLockOwnerResponse{
  93. Owner: owner,
  94. }, nil
  95. }
  96. // TransferLocks is a grpc handler to handle FilerServer's TransferLocksRequest
  97. func (fs *FilerServer) TransferLocks(ctx context.Context, req *filer_pb.TransferLocksRequest) (*filer_pb.TransferLocksResponse, error) {
  98. for _, lock := range req.Locks {
  99. fs.filer.Dlm.InsertLock(lock.Name, lock.ExpiredAtNs, lock.RenewToken, lock.Owner)
  100. }
  101. return &filer_pb.TransferLocksResponse{}, nil
  102. }
  103. func (fs *FilerServer) OnDlmChangeSnapshot(snapshot []pb.ServerAddress) {
  104. locks := fs.filer.Dlm.SelectNotOwnedLocks(snapshot)
  105. if len(locks) == 0 {
  106. return
  107. }
  108. for _, lock := range locks {
  109. server := fs.filer.Dlm.CalculateTargetServer(lock.Key, snapshot)
  110. if err := pb.WithFilerClient(false, 0, server, fs.grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
  111. _, err := client.TransferLocks(context.Background(), &filer_pb.TransferLocksRequest{
  112. Locks: []*filer_pb.Lock{
  113. {
  114. Name: lock.Key,
  115. RenewToken: lock.Token,
  116. ExpiredAtNs: lock.ExpiredAtNs,
  117. Owner: lock.Owner,
  118. },
  119. },
  120. })
  121. return err
  122. }); err != nil {
  123. // it may not be worth retrying, since the lock may have expired
  124. glog.Errorf("transfer lock %v to %v: %v", lock.Key, server, err)
  125. }
  126. }
  127. }