mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-08 22:31:04 +00:00
lib/db: Configurable block GC time (#6295)
Also retain the interval over restarts by storing last GC time in the database. This to make sure that GC eventually happens even if the interval is configured to a long time (say, a month).
This commit is contained in:
parent
8fc2dfad0c
commit
bf4c8439e8
@ -119,6 +119,10 @@ are mostly useful for developers. Use with care.
|
|||||||
"h", "m" and "s" abbreviations for hours minutes and seconds.
|
"h", "m" and "s" abbreviations for hours minutes and seconds.
|
||||||
Valid values are like "720h", "30s", etc.
|
Valid values are like "720h", "30s", etc.
|
||||||
|
|
||||||
|
STGCBLOCKSEVERY Set to a time interval to override the default database
|
||||||
|
block GC interval of 13 hours. Same format as the
|
||||||
|
STRECHECKDBEVERY variable.
|
||||||
|
|
||||||
GOMAXPROCS Set the maximum number of CPU cores to use. Defaults to all
|
GOMAXPROCS Set the maximum number of CPU cores to use. Defaults to all
|
||||||
available CPU cores.
|
available CPU cores.
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ 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"
|
||||||
@ -25,9 +26,18 @@ const (
|
|||||||
// false positive rate instead.
|
// false positive rate instead.
|
||||||
blockGCBloomCapacity = 100000
|
blockGCBloomCapacity = 100000
|
||||||
blockGCBloomFalsePositiveRate = 0.01 // 1%
|
blockGCBloomFalsePositiveRate = 0.01 // 1%
|
||||||
blockGCInterval = 13 * time.Hour
|
blockGCDefaultInterval = 13 * time.Hour
|
||||||
|
blockGCTimeKey = "lastGCTime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var blockGCInterval = blockGCDefaultInterval
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if dur, err := time.ParseDuration(os.Getenv("STGCBLOCKSEVERY")); err == nil {
|
||||||
|
blockGCInterval = 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
|
||||||
@ -463,7 +473,7 @@ func (db *Lowlevel) dropPrefix(prefix []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (db *Lowlevel) gcRunner() {
|
func (db *Lowlevel) gcRunner() {
|
||||||
t := time.NewTicker(blockGCInterval)
|
t := time.NewTimer(db.timeUntil(blockGCTimeKey, blockGCInterval))
|
||||||
defer t.Stop()
|
defer t.Stop()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -473,10 +483,32 @@ func (db *Lowlevel) gcRunner() {
|
|||||||
if err := db.gcBlocks(); err != nil {
|
if err := db.gcBlocks(); err != nil {
|
||||||
l.Warnln("Database block GC failed:", err)
|
l.Warnln("Database block GC failed:", err)
|
||||||
}
|
}
|
||||||
|
db.recordTime(blockGCTimeKey)
|
||||||
|
t.Reset(db.timeUntil(blockGCTimeKey, blockGCInterval))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// recordTime records the current time under the given key, affecting the
|
||||||
|
// next call to timeUntil with the same key.
|
||||||
|
func (db *Lowlevel) recordTime(key string) {
|
||||||
|
miscDB := NewMiscDataNamespace(db)
|
||||||
|
_ = miscDB.PutInt64(key, time.Now().Unix()) // error wilfully ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeUntil returns how long we should wait until the next interval, or
|
||||||
|
// zero if it should happen directly.
|
||||||
|
func (db *Lowlevel) timeUntil(key string, every time.Duration) time.Duration {
|
||||||
|
miscDB := NewMiscDataNamespace(db)
|
||||||
|
lastTime, _, _ := miscDB.Int64(key) // error wilfully ignored
|
||||||
|
nextTime := time.Unix(lastTime, 0).Add(every)
|
||||||
|
sleepTime := time.Until(nextTime)
|
||||||
|
if sleepTime < 0 {
|
||||||
|
sleepTime = 0
|
||||||
|
}
|
||||||
|
return sleepTime
|
||||||
|
}
|
||||||
|
|
||||||
func (db *Lowlevel) gcBlocks() error {
|
func (db *Lowlevel) gcBlocks() error {
|
||||||
// The block GC uses a bloom filter to track used block lists. This means
|
// The block GC uses a bloom filter to track used block lists. This means
|
||||||
// iterating over all items, adding their block lists to the filter, then
|
// iterating over all items, adding their block lists to the filter, then
|
||||||
|
@ -451,5 +451,7 @@ func (db *schemaUpdater) updateSchema7to8(_ int) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db.recordTime(blockGCTimeKey)
|
||||||
|
|
||||||
return t.commit()
|
return t.commit()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user