mirror of
https://github.com/octoleo/syncthing.git
synced 2024-09-19 21:29:01 +00:00
lib/db, lib/model: Refactor removing expired pending folders (#7537)
This commit is contained in:
parent
1658afc883
commit
ec0a66c75b
@ -66,16 +66,11 @@ func (db *Lowlevel) PendingDevices() (map[protocol.DeviceID]ObservedDevice, erro
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *Lowlevel) AddOrUpdatePendingFolder(id, label string, device protocol.DeviceID, receiveEncrypted bool) error {
|
func (db *Lowlevel) AddOrUpdatePendingFolder(id string, of ObservedFolder, device protocol.DeviceID) error {
|
||||||
key, err := db.keyer.GeneratePendingFolderKey(nil, device[:], []byte(id))
|
key, err := db.keyer.GeneratePendingFolderKey(nil, device[:], []byte(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
of := ObservedFolder{
|
|
||||||
Time: time.Now().Truncate(time.Second),
|
|
||||||
Label: label,
|
|
||||||
ReceiveEncrypted: receiveEncrypted,
|
|
||||||
}
|
|
||||||
bs, err := of.Marshal()
|
bs, err := of.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -112,42 +107,6 @@ func (db *Lowlevel) RemovePendingFolder(id string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemovePendingFoldersBeforeTime removes entries for a specific device which are older
|
|
||||||
// than a given timestamp or invalid. It returns only the valid removed folder IDs.
|
|
||||||
func (db *Lowlevel) RemovePendingFoldersBeforeTime(device protocol.DeviceID, oldest time.Time) ([]string, error) {
|
|
||||||
prefixKey, err := db.keyer.GeneratePendingFolderKey(nil, device[:], nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
iter, err := db.NewPrefixIterator(prefixKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer iter.Release()
|
|
||||||
oldest = oldest.Truncate(time.Second)
|
|
||||||
var res []string
|
|
||||||
for iter.Next() {
|
|
||||||
var of ObservedFolder
|
|
||||||
var folderID string
|
|
||||||
if err = of.Unmarshal(iter.Value()); err != nil {
|
|
||||||
l.Infof("Invalid pending folder entry, deleting from database: %x", iter.Key())
|
|
||||||
} else if of.Time.Before(oldest) {
|
|
||||||
folderID = string(db.keyer.FolderFromPendingFolderKey(iter.Key()))
|
|
||||||
l.Infof("Removing stale pending folder %s (%s) from device %s, last seen %v",
|
|
||||||
folderID, of.Label, device.Short(), of.Time)
|
|
||||||
} else {
|
|
||||||
// Keep entries younger or equal to the given timestamp
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := db.Delete(iter.Key()); err != nil {
|
|
||||||
l.Warnf("Failed to remove pending folder entry: %v", err)
|
|
||||||
} else if len(folderID) > 0 {
|
|
||||||
res = append(res, folderID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consolidated information about a pending folder
|
// Consolidated information about a pending folder
|
||||||
type PendingFolder struct {
|
type PendingFolder struct {
|
||||||
OfferedBy map[protocol.DeviceID]ObservedFolder `json:"offeredBy"`
|
OfferedBy map[protocol.DeviceID]ObservedFolder `json:"offeredBy"`
|
||||||
|
@ -1306,13 +1306,17 @@ func (m *model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *model) ccHandleFolders(folders []protocol.Folder, deviceCfg config.DeviceConfiguration, ccDeviceInfos map[string]*indexSenderStartInfo, indexSenders *indexSenderRegistry) ([]string, map[string]struct{}, error) {
|
func (m *model) ccHandleFolders(folders []protocol.Folder, deviceCfg config.DeviceConfiguration, ccDeviceInfos map[string]*indexSenderStartInfo, indexSenders *indexSenderRegistry) ([]string, map[string]struct{}, error) {
|
||||||
handleTime := time.Now()
|
|
||||||
var folderDevice config.FolderDeviceConfiguration
|
var folderDevice config.FolderDeviceConfiguration
|
||||||
tempIndexFolders := make([]string, 0, len(folders))
|
tempIndexFolders := make([]string, 0, len(folders))
|
||||||
paused := make(map[string]struct{}, len(folders))
|
paused := make(map[string]struct{}, len(folders))
|
||||||
seenFolders := make(map[string]struct{}, len(folders))
|
seenFolders := make(map[string]struct{}, len(folders))
|
||||||
updatedPending := make([]updatedPendingFolder, 0, len(folders))
|
updatedPending := make([]updatedPendingFolder, 0, len(folders))
|
||||||
deviceID := deviceCfg.DeviceID
|
deviceID := deviceCfg.DeviceID
|
||||||
|
expiredPending, err := m.db.PendingFoldersForDevice(deviceID)
|
||||||
|
if err != nil {
|
||||||
|
l.Infof("Could not get pending folders for cleanup: %v", err)
|
||||||
|
}
|
||||||
|
of := db.ObservedFolder{Time: time.Now().Truncate(time.Second)}
|
||||||
for _, folder := range folders {
|
for _, folder := range folders {
|
||||||
seenFolders[folder.ID] = struct{}{}
|
seenFolders[folder.ID] = struct{}{}
|
||||||
|
|
||||||
@ -1326,8 +1330,10 @@ func (m *model) ccHandleFolders(folders []protocol.Folder, deviceCfg config.Devi
|
|||||||
l.Infof("Ignoring folder %s from device %s since we are configured to", folder.Description(), deviceID)
|
l.Infof("Ignoring folder %s from device %s since we are configured to", folder.Description(), deviceID)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
recvEnc := len(ccDeviceInfos[folder.ID].local.EncryptionPasswordToken) > 0
|
delete(expiredPending, folder.ID)
|
||||||
if err := m.db.AddOrUpdatePendingFolder(folder.ID, folder.Label, deviceID, recvEnc); err != nil {
|
of.Label = folder.Label
|
||||||
|
of.ReceiveEncrypted = len(ccDeviceInfos[folder.ID].local.EncryptionPasswordToken) > 0
|
||||||
|
if err := m.db.AddOrUpdatePendingFolder(folder.ID, of, deviceID); err != nil {
|
||||||
l.Warnf("Failed to persist pending folder entry to database: %v", err)
|
l.Warnf("Failed to persist pending folder entry to database: %v", err)
|
||||||
}
|
}
|
||||||
indexSenders.addPending(cfg, ccDeviceInfos[folder.ID])
|
indexSenders.addPending(cfg, ccDeviceInfos[folder.ID])
|
||||||
@ -1335,7 +1341,7 @@ func (m *model) ccHandleFolders(folders []protocol.Folder, deviceCfg config.Devi
|
|||||||
FolderID: folder.ID,
|
FolderID: folder.ID,
|
||||||
FolderLabel: folder.Label,
|
FolderLabel: folder.Label,
|
||||||
DeviceID: deviceID,
|
DeviceID: deviceID,
|
||||||
ReceiveEncrypted: recvEnc,
|
ReceiveEncrypted: of.ReceiveEncrypted,
|
||||||
})
|
})
|
||||||
// DEPRECATED: Only for backwards compatibility, should be removed.
|
// DEPRECATED: Only for backwards compatibility, should be removed.
|
||||||
m.evLogger.Log(events.FolderRejected, map[string]string{
|
m.evLogger.Log(events.FolderRejected, map[string]string{
|
||||||
@ -1412,18 +1418,16 @@ func (m *model) ccHandleFolders(folders []protocol.Folder, deviceCfg config.Devi
|
|||||||
}
|
}
|
||||||
|
|
||||||
indexSenders.removeAllExcept(seenFolders)
|
indexSenders.removeAllExcept(seenFolders)
|
||||||
// All current pending folders were touched above, so discard any with older timestamps
|
for folder := range expiredPending {
|
||||||
expiredPending, err := m.db.RemovePendingFoldersBeforeTime(deviceID, handleTime)
|
m.db.RemovePendingFolderForDevice(folder, deviceID)
|
||||||
if err != nil {
|
|
||||||
l.Infof("Could not clean up pending folder entries: %v", err)
|
|
||||||
}
|
}
|
||||||
if len(updatedPending) > 0 || len(expiredPending) > 0 {
|
if len(updatedPending) > 0 || len(expiredPending) > 0 {
|
||||||
expiredPendingList := make([]map[string]string, len(expiredPending))
|
expiredPendingList := make([]map[string]string, 0, len(expiredPending))
|
||||||
for i, folderID := range expiredPending {
|
for folderID := range expiredPending {
|
||||||
expiredPendingList[i] = map[string]string{
|
expiredPendingList = append(expiredPendingList, map[string]string{
|
||||||
"folderID": folderID,
|
"folderID": folderID,
|
||||||
"deviceID": deviceID.String(),
|
"deviceID": deviceID.String(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
m.evLogger.Log(events.PendingFoldersChanged, map[string]interface{}{
|
m.evLogger.Log(events.PendingFoldersChanged, map[string]interface{}{
|
||||||
"added": updatedPending,
|
"added": updatedPending,
|
||||||
|
@ -4173,7 +4173,11 @@ func TestPendingFolder(t *testing.T) {
|
|||||||
|
|
||||||
setDevice(t, w, config.DeviceConfiguration{DeviceID: device2})
|
setDevice(t, w, config.DeviceConfiguration{DeviceID: device2})
|
||||||
pfolder := "default"
|
pfolder := "default"
|
||||||
if err := m.db.AddOrUpdatePendingFolder(pfolder, pfolder, device2, false); err != nil {
|
of := db.ObservedFolder{
|
||||||
|
Time: time.Now().Truncate(time.Second),
|
||||||
|
Label: pfolder,
|
||||||
|
}
|
||||||
|
if err := m.db.AddOrUpdatePendingFolder(pfolder, of, device2); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
deviceFolders, err := m.PendingFolders(protocol.EmptyDeviceID)
|
deviceFolders, err := m.PendingFolders(protocol.EmptyDeviceID)
|
||||||
@ -4192,7 +4196,7 @@ func TestPendingFolder(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
setDevice(t, w, config.DeviceConfiguration{DeviceID: device3})
|
setDevice(t, w, config.DeviceConfiguration{DeviceID: device3})
|
||||||
if err := m.db.AddOrUpdatePendingFolder(pfolder, pfolder, device3, false); err != nil {
|
if err := m.db.AddOrUpdatePendingFolder(pfolder, of, device3); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
deviceFolders, err = m.PendingFolders(device2)
|
deviceFolders, err = m.PendingFolders(device2)
|
||||||
|
Loading…
Reference in New Issue
Block a user