chore: switch database engine to sqlite (fixes #9954) (#9965)

Switch the database from LevelDB to SQLite, for greater stability and
simpler code.

Co-authored-by: Tommy van der Vorst <tommy@pixelspark.nl>
Co-authored-by: bt90 <btom1990@googlemail.com>
This commit is contained in:
Jakob Borg
2025-03-29 13:50:08 +01:00
committed by GitHub
co-authored by Tommy van der Vorst bt90
parent b1c8f88a44
commit 025905fcdf
146 changed files with 8315 additions and 11984 deletions
+30 -29
View File
@@ -10,8 +10,8 @@ import (
"sort"
"time"
"github.com/syncthing/syncthing/internal/itererr"
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/db"
"github.com/syncthing/syncthing/lib/events"
"github.com/syncthing/syncthing/lib/ignore"
"github.com/syncthing/syncthing/lib/protocol"
@@ -57,8 +57,8 @@ type receiveOnlyFolder struct {
*sendReceiveFolder
}
func newReceiveOnlyFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, ver versioner.Versioner, evLogger events.Logger, ioLimiter *semaphore.Semaphore) service {
sr := newSendReceiveFolder(model, fset, ignores, cfg, ver, evLogger, ioLimiter).(*sendReceiveFolder)
func newReceiveOnlyFolder(model *model, ignores *ignore.Matcher, cfg config.FolderConfiguration, ver versioner.Versioner, evLogger events.Logger, ioLimiter *semaphore.Semaphore) service {
sr := newSendReceiveFolder(model, ignores, cfg, ver, evLogger, ioLimiter).(*sendReceiveFolder)
sr.localFlags = protocol.FlagLocalReceiveOnly // gets propagated to the scanner, and set on locally changed files
return &receiveOnlyFolder{sr}
}
@@ -83,30 +83,31 @@ func (f *receiveOnlyFolder) revert() error {
scanChan: scanChan,
}
batch := db.NewFileInfoBatch(func(files []protocol.FileInfo) error {
batch := NewFileInfoBatch(func(files []protocol.FileInfo) error {
f.updateLocalsFromScanning(files)
return nil
})
snap, err := f.dbSnapshot()
if err != nil {
return err
}
defer snap.Release()
snap.WithHave(protocol.LocalDeviceID, func(fi protocol.FileInfo) bool {
for fi, err := range itererr.Zip(f.db.AllLocalFiles(f.folderID, protocol.LocalDeviceID)) {
if err != nil {
return err
}
if !fi.IsReceiveOnlyChanged() {
// We're only interested in files that have changed locally in
// receive only mode.
return true
continue
}
fi.LocalFlags &^= protocol.FlagLocalReceiveOnly
switch gf, ok := snap.GetGlobal(fi.Name); {
switch gf, ok, err := f.db.GetGlobalFile(f.folderID, fi.Name); {
case err != nil:
return err
case !ok:
msg := "Unexpected global file that we have locally"
msg := "Unexpectedly missing global file that we have locally"
l.Debugf("%v revert: %v: %v", f, msg, fi.Name)
f.evLogger.Log(events.Failure, msg)
return true
continue
case gf.IsReceiveOnlyChanged():
// The global file is our own. A revert then means to delete it.
// We'll delete files directly, directories get queued and
@@ -115,13 +116,13 @@ func (f *receiveOnlyFolder) revert() error {
fi.Version = protocol.Vector{} // if this file ever resurfaces anywhere we want our delete to be strictly older
break
}
handled, err := delQueue.handle(fi, snap)
l.Debugf("Revert: deleting %s: %v\n", fi.Name, err)
handled, err := delQueue.handle(fi)
if err != nil {
l.Infof("Revert: deleting %s: %v\n", fi.Name, err)
return true // continue
continue
}
if !handled {
return true // continue
continue
}
fi.SetDeleted(f.shortID)
fi.Version = protocol.Vector{} // if this file ever resurfaces anywhere we want our delete to be strictly older
@@ -144,13 +145,13 @@ func (f *receiveOnlyFolder) revert() error {
batch.Append(fi)
_ = batch.FlushIfFull()
return true
})
_ = batch.Flush()
}
if err := batch.Flush(); err != nil {
return err
}
// Handle any queued directories
deleted, err := delQueue.flush(snap)
deleted, err := delQueue.flush()
if err != nil {
l.Infoln("Revert:", err)
}
@@ -179,15 +180,15 @@ func (f *receiveOnlyFolder) revert() error {
// directories for last.
type deleteQueue struct {
handler interface {
deleteItemOnDisk(item protocol.FileInfo, snap *db.Snapshot, scanChan chan<- string) error
deleteDirOnDisk(dir string, snap *db.Snapshot, scanChan chan<- string) error
deleteItemOnDisk(item protocol.FileInfo, scanChan chan<- string) error
deleteDirOnDisk(dir string, scanChan chan<- string) error
}
ignores *ignore.Matcher
dirs []string
scanChan chan<- string
}
func (q *deleteQueue) handle(fi protocol.FileInfo, snap *db.Snapshot) (bool, error) {
func (q *deleteQueue) handle(fi protocol.FileInfo) (bool, error) {
// Things that are ignored but not marked deletable are not processed.
ign := q.ignores.Match(fi.Name)
if ign.IsIgnored() && !ign.IsDeletable() {
@@ -201,11 +202,11 @@ func (q *deleteQueue) handle(fi protocol.FileInfo, snap *db.Snapshot) (bool, err
}
// Kill it.
err := q.handler.deleteItemOnDisk(fi, snap, q.scanChan)
err := q.handler.deleteItemOnDisk(fi, q.scanChan)
return true, err
}
func (q *deleteQueue) flush(snap *db.Snapshot) ([]string, error) {
func (q *deleteQueue) flush() ([]string, error) {
// Process directories from the leaves inward.
sort.Sort(sort.Reverse(sort.StringSlice(q.dirs)))
@@ -213,7 +214,7 @@ func (q *deleteQueue) flush(snap *db.Snapshot) ([]string, error) {
var deleted []string
for _, dir := range q.dirs {
if err := q.handler.deleteDirOnDisk(dir, snap, q.scanChan); err == nil {
if err := q.handler.deleteDirOnDisk(dir, q.scanChan); err == nil {
deleted = append(deleted, dir)
} else if firstError == nil {
firstError = err