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
-13
View File
@@ -1,13 +0,0 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package stats
import (
"github.com/syncthing/syncthing/lib/logger"
)
var l = logger.DefaultLogger.NewFacility("stats", "Persistent device and folder statistics")
+8 -16
View File
@@ -9,9 +9,7 @@ package stats
import (
"time"
"github.com/syncthing/syncthing/lib/db"
"github.com/syncthing/syncthing/lib/db/backend"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/internal/db"
)
const (
@@ -25,19 +23,17 @@ type DeviceStatistics struct {
}
type DeviceStatisticsReference struct {
ns *db.NamespacedKV
device protocol.DeviceID
kv *db.Typed
}
func NewDeviceStatisticsReference(dba backend.Backend, device protocol.DeviceID) *DeviceStatisticsReference {
func NewDeviceStatisticsReference(kv *db.Typed) *DeviceStatisticsReference {
return &DeviceStatisticsReference{
ns: db.NewDeviceStatisticsNamespace(dba, device.String()),
device: device,
kv: kv,
}
}
func (s *DeviceStatisticsReference) GetLastSeen() (time.Time, error) {
t, ok, err := s.ns.Time(lastSeenKey)
t, ok, err := s.kv.Time(lastSeenKey)
if err != nil {
return time.Time{}, err
} else if !ok {
@@ -45,29 +41,25 @@ func (s *DeviceStatisticsReference) GetLastSeen() (time.Time, error) {
// time.Time{} from s.ns
return time.Unix(0, 0), nil
}
l.Debugln("stats.DeviceStatisticsReference.GetLastSeen:", s.device, t)
return t, nil
}
func (s *DeviceStatisticsReference) GetLastConnectionDuration() (time.Duration, error) {
d, ok, err := s.ns.Int64(connDurationKey)
d, ok, err := s.kv.Int64(connDurationKey)
if err != nil {
return 0, err
} else if !ok {
return 0, nil
}
l.Debugln("stats.DeviceStatisticsReference.GetLastConnectionDuration:", s.device, d)
return time.Duration(d), nil
}
func (s *DeviceStatisticsReference) WasSeen() error {
l.Debugln("stats.DeviceStatisticsReference.WasSeen:", s.device)
return s.ns.PutTime(lastSeenKey, time.Now().Truncate(time.Second))
return s.kv.PutTime(lastSeenKey, time.Now().Truncate(time.Second))
}
func (s *DeviceStatisticsReference) LastConnectionDuration(d time.Duration) error {
l.Debugln("stats.DeviceStatisticsReference.LastConnectionDuration:", s.device, d)
return s.ns.PutInt64(connDurationKey, d.Nanoseconds())
return s.kv.PutInt64(connDurationKey, d.Nanoseconds())
}
func (s *DeviceStatisticsReference) GetStatistics() (DeviceStatistics, error) {
+12 -15
View File
@@ -9,7 +9,7 @@ package stats
import (
"time"
"github.com/syncthing/syncthing/lib/db"
"github.com/syncthing/syncthing/internal/db"
)
type FolderStatistics struct {
@@ -18,8 +18,7 @@ type FolderStatistics struct {
}
type FolderStatisticsReference struct {
ns *db.NamespacedKV
folder string
kv *db.Typed
}
type LastFile struct {
@@ -28,27 +27,26 @@ type LastFile struct {
Deleted bool `json:"deleted"`
}
func NewFolderStatisticsReference(ldb *db.Lowlevel, folder string) *FolderStatisticsReference {
func NewFolderStatisticsReference(kv *db.Typed) *FolderStatisticsReference {
return &FolderStatisticsReference{
ns: db.NewFolderStatisticsNamespace(ldb, folder),
folder: folder,
kv: kv,
}
}
func (s *FolderStatisticsReference) GetLastFile() (LastFile, error) {
at, ok, err := s.ns.Time("lastFileAt")
at, ok, err := s.kv.Time("lastFileAt")
if err != nil {
return LastFile{}, err
} else if !ok {
return LastFile{}, nil
}
file, ok, err := s.ns.String("lastFileName")
file, ok, err := s.kv.String("lastFileName")
if err != nil {
return LastFile{}, err
} else if !ok {
return LastFile{}, nil
}
deleted, _, err := s.ns.Bool("lastFileDeleted")
deleted, _, err := s.kv.Bool("lastFileDeleted")
if err != nil {
return LastFile{}, err
}
@@ -60,25 +58,24 @@ func (s *FolderStatisticsReference) GetLastFile() (LastFile, error) {
}
func (s *FolderStatisticsReference) ReceivedFile(file string, deleted bool) error {
l.Debugln("stats.FolderStatisticsReference.ReceivedFile:", s.folder, file)
if err := s.ns.PutTime("lastFileAt", time.Now().Truncate(time.Second)); err != nil {
if err := s.kv.PutTime("lastFileAt", time.Now().Truncate(time.Second)); err != nil {
return err
}
if err := s.ns.PutString("lastFileName", file); err != nil {
if err := s.kv.PutString("lastFileName", file); err != nil {
return err
}
if err := s.ns.PutBool("lastFileDeleted", deleted); err != nil {
if err := s.kv.PutBool("lastFileDeleted", deleted); err != nil {
return err
}
return nil
}
func (s *FolderStatisticsReference) ScanCompleted() error {
return s.ns.PutTime("lastScan", time.Now().Truncate(time.Second))
return s.kv.PutTime("lastScan", time.Now().Truncate(time.Second))
}
func (s *FolderStatisticsReference) GetLastScanTime() (time.Time, error) {
lastScan, ok, err := s.ns.Time("lastScan")
lastScan, ok, err := s.kv.Time("lastScan")
if err != nil {
return time.Time{}, err
} else if !ok {
+10 -5
View File
@@ -13,15 +13,20 @@ import (
"testing"
"time"
"github.com/syncthing/syncthing/lib/db/backend"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/internal/db"
"github.com/syncthing/syncthing/internal/db/sqlite"
)
func TestDeviceStat(t *testing.T) {
db := backend.OpenLevelDBMemory()
defer db.Close()
sdb, err := sqlite.OpenTemp()
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
sdb.Close()
})
sr := NewDeviceStatisticsReference(db, protocol.LocalDeviceID)
sr := NewDeviceStatisticsReference(db.NewTyped(sdb, "devstatref"))
if err := sr.WasSeen(); err != nil {
t.Fatal(err)
}