Skip to content

Commit

Permalink
mvcc/backend: Delete orphaned db.tmp files before defrag
Browse files Browse the repository at this point in the history
  • Loading branch information
jpbetz committed Feb 13, 2020
1 parent 61f2794 commit 9cb6fd5
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 4 deletions.
19 changes: 19 additions & 0 deletions etcdserver/api/snap/snapshotter.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,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(s.lg, names)
if len(snaps) == 0 {
return nil, ErrNoSnapshot
Expand All @@ -231,3 +234,19 @@ func checkSuffix(lg *zap.Logger, names []string) []string {
}
return snaps
}

// 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") {
if s.lg != nil {
s.lg.Info("found orphaned defragmentation file; deleting", zap.String("path", 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
}
20 changes: 16 additions & 4 deletions mvcc/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,13 +358,24 @@ func (b *backend) defrag() error {

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
}

dbp := b.db.Path()
tdbp := tmpdb.Path()
size1, sizeInUse1 := b.Size(), b.SizeInUse()
if b.lg != nil {
b.lg.Info(
Expand All @@ -376,12 +387,12 @@ func (b *backend) defrag() error {
zap.String("current-db-size-in-use", humanize.Bytes(uint64(sizeInUse1))),
)
}

// gofail: var defragBeforeCopy struct{}
err = defragdb(b.db, tmpdb, defragLimit)
if err != nil {
tmpdb.Close()
if rmErr := os.RemoveAll(tmpdb.Path()); rmErr != nil {
b.lg.Error("failed to remove dirs under tmpdb", zap.Error(rmErr))
b.lg.Error("failed to remove db.tmp after defragmentation completed", zap.Error(rmErr))
}
return err
}
Expand All @@ -394,6 +405,7 @@ func (b *backend) defrag() error {
if err != nil {
b.lg.Fatal("failed to close tmp database", zap.Error(err))
}
// gofail: var defragBeforeRename struct{}
err = os.Rename(tdbp, dbp)
if err != nil {
b.lg.Fatal("failed to rename tmp database", zap.Error(err))
Expand Down

0 comments on commit 9cb6fd5

Please sign in to comment.