mvcc/backend: Delete orphaned db.tmp files before defrag

This commit is contained in:
Joe Betz 2020-02-12 10:12:48 -08:00
parent 70853d60e7
commit b3d9e29096
No known key found for this signature in database
GPG Key ID: 4930C680B6E0DDB8
2 changed files with 35 additions and 3 deletions

View File

@ -310,21 +310,35 @@ func (b *backend) defrag() error {
b.batchTx.unsafeCommit(true)
b.batchTx.tx = nil
tmpdb, err := bolt.Open(b.db.Path()+".tmp", 0600, boltOpenOptions)
// Create a temporary file to ensure we start with a clean slate.
// Snapshotter.cleanupSnapdir cleans up any of these that are found during startup.
dir := filepath.Dir(b.db.Path())
temp, err := ioutil.TempFile(dir, "db.tmp.*")
if err != nil {
return err
}
options := *boltOpenOptions
options.OpenFile = func(path string, i int, mode os.FileMode) (file *os.File, err error) {
return temp, nil
}
tdbp := temp.Name()
tmpdb, err := bolt.Open(tdbp, 0600, &options)
if err != nil {
return err
}
// gofail: var defragBeforeCopy struct{}
err = defragdb(b.db, tmpdb, defragLimit)
if err != nil {
tmpdb.Close()
os.RemoveAll(tmpdb.Path())
if rmErr := os.RemoveAll(tmpdb.Path()); rmErr != nil {
plog.Fatalf("failed to remove db.tmp after defragmentation completed: %v", rmErr)
}
return err
}
dbp := b.db.Path()
tdbp := tmpdb.Path()
err = b.db.Close()
if err != nil {
@ -334,6 +348,7 @@ func (b *backend) defrag() error {
if err != nil {
plog.Fatalf("cannot close database (%s)", err)
}
// gofail: var defragBeforeRename struct{}
err = os.Rename(tdbp, dbp)
if err != nil {
plog.Fatalf("cannot rename database (%s)", err)

View File

@ -172,6 +172,9 @@ func (s *Snapshotter) snapNames() ([]string, error) {
if err != nil {
return nil, err
}
if err = s.cleanupSnapdir(names); err != nil {
return nil, err
}
snaps := checkSuffix(names)
if len(snaps) == 0 {
return nil, ErrNoSnapshot
@ -202,3 +205,17 @@ func renameBroken(path string) {
plog.Warningf("cannot rename broken snapshot file %v to %v: %v", path, brokenPath, err)
}
}
// cleanupSnapdir removes any files that should not be in the snapshot directory:
// - db.tmp prefixed files that can be orphaned by defragmentation
func (s *Snapshotter) cleanupSnapdir(filenames []string) error {
for _, filename := range filenames {
if strings.HasPrefix(filename, "db.tmp") {
plog.Infof("found orphaned defragmentation file; deleting: %s", filename)
if rmErr := os.Remove(filepath.Join(s.dir, filename)); rmErr != nil && !os.IsNotExist(rmErr) {
return fmt.Errorf("failed to remove orphaned defragmentation file %s: %v", filename, rmErr)
}
}
}
return nil
}