interface.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // Copyright (C) 2025 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package db
  7. import (
  8. "iter"
  9. "time"
  10. "github.com/syncthing/syncthing/lib/config"
  11. "github.com/syncthing/syncthing/lib/protocol"
  12. "github.com/thejerf/suture/v4"
  13. )
  14. type DBService interface {
  15. suture.Service
  16. // Starts maintenance asynchronously, if not already running
  17. // Returns a channel that will receive the result when the requested maintenance finishes
  18. StartMaintenance() <-chan error
  19. // Returns the last time database maintenance completed
  20. // This will return time zero when database maintenance has never completed successfully.
  21. LastMaintenanceTime() time.Time
  22. }
  23. type DB interface {
  24. // Create a service that performs database maintenance periodically (no
  25. // more often than the requested interval)
  26. Service(maintenanceInterval time.Duration) DBService
  27. // Basics
  28. Update(folder string, device protocol.DeviceID, fs []protocol.FileInfo) error
  29. Close() error
  30. // Single files
  31. GetDeviceFile(folder string, device protocol.DeviceID, file string) (protocol.FileInfo, bool, error)
  32. GetGlobalAvailability(folder, file string) ([]protocol.DeviceID, error)
  33. GetGlobalFile(folder string, file string) (protocol.FileInfo, bool, error)
  34. // File iterators
  35. //
  36. // n.b. there is a slight inconsistency in the return types where some
  37. // return a FileInfo iterator and some a FileMetadata iterator. The
  38. // latter is more lightweight, and the discrepancy depends on how the
  39. // functions tend to be used. We can introduce more variations as
  40. // required.
  41. AllGlobalFiles(folder string) (iter.Seq[FileMetadata], func() error)
  42. AllGlobalFilesPrefix(folder string, prefix string) (iter.Seq[FileMetadata], func() error)
  43. AllLocalFiles(folder string, device protocol.DeviceID) (iter.Seq[protocol.FileInfo], func() error)
  44. AllLocalFilesBySequence(folder string, device protocol.DeviceID, startSeq int64, limit int) (iter.Seq[protocol.FileInfo], func() error)
  45. AllLocalFilesWithPrefix(folder string, device protocol.DeviceID, prefix string) (iter.Seq[protocol.FileInfo], func() error)
  46. AllLocalFilesWithBlocksHash(folder string, h []byte) (iter.Seq[FileMetadata], func() error)
  47. AllNeededGlobalFiles(folder string, device protocol.DeviceID, order config.PullOrder, limit, offset int) (iter.Seq[protocol.FileInfo], func() error)
  48. AllLocalBlocksWithHash(folder string, hash []byte) (iter.Seq[BlockMapEntry], func() error)
  49. // Cleanup
  50. DropAllFiles(folder string, device protocol.DeviceID) error
  51. DropDevice(device protocol.DeviceID) error
  52. DropFilesNamed(folder string, device protocol.DeviceID, names []string) error
  53. DropFolder(folder string) error
  54. // Various metadata
  55. GetDeviceSequence(folder string, device protocol.DeviceID) (int64, error)
  56. ListFolders() ([]string, error)
  57. ListDevicesForFolder(folder string) ([]protocol.DeviceID, error)
  58. RemoteSequences(folder string) (map[protocol.DeviceID]int64, error)
  59. // Counts
  60. CountGlobal(folder string) (Counts, error)
  61. CountLocal(folder string, device protocol.DeviceID) (Counts, error)
  62. CountNeed(folder string, device protocol.DeviceID) (Counts, error)
  63. CountReceiveOnlyChanged(folder string) (Counts, error)
  64. // Index IDs
  65. DropAllIndexIDs() error
  66. GetIndexID(folder string, device protocol.DeviceID) (protocol.IndexID, error)
  67. SetIndexID(folder string, device protocol.DeviceID, id protocol.IndexID) error
  68. // MtimeFS
  69. DeleteMtime(folder, name string) error
  70. GetMtime(folder, name string) (ondisk, virtual time.Time)
  71. PutMtime(folder, name string, ondisk, virtual time.Time) error
  72. KV
  73. }
  74. // Generic KV store
  75. type KV interface {
  76. GetKV(key string) ([]byte, error)
  77. PutKV(key string, val []byte) error
  78. DeleteKV(key string) error
  79. PrefixKV(prefix string) (iter.Seq[KeyValue], func() error)
  80. }
  81. type BlockMapEntry struct {
  82. BlocklistHash []byte
  83. Offset int64
  84. BlockIndex int
  85. Size int
  86. FileName string
  87. }
  88. type KeyValue struct {
  89. Key string
  90. Value []byte
  91. }
  92. type FileMetadata struct {
  93. Name string
  94. Sequence int64
  95. ModNanos int64
  96. Size int64
  97. LocalFlags protocol.FlagLocal
  98. Type protocol.FileInfoType
  99. Deleted bool
  100. }
  101. func (f *FileMetadata) ModTime() time.Time {
  102. return time.Unix(0, f.ModNanos)
  103. }
  104. func (f *FileMetadata) IsReceiveOnlyChanged() bool {
  105. return f.LocalFlags&protocol.FlagLocalReceiveOnly != 0
  106. }
  107. func (f *FileMetadata) IsDirectory() bool {
  108. return f.Type == protocol.FileInfoTypeDirectory
  109. }
  110. func (f *FileMetadata) ShouldConflict() bool {
  111. return f.LocalFlags&protocol.LocalConflictFlags != 0
  112. }
  113. func (f *FileMetadata) IsInvalid() bool {
  114. return f.LocalFlags.IsInvalid()
  115. }