Skip to content

Commit c5f8393

Browse files
committed
internal/base: add DirLockSet
Refactor AcquireOrValidateDirectoryLock into a AcquireOrValidate method on a DirLockSet type, accumulating the acquired directory locks. This helps clean up the release of WAL recovery directories in Open.
1 parent b64943a commit c5f8393

File tree

2 files changed

+38
-20
lines changed

2 files changed

+38
-20
lines changed

internal/base/directory_lock.go

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,24 @@ import (
1414
"github.com/cockroachdb/pebble/vfs"
1515
)
1616

17-
// AcquireOrValidateDirectoryLock attempts to acquire a lock on the
18-
// provided directory, or validates a pre-acquired DirLock.
19-
func AcquireOrValidateDirectoryLock(
17+
// DirLockSet is a set of directory locks that have been acquired.
18+
type DirLockSet struct {
19+
acquired []*DirLock
20+
}
21+
22+
// Close releases all of the directory locks in the set.
23+
func (s *DirLockSet) Close() error {
24+
var err error
25+
for _, l := range s.acquired {
26+
err = errors.CombineErrors(err, l.Close())
27+
}
28+
s.acquired = nil
29+
return err
30+
}
31+
32+
// AcquireOrValidate attempts to acquire a lock on the provided directory, or
33+
// validates a pre-acquired DirLock.
34+
func (s *DirLockSet) AcquireOrValidate(
2035
preAcquiredLock *DirLock, dirname string, fs vfs.FS,
2136
) (*DirLock, error) {
2237
// If a pre-acquired lock is provided, check that it matches the directory
@@ -25,11 +40,20 @@ func AcquireOrValidateDirectoryLock(
2540
if err := preAcquiredLock.pathMatches(dirname); err != nil {
2641
return preAcquiredLock, err
2742
}
28-
return preAcquiredLock, preAcquiredLock.refForOpen()
43+
if err := preAcquiredLock.refForOpen(); err != nil {
44+
return preAcquiredLock, err
45+
}
46+
s.acquired = append(s.acquired, preAcquiredLock)
47+
return preAcquiredLock, nil
2948
}
3049

3150
// Otherwise, acquire the lock for the directory.
32-
return LockDirectory(dirname, fs)
51+
l, err := LockDirectory(dirname, fs)
52+
if err != nil {
53+
return nil, err
54+
}
55+
s.acquired = append(s.acquired, l)
56+
return l, nil
3357
}
3458

3559
// LockDirectory acquires the directory lock in the named directory, preventing

open.go

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,10 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
109109
}
110110
defer maybeCleanUp(dataDir.Close)
111111

112+
var dirLocks base.DirLockSet
113+
112114
// Lock the database directory.
113-
fileLock, err := base.AcquireOrValidateDirectoryLock(opts.Lock, dirname, opts.FS)
115+
fileLock, err := dirLocks.AcquireOrValidate(opts.Lock, dirname, opts.FS)
114116
if err != nil {
115117
return nil, err
116118
}
@@ -336,7 +338,7 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
336338

337339
// Lock the dedicated WAL directory, if configured.
338340
if walDirname != dirname {
339-
walOpts.Primary.Lock, err = base.AcquireOrValidateDirectoryLock(opts.WALDirLock, walDirname, opts.FS)
341+
walOpts.Primary.Lock, err = dirLocks.AcquireOrValidate(opts.WALDirLock, walDirname, opts.FS)
340342
if err != nil {
341343
return nil, err
342344
}
@@ -346,7 +348,7 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
346348
// Lock the secondary WAL directory, if distinct from the data directory
347349
// and primary WAL directory.
348350
if secondaryWalDirName != dirname && secondaryWalDirName != walDirname {
349-
walOpts.Secondary.Lock, err = base.AcquireOrValidateDirectoryLock(
351+
walOpts.Secondary.Lock, err = dirLocks.AcquireOrValidate(
350352
opts.WALFailover.Secondary.Lock, secondaryWalDirName, opts.WALFailover.Secondary.FS)
351353
if err != nil {
352354
return nil, err
@@ -359,21 +361,13 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
359361
})
360362
}
361363
walDirs := walOpts.Dirs()
362-
walRecoveryLocks := make([]*base.DirLock, len(opts.WALRecoveryDirs))
363-
defer func() {
364-
// We only need the recovery WALs during Open, so we can release
365-
// the locks after the WALs have been scanned.
366-
for _, l := range walRecoveryLocks {
367-
if l != nil {
368-
_ = l.Close()
369-
}
370-
}
371-
}()
372-
for i, dir := range opts.WALRecoveryDirs {
364+
var recoveryDirLocks base.DirLockSet
365+
defer func() { _ = recoveryDirLocks.Close() }()
366+
for _, dir := range opts.WALRecoveryDirs {
373367
dir.Dirname = resolveStorePath(dirname, dir.Dirname)
374368
if dir.Dirname != dirname {
375369
// Acquire a lock on the WAL recovery directory.
376-
walRecoveryLocks[i], err = base.AcquireOrValidateDirectoryLock(dir.Lock, dir.Dirname, dir.FS)
370+
_, err = recoveryDirLocks.AcquireOrValidate(dir.Lock, dir.Dirname, dir.FS)
377371
if err != nil {
378372
return nil, errors.Wrapf(err, "error acquiring lock on WAL recovery directory %q", dir.Dirname)
379373
}

0 commit comments

Comments
 (0)