MCPcopy
hub / github.com/restic/restic / Lock

Method Lock

internal/repository/lock.go:46–106  ·  view source on GitHub ↗

Lock wraps the ctx such that it is cancelled when the repository is unlocked cancelling the original context also stops the lock refresh

(ctx context.Context, r *Repository, exclusive bool, retryLock time.Duration, printRetry func(msg string), logger func(format string, args ...interface{}))

Source from the content-addressed store, hash-verified

44// Lock wraps the ctx such that it is cancelled when the repository is unlocked
45// cancelling the original context also stops the lock refresh
46func (l *locker) Lock(ctx context.Context, r *Repository, exclusive bool, retryLock time.Duration, printRetry func(msg string), logger func(format string, args ...interface{})) (*Unlocker, context.Context, error) {
47 var lock *restic.Lock
48 var err error
49
50 retrySleep := minDuration(l.retrySleepStart, retryLock)
51 retryMessagePrinted := false
52 retryTimeout := time.After(retryLock)
53
54 repo := &internalRepository{r}
55
56retryLoop:
57 for {
58 lock, err = restic.NewLock(ctx, repo, exclusive)
59 if err != nil && restic.IsAlreadyLocked(err) {
60
61 if !retryMessagePrinted {
62 printRetry(fmt.Sprintf("repo already locked, waiting up to %s for the lock\n", retryLock))
63 retryMessagePrinted = true
64 }
65
66 debug.Log("repo already locked, retrying in %v", retrySleep)
67 retrySleepCh := time.After(retrySleep)
68
69 select {
70 case <-ctx.Done():
71 return nil, ctx, ctx.Err()
72 case <-retryTimeout:
73 debug.Log("repo already locked, timeout expired")
74 // Last lock attempt
75 lock, err = restic.NewLock(ctx, repo, exclusive)
76 break retryLoop
77 case <-retrySleepCh:
78 retrySleep = minDuration(retrySleep*2, l.retrySleepMax)
79 }
80 } else {
81 // anything else, either a successful lock or another error
82 break retryLoop
83 }
84 }
85 if restic.IsInvalidLock(err) {
86 return nil, ctx, errors.Fatalf("%v\n\nthe `unlock --remove-all` command can be used to remove invalid locks. Make sure that no other restic process is accessing the repository when running the command", err)
87 }
88 if err != nil {
89 return nil, ctx, fmt.Errorf("unable to create lock in backend: %w", err)
90 }
91 debug.Log("create lock %p (exclusive %v)", lock, exclusive)
92
93 ctx, cancel := context.WithCancel(ctx)
94 lockInfo := &lockContext{
95 lock: lock,
96 cancel: cancel,
97 }
98 lockInfo.refreshWG.Add(2)
99 refreshChan := make(chan struct{})
100 forceRefreshChan := make(chan refreshLockRequest)
101
102 go l.refreshLocks(ctx, repo.be, lockInfo, refreshChan, forceRefreshChan, logger)
103 go l.monitorLockRefresh(ctx, lockInfo, refreshChan, forceRefreshChan, logger)

Callers 15

cacheFileMethod · 0.45
LoadMethod · 0.45
typeDependentLimitMethod · 0.45
FreezeMethod · 0.45
RoundTripMethod · 0.45
TestListMethod · 0.45
SaveMethod · 0.45
openReaderMethod · 0.45
StatMethod · 0.45
RemoveMethod · 0.45
ListMethod · 0.45
DeleteMethod · 0.45

Calls 12

refreshLocksMethod · 0.95
monitorLockRefreshMethod · 0.95
NewLockFunction · 0.92
IsAlreadyLockedFunction · 0.92
LogFunction · 0.92
IsInvalidLockFunction · 0.92
FatalfFunction · 0.92
minDurationFunction · 0.85
ErrMethod · 0.80
ErrorfMethod · 0.80
DoneMethod · 0.45
AddMethod · 0.45

Tested by 10

LoadBlobMethod · 0.36
TestSaveBlobAsyncFunction · 0.36
SaveMethod · 0.36
checkedLockRepoFunction · 0.36
SaveMethod · 0.36
TestParallelRemoveFunction · 0.36
CompleteItemMethod · 0.36
FinishMethod · 0.36
LoadMethod · 0.36