@@ -103,14 +103,14 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
103103 }
104104
105105 // Open the database and WAL directories first.
106- dirs , err := prepareAndOpenDirs (dirname , opts )
106+ dirs , err := prepareOpenAndLockDirs (dirname , opts )
107107 if err != nil {
108- return nil , errors .Wrapf (err , "error opening database at %q" , dirname )
108+ err = errors .Wrapf (err , "error opening database at %q" , dirname )
109+ err = errors .CombineErrors (err , dirs .Close ())
110+ return nil , err
109111 }
110112 defer maybeCleanUp (dirs .Close )
111113
112- var dirLocks base.DirLockSet
113-
114114 rs , err := recoverState (opts , dirname )
115115 if err != nil {
116116 return nil , err
@@ -294,8 +294,8 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
294294 })
295295
296296 walOpts := wal.Options {
297- Primary : wal. Dir { FS : opts . FS , Dirname : dirs .WALPrimary . Dirname } ,
298- Secondary : wal. Dir {} ,
297+ Primary : dirs .WALPrimary ,
298+ Secondary : dirs . WALSecondary ,
299299 MinUnflushedWALNum : wal .NumWAL (d .mu .versions .minUnflushedLogNum ),
300300 MaxNumRecyclableLogs : opts .MemTableStopWritesThreshold + 1 ,
301301 NoSyncOnClose : opts .NoSyncOnClose ,
@@ -308,45 +308,7 @@ func Open(dirname string, opts *Options) (db *DB, err error) {
308308 EventListener : walEventListenerAdaptor {l : opts .EventListener },
309309 WriteWALSyncOffsets : func () bool { return d .FormatMajorVersion () >= FormatWALSyncChunks },
310310 }
311- // Ensure we release the WAL directory locks if we fail to open the
312- // database. If we fail before initializing the WAL manager, this defer is
313- // responsible for releasing the locks. If we fail after initializing the
314- // WAL manager, closing the WAL manager will release the locks.
315- //
316- // TODO(jackson): Open's cleanup error handling logic is convoluted; can we
317- // simplify it?
318- defer maybeCleanUp (func () (err error ) {
319- if d .mu .log .manager == nil {
320- if walOpts .Primary .Lock != nil {
321- err = errors .CombineErrors (err , walOpts .Primary .Lock .Close ())
322- }
323- if walOpts .Secondary .Lock != nil {
324- err = errors .CombineErrors (err , walOpts .Secondary .Lock .Close ())
325- }
326- return err
327- }
328- return nil
329- })
330-
331- // Lock the dedicated WAL directory, if configured.
332- if dirs .WALPrimary .Dirname != dirname {
333- walOpts .Primary .Lock , err = dirLocks .AcquireOrValidate (opts .WALDirLock , dirs .WALPrimary .Dirname , opts .FS )
334- if err != nil {
335- return nil , err
336- }
337- }
338311 if ! opts .ReadOnly && opts .WALFailover != nil {
339- walOpts .Secondary = opts .WALFailover .Secondary
340- // Lock the secondary WAL directory, if distinct from the data directory
341- // and primary WAL directory.
342- if dirs .WALSecondary .Dirname != dirname && dirs .WALSecondary .Dirname != dirs .WALPrimary .Dirname {
343- walOpts .Secondary .Lock , err = dirLocks .AcquireOrValidate (
344- opts .WALFailover .Secondary .Lock , dirs .WALSecondary .Dirname , opts .WALFailover .Secondary .FS )
345- if err != nil {
346- return nil , err
347- }
348- }
349- walOpts .Secondary .Dirname = dirs .WALSecondary .Dirname
350312 walOpts .FailoverOptions = opts .WALFailover .FailoverOptions
351313 walOpts .FailoverWriteAndSyncLatency = prometheus .NewHistogram (prometheus.HistogramOpts {
352314 Buckets : FsyncLatencyBuckets ,
@@ -617,20 +579,23 @@ type resolvedDirs struct {
617579
618580// Close closes the data directory and the directory locks.
619581func (d * resolvedDirs ) Close () error {
620- err := errors .CombineErrors (
621- d .DataDir .Close (),
622- d .DirLocks .Close (),
623- )
582+ var err error
583+ if d .DataDir != nil {
584+ err = errors .CombineErrors (err , d .DataDir .Close ())
585+ }
586+ err = errors .CombineErrors (err , d .DirLocks .Close ())
624587 * d = resolvedDirs {}
625588 return err
626589}
627590
628- // prepareAndOpenDirs resolves the various directory paths indicated within
591+ // prepareOpenAndLockDirs resolves the various directory paths indicated within
629592// Options (substituting {store_path} relative paths as necessary), creates the
630- // directories if they don't exist, and locks the database directory .
593+ // directories if they don't exist, and acquires directory locks as necessary .
631594//
632- // Returns an error if ReadOnly is set and the directories don't exist.
633- func prepareAndOpenDirs (dirname string , opts * Options ) (dirs * resolvedDirs , err error ) {
595+ // Returns an error if ReadOnly is set and the directories don't exist. Always
596+ // returns a non-nil resolvedDirs that may be closed to release all resources
597+ // acquired before any error was encountered.
598+ func prepareOpenAndLockDirs (dirname string , opts * Options ) (dirs * resolvedDirs , err error ) {
634599 dirs = & resolvedDirs {}
635600 dirs .WALPrimary .Dirname = dirname
636601 dirs .WALPrimary .FS = opts .FS
@@ -676,7 +641,6 @@ func prepareAndOpenDirs(dirname string, opts *Options) (dirs *resolvedDirs, err
676641 // Check that the wal dir exists.
677642 walDir , err := opts .FS .OpenDir (dirs .WALPrimary .Dirname )
678643 if err != nil {
679- dirs .DataDir .Close ()
680644 return dirs , err
681645 }
682646 walDir .Close ()
@@ -685,10 +649,24 @@ func prepareAndOpenDirs(dirname string, opts *Options) (dirs *resolvedDirs, err
685649 // Lock the database directory.
686650 _ , err = dirs .DirLocks .AcquireOrValidate (opts .Lock , dirname , opts .FS )
687651 if err != nil {
688- dirs .DataDir .Close ()
689652 return dirs , err
690653 }
691-
654+ // Lock the dedicated WAL directory, if configured.
655+ if dirs .WALPrimary .Dirname != dirname {
656+ dirs .WALPrimary .Lock , err = dirs .DirLocks .AcquireOrValidate (opts .WALDirLock , dirs .WALPrimary .Dirname , opts .FS )
657+ if err != nil {
658+ return dirs , err
659+ }
660+ }
661+ // Lock the secondary WAL directory, if distinct from the data directory
662+ // and primary WAL directory.
663+ if opts .WALFailover != nil && dirs .WALSecondary .Dirname != dirname && dirs .WALSecondary .Dirname != dirs .WALPrimary .Dirname {
664+ dirs .WALSecondary .Lock , err = dirs .DirLocks .AcquireOrValidate (
665+ opts .WALFailover .Secondary .Lock , dirs .WALSecondary .Dirname , dirs .WALSecondary .FS )
666+ if err != nil {
667+ return dirs , err
668+ }
669+ }
692670 return dirs , nil
693671}
694672
0 commit comments