Skip to content

Commit 77c0947

Browse files
committed
db: refactor prepareAndOpenDirs
Refactor Open and its use of prepareAndOpenDirs to encapsulate the set of resolved directory paths in a new resolvedDirs struct.
1 parent c5f8393 commit 77c0947

File tree

3 files changed

+62
-46
lines changed

3 files changed

+62
-46
lines changed

db.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import (
3636
"github.com/cockroachdb/pebble/sstable"
3737
"github.com/cockroachdb/pebble/sstable/blob"
3838
"github.com/cockroachdb/pebble/sstable/block"
39-
"github.com/cockroachdb/pebble/vfs"
4039
"github.com/cockroachdb/pebble/vfs/atomicfs"
4140
"github.com/cockroachdb/pebble/wal"
4241
"github.com/cockroachdb/tokenbucket"
@@ -293,8 +292,7 @@ type DB struct {
293292
// objProvider is used to access and manage SSTs.
294293
objProvider objstorage.Provider
295294

296-
dataDirLock *base.DirLock
297-
dataDir vfs.File
295+
dirs *resolvedDirs
298296

299297
fileCache *fileCacheHandle
300298
newIters tableNewIters
@@ -1551,13 +1549,12 @@ func (d *DB) Close() error {
15511549
panic("pebble: log-writer should be nil in read-only mode")
15521550
}
15531551
err = firstError(err, d.mu.log.manager.Close())
1554-
err = firstError(err, d.dataDirLock.Close())
15551552

15561553
// Note that versionSet.close() only closes the MANIFEST. The versions list
15571554
// is still valid for the checks below.
15581555
err = firstError(err, d.mu.versions.close())
15591556

1560-
err = firstError(err, d.dataDir.Close())
1557+
err = firstError(err, d.dirs.Close())
15611558

15621559
d.readState.val.unrefLocked()
15631560

flushable_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func TestIngestedSSTFlushableAPI(t *testing.T) {
100100
// point before we update the MANIFEST (via UpdateVersionLocked), otherwise
101101
// a crash can have the tables referenced in the MANIFEST, but not present
102102
// in the directory.
103-
if err := d.dataDir.Sync(); err != nil {
103+
if err := d.dirs.DataDir.Sync(); err != nil {
104104
t.Fatal(err)
105105
}
106106

open.go

Lines changed: 59 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)