mirror of
https://github.com/syncthing/syncthing.git
synced 2026-03-31 12:41:27 -04:00
This is a draft because I haven't adjusted all the tests yet, I'd like to get feedback on the change overall first, before spending time on that. In my opinion the main win of this change is in it's lower complexity resp. fewer moving parts. It should also be faster as it only does one query instead of two, but I have no idea if that's practically relevant. This also mirrors the v1 DB, where a block map key had the name appended. Not that this is an argument for the change, it was mostly reassuring me that I might not be missing something key here conceptually (I might still be of course, please tell me :) ). And the change isn't mainly intrinsically motivated, instead it came up while fixing a bug in the copier. And the nested nature of that code makes the fix harder, and "un-nesting" it required me to understand what's happening. This change fell out of that.
124 lines
4.1 KiB
Go
124 lines
4.1 KiB
Go
// Copyright (C) 2025 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/internal/db/sqlite"
|
|
|
|
import (
|
|
"iter"
|
|
"time"
|
|
|
|
"github.com/syncthing/syncthing/lib/config"
|
|
"github.com/syncthing/syncthing/lib/protocol"
|
|
"github.com/thejerf/suture/v4"
|
|
)
|
|
|
|
type DB interface {
|
|
Service(maintenanceInterval time.Duration) suture.Service
|
|
|
|
// Basics
|
|
Update(folder string, device protocol.DeviceID, fs []protocol.FileInfo) error
|
|
Close() error
|
|
|
|
// Single files
|
|
GetDeviceFile(folder string, device protocol.DeviceID, file string) (protocol.FileInfo, bool, error)
|
|
GetGlobalAvailability(folder, file string) ([]protocol.DeviceID, error)
|
|
GetGlobalFile(folder string, file string) (protocol.FileInfo, bool, error)
|
|
|
|
// File iterators
|
|
//
|
|
// n.b. there is a slight inconsistency in the return types where some
|
|
// return a FileInfo iterator and some a FileMetadata iterator. The
|
|
// latter is more lightweight, and the discrepancy depends on how the
|
|
// functions tend to be used. We can introduce more variations as
|
|
// required.
|
|
AllGlobalFiles(folder string) (iter.Seq[FileMetadata], func() error)
|
|
AllGlobalFilesPrefix(folder string, prefix string) (iter.Seq[FileMetadata], func() error)
|
|
AllLocalFiles(folder string, device protocol.DeviceID) (iter.Seq[protocol.FileInfo], func() error)
|
|
AllLocalFilesBySequence(folder string, device protocol.DeviceID, startSeq int64, limit int) (iter.Seq[protocol.FileInfo], func() error)
|
|
AllLocalFilesWithPrefix(folder string, device protocol.DeviceID, prefix string) (iter.Seq[protocol.FileInfo], func() error)
|
|
AllLocalFilesWithBlocksHash(folder string, h []byte) (iter.Seq[FileMetadata], func() error)
|
|
AllNeededGlobalFiles(folder string, device protocol.DeviceID, order config.PullOrder, limit, offset int) (iter.Seq[protocol.FileInfo], func() error)
|
|
AllLocalBlocksWithHash(folder string, hash []byte) (iter.Seq[BlockMapEntry], func() error)
|
|
|
|
// Cleanup
|
|
DropAllFiles(folder string, device protocol.DeviceID) error
|
|
DropDevice(device protocol.DeviceID) error
|
|
DropFilesNamed(folder string, device protocol.DeviceID, names []string) error
|
|
DropFolder(folder string) error
|
|
|
|
// Various metadata
|
|
GetDeviceSequence(folder string, device protocol.DeviceID) (int64, error)
|
|
ListFolders() ([]string, error)
|
|
ListDevicesForFolder(folder string) ([]protocol.DeviceID, error)
|
|
RemoteSequences(folder string) (map[protocol.DeviceID]int64, error)
|
|
|
|
// Counts
|
|
CountGlobal(folder string) (Counts, error)
|
|
CountLocal(folder string, device protocol.DeviceID) (Counts, error)
|
|
CountNeed(folder string, device protocol.DeviceID) (Counts, error)
|
|
CountReceiveOnlyChanged(folder string) (Counts, error)
|
|
|
|
// Index IDs
|
|
DropAllIndexIDs() error
|
|
GetIndexID(folder string, device protocol.DeviceID) (protocol.IndexID, error)
|
|
SetIndexID(folder string, device protocol.DeviceID, id protocol.IndexID) error
|
|
|
|
// MtimeFS
|
|
DeleteMtime(folder, name string) error
|
|
GetMtime(folder, name string) (ondisk, virtual time.Time)
|
|
PutMtime(folder, name string, ondisk, virtual time.Time) error
|
|
|
|
KV
|
|
}
|
|
|
|
// Generic KV store
|
|
type KV interface {
|
|
GetKV(key string) ([]byte, error)
|
|
PutKV(key string, val []byte) error
|
|
DeleteKV(key string) error
|
|
PrefixKV(prefix string) (iter.Seq[KeyValue], func() error)
|
|
}
|
|
|
|
type BlockMapEntry struct {
|
|
BlocklistHash []byte
|
|
Offset int64
|
|
BlockIndex int
|
|
Size int
|
|
FileName string
|
|
}
|
|
|
|
type KeyValue struct {
|
|
Key string
|
|
Value []byte
|
|
}
|
|
|
|
type FileMetadata struct {
|
|
Name string
|
|
Sequence int64
|
|
ModNanos int64
|
|
Size int64
|
|
LocalFlags int64
|
|
Type protocol.FileInfoType
|
|
Deleted bool
|
|
Invalid bool
|
|
}
|
|
|
|
func (f *FileMetadata) ModTime() time.Time {
|
|
return time.Unix(0, f.ModNanos)
|
|
}
|
|
|
|
func (f *FileMetadata) IsReceiveOnlyChanged() bool {
|
|
return f.LocalFlags&protocol.FlagLocalReceiveOnly != 0
|
|
}
|
|
|
|
func (f *FileMetadata) IsDirectory() bool {
|
|
return f.Type == protocol.FileInfoTypeDirectory
|
|
}
|
|
|
|
func (f *FileMetadata) ShouldConflict() bool {
|
|
return f.LocalFlags&protocol.LocalConflictFlags != 0
|
|
}
|