mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-22 19:08:58 +00:00
42e677c055
This adds guardrails to the index sending and receiving, to verify that what we thinks is happening is what actually happens.
88 lines
2.2 KiB
Go
88 lines
2.2 KiB
Go
// Copyright (C) 2021 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 "github.com/syncthing/syncthing/lib/protocol"
|
|
|
|
// How many files to send in each Index/IndexUpdate message.
|
|
const (
|
|
MaxBatchSizeBytes = 250 * 1024 // Aim for making index messages no larger than 250 KiB (uncompressed)
|
|
MaxBatchSizeFiles = 1000 // Either way, don't include more files than this
|
|
)
|
|
|
|
// FileInfoBatch is a utility to do file operations on the database in suitably
|
|
// sized batches.
|
|
type FileInfoBatch struct {
|
|
infos []protocol.FileInfo
|
|
size int
|
|
flushFn func([]protocol.FileInfo) error
|
|
error error
|
|
}
|
|
|
|
// NewFileInfoBatch returns a new FileInfoBatch that calls fn when it's time
|
|
// to flush. Errors from the flush function are considered non-recoverable;
|
|
// once an error is returned the flush function wil not be called again, and
|
|
// any further calls to Flush will return the same error (unless Reset is
|
|
// called).
|
|
func NewFileInfoBatch(fn func([]protocol.FileInfo) error) *FileInfoBatch {
|
|
return &FileInfoBatch{flushFn: fn}
|
|
}
|
|
|
|
func (b *FileInfoBatch) SetFlushFunc(fn func([]protocol.FileInfo) error) {
|
|
b.flushFn = fn
|
|
}
|
|
|
|
func (b *FileInfoBatch) Append(f protocol.FileInfo) {
|
|
if b.error != nil {
|
|
panic("bug: calling append on a failed batch")
|
|
}
|
|
if b.infos == nil {
|
|
b.infos = make([]protocol.FileInfo, 0, MaxBatchSizeFiles)
|
|
}
|
|
b.infos = append(b.infos, f)
|
|
b.size += f.ProtoSize()
|
|
}
|
|
|
|
func (b *FileInfoBatch) Full() bool {
|
|
return len(b.infos) >= MaxBatchSizeFiles || b.size >= MaxBatchSizeBytes
|
|
}
|
|
|
|
func (b *FileInfoBatch) FlushIfFull() error {
|
|
if b.error != nil {
|
|
return b.error
|
|
}
|
|
if b.Full() {
|
|
return b.Flush()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *FileInfoBatch) Flush() error {
|
|
if b.error != nil {
|
|
return b.error
|
|
}
|
|
if len(b.infos) == 0 {
|
|
return nil
|
|
}
|
|
if err := b.flushFn(b.infos); err != nil {
|
|
b.error = err
|
|
return err
|
|
}
|
|
b.Reset()
|
|
return nil
|
|
}
|
|
|
|
func (b *FileInfoBatch) Reset() {
|
|
b.infos = nil
|
|
b.error = nil
|
|
b.size = 0
|
|
}
|
|
|
|
func (b *FileInfoBatch) Size() int {
|
|
return b.size
|
|
}
|