mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-22 19:08:58 +00:00
This commit is contained in:
parent
ef5ca0c218
commit
881e923105
@ -702,7 +702,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
dbFile := locations[locDatabase]
|
dbFile := locations[locDatabase]
|
||||||
ldb, err := db.Open(dbFile)
|
ldb, err := db.Open(dbFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Cannot open database:", err, "- Is another copy of Syncthing already running?")
|
l.Fatalln("Error opening database:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if runtimeOptions.resetDeltaIdxs {
|
if runtimeOptions.resetDeltaIdxs {
|
||||||
|
@ -9,6 +9,7 @@ package db
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@ -60,31 +61,32 @@ func Open(file string) (*Instance, error) {
|
|||||||
// the database and reindexing...
|
// the database and reindexing...
|
||||||
l.Infoln("Database corruption detected, unable to recover. Reinitializing...")
|
l.Infoln("Database corruption detected, unable to recover. Reinitializing...")
|
||||||
if err := os.RemoveAll(file); err != nil {
|
if err := os.RemoveAll(file); err != nil {
|
||||||
return nil, err
|
return nil, errorSuggestion{err, "failed to delete corrupted database"}
|
||||||
}
|
}
|
||||||
db, err = leveldb.OpenFile(file, opts)
|
db, err = leveldb.OpenFile(file, opts)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errorSuggestion{err, "is another instance of Syncthing running?"}
|
||||||
}
|
}
|
||||||
|
|
||||||
return newDBInstance(db, file), nil
|
return newDBInstance(db, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
func OpenMemory() *Instance {
|
func OpenMemory() *Instance {
|
||||||
db, _ := leveldb.Open(storage.NewMemStorage(), nil)
|
db, _ := leveldb.Open(storage.NewMemStorage(), nil)
|
||||||
return newDBInstance(db, "<memory>")
|
ldb, _ := newDBInstance(db, "<memory>")
|
||||||
|
return ldb
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDBInstance(db *leveldb.DB, location string) *Instance {
|
func newDBInstance(db *leveldb.DB, location string) (*Instance, error) {
|
||||||
i := &Instance{
|
i := &Instance{
|
||||||
DB: db,
|
DB: db,
|
||||||
location: location,
|
location: location,
|
||||||
}
|
}
|
||||||
i.folderIdx = newSmallIndex(i, []byte{KeyTypeFolderIdx})
|
i.folderIdx = newSmallIndex(i, []byte{KeyTypeFolderIdx})
|
||||||
i.deviceIdx = newSmallIndex(i, []byte{KeyTypeDeviceIdx})
|
i.deviceIdx = newSmallIndex(i, []byte{KeyTypeDeviceIdx})
|
||||||
i.updateSchema()
|
err := i.updateSchema()
|
||||||
return i
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Committed returns the number of items committed to the database since startup
|
// Committed returns the number of items committed to the database since startup
|
||||||
@ -935,3 +937,12 @@ func resize(k []byte, reqLen int) []byte {
|
|||||||
}
|
}
|
||||||
return k[:reqLen]
|
return k[:reqLen]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type errorSuggestion struct {
|
||||||
|
inner error
|
||||||
|
suggestion string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e errorSuggestion) Error() string {
|
||||||
|
return fmt.Sprintf("%s (%s)", e.inner.Error(), e.suggestion)
|
||||||
|
}
|
||||||
|
@ -7,20 +7,50 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/syncthing/syncthing/lib/protocol"
|
"github.com/syncthing/syncthing/lib/protocol"
|
||||||
"github.com/syndtr/goleveldb/leveldb/util"
|
"github.com/syndtr/goleveldb/leveldb/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const dbVersion = 5
|
// List of all dbVersion to dbMinSyncthingVersion pairs for convenience
|
||||||
|
// 0: v0.14.0
|
||||||
|
// 1: v0.14.46
|
||||||
|
// 2: v0.14.48
|
||||||
|
// 3: v0.14.49
|
||||||
|
// 4: v0.14.49
|
||||||
|
// 5: v0.14.50
|
||||||
|
const (
|
||||||
|
dbVersion = 5
|
||||||
|
dbMinSyncthingVersion = "v0.14.49"
|
||||||
|
)
|
||||||
|
|
||||||
func (db *Instance) updateSchema() {
|
type databaseDowngradeError struct {
|
||||||
|
minSyncthingVersion string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e databaseDowngradeError) Error() string {
|
||||||
|
if e.minSyncthingVersion == "" {
|
||||||
|
return "newer Syncthing required"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Syncthing %s required", e.minSyncthingVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Instance) updateSchema() error {
|
||||||
miscDB := NewNamespacedKV(db, string(KeyTypeMiscData))
|
miscDB := NewNamespacedKV(db, string(KeyTypeMiscData))
|
||||||
prevVersion, _ := miscDB.Int64("dbVersion")
|
prevVersion, _ := miscDB.Int64("dbVersion")
|
||||||
|
|
||||||
if prevVersion >= dbVersion {
|
if prevVersion > dbVersion {
|
||||||
return
|
err := databaseDowngradeError{}
|
||||||
|
if minSyncthingVersion, ok := miscDB.String("dbMinSyncthingVersion"); ok {
|
||||||
|
err.minSyncthingVersion = minSyncthingVersion
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if prevVersion == dbVersion {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if prevVersion < 1 {
|
if prevVersion < 1 {
|
||||||
@ -41,6 +71,9 @@ func (db *Instance) updateSchema() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
miscDB.PutInt64("dbVersion", dbVersion)
|
miscDB.PutInt64("dbVersion", dbVersion)
|
||||||
|
miscDB.PutString("dbMinSyncthingVersion", dbMinSyncthingVersion)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *Instance) updateSchema0to1() {
|
func (db *Instance) updateSchema0to1() {
|
||||||
|
@ -8,6 +8,7 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/syncthing/syncthing/lib/fs"
|
"github.com/syncthing/syncthing/lib/fs"
|
||||||
@ -159,7 +160,7 @@ func TestIgnoredFiles(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
db := newDBInstance(ldb, "<memory>")
|
db, _ := newDBInstance(ldb, "<memory>")
|
||||||
fs := NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), db)
|
fs := NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), db)
|
||||||
|
|
||||||
// The contents of the database are like this:
|
// The contents of the database are like this:
|
||||||
@ -280,7 +281,7 @@ func TestUpdate0to3(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
db := newDBInstance(ldb, "<memory>")
|
db, _ := newDBInstance(ldb, "<memory>")
|
||||||
|
|
||||||
folder := []byte(update0to3Folder)
|
folder := []byte(update0to3Folder)
|
||||||
|
|
||||||
@ -338,3 +339,27 @@ func TestUpdate0to3(t *testing.T) {
|
|||||||
t.Errorf(`Missing needed file "%v"`, n)
|
t.Errorf(`Missing needed file "%v"`, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDowngrade(t *testing.T) {
|
||||||
|
loc := "testdata/downgrade.db"
|
||||||
|
db, err := Open(loc)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
db.Close()
|
||||||
|
os.RemoveAll(loc)
|
||||||
|
}()
|
||||||
|
|
||||||
|
miscDB := NewNamespacedKV(db, string(KeyTypeMiscData))
|
||||||
|
miscDB.PutInt64("dbVersion", dbVersion+1)
|
||||||
|
l.Infoln(dbVersion)
|
||||||
|
|
||||||
|
db.Close()
|
||||||
|
db, err = Open(loc)
|
||||||
|
if err, ok := err.(databaseDowngradeError); !ok {
|
||||||
|
t.Fatal("Expected error due to database downgrade, got", err)
|
||||||
|
} else if err.minSyncthingVersion != dbMinSyncthingVersion {
|
||||||
|
t.Fatalf("Error has %v as min Syncthing version, expected %v", err.minSyncthingVersion, dbMinSyncthingVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user