From 87836883918ca4e34c0cf258c153f03b4df20c18 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Sun, 16 Aug 2015 16:10:16 +0200 Subject: [PATCH] Recover from 'corrupted or incomplete CURRENT file' etc (fixes #2017) --- cmd/syncthing/main.go | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index b5c45794b..aedcf71ee 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -591,9 +591,19 @@ func syncthingMain() { dbFile := locations[locDatabase] ldb, err := leveldb.OpenFile(dbFile, dbOpts()) - if err != nil && errors.IsCorrupted(err) { + if leveldbIsCorrupted(err) { ldb, err = leveldb.RecoverFile(dbFile, dbOpts()) } + if leveldbIsCorrupted(err) { + // The database is corrupted, and we've tried to recover it but it + // didn't work. At this point there isn't much to do beyond dropping + // the database and reindexing... + l.Infoln("Database corruption detected, unable to recover. Reinitializing...") + if err := resetDB(); err != nil { + l.Fatalln("Remove database:", err) + } + ldb, err = leveldb.OpenFile(dbFile, dbOpts()) + } if err != nil { l.Fatalln("Cannot open database:", err, "- Is another copy of Syncthing already running?") } @@ -1105,3 +1115,19 @@ func checkShortIDs(cfg *config.Wrapper) error { } return nil } + +// A "better" version of leveldb's errors.IsCorrupted. +func leveldbIsCorrupted(err error) bool { + switch { + case err == nil: + return false + + case errors.IsCorrupted(err): + return true + + case strings.Contains(err.Error(), "corrupted"): + return true + } + + return false +}