all: Pass db intervals as args not env vars (#6448)
This commit is contained in:
@@ -670,6 +670,12 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
secs, _ := strconv.Atoi(t)
|
secs, _ := strconv.Atoi(t)
|
||||||
appOpts.DeadlockTimeoutS = secs
|
appOpts.DeadlockTimeoutS = secs
|
||||||
}
|
}
|
||||||
|
if dur, err := time.ParseDuration(os.Getenv("STRECHECKDBEVERY")); err == nil {
|
||||||
|
appOpts.DBRecheckInterval = dur
|
||||||
|
}
|
||||||
|
if dur, err := time.ParseDuration(os.Getenv("STGCINDIRECTEVERY")); err == nil {
|
||||||
|
appOpts.DBIndirectGCInterval = dur
|
||||||
|
}
|
||||||
|
|
||||||
app := syncthing.New(cfg, ldb, evLogger, cert, appOpts)
|
app := syncthing.New(cfg, ldb, evLogger, cert, appOpts)
|
||||||
|
|
||||||
|
|||||||
+45
-24
@@ -9,7 +9,6 @@ package db
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/syncthing/syncthing/lib/db/backend"
|
"github.com/syncthing/syncthing/lib/db/backend"
|
||||||
@@ -31,16 +30,10 @@ const (
|
|||||||
|
|
||||||
// Use indirection for the block list when it exceeds this many entries
|
// Use indirection for the block list when it exceeds this many entries
|
||||||
blocksIndirectionCutoff = 3
|
blocksIndirectionCutoff = 3
|
||||||
|
|
||||||
|
recheckDefaultInterval = 30 * 24 * time.Hour
|
||||||
)
|
)
|
||||||
|
|
||||||
var indirectGCInterval = indirectGCDefaultInterval
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
if dur, err := time.ParseDuration(os.Getenv("STGCINDIRECTEVERY")); err == nil {
|
|
||||||
indirectGCInterval = dur
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lowlevel is the lowest level database interface. It has a very simple
|
// Lowlevel is the lowest level database interface. It has a very simple
|
||||||
// purpose: hold the actual backend database, and the in-memory state
|
// purpose: hold the actual backend database, and the in-memory state
|
||||||
// that belong to that database. In the same way that a single on disk
|
// that belong to that database. In the same way that a single on disk
|
||||||
@@ -48,27 +41,55 @@ func init() {
|
|||||||
// any given backend.
|
// any given backend.
|
||||||
type Lowlevel struct {
|
type Lowlevel struct {
|
||||||
backend.Backend
|
backend.Backend
|
||||||
folderIdx *smallIndex
|
folderIdx *smallIndex
|
||||||
deviceIdx *smallIndex
|
deviceIdx *smallIndex
|
||||||
keyer keyer
|
keyer keyer
|
||||||
gcMut sync.RWMutex
|
gcMut sync.RWMutex
|
||||||
gcKeyCount int
|
gcKeyCount int
|
||||||
gcStop chan struct{}
|
gcStop chan struct{}
|
||||||
|
indirectGCInterval time.Duration
|
||||||
|
recheckInterval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLowlevel(backend backend.Backend) *Lowlevel {
|
func NewLowlevel(backend backend.Backend, opts ...Option) *Lowlevel {
|
||||||
db := &Lowlevel{
|
db := &Lowlevel{
|
||||||
Backend: backend,
|
Backend: backend,
|
||||||
folderIdx: newSmallIndex(backend, []byte{KeyTypeFolderIdx}),
|
folderIdx: newSmallIndex(backend, []byte{KeyTypeFolderIdx}),
|
||||||
deviceIdx: newSmallIndex(backend, []byte{KeyTypeDeviceIdx}),
|
deviceIdx: newSmallIndex(backend, []byte{KeyTypeDeviceIdx}),
|
||||||
gcMut: sync.NewRWMutex(),
|
gcMut: sync.NewRWMutex(),
|
||||||
gcStop: make(chan struct{}),
|
gcStop: make(chan struct{}),
|
||||||
|
indirectGCInterval: indirectGCDefaultInterval,
|
||||||
|
recheckInterval: recheckDefaultInterval,
|
||||||
|
}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(db)
|
||||||
}
|
}
|
||||||
db.keyer = newDefaultKeyer(db.folderIdx, db.deviceIdx)
|
db.keyer = newDefaultKeyer(db.folderIdx, db.deviceIdx)
|
||||||
go db.gcRunner()
|
go db.gcRunner()
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Option func(*Lowlevel)
|
||||||
|
|
||||||
|
// WithRecheckInterval sets the time interval in between metadata recalculations
|
||||||
|
// and consistency checks.
|
||||||
|
func WithRecheckInterval(dur time.Duration) Option {
|
||||||
|
return func(db *Lowlevel) {
|
||||||
|
if dur > 0 {
|
||||||
|
db.recheckInterval = dur
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithIndirectGCInterval sets the time interval in between GC runs.
|
||||||
|
func WithIndirectGCInterval(dur time.Duration) Option {
|
||||||
|
return func(db *Lowlevel) {
|
||||||
|
if dur > 0 {
|
||||||
|
db.indirectGCInterval = dur
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (db *Lowlevel) Close() error {
|
func (db *Lowlevel) Close() error {
|
||||||
close(db.gcStop)
|
close(db.gcStop)
|
||||||
return db.Backend.Close()
|
return db.Backend.Close()
|
||||||
@@ -498,7 +519,7 @@ func (db *Lowlevel) gcRunner() {
|
|||||||
// directly, give the system a while to get up and running and do other
|
// directly, give the system a while to get up and running and do other
|
||||||
// stuff first. (We might have migrations and stuff which would be
|
// stuff first. (We might have migrations and stuff which would be
|
||||||
// better off running before GC.)
|
// better off running before GC.)
|
||||||
next := db.timeUntil(indirectGCTimeKey, indirectGCInterval)
|
next := db.timeUntil(indirectGCTimeKey, db.indirectGCInterval)
|
||||||
if next < time.Minute {
|
if next < time.Minute {
|
||||||
next = time.Minute
|
next = time.Minute
|
||||||
}
|
}
|
||||||
@@ -515,7 +536,7 @@ func (db *Lowlevel) gcRunner() {
|
|||||||
l.Warnln("Database indirection GC failed:", err)
|
l.Warnln("Database indirection GC failed:", err)
|
||||||
}
|
}
|
||||||
db.recordTime(indirectGCTimeKey)
|
db.recordTime(indirectGCTimeKey)
|
||||||
t.Reset(db.timeUntil(indirectGCTimeKey, indirectGCInterval))
|
t.Reset(db.timeUntil(indirectGCTimeKey, db.indirectGCInterval))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -669,7 +690,7 @@ func (db *Lowlevel) loadMetadataTracker(folder string) *metadataTracker {
|
|||||||
return db.getMetaAndCheck(folder)
|
return db.getMetaAndCheck(folder)
|
||||||
}
|
}
|
||||||
|
|
||||||
if age := time.Since(meta.Created()); age > databaseRecheckInterval {
|
if age := time.Since(meta.Created()); age > db.recheckInterval {
|
||||||
l.Infof("Stored folder metadata for %q is %v old; recalculating", folder, age)
|
l.Infof("Stored folder metadata for %q is %v old; recalculating", folder, age)
|
||||||
return db.getMetaAndCheck(folder)
|
return db.getMetaAndCheck(folder)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/syncthing/syncthing/lib/db/backend"
|
"github.com/syncthing/syncthing/lib/db/backend"
|
||||||
@@ -62,14 +61,6 @@ type FileIntf interface {
|
|||||||
// continue iteration, false to stop.
|
// continue iteration, false to stop.
|
||||||
type Iterator func(f FileIntf) bool
|
type Iterator func(f FileIntf) bool
|
||||||
|
|
||||||
var databaseRecheckInterval = 30 * 24 * time.Hour
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
if dur, err := time.ParseDuration(os.Getenv("STRECHECKDBEVERY")); err == nil {
|
|
||||||
databaseRecheckInterval = dur
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFileSet(folder string, fs fs.Filesystem, db *Lowlevel) *FileSet {
|
func NewFileSet(folder string, fs fs.Filesystem, db *Lowlevel) *FileSet {
|
||||||
return &FileSet{
|
return &FileSet{
|
||||||
folder: folder,
|
folder: folder,
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ type Options struct {
|
|||||||
ProfilerURL string
|
ProfilerURL string
|
||||||
ResetDeltaIdxs bool
|
ResetDeltaIdxs bool
|
||||||
Verbose bool
|
Verbose bool
|
||||||
|
// null duration means use default value
|
||||||
|
DBRecheckInterval time.Duration
|
||||||
|
DBIndirectGCInterval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
@@ -90,7 +93,7 @@ type App struct {
|
|||||||
func New(cfg config.Wrapper, dbBackend backend.Backend, evLogger events.Logger, cert tls.Certificate, opts Options) *App {
|
func New(cfg config.Wrapper, dbBackend backend.Backend, evLogger events.Logger, cert tls.Certificate, opts Options) *App {
|
||||||
a := &App{
|
a := &App{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
ll: db.NewLowlevel(dbBackend),
|
ll: db.NewLowlevel(dbBackend, db.WithRecheckInterval(opts.DBRecheckInterval), db.WithIndirectGCInterval(opts.DBIndirectGCInterval)),
|
||||||
evLogger: evLogger,
|
evLogger: evLogger,
|
||||||
opts: opts,
|
opts: opts,
|
||||||
cert: cert,
|
cert: cert,
|
||||||
|
|||||||
Reference in New Issue
Block a user