@@ -109,6 +109,9 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
109109 err = errors .CombineErrors (err , dirs .Close ())
110110 return nil , err
111111 }
112+ // Locks in RecoveryDirLocks can be closed as soon as we've finished opening
113+ // the database.
114+ defer func () { _ = dirs .RecoveryDirLocks .Close () }()
112115 defer maybeCleanUp (dirs .Close )
113116
114117 rs , err := recoverState (opts , dirname )
@@ -314,20 +317,7 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
314317 Buckets : FsyncLatencyBuckets ,
315318 })
316319 }
317- walDirs := walOpts .Dirs ()
318- var recoveryDirLocks base.DirLockSet
319- defer func () { _ = recoveryDirLocks .Close () }()
320- for _ , dir := range opts .WALRecoveryDirs {
321- dir .Dirname = resolveStorePath (dirname , dir .Dirname )
322- if dir .Dirname != dirname {
323- // Acquire a lock on the WAL recovery directory.
324- _ , err = recoveryDirLocks .AcquireOrValidate (dir .Lock , dir .Dirname , dir .FS )
325- if err != nil {
326- return nil , errors .Wrapf (err , "error acquiring lock on WAL recovery directory %q" , dir .Dirname )
327- }
328- }
329- walDirs = append (walDirs , dir )
330- }
320+ walDirs := d .dirs .WALDirs ()
331321 wals , err := wal .Scan (walDirs ... )
332322 if err != nil {
333323 return nil , err
@@ -576,10 +566,23 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
576566
577567// resolvedDirs is a set of resolved directory paths and locks.
578568type resolvedDirs struct {
579- DirLocks base.DirLockSet
580- DataDir vfs.File
581- WALPrimary wal.Dir
582- WALSecondary wal.Dir
569+ DirLocks base.DirLockSet
570+ RecoveryDirLocks base.DirLockSet
571+ DataDir vfs.File
572+ WALPrimary wal.Dir
573+ WALSecondary wal.Dir
574+ WALRecovery []wal.Dir
575+ }
576+
577+ // WALDirs returns the set of resolved directories that may contain WAL files
578+ // relevant to recovery.
579+ func (d * resolvedDirs ) WALDirs () []wal.Dir {
580+ dirs := []wal.Dir {d .WALPrimary }
581+ if d .WALSecondary .Dirname != "" {
582+ dirs = append (dirs , d .WALSecondary )
583+ }
584+ dirs = append (dirs , d .WALRecovery ... )
585+ return dirs
583586}
584587
585588// Close closes the data directory and the directory locks.
@@ -589,6 +592,7 @@ func (d *resolvedDirs) Close() error {
589592 err = errors .CombineErrors (err , d .DataDir .Close ())
590593 }
591594 err = errors .CombineErrors (err , d .DirLocks .Close ())
595+ err = errors .CombineErrors (err , d .RecoveryDirLocks .Close ())
592596 * d = resolvedDirs {}
593597 return err
594598}
@@ -672,6 +676,19 @@ func prepareOpenAndLockDirs(dirname string, opts *Options) (dirs *resolvedDirs,
672676 return dirs , err
673677 }
674678 }
679+
680+ // Resolve path names and acquire locks for the WAL recovery directories.
681+ for _ , dir := range opts .WALRecoveryDirs {
682+ dir .Dirname = resolveStorePath (dirname , dir .Dirname )
683+ if dir .Dirname != dirname {
684+ // Acquire a lock on the WAL recovery directory.
685+ dir .Lock , err = dirs .RecoveryDirLocks .AcquireOrValidate (dir .Lock , dir .Dirname , dir .FS )
686+ if err != nil {
687+ return dirs , errors .Wrapf (err , "error acquiring lock on WAL recovery directory %q" , dir .Dirname )
688+ }
689+ }
690+ dirs .WALRecovery = append (dirs .WALRecovery , dir )
691+ }
675692 return dirs , nil
676693}
677694
0 commit comments