@@ -103,21 +103,14 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
103103 }
104104
105105 // Open the database and WAL directories first.
106- walDirname , secondaryWalDirName , dataDir , err := prepareAndOpenDirs (dirname , opts )
106+ dirs , err := prepareAndOpenDirs (dirname , opts )
107107 if err != nil {
108108 return nil , errors .Wrapf (err , "error opening database at %q" , dirname )
109109 }
110- defer maybeCleanUp (dataDir .Close )
110+ defer maybeCleanUp (dirs .Close )
111111
112112 var dirLocks base.DirLockSet
113113
114- // Lock the database directory.
115- fileLock , err := dirLocks .AcquireOrValidate (opts .Lock , dirname , opts .FS )
116- if err != nil {
117- return nil , err
118- }
119- defer maybeCleanUp (fileLock .Close )
120-
121114 rs , err := recoverState (opts , dirname )
122115 if err != nil {
123116 return nil , err
@@ -173,8 +166,7 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
173166 split : opts .Comparer .Split ,
174167 abbreviatedKey : opts .Comparer .AbbreviatedKey ,
175168 largeBatchThreshold : (opts .MemTableSize - uint64 (memTableEmptySize )) / 2 ,
176- dataDirLock : fileLock ,
177- dataDir : dataDir ,
169+ dirs : dirs ,
178170 objProvider : rs .objProvider ,
179171 closed : new (atomic.Value ),
180172 closedCh : make (chan struct {}),
@@ -302,7 +294,7 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
302294 })
303295
304296 walOpts := wal.Options {
305- Primary : wal.Dir {FS : opts .FS , Dirname : walDirname },
297+ Primary : wal.Dir {FS : opts .FS , Dirname : dirs . WALPrimary . Dirname },
306298 Secondary : wal.Dir {},
307299 MinUnflushedWALNum : wal .NumWAL (d .mu .versions .minUnflushedLogNum ),
308300 MaxNumRecyclableLogs : opts .MemTableStopWritesThreshold + 1 ,
@@ -337,8 +329,8 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
337329 })
338330
339331 // Lock the dedicated WAL directory, if configured.
340- if walDirname != dirname {
341- walOpts .Primary .Lock , err = dirLocks .AcquireOrValidate (opts .WALDirLock , walDirname , opts .FS )
332+ if dirs . WALPrimary . Dirname != dirname {
333+ walOpts .Primary .Lock , err = dirLocks .AcquireOrValidate (opts .WALDirLock , dirs . WALPrimary . Dirname , opts .FS )
342334 if err != nil {
343335 return nil , err
344336 }
@@ -347,14 +339,14 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
347339 walOpts .Secondary = opts .WALFailover .Secondary
348340 // Lock the secondary WAL directory, if distinct from the data directory
349341 // and primary WAL directory.
350- if secondaryWalDirName != dirname && secondaryWalDirName != walDirname {
342+ if dirs . WALSecondary . Dirname != dirname && dirs . WALSecondary . Dirname != dirs . WALPrimary . Dirname {
351343 walOpts .Secondary .Lock , err = dirLocks .AcquireOrValidate (
352- opts .WALFailover .Secondary .Lock , secondaryWalDirName , opts .WALFailover .Secondary .FS )
344+ opts .WALFailover .Secondary .Lock , dirs . WALSecondary . Dirname , opts .WALFailover .Secondary .FS )
353345 if err != nil {
354346 return nil , err
355347 }
356348 }
357- walOpts .Secondary .Dirname = secondaryWalDirName
349+ walOpts .Secondary .Dirname = dirs . WALSecondary . Dirname
358350 walOpts .FailoverOptions = opts .WALFailover .FailoverOptions
359351 walOpts .FailoverWriteAndSyncLatency = prometheus .NewHistogram (prometheus.HistogramOpts {
360352 Buckets : FsyncLatencyBuckets ,
@@ -525,7 +517,7 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
525517 if err := opts .FS .Rename (tmpPath , optionsPath ); err != nil {
526518 return nil , err
527519 }
528- if err := d .dataDir .Sync (); err != nil {
520+ if err := d .dirs . DataDir .Sync (); err != nil {
529521 return nil , err
530522 }
531523
@@ -615,62 +607,89 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
615607 return d , nil
616608}
617609
618- // prepareAndOpenDirs opens the directories for the store (and creates them if
619- // necessary).
610+ // resolvedDirs is a set of resolved directory paths and locks.
611+ type resolvedDirs struct {
612+ DirLocks base.DirLockSet
613+ DataDir vfs.File
614+ WALPrimary wal.Dir
615+ WALSecondary wal.Dir
616+ }
617+
618+ // Close closes the data directory and the directory locks.
619+ func (d * resolvedDirs ) Close () error {
620+ err := errors .CombineErrors (
621+ d .DataDir .Close (),
622+ d .DirLocks .Close (),
623+ )
624+ * d = resolvedDirs {}
625+ return err
626+ }
627+
628+ // prepareAndOpenDirs resolves the various directory paths indicated within
629+ // Options (substituting {store_path} relative paths as necessary), creates the
630+ // directories if they don't exist, and locks the database directory.
620631//
621632// Returns an error if ReadOnly is set and the directories don't exist.
622- func prepareAndOpenDirs (
623- dirname string , opts * Options ,
624- ) ( walDirname string , secondaryWalDirName string , dataDir vfs. File , err error ) {
625- walDirname = dirname
633+ func prepareAndOpenDirs (dirname string , opts * Options ) ( dirs * resolvedDirs , err error ) {
634+ dirs = & resolvedDirs {}
635+ dirs . WALPrimary . Dirname = dirname
636+ dirs . WALPrimary . FS = opts . FS
626637 if opts .WALDir != "" {
627- walDirname = resolveStorePath (dirname , opts .WALDir )
638+ dirs . WALPrimary . Dirname = resolveStorePath (dirname , opts .WALDir )
628639 }
629640 if opts .WALFailover != nil {
630- secondaryWalDirName = resolveStorePath (dirname , opts .WALFailover .Secondary .Dirname )
641+ dirs .WALSecondary .Dirname = resolveStorePath (dirname , opts .WALFailover .Secondary .Dirname )
642+ dirs .WALSecondary .FS = opts .WALFailover .Secondary .FS
631643 }
632644
633645 // Create directories if needed.
634646 if ! opts .ReadOnly {
635647 f , err := mkdirAllAndSyncParents (opts .FS , dirname )
636648 if err != nil {
637- return "" , "" , nil , err
649+ return dirs , err
638650 }
639651 f .Close ()
640- if walDirname != dirname {
641- f , err := mkdirAllAndSyncParents (opts .FS , walDirname )
652+ if dirs . WALPrimary . Dirname != dirname {
653+ f , err := mkdirAllAndSyncParents (opts .FS , dirs . WALPrimary . Dirname )
642654 if err != nil {
643- return "" , "" , nil , err
655+ return dirs , err
644656 }
645657 f .Close ()
646658 }
647659 if opts .WALFailover != nil {
648- f , err := mkdirAllAndSyncParents (opts .WALFailover .Secondary .FS , secondaryWalDirName )
660+ f , err := mkdirAllAndSyncParents (opts .WALFailover .Secondary .FS , dirs . WALSecondary . Dirname )
649661 if err != nil {
650- return "" , "" , nil , err
662+ return dirs , err
651663 }
652664 f .Close ()
653665 }
654666 }
655667
656- dataDir , err = opts .FS .OpenDir (dirname )
668+ dirs . DataDir , err = opts .FS .OpenDir (dirname )
657669 if err != nil {
658670 if opts .ReadOnly && oserror .IsNotExist (err ) {
659- return "" , "" , nil , errors .Errorf ("pebble: database %q does not exist" , dirname )
671+ return dirs , errors .Errorf ("pebble: database %q does not exist" , dirname )
660672 }
661- return "" , "" , nil , err
673+ return dirs , err
662674 }
663- if opts .ReadOnly && walDirname != dirname {
675+ if opts .ReadOnly && dirs . WALPrimary . Dirname != dirname {
664676 // Check that the wal dir exists.
665- walDir , err := opts .FS .OpenDir (walDirname )
677+ walDir , err := opts .FS .OpenDir (dirs . WALPrimary . Dirname )
666678 if err != nil {
667- dataDir .Close ()
668- return "" , "" , nil , err
679+ dirs . DataDir .Close ()
680+ return dirs , err
669681 }
670682 walDir .Close ()
671683 }
672684
673- return walDirname , secondaryWalDirName , dataDir , nil
685+ // Lock the database directory.
686+ _ , err = dirs .DirLocks .AcquireOrValidate (opts .Lock , dirname , opts .FS )
687+ if err != nil {
688+ dirs .DataDir .Close ()
689+ return dirs , err
690+ }
691+
692+ return dirs , nil
674693}
675694
676695// GetVersion returns the engine version string from the latest options
0 commit comments