Kaynağa Gözat

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

Simon Frei 7 yıl önce
ebeveyn
işleme
f6458d1b8f

+ 10 - 5
lib/config/config.go

@@ -325,13 +325,18 @@ func (cfg *Configuration) clean() error {
 		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)
-
 	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 versioning configuration parameter map is not nil
+
+	// Ensure that the folder list is sorted by ID
+	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 {
 		cfg.Folders[i].Devices = ensureExistingDevices(cfg.Folders[i].Devices, existingDevices)
 		cfg.Folders[i].Devices = ensureNoDuplicateFolderDevices(cfg.Folders[i].Devices)

+ 14 - 0
lib/config/folderconfiguration.go

@@ -278,3 +278,17 @@ func (l FolderDeviceConfigurationList) Len() int {
 func (f *FolderConfiguration) CheckFreeSpace() (err error) {
 	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]
+}

+ 7 - 0
lib/config/wrapper.go

@@ -267,6 +267,13 @@ func (w *Wrapper) Folders() map[string]FolderConfiguration {
 	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
 // folder with the same ID.
 func (w *Wrapper) SetFolder(fld FolderConfiguration) (Waiter, error) {

+ 22 - 24
lib/model/model.go

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

+ 26 - 0
lib/model/model_test.go

@@ -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) {
 	// Nothing happens if AutoAcceptFolders not set
 	tcfg := defaultAutoAcceptCfg.Copy()