This keeps the data we need about sequence numbers and object counts persistently in the database. The sizeTracker is expanded into a metadataTracker than handled multiple folders, and the Counts struct is made protobuf serializable. It gains a Sequence field to assist in tracking that as well, and a collection of Counts become a CountsSet (for serialization purposes). The initial database scan is also a consistency check of the global entries. This shouldn't strictly be necessary. Nonetheless I added a created timestamp to the metadata and set a variable to compare against that. When the time since the metadata creation is old enough, we drop the metadata and rebuild from scratch like we used to, while also consistency checking. A new environment variable STCHECKDBEVERY can override this interval, and for example be set to zero to force the check immediately. GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4547 LGTM: imsodin
85 lines
1.7 KiB
Go
85 lines
1.7 KiB
Go
// 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 db
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
|
|
"github.com/syncthing/syncthing/lib/protocol"
|
|
"github.com/syndtr/goleveldb/leveldb"
|
|
"github.com/syndtr/goleveldb/leveldb/opt"
|
|
)
|
|
|
|
const (
|
|
KeyTypeDevice = iota
|
|
KeyTypeGlobal
|
|
KeyTypeBlock
|
|
KeyTypeDeviceStatistic
|
|
KeyTypeFolderStatistic
|
|
KeyTypeVirtualMtime
|
|
KeyTypeFolderIdx
|
|
KeyTypeDeviceIdx
|
|
KeyTypeIndexID
|
|
KeyTypeFolderMeta
|
|
)
|
|
|
|
func (l VersionList) String() string {
|
|
var b bytes.Buffer
|
|
var id protocol.DeviceID
|
|
b.WriteString("{")
|
|
for i, v := range l.Versions {
|
|
if i > 0 {
|
|
b.WriteString(", ")
|
|
}
|
|
copy(id[:], v.Device)
|
|
fmt.Fprintf(&b, "{%v, %v}", v.Version, id)
|
|
}
|
|
b.WriteString("}")
|
|
return b.String()
|
|
}
|
|
|
|
type fileList []protocol.FileInfo
|
|
|
|
func (l fileList) Len() int {
|
|
return len(l)
|
|
}
|
|
|
|
func (l fileList) Swap(a, b int) {
|
|
l[a], l[b] = l[b], l[a]
|
|
}
|
|
|
|
func (l fileList) Less(a, b int) bool {
|
|
return l[a].Name < l[b].Name
|
|
}
|
|
|
|
type dbReader interface {
|
|
Get([]byte, *opt.ReadOptions) ([]byte, error)
|
|
}
|
|
|
|
// Flush batches to disk when they contain this many records.
|
|
const batchFlushSize = 64
|
|
|
|
func getFile(db dbReader, key []byte) (protocol.FileInfo, bool) {
|
|
bs, err := db.Get(key, nil)
|
|
if err == leveldb.ErrNotFound {
|
|
return protocol.FileInfo{}, false
|
|
}
|
|
if err != nil {
|
|
l.Debugln("surprise error:", err)
|
|
return protocol.FileInfo{}, false
|
|
}
|
|
|
|
var f protocol.FileInfo
|
|
err = f.Unmarshal(bs)
|
|
if err != nil {
|
|
l.Debugln("unmarshal error:", err)
|
|
return protocol.FileInfo{}, false
|
|
}
|
|
return f, true
|
|
}
|