Skip to content

Commit 323c049

Browse files
committed
db: move recoverState into recovery.go
Move recoverState into a separate file.
1 parent 6344314 commit 323c049

File tree

2 files changed

+134
-122
lines changed

2 files changed

+134
-122
lines changed

open.go

Lines changed: 0 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,9 @@ import (
2929
"github.com/cockroachdb/pebble/internal/manifest"
3030
"github.com/cockroachdb/pebble/internal/manual"
3131
"github.com/cockroachdb/pebble/objstorage"
32-
"github.com/cockroachdb/pebble/objstorage/objstorageprovider"
3332
"github.com/cockroachdb/pebble/objstorage/remote"
3433
"github.com/cockroachdb/pebble/record"
3534
"github.com/cockroachdb/pebble/vfs"
36-
"github.com/cockroachdb/pebble/vfs/atomicfs"
3735
"github.com/cockroachdb/pebble/wal"
3836
"github.com/prometheus/client_golang/prometheus"
3937
)
@@ -1220,123 +1218,3 @@ func (l walEventListenerAdaptor) LogCreated(ci wal.CreateInfo) {
12201218
}
12211219
l.l.WALCreated(wci)
12221220
}
1223-
1224-
// recoverState reads the named database directory and recovers the set of files
1225-
// encoding the database state at the moment the previous process exited.
1226-
// recoverState is read only and does not mutate the on-disk state.
1227-
func recoverState(opts *Options, dirname string) (s *recoveredState, err error) {
1228-
rs := &recoveredState{
1229-
dirname: dirname,
1230-
fs: opts.FS,
1231-
}
1232-
if err := rs.init(opts, dirname); err != nil {
1233-
return nil, errors.CombineErrors(err, rs.Close())
1234-
}
1235-
return rs, nil
1236-
}
1237-
1238-
func (rs *recoveredState) init(opts *Options, dirname string) error {
1239-
// List the directory contents. This also happens to include WAL log files,
1240-
// if they are in the same dir.
1241-
var err error
1242-
if rs.ls, err = opts.FS.List(dirname); err != nil {
1243-
return errors.Wrapf(err, "pebble: database %q", dirname)
1244-
}
1245-
// Find the currently format major version and active manifest.
1246-
rs.fmv, rs.fmvMarker, err = lookupFormatMajorVersion(opts.FS, dirname, rs.ls)
1247-
if err != nil {
1248-
return errors.Wrapf(err, "pebble: database %q", dirname)
1249-
}
1250-
rs.manifestMarker, rs.manifestFileNum, rs.manifestExists, err = findCurrentManifest(opts.FS, dirname, rs.ls)
1251-
if err != nil {
1252-
return errors.Wrapf(err, "pebble: database %q", dirname)
1253-
}
1254-
// Open the object storage provider.
1255-
providerSettings := opts.MakeObjStorageProviderSettings(dirname)
1256-
providerSettings.FSDirInitialListing = rs.ls
1257-
rs.objProvider, err = objstorageprovider.Open(providerSettings)
1258-
if err != nil {
1259-
return errors.Wrapf(err, "pebble: database %q", dirname)
1260-
}
1261-
1262-
// Identify the maximal file number in the directory. We do not want to
1263-
// reuse any existing file numbers even if they are obsolete file numbers to
1264-
// avoid modifying an ingested sstable's original external file.
1265-
//
1266-
// We also identify the most recent OPTIONS file, so we can validate our
1267-
// configured Options against the previous options, and we collect any
1268-
// orphaned temporary files that should be removed.
1269-
var previousOptionsFileNum base.DiskFileNum
1270-
for _, filename := range rs.ls {
1271-
ft, fn, ok := base.ParseFilename(opts.FS, filename)
1272-
if !ok {
1273-
continue
1274-
}
1275-
rs.maxFilenumUsed = max(rs.maxFilenumUsed, fn)
1276-
switch ft {
1277-
case base.FileTypeLog:
1278-
// Ignore.
1279-
case base.FileTypeOptions:
1280-
if previousOptionsFileNum < fn {
1281-
previousOptionsFileNum = fn
1282-
rs.previousOptionsFilename = filename
1283-
}
1284-
case base.FileTypeTemp, base.FileTypeOldTemp:
1285-
rs.obsoleteTempFilenames = append(rs.obsoleteTempFilenames, filename)
1286-
}
1287-
}
1288-
return nil
1289-
}
1290-
1291-
// recoveredState encapsulates state recovered from reading the database
1292-
// directory.
1293-
type recoveredState struct {
1294-
dirname string
1295-
fmv FormatMajorVersion
1296-
fmvMarker *atomicfs.Marker
1297-
fs vfs.FS
1298-
ls []string
1299-
manifestMarker *atomicfs.Marker
1300-
manifestFileNum base.DiskFileNum
1301-
manifestExists bool
1302-
maxFilenumUsed base.DiskFileNum
1303-
obsoleteTempFilenames []string
1304-
objProvider objstorage.Provider
1305-
previousOptionsFilename string
1306-
}
1307-
1308-
// RemoveObsolete removes obsolete files uncovered during recovery.
1309-
func (rs *recoveredState) RemoveObsolete() error {
1310-
var err error
1311-
// Atomic markers may leave behind obsolete files if there's a crash
1312-
// mid-update.
1313-
if rs.fmvMarker != nil {
1314-
err = errors.CombineErrors(err, rs.fmvMarker.RemoveObsolete())
1315-
}
1316-
if rs.manifestMarker != nil {
1317-
err = errors.CombineErrors(err, rs.manifestMarker.RemoveObsolete())
1318-
}
1319-
// Some codepaths write to a temporary file and then rename it to its final
1320-
// location when complete. A temp file is leftover if a process exits
1321-
// before the rename. Remove any that were found.
1322-
for _, filename := range rs.obsoleteTempFilenames {
1323-
err = errors.CombineErrors(err, rs.fs.Remove(rs.fs.PathJoin(rs.dirname, filename)))
1324-
}
1325-
return err
1326-
}
1327-
1328-
// Close closes resources held by the RecoveredState, including open file
1329-
// descriptors.
1330-
func (rs *recoveredState) Close() error {
1331-
var err error
1332-
if rs.fmvMarker != nil {
1333-
err = errors.CombineErrors(err, rs.fmvMarker.Close())
1334-
}
1335-
if rs.manifestMarker != nil {
1336-
err = errors.CombineErrors(err, rs.manifestMarker.Close())
1337-
}
1338-
if rs.objProvider != nil {
1339-
err = errors.CombineErrors(err, rs.objProvider.Close())
1340-
}
1341-
return err
1342-
}

recovery.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// Copyright 2025 The LevelDB-Go and Pebble Authors. All rights reserved. Use
2+
// of this source code is governed by a BSD-style license that can be found in
3+
// the LICENSE file.
4+
5+
package pebble
6+
7+
import (
8+
"github.com/cockroachdb/errors"
9+
"github.com/cockroachdb/pebble/internal/base"
10+
"github.com/cockroachdb/pebble/objstorage"
11+
"github.com/cockroachdb/pebble/objstorage/objstorageprovider"
12+
"github.com/cockroachdb/pebble/vfs"
13+
"github.com/cockroachdb/pebble/vfs/atomicfs"
14+
)
15+
16+
// recoverState reads the named database directory and recovers the set of files
17+
// encoding the database state at the moment the previous process exited.
18+
// recoverState is read only and does not mutate the on-disk state.
19+
func recoverState(opts *Options, dirname string) (s *recoveredState, err error) {
20+
rs := &recoveredState{
21+
dirname: dirname,
22+
fs: opts.FS,
23+
}
24+
if err := rs.init(opts, dirname); err != nil {
25+
return nil, errors.CombineErrors(err, rs.Close())
26+
}
27+
return rs, nil
28+
}
29+
30+
func (rs *recoveredState) init(opts *Options, dirname string) error {
31+
// List the directory contents. This also happens to include WAL log files,
32+
// if they are in the same dir.
33+
var err error
34+
if rs.ls, err = opts.FS.List(dirname); err != nil {
35+
return errors.Wrapf(err, "pebble: database %q", dirname)
36+
}
37+
// Find the currently format major version and active manifest.
38+
rs.fmv, rs.fmvMarker, err = lookupFormatMajorVersion(opts.FS, dirname, rs.ls)
39+
if err != nil {
40+
return errors.Wrapf(err, "pebble: database %q", dirname)
41+
}
42+
rs.manifestMarker, rs.manifestFileNum, rs.manifestExists, err = findCurrentManifest(opts.FS, dirname, rs.ls)
43+
if err != nil {
44+
return errors.Wrapf(err, "pebble: database %q", dirname)
45+
}
46+
// Open the object storage provider.
47+
providerSettings := opts.MakeObjStorageProviderSettings(dirname)
48+
providerSettings.FSDirInitialListing = rs.ls
49+
rs.objProvider, err = objstorageprovider.Open(providerSettings)
50+
if err != nil {
51+
return errors.Wrapf(err, "pebble: database %q", dirname)
52+
}
53+
54+
// Identify the maximal file number in the directory. We do not want to
55+
// reuse any existing file numbers even if they are obsolete file numbers to
56+
// avoid modifying an ingested sstable's original external file.
57+
//
58+
// We also identify the most recent OPTIONS file, so we can validate our
59+
// configured Options against the previous options, and we collect any
60+
// orphaned temporary files that should be removed.
61+
var previousOptionsFileNum base.DiskFileNum
62+
for _, filename := range rs.ls {
63+
ft, fn, ok := base.ParseFilename(opts.FS, filename)
64+
if !ok {
65+
continue
66+
}
67+
rs.maxFilenumUsed = max(rs.maxFilenumUsed, fn)
68+
switch ft {
69+
case base.FileTypeLog:
70+
// Ignore.
71+
case base.FileTypeOptions:
72+
if previousOptionsFileNum < fn {
73+
previousOptionsFileNum = fn
74+
rs.previousOptionsFilename = filename
75+
}
76+
case base.FileTypeTemp, base.FileTypeOldTemp:
77+
rs.obsoleteTempFilenames = append(rs.obsoleteTempFilenames, filename)
78+
}
79+
}
80+
return nil
81+
}
82+
83+
// recoveredState encapsulates state recovered from reading the database
84+
// directory.
85+
type recoveredState struct {
86+
dirname string
87+
fmv FormatMajorVersion
88+
fmvMarker *atomicfs.Marker
89+
fs vfs.FS
90+
ls []string
91+
manifestMarker *atomicfs.Marker
92+
manifestFileNum base.DiskFileNum
93+
manifestExists bool
94+
maxFilenumUsed base.DiskFileNum
95+
obsoleteTempFilenames []string
96+
objProvider objstorage.Provider
97+
previousOptionsFilename string
98+
}
99+
100+
// RemoveObsolete removes obsolete files uncovered during recovery.
101+
func (rs *recoveredState) RemoveObsolete() error {
102+
var err error
103+
// Atomic markers may leave behind obsolete files if there's a crash
104+
// mid-update.
105+
if rs.fmvMarker != nil {
106+
err = errors.CombineErrors(err, rs.fmvMarker.RemoveObsolete())
107+
}
108+
if rs.manifestMarker != nil {
109+
err = errors.CombineErrors(err, rs.manifestMarker.RemoveObsolete())
110+
}
111+
// Some codepaths write to a temporary file and then rename it to its final
112+
// location when complete. A temp file is leftover if a process exits
113+
// before the rename. Remove any that were found.
114+
for _, filename := range rs.obsoleteTempFilenames {
115+
err = errors.CombineErrors(err, rs.fs.Remove(rs.fs.PathJoin(rs.dirname, filename)))
116+
}
117+
return err
118+
}
119+
120+
// Close closes resources held by the RecoveredState, including open file
121+
// descriptors.
122+
func (rs *recoveredState) Close() error {
123+
var err error
124+
if rs.fmvMarker != nil {
125+
err = errors.CombineErrors(err, rs.fmvMarker.Close())
126+
}
127+
if rs.manifestMarker != nil {
128+
err = errors.CombineErrors(err, rs.manifestMarker.Close())
129+
}
130+
if rs.objProvider != nil {
131+
err = errors.CombineErrors(err, rs.objProvider.Close())
132+
}
133+
return err
134+
}

0 commit comments

Comments
 (0)