Refactor config commit stuff to support restartless updates better
Includes restartless updates of the GUI settings (listening port etc) as a proof of concept.
This commit is contained in:
@@ -17,6 +17,7 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
stdsync "sync"
|
||||
@@ -1718,6 +1719,37 @@ func (m *Model) String() string {
|
||||
return fmt.Sprintf("model@%p", m)
|
||||
}
|
||||
|
||||
func (m *Model) VerifyConfiguration(from, to config.Configuration) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Model) CommitConfiguration(from, to config.Configuration) bool {
|
||||
// TODO: This should not use reflect, and should take more care to try to handle stuff without restart.
|
||||
|
||||
// Adding, removing or changing folders requires restart
|
||||
if !reflect.DeepEqual(from.Folders, to.Folders) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Removing a device requres restart
|
||||
toDevs := make(map[protocol.DeviceID]bool, len(from.Devices))
|
||||
for _, dev := range to.Devices {
|
||||
toDevs[dev.DeviceID] = true
|
||||
}
|
||||
for _, dev := range from.Devices {
|
||||
if _, ok := toDevs[dev.DeviceID]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// All of the generic options require restart
|
||||
if !reflect.DeepEqual(from.Options, to.Options) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func symlinkInvalid(isLink bool) bool {
|
||||
if !symlinks.Supported && isLink {
|
||||
SymlinkWarning.Do(func() {
|
||||
|
||||
@@ -317,21 +317,22 @@ func TestDeviceRename(t *testing.T) {
|
||||
|
||||
defer os.Remove("tmpconfig.xml")
|
||||
|
||||
cfg := config.New(device1)
|
||||
cfg.Devices = []config.DeviceConfiguration{
|
||||
rawCfg := config.New(device1)
|
||||
rawCfg.Devices = []config.DeviceConfiguration{
|
||||
{
|
||||
DeviceID: device1,
|
||||
},
|
||||
}
|
||||
cfg := config.Wrap("tmpconfig.xml", rawCfg)
|
||||
|
||||
db, _ := leveldb.Open(storage.NewMemStorage(), nil)
|
||||
m := NewModel(config.Wrap("tmpconfig.xml", cfg), protocol.LocalDeviceID, "device", "syncthing", "dev", db)
|
||||
if cfg.Devices[0].Name != "" {
|
||||
m := NewModel(cfg, protocol.LocalDeviceID, "device", "syncthing", "dev", db)
|
||||
if cfg.Devices()[device1].Name != "" {
|
||||
t.Errorf("Device already has a name")
|
||||
}
|
||||
|
||||
m.ClusterConfig(device1, ccm)
|
||||
if cfg.Devices[0].Name != "" {
|
||||
if cfg.Devices()[device1].Name != "" {
|
||||
t.Errorf("Device already has a name")
|
||||
}
|
||||
|
||||
@@ -342,13 +343,13 @@ func TestDeviceRename(t *testing.T) {
|
||||
},
|
||||
}
|
||||
m.ClusterConfig(device1, ccm)
|
||||
if cfg.Devices[0].Name != "tester" {
|
||||
if cfg.Devices()[device1].Name != "tester" {
|
||||
t.Errorf("Device did not get a name")
|
||||
}
|
||||
|
||||
ccm.Options[0].Value = "tester2"
|
||||
m.ClusterConfig(device1, ccm)
|
||||
if cfg.Devices[0].Name != "tester" {
|
||||
if cfg.Devices()[device1].Name != "tester" {
|
||||
t.Errorf("Device name got overwritten")
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"time"
|
||||
@@ -37,8 +38,10 @@ func NewProgressEmitter(cfg *config.Wrapper) *ProgressEmitter {
|
||||
timer: time.NewTimer(time.Millisecond),
|
||||
mut: sync.NewMutex(),
|
||||
}
|
||||
t.Changed(cfg.Raw())
|
||||
|
||||
t.CommitConfiguration(config.Configuration{}, cfg.Raw())
|
||||
cfg.Subscribe(t)
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
@@ -81,17 +84,22 @@ func (t *ProgressEmitter) Serve() {
|
||||
}
|
||||
}
|
||||
|
||||
// Changed implements the config.Handler Interface to handle configuration
|
||||
// changes
|
||||
func (t *ProgressEmitter) Changed(cfg config.Configuration) error {
|
||||
// VerifyConfiguration implements the config.Committer interface
|
||||
func (t *ProgressEmitter) VerifyConfiguration(from, to config.Configuration) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CommitConfiguration implements the config.Committer interface
|
||||
func (t *ProgressEmitter) CommitConfiguration(from, to config.Configuration) bool {
|
||||
t.mut.Lock()
|
||||
defer t.mut.Unlock()
|
||||
|
||||
t.interval = time.Duration(cfg.Options.ProgressUpdateIntervalS) * time.Second
|
||||
t.interval = time.Duration(to.Options.ProgressUpdateIntervalS) * time.Second
|
||||
if debug {
|
||||
l.Debugln("progress emitter: updated interval", t.interval)
|
||||
}
|
||||
return nil
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Stop stops the emitter.
|
||||
@@ -138,3 +146,7 @@ func (t *ProgressEmitter) BytesCompleted(folder string) (bytes int64) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t *ProgressEmitter) String() string {
|
||||
return fmt.Sprintf("ProgressEmitter@%p", t)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user