lib/config, lib/model: Include paused folders in cluster config (fixes #4897)

This commit is contained in:
Simon Frei 2018-04-22 18:01:52 +02:00 committed by Audrius Butkevicius
parent 56cf2db68b
commit f6458d1b8f
5 changed files with 79 additions and 29 deletions

View File

@ -325,13 +325,18 @@ func (cfg *Configuration) clean() error {
existingDevices[device.DeviceID] = true existingDevices[device.DeviceID] = true
} }
// Ensure that the device list is free from duplicates // Ensure that the device list is
// - free from duplicates
// - sorted by ID
cfg.Devices = ensureNoDuplicateDevices(cfg.Devices) cfg.Devices = ensureNoDuplicateDevices(cfg.Devices)
sort.Sort(DeviceConfigurationList(cfg.Devices)) sort.Sort(DeviceConfigurationList(cfg.Devices))
// Ensure that any loose devices are not present in the wrong places
// Ensure that there are no duplicate devices // Ensure that the folder list is sorted by ID
// Ensure that the versioning configuration parameter map is not nil sort.Sort(FolderConfigurationList(cfg.Folders))
// Ensure that in all folder configs
// - any loose devices are not present in the wrong places
// - there are no duplicate devices
// - the versioning configuration parameter map is not nil
for i := range cfg.Folders { for i := range cfg.Folders {
cfg.Folders[i].Devices = ensureExistingDevices(cfg.Folders[i].Devices, existingDevices) cfg.Folders[i].Devices = ensureExistingDevices(cfg.Folders[i].Devices, existingDevices)
cfg.Folders[i].Devices = ensureNoDuplicateFolderDevices(cfg.Folders[i].Devices) cfg.Folders[i].Devices = ensureNoDuplicateFolderDevices(cfg.Folders[i].Devices)

View File

@ -278,3 +278,17 @@ func (l FolderDeviceConfigurationList) Len() int {
func (f *FolderConfiguration) CheckFreeSpace() (err error) { func (f *FolderConfiguration) CheckFreeSpace() (err error) {
return checkFreeSpace(f.MinDiskFree, f.Filesystem()) return checkFreeSpace(f.MinDiskFree, f.Filesystem())
} }
type FolderConfigurationList []FolderConfiguration
func (l FolderConfigurationList) Len() int {
return len(l)
}
func (l FolderConfigurationList) Less(a, b int) bool {
return l[a].ID < l[b].ID
}
func (l FolderConfigurationList) Swap(a, b int) {
l[a], l[b] = l[b], l[a]
}

View File

@ -267,6 +267,13 @@ func (w *Wrapper) Folders() map[string]FolderConfiguration {
return w.folderMap return w.folderMap
} }
// FolderList returns a slice of folders.
func (w *Wrapper) FolderList() []FolderConfiguration {
w.mut.Lock()
defer w.mut.Unlock()
return append([]FolderConfiguration(nil), w.cfg.Folders...)
}
// SetFolder adds a new folder to the configuration, or overwrites an existing // SetFolder adds a new folder to the configuration, or overwrites an existing
// folder with the same ID. // folder with the same ID.
func (w *Wrapper) SetFolder(fld FolderConfiguration) (Waiter, error) { func (w *Wrapper) SetFolder(fld FolderConfiguration) (Waiter, error) {

View File

@ -2154,17 +2154,14 @@ func (m *Model) generateClusterConfig(device protocol.DeviceID) protocol.Cluster
var message protocol.ClusterConfig var message protocol.ClusterConfig
m.fmut.RLock() m.fmut.RLock()
// The list of folders in the message is sorted, so we always get the folderFiles := m.folderFiles
// same order. m.fmut.RUnlock()
folders := m.deviceFolders[device]
sort.Strings(folders)
for _, folder := range folders { var fs *db.FileSet
folderCfg := m.cfg.Folders()[folder]
fs := m.folderFiles[folder]
for _, folderCfg := range m.cfg.FolderList() {
protocolFolder := protocol.Folder{ protocolFolder := protocol.Folder{
ID: folder, ID: folderCfg.ID,
Label: folderCfg.Label, Label: folderCfg.Label,
ReadOnly: folderCfg.Type == config.FolderTypeSendOnly, ReadOnly: folderCfg.Type == config.FolderTypeSendOnly,
IgnorePermissions: folderCfg.IgnorePerms, IgnorePermissions: folderCfg.IgnorePerms,
@ -2173,36 +2170,37 @@ func (m *Model) generateClusterConfig(device protocol.DeviceID) protocol.Cluster
Paused: folderCfg.Paused, Paused: folderCfg.Paused,
} }
// Devices are sorted, so we always get the same order. if !folderCfg.Paused {
for _, device := range m.folderDevices.sortedDevices(folder) { fs = folderFiles[folderCfg.ID]
deviceCfg := m.cfg.Devices()[device]
var indexID protocol.IndexID
var maxSequence int64
if device == m.id {
indexID = fs.IndexID(protocol.LocalDeviceID)
maxSequence = fs.Sequence(protocol.LocalDeviceID)
} else {
indexID = fs.IndexID(device)
maxSequence = fs.Sequence(device)
} }
for _, device := range folderCfg.Devices {
deviceCfg, _ := m.cfg.Device(device.DeviceID)
protocolDevice := protocol.Device{ protocolDevice := protocol.Device{
ID: device, ID: deviceCfg.DeviceID,
Name: deviceCfg.Name, Name: deviceCfg.Name,
Addresses: deviceCfg.Addresses, Addresses: deviceCfg.Addresses,
Compression: deviceCfg.Compression, Compression: deviceCfg.Compression,
CertName: deviceCfg.CertName, CertName: deviceCfg.CertName,
Introducer: deviceCfg.Introducer, Introducer: deviceCfg.Introducer,
IndexID: indexID, }
MaxSequence: maxSequence,
if !folderCfg.Paused {
if deviceCfg.DeviceID == m.id {
protocolDevice.IndexID = fs.IndexID(protocol.LocalDeviceID)
protocolDevice.MaxSequence = fs.Sequence(protocol.LocalDeviceID)
} else {
protocolDevice.IndexID = fs.IndexID(deviceCfg.DeviceID)
protocolDevice.MaxSequence = fs.Sequence(deviceCfg.DeviceID)
}
} }
protocolFolder.Devices = append(protocolFolder.Devices, protocolDevice) protocolFolder.Devices = append(protocolFolder.Devices, protocolDevice)
} }
message.Folders = append(message.Folders, protocolFolder) message.Folders = append(message.Folders, protocolFolder)
} }
m.fmut.RUnlock()
return message return message
} }

View File

@ -1043,6 +1043,32 @@ func TestIntroducer(t *testing.T) {
} }
} }
func TestIssue4897(t *testing.T) {
_, m := newState(config.Configuration{
Devices: []config.DeviceConfiguration{
{
DeviceID: device1,
Introducer: true,
},
},
Folders: []config.FolderConfiguration{
{
ID: "folder1",
Path: "testdata",
Devices: []config.FolderDeviceConfiguration{
{DeviceID: device1},
},
Paused: true,
},
},
})
cm := m.generateClusterConfig(device1)
if l := len(cm.Folders); l != 1 {
t.Errorf("Cluster config contains %v folders, expected 1", l)
}
}
func TestAutoAcceptRejected(t *testing.T) { func TestAutoAcceptRejected(t *testing.T) {
// Nothing happens if AutoAcceptFolders not set // Nothing happens if AutoAcceptFolders not set
tcfg := defaultAutoAcceptCfg.Copy() tcfg := defaultAutoAcceptCfg.Copy()