mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-08 22:31:04 +00:00
parent
f6f696c6c5
commit
b1c74860e8
@ -22,6 +22,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/locations"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/urfave/cli"
|
||||
@ -85,7 +86,7 @@ func main() {
|
||||
myID := protocol.NewDeviceID(cert.Certificate[0])
|
||||
|
||||
// Load the config
|
||||
cfg, err := config.Load(locations.Get(locations.ConfigFile), myID)
|
||||
cfg, err := config.Load(locations.Get(locations.ConfigFile), myID, events.NoopLogger)
|
||||
if err != nil {
|
||||
log.Fatalln(errors.Wrap(err, "loading config"))
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/discover"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
@ -82,7 +83,7 @@ func checkServers(deviceID protocol.DeviceID, servers ...string) {
|
||||
}
|
||||
|
||||
func checkServer(deviceID protocol.DeviceID, server string) checkResult {
|
||||
disco, err := discover.NewGlobal(server, tls.Certificate{}, nil)
|
||||
disco, err := discover.NewGlobal(server, tls.Certificate{}, nil, events.NoopLogger)
|
||||
if err != nil {
|
||||
return checkResult{error: err}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/relay/protocol"
|
||||
"github.com/syncthing/syncthing/lib/tlsutil"
|
||||
@ -194,7 +195,7 @@ func main() {
|
||||
log.Println("ID:", id)
|
||||
}
|
||||
|
||||
wrapper := config.Wrap("config", config.New(id))
|
||||
wrapper := config.Wrap("config", config.New(id), events.NoopLogger)
|
||||
wrapper.SetOptions(config.OptionsConfiguration{
|
||||
NATLeaseM: natLease,
|
||||
NATRenewalM: natRenewal,
|
||||
|
@ -394,7 +394,7 @@ func main() {
|
||||
}
|
||||
|
||||
func openGUI(myID protocol.DeviceID) error {
|
||||
cfg, err := loadOrDefaultConfig(myID)
|
||||
cfg, err := loadOrDefaultConfig(myID, events.NoopLogger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -437,7 +437,7 @@ func generate(generateDir string) error {
|
||||
l.Warnln("Config exists; will not overwrite.")
|
||||
return nil
|
||||
}
|
||||
cfg, err := syncthing.DefaultConfig(cfgFile, myID, noDefaultFolder)
|
||||
cfg, err := syncthing.DefaultConfig(cfgFile, myID, events.NoopLogger, noDefaultFolder)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -471,7 +471,7 @@ func debugFacilities() string {
|
||||
}
|
||||
|
||||
func checkUpgrade() upgrade.Release {
|
||||
cfg, _ := loadOrDefaultConfig(protocol.EmptyDeviceID)
|
||||
cfg, _ := loadOrDefaultConfig(protocol.EmptyDeviceID, events.NoopLogger)
|
||||
opts := cfg.Options()
|
||||
release, err := upgrade.LatestRelease(opts.ReleasesURL, build.Version, opts.UpgradeToPreReleases)
|
||||
if err != nil {
|
||||
@ -512,7 +512,7 @@ func performUpgrade(release upgrade.Release) {
|
||||
}
|
||||
|
||||
func upgradeViaRest() error {
|
||||
cfg, _ := loadOrDefaultConfig(protocol.EmptyDeviceID)
|
||||
cfg, _ := loadOrDefaultConfig(protocol.EmptyDeviceID, events.NoopLogger)
|
||||
u, err := url.Parse(cfg.GUI().URL())
|
||||
if err != nil {
|
||||
return err
|
||||
@ -566,7 +566,11 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cfg, err := syncthing.LoadConfigAtStartup(locations.Get(locations.ConfigFile), cert, runtimeOptions.allowNewerConfig, noDefaultFolder)
|
||||
evLogger := events.NewLogger()
|
||||
go evLogger.Serve()
|
||||
defer evLogger.Stop()
|
||||
|
||||
cfg, err := syncthing.LoadConfigAtStartup(locations.Get(locations.ConfigFile), cert, evLogger, runtimeOptions.allowNewerConfig, noDefaultFolder)
|
||||
if err != nil {
|
||||
l.Warnln("Failed to initialize config:", err)
|
||||
os.Exit(exitError)
|
||||
@ -594,7 +598,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
appOpts.DeadlockTimeoutS = secs
|
||||
}
|
||||
|
||||
app := syncthing.New(cfg, ldb, cert, appOpts)
|
||||
app := syncthing.New(cfg, ldb, evLogger, cert, appOpts)
|
||||
|
||||
setupSignalHandling(app)
|
||||
|
||||
@ -639,7 +643,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
if runtimeOptions.NoUpgrade {
|
||||
l.Infof("No automatic upgrades; STNOUPGRADE environment variable defined.")
|
||||
} else {
|
||||
go autoUpgrade(cfg, app)
|
||||
go autoUpgrade(cfg, app, evLogger)
|
||||
}
|
||||
}
|
||||
|
||||
@ -684,12 +688,12 @@ func setupSignalHandling(app *syncthing.App) {
|
||||
}()
|
||||
}
|
||||
|
||||
func loadOrDefaultConfig(myID protocol.DeviceID) (config.Wrapper, error) {
|
||||
func loadOrDefaultConfig(myID protocol.DeviceID, evLogger events.Logger) (config.Wrapper, error) {
|
||||
cfgFile := locations.Get(locations.ConfigFile)
|
||||
cfg, err := config.Load(cfgFile, myID)
|
||||
cfg, err := config.Load(cfgFile, myID, evLogger)
|
||||
|
||||
if err != nil {
|
||||
cfg, err = syncthing.DefaultConfig(cfgFile, myID, noDefaultFolder)
|
||||
cfg, err = syncthing.DefaultConfig(cfgFile, myID, evLogger, noDefaultFolder)
|
||||
}
|
||||
|
||||
return cfg, err
|
||||
@ -774,9 +778,9 @@ func standbyMonitor(app *syncthing.App) {
|
||||
}
|
||||
}
|
||||
|
||||
func autoUpgrade(cfg config.Wrapper, app *syncthing.App) {
|
||||
func autoUpgrade(cfg config.Wrapper, app *syncthing.App, evLogger events.Logger) {
|
||||
timer := time.NewTimer(0)
|
||||
sub := events.Default.Subscribe(events.DeviceConnected)
|
||||
sub := evLogger.Subscribe(events.DeviceConnected)
|
||||
for {
|
||||
select {
|
||||
case event := <-sub.C():
|
||||
@ -798,7 +802,7 @@ func autoUpgrade(cfg config.Wrapper, app *syncthing.App) {
|
||||
|
||||
rel, err := upgrade.LatestRelease(opts.ReleasesURL, build.Version, opts.UpgradeToPreReleases)
|
||||
if err == upgrade.ErrUpgradeUnsupported {
|
||||
events.Default.Unsubscribe(sub)
|
||||
sub.Unsubscribe()
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
@ -822,7 +826,7 @@ func autoUpgrade(cfg config.Wrapper, app *syncthing.App) {
|
||||
timer.Reset(checkInterval)
|
||||
continue
|
||||
}
|
||||
events.Default.Unsubscribe(sub)
|
||||
sub.Unsubscribe()
|
||||
l.Warnf("Automatically upgraded to version %q. Restarting in 1 minute.", rel.Tag)
|
||||
time.Sleep(time.Minute)
|
||||
app.Stop(syncthing.ExitUpgrade)
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/locations"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
@ -450,7 +451,7 @@ func childEnv() []string {
|
||||
// panicUploadMaxWait uploading panics...
|
||||
func maybeReportPanics() {
|
||||
// Try to get a config to see if/where panics should be reported.
|
||||
cfg, err := loadOrDefaultConfig(protocol.EmptyDeviceID)
|
||||
cfg, err := loadOrDefaultConfig(protocol.EmptyDeviceID, events.NoopLogger)
|
||||
if err != nil {
|
||||
l.Warnln("Couldn't load config; not reporting crash")
|
||||
return
|
||||
|
@ -71,6 +71,7 @@ type service struct {
|
||||
model model.Model
|
||||
eventSubs map[events.EventType]events.BufferedSubscription
|
||||
eventSubsMut sync.Mutex
|
||||
evLogger events.Logger
|
||||
discoverer discover.CachingMux
|
||||
connectionsService connections.Service
|
||||
fss model.FolderSummaryService
|
||||
@ -105,7 +106,7 @@ type Service interface {
|
||||
WaitForStart() error
|
||||
}
|
||||
|
||||
func New(id protocol.DeviceID, cfg config.Wrapper, assetDir, tlsDefaultCommonName string, m model.Model, defaultSub, diskSub events.BufferedSubscription, discoverer discover.CachingMux, connectionsService connections.Service, urService *ur.Service, fss model.FolderSummaryService, errors, systemLog logger.Recorder, cpu Rater, contr Controller, noUpgrade bool) Service {
|
||||
func New(id protocol.DeviceID, cfg config.Wrapper, assetDir, tlsDefaultCommonName string, m model.Model, defaultSub, diskSub events.BufferedSubscription, evLogger events.Logger, discoverer discover.CachingMux, connectionsService connections.Service, urService *ur.Service, fss model.FolderSummaryService, errors, systemLog logger.Recorder, cpu Rater, contr Controller, noUpgrade bool) Service {
|
||||
s := &service{
|
||||
id: id,
|
||||
cfg: cfg,
|
||||
@ -116,6 +117,7 @@ func New(id protocol.DeviceID, cfg config.Wrapper, assetDir, tlsDefaultCommonNam
|
||||
DiskEventMask: diskSub,
|
||||
},
|
||||
eventSubsMut: sync.NewMutex(),
|
||||
evLogger: evLogger,
|
||||
discoverer: discoverer,
|
||||
connectionsService: connectionsService,
|
||||
fss: fss,
|
||||
@ -315,7 +317,7 @@ func (s *service) serve(stop chan struct{}) {
|
||||
|
||||
// Wrap everything in basic auth, if user/password is set.
|
||||
if guiCfg.IsAuthEnabled() {
|
||||
handler = basicAuthAndSessionMiddleware("sessionid-"+s.id.String()[:5], guiCfg, s.cfg.LDAP(), handler)
|
||||
handler = basicAuthAndSessionMiddleware("sessionid-"+s.id.String()[:5], guiCfg, s.cfg.LDAP(), handler, s.evLogger)
|
||||
}
|
||||
|
||||
// Redirect to HTTPS if we are supposed to
|
||||
@ -1215,7 +1217,7 @@ func (s *service) getEventSub(mask events.EventType) events.BufferedSubscription
|
||||
s.eventSubsMut.Lock()
|
||||
bufsub, ok := s.eventSubs[mask]
|
||||
if !ok {
|
||||
evsub := events.Default.Subscribe(mask)
|
||||
evsub := s.evLogger.Subscribe(mask)
|
||||
bufsub = events.NewBufferedSubscription(evsub, EventSubBufferSize)
|
||||
s.eventSubs[mask] = bufsub
|
||||
}
|
||||
|
@ -28,14 +28,14 @@ var (
|
||||
sessionsMut = sync.NewMutex()
|
||||
)
|
||||
|
||||
func emitLoginAttempt(success bool, username string) {
|
||||
events.Default.Log(events.LoginAttempt, map[string]interface{}{
|
||||
func emitLoginAttempt(success bool, username string, evLogger events.Logger) {
|
||||
evLogger.Log(events.LoginAttempt, map[string]interface{}{
|
||||
"success": success,
|
||||
"username": username,
|
||||
})
|
||||
}
|
||||
|
||||
func basicAuthAndSessionMiddleware(cookieName string, guiCfg config.GUIConfiguration, ldapCfg config.LDAPConfiguration, next http.Handler) http.Handler {
|
||||
func basicAuthAndSessionMiddleware(cookieName string, guiCfg config.GUIConfiguration, ldapCfg config.LDAPConfiguration, next http.Handler, evLogger events.Logger) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if guiCfg.IsValidAPIKey(r.Header.Get("X-API-Key")) {
|
||||
next.ServeHTTP(w, r)
|
||||
@ -94,7 +94,7 @@ func basicAuthAndSessionMiddleware(cookieName string, guiCfg config.GUIConfigura
|
||||
}
|
||||
|
||||
if !authOk {
|
||||
emitLoginAttempt(false, username)
|
||||
emitLoginAttempt(false, username, evLogger)
|
||||
error()
|
||||
return
|
||||
}
|
||||
@ -109,7 +109,7 @@ func basicAuthAndSessionMiddleware(cookieName string, guiCfg config.GUIConfigura
|
||||
MaxAge: 0,
|
||||
})
|
||||
|
||||
emitLoginAttempt(true, username)
|
||||
emitLoginAttempt(true, username, evLogger)
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
@ -100,9 +100,9 @@ func TestStopAfterBrokenConfig(t *testing.T) {
|
||||
RawUseTLS: false,
|
||||
},
|
||||
}
|
||||
w := config.Wrap("/dev/null", cfg)
|
||||
w := config.Wrap("/dev/null", cfg, events.NoopLogger)
|
||||
|
||||
srv := New(protocol.LocalDeviceID, w, "", "syncthing", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, false).(*service)
|
||||
srv := New(protocol.LocalDeviceID, w, "", "syncthing", nil, nil, nil, events.NoopLogger, nil, nil, nil, nil, nil, nil, nil, nil, false).(*service)
|
||||
defer os.Remove(token)
|
||||
srv.started = make(chan string)
|
||||
|
||||
@ -512,8 +512,8 @@ func startHTTP(cfg *mockedConfig) (string, error) {
|
||||
|
||||
// Instantiate the API service
|
||||
urService := ur.New(cfg, m, connections, false)
|
||||
summaryService := model.NewFolderSummaryService(cfg, m, protocol.LocalDeviceID)
|
||||
svc := New(protocol.LocalDeviceID, cfg, assetDir, "syncthing", m, eventSub, diskEventSub, discoverer, connections, urService, summaryService, errorLog, systemLog, cpu, nil, false).(*service)
|
||||
summaryService := model.NewFolderSummaryService(cfg, m, protocol.LocalDeviceID, events.NoopLogger)
|
||||
svc := New(protocol.LocalDeviceID, cfg, assetDir, "syncthing", m, eventSub, diskEventSub, events.NoopLogger, discoverer, connections, urService, summaryService, errorLog, systemLog, cpu, nil, false).(*service)
|
||||
defer os.Remove(token)
|
||||
svc.started = addrChan
|
||||
|
||||
@ -979,7 +979,7 @@ func TestEventMasks(t *testing.T) {
|
||||
cfg := new(mockedConfig)
|
||||
defSub := new(mockedEventSub)
|
||||
diskSub := new(mockedEventSub)
|
||||
svc := New(protocol.LocalDeviceID, cfg, "", "syncthing", nil, defSub, diskSub, nil, nil, nil, nil, nil, nil, nil, nil, false).(*service)
|
||||
svc := New(protocol.LocalDeviceID, cfg, "", "syncthing", nil, defSub, diskSub, events.NoopLogger, nil, nil, nil, nil, nil, nil, nil, nil, false).(*service)
|
||||
defer os.Remove(token)
|
||||
|
||||
if mask := svc.getEventMask(""); mask != DefaultEventMask {
|
||||
|
@ -44,7 +44,7 @@ func (validationError) String() string {
|
||||
func TestReplaceCommit(t *testing.T) {
|
||||
t.Skip("broken, fails randomly, #3834")
|
||||
|
||||
w := Wrap("/dev/null", Configuration{Version: 0})
|
||||
w := wrap("/dev/null", Configuration{Version: 0})
|
||||
if w.RawCopy().Version != 0 {
|
||||
t.Fatal("Config incorrect")
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/d4l3k/messagediff"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
@ -86,7 +87,7 @@ func TestDefaultValues(t *testing.T) {
|
||||
func TestDeviceConfig(t *testing.T) {
|
||||
for i := OldestHandledVersion; i <= CurrentVersion; i++ {
|
||||
os.RemoveAll(filepath.Join("testdata", DefaultMarkerName))
|
||||
wr, err := Load(fmt.Sprintf("testdata/v%d.xml", i), device1)
|
||||
wr, err := load(fmt.Sprintf("testdata/v%d.xml", i), device1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -168,7 +169,7 @@ func TestDeviceConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNoListenAddresses(t *testing.T) {
|
||||
cfg, err := Load("testdata/nolistenaddress.xml", device1)
|
||||
cfg, err := load("testdata/nolistenaddress.xml", device1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -225,7 +226,7 @@ func TestOverriddenValues(t *testing.T) {
|
||||
}
|
||||
|
||||
os.Unsetenv("STNOUPGRADE")
|
||||
cfg, err := Load("testdata/overridenvalues.xml", device1)
|
||||
cfg, err := load("testdata/overridenvalues.xml", device1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -270,7 +271,7 @@ func TestDeviceAddressesDynamic(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
cfg, err := Load("testdata/deviceaddressesdynamic.xml", device4)
|
||||
cfg, err := load("testdata/deviceaddressesdynamic.xml", device4)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -319,7 +320,7 @@ func TestDeviceCompression(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
cfg, err := Load("testdata/devicecompression.xml", device4)
|
||||
cfg, err := load("testdata/devicecompression.xml", device4)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -365,7 +366,7 @@ func TestDeviceAddressesStatic(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
cfg, err := Load("testdata/deviceaddressesstatic.xml", device4)
|
||||
cfg, err := load("testdata/deviceaddressesstatic.xml", device4)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -377,7 +378,7 @@ func TestDeviceAddressesStatic(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVersioningConfig(t *testing.T) {
|
||||
cfg, err := Load("testdata/versioningconfig.xml", device4)
|
||||
cfg, err := load("testdata/versioningconfig.xml", device4)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -404,7 +405,7 @@ func TestIssue1262(t *testing.T) {
|
||||
t.Skipf("path gets converted to absolute as part of the filesystem initialization on linux")
|
||||
}
|
||||
|
||||
cfg, err := Load("testdata/issue-1262.xml", device4)
|
||||
cfg, err := load("testdata/issue-1262.xml", device4)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -418,7 +419,7 @@ func TestIssue1262(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIssue1750(t *testing.T) {
|
||||
cfg, err := Load("testdata/issue-1750.xml", device4)
|
||||
cfg, err := load("testdata/issue-1750.xml", device4)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -520,7 +521,7 @@ func TestNewSaveLoad(t *testing.T) {
|
||||
}
|
||||
|
||||
intCfg := New(device1)
|
||||
cfg := Wrap(path, intCfg)
|
||||
cfg := wrap(path, intCfg)
|
||||
|
||||
// To make the equality pass later
|
||||
cfg.(*wrapper).cfg.XMLName.Local = "configuration"
|
||||
@ -537,7 +538,7 @@ func TestNewSaveLoad(t *testing.T) {
|
||||
t.Error(path, "does not exist")
|
||||
}
|
||||
|
||||
cfg2, err := Load(path, device1)
|
||||
cfg2, err := load(path, device1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -564,7 +565,7 @@ func TestPrepare(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCopy(t *testing.T) {
|
||||
wrapper, err := Load("testdata/example.xml", device1)
|
||||
wrapper, err := load("testdata/example.xml", device1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -603,7 +604,7 @@ func TestCopy(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPullOrder(t *testing.T) {
|
||||
wrapper, err := Load("testdata/pullorder.xml", device1)
|
||||
wrapper, err := load("testdata/pullorder.xml", device1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -643,7 +644,7 @@ func TestPullOrder(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wrapper = Wrap("testdata/pullorder.xml", cfg)
|
||||
wrapper = wrap("testdata/pullorder.xml", cfg)
|
||||
folders = wrapper.Folders()
|
||||
|
||||
for _, tc := range expected {
|
||||
@ -654,7 +655,7 @@ func TestPullOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLargeRescanInterval(t *testing.T) {
|
||||
wrapper, err := Load("testdata/largeinterval.xml", device1)
|
||||
wrapper, err := load("testdata/largeinterval.xml", device1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -692,7 +693,7 @@ func TestGUIConfigURL(t *testing.T) {
|
||||
func TestDuplicateDevices(t *testing.T) {
|
||||
// Duplicate devices should be removed
|
||||
|
||||
wrapper, err := Load("testdata/dupdevices.xml", device1)
|
||||
wrapper, err := load("testdata/dupdevices.xml", device1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -710,7 +711,7 @@ func TestDuplicateDevices(t *testing.T) {
|
||||
func TestDuplicateFolders(t *testing.T) {
|
||||
// Duplicate folders are a loading error
|
||||
|
||||
_, err := Load("testdata/dupfolders.xml", device1)
|
||||
_, err := load("testdata/dupfolders.xml", device1)
|
||||
if err == nil || !strings.Contains(err.Error(), errFolderIDDuplicate.Error()) {
|
||||
t.Fatal(`Expected error to mention "duplicate folder ID":`, err)
|
||||
}
|
||||
@ -721,7 +722,7 @@ func TestEmptyFolderPaths(t *testing.T) {
|
||||
// get messed up by the prepare steps (e.g., become the current dir or
|
||||
// get a slash added so that it becomes the root directory or similar).
|
||||
|
||||
_, err := Load("testdata/nopath.xml", device1)
|
||||
_, err := load("testdata/nopath.xml", device1)
|
||||
if err == nil || !strings.Contains(err.Error(), errFolderPathEmpty.Error()) {
|
||||
t.Fatal("Expected error due to empty folder path, got", err)
|
||||
}
|
||||
@ -790,7 +791,7 @@ func TestIgnoredDevices(t *testing.T) {
|
||||
// Verify that ignored devices that are also present in the
|
||||
// configuration are not in fact ignored.
|
||||
|
||||
wrapper, err := Load("testdata/ignoreddevices.xml", device1)
|
||||
wrapper, err := load("testdata/ignoreddevices.xml", device1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -808,7 +809,7 @@ func TestIgnoredFolders(t *testing.T) {
|
||||
// configuration are not in fact ignored.
|
||||
// Also, verify that folders that are shared with a device are not ignored.
|
||||
|
||||
wrapper, err := Load("testdata/ignoredfolders.xml", device1)
|
||||
wrapper, err := load("testdata/ignoredfolders.xml", device1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -844,7 +845,7 @@ func TestIgnoredFolders(t *testing.T) {
|
||||
func TestGetDevice(t *testing.T) {
|
||||
// Verify that the Device() call does the right thing
|
||||
|
||||
wrapper, err := Load("testdata/ignoreddevices.xml", device1)
|
||||
wrapper, err := load("testdata/ignoreddevices.xml", device1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -871,7 +872,7 @@ func TestGetDevice(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSharesRemovedOnDeviceRemoval(t *testing.T) {
|
||||
wrapper, err := Load("testdata/example.xml", device1)
|
||||
wrapper, err := load("testdata/example.xml", device1)
|
||||
if err != nil {
|
||||
t.Errorf("Failed: %s", err)
|
||||
}
|
||||
@ -956,7 +957,7 @@ func TestIssue4219(t *testing.T) {
|
||||
t.Errorf("There should be three ignored folders, not %d", ignoredFolders)
|
||||
}
|
||||
|
||||
w := Wrap("/tmp/cfg", cfg)
|
||||
w := wrap("/tmp/cfg", cfg)
|
||||
if !w.IgnoredFolder(device2, "t1") {
|
||||
t.Error("Folder device2 t1 should be ignored")
|
||||
}
|
||||
@ -1145,3 +1146,11 @@ func defaultConfigAsMap() map[string]interface{} {
|
||||
}
|
||||
return tmp
|
||||
}
|
||||
|
||||
func load(path string, myID protocol.DeviceID) (Wrapper, error) {
|
||||
return Load(path, myID, events.NoopLogger)
|
||||
}
|
||||
|
||||
func wrap(path string, cfg Configuration) Wrapper {
|
||||
return Wrap(path, cfg, events.NoopLogger)
|
||||
}
|
||||
|
@ -98,6 +98,7 @@ type Wrapper interface {
|
||||
type wrapper struct {
|
||||
cfg Configuration
|
||||
path string
|
||||
evLogger events.Logger
|
||||
|
||||
deviceMap map[protocol.DeviceID]DeviceConfiguration
|
||||
folderMap map[string]FolderConfiguration
|
||||
@ -133,10 +134,11 @@ func (w *wrapper) StunServers() []string {
|
||||
|
||||
// Wrap wraps an existing Configuration structure and ties it to a file on
|
||||
// disk.
|
||||
func Wrap(path string, cfg Configuration) Wrapper {
|
||||
func Wrap(path string, cfg Configuration, evLogger events.Logger) Wrapper {
|
||||
w := &wrapper{
|
||||
cfg: cfg,
|
||||
path: path,
|
||||
evLogger: evLogger,
|
||||
mut: sync.NewMutex(),
|
||||
}
|
||||
return w
|
||||
@ -144,7 +146,7 @@ func Wrap(path string, cfg Configuration) Wrapper {
|
||||
|
||||
// Load loads an existing file on disk and returns a new configuration
|
||||
// wrapper.
|
||||
func Load(path string, myID protocol.DeviceID) (Wrapper, error) {
|
||||
func Load(path string, myID protocol.DeviceID, evLogger events.Logger) (Wrapper, error) {
|
||||
fd, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -156,7 +158,7 @@ func Load(path string, myID protocol.DeviceID) (Wrapper, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return Wrap(path, cfg), nil
|
||||
return Wrap(path, cfg, evLogger), nil
|
||||
}
|
||||
|
||||
func (w *wrapper) ConfigPath() string {
|
||||
@ -450,7 +452,7 @@ func (w *wrapper) Save() error {
|
||||
return err
|
||||
}
|
||||
|
||||
events.Default.Log(events.ConfigSaved, w.cfg)
|
||||
w.evLogger.Log(events.ConfigSaved, w.cfg)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
)
|
||||
|
||||
func TestIsLANHost(t *testing.T) {
|
||||
@ -35,7 +36,7 @@ func TestIsLANHost(t *testing.T) {
|
||||
Options: config.OptionsConfiguration{
|
||||
AlwaysLocalNets: []string{"10.20.30.0/24"},
|
||||
},
|
||||
})
|
||||
}, events.NoopLogger)
|
||||
s := &service{cfg: cfg}
|
||||
|
||||
for _, tc := range cases {
|
||||
|
@ -8,6 +8,7 @@ package connections
|
||||
|
||||
import (
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"golang.org/x/time/rate"
|
||||
"math/rand"
|
||||
@ -25,7 +26,7 @@ func init() {
|
||||
}
|
||||
|
||||
func initConfig() config.Wrapper {
|
||||
cfg := config.Wrap("/dev/null", config.New(device1))
|
||||
cfg := config.Wrap("/dev/null", config.New(device1), events.NoopLogger)
|
||||
dev1Conf = config.NewDeviceConfiguration(device1, "device1")
|
||||
dev2Conf = config.NewDeviceConfiguration(device2, "device2")
|
||||
dev3Conf = config.NewDeviceConfiguration(device3, "device3")
|
||||
|
@ -120,6 +120,7 @@ type service struct {
|
||||
limiter *limiter
|
||||
natService *nat.Service
|
||||
natServiceToken *suture.ServiceToken
|
||||
evLogger events.Logger
|
||||
|
||||
listenersMut sync.RWMutex
|
||||
listeners map[string]genericListener
|
||||
@ -130,7 +131,7 @@ type service struct {
|
||||
connectionStatus map[string]ConnectionStatusEntry // address -> latest error/status
|
||||
}
|
||||
|
||||
func NewService(cfg config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *tls.Config, discoverer discover.Finder, bepProtocolName string, tlsDefaultCommonName string) Service {
|
||||
func NewService(cfg config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *tls.Config, discoverer discover.Finder, bepProtocolName string, tlsDefaultCommonName string, evLogger events.Logger) Service {
|
||||
service := &service{
|
||||
Supervisor: suture.New("connections.Service", suture.Spec{
|
||||
Log: func(line string) {
|
||||
@ -148,6 +149,7 @@ func NewService(cfg config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *t
|
||||
tlsDefaultCommonName: tlsDefaultCommonName,
|
||||
limiter: newLimiter(cfg),
|
||||
natService: nat.NewService(myID, cfg),
|
||||
evLogger: evLogger,
|
||||
|
||||
listenersMut: sync.NewRWMutex(),
|
||||
listeners: make(map[string]genericListener),
|
||||
@ -552,7 +554,7 @@ func (s *service) createListener(factory listenerFactory, uri *url.URL) bool {
|
||||
}
|
||||
|
||||
func (s *service) logListenAddressesChangedEvent(l genericListener) {
|
||||
events.Default.Log(events.ListenAddressesChanged, map[string]interface{}{
|
||||
s.evLogger.Log(events.ListenAddressesChanged, map[string]interface{}{
|
||||
"address": l.URI(),
|
||||
"lan": l.LANAddresses(),
|
||||
"wan": l.WANAddresses(),
|
||||
@ -579,7 +581,7 @@ func (s *service) CommitConfiguration(from, to config.Configuration) bool {
|
||||
|
||||
s.listenersMut.Lock()
|
||||
seen := make(map[string]struct{})
|
||||
for _, addr := range config.Wrap("", to).ListenAddresses() {
|
||||
for _, addr := range config.Wrap("", to, s.evLogger).ListenAddresses() {
|
||||
if addr == "" {
|
||||
// We can get an empty address if there is an empty listener
|
||||
// element in the config, indicating no listeners should be
|
||||
|
@ -35,6 +35,7 @@ type globalClient struct {
|
||||
queryClient httpClient
|
||||
noAnnounce bool
|
||||
noLookup bool
|
||||
evLogger events.Logger
|
||||
errorHolder
|
||||
}
|
||||
|
||||
@ -70,7 +71,7 @@ func (e lookupError) CacheFor() time.Duration {
|
||||
return e.cacheFor
|
||||
}
|
||||
|
||||
func NewGlobal(server string, cert tls.Certificate, addrList AddressLister) (FinderService, error) {
|
||||
func NewGlobal(server string, cert tls.Certificate, addrList AddressLister, evLogger events.Logger) (FinderService, error) {
|
||||
server, opts, err := parseOptions(server)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -125,6 +126,7 @@ func NewGlobal(server string, cert tls.Certificate, addrList AddressLister) (Fin
|
||||
queryClient: queryClient,
|
||||
noAnnounce: opts.noAnnounce,
|
||||
noLookup: opts.noLookup,
|
||||
evLogger: evLogger,
|
||||
}
|
||||
cl.Service = util.AsService(cl.serve)
|
||||
if !opts.noAnnounce {
|
||||
@ -197,8 +199,8 @@ func (c *globalClient) serve(stop chan struct{}) {
|
||||
timer := time.NewTimer(0)
|
||||
defer timer.Stop()
|
||||
|
||||
eventSub := events.Default.Subscribe(events.ListenAddressesChanged)
|
||||
defer events.Default.Unsubscribe(eventSub)
|
||||
eventSub := c.evLogger.Subscribe(events.ListenAddressesChanged)
|
||||
defer eventSub.Unsubscribe()
|
||||
|
||||
for {
|
||||
select {
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/tlsutil"
|
||||
)
|
||||
@ -54,15 +55,15 @@ func TestGlobalOverHTTP(t *testing.T) {
|
||||
// is only allowed in combination with the "insecure" and "noannounce"
|
||||
// parameters.
|
||||
|
||||
if _, err := NewGlobal("http://192.0.2.42/", tls.Certificate{}, nil); err == nil {
|
||||
if _, err := NewGlobal("http://192.0.2.42/", tls.Certificate{}, nil, events.NoopLogger); err == nil {
|
||||
t.Fatal("http is not allowed without insecure and noannounce")
|
||||
}
|
||||
|
||||
if _, err := NewGlobal("http://192.0.2.42/?insecure", tls.Certificate{}, nil); err == nil {
|
||||
if _, err := NewGlobal("http://192.0.2.42/?insecure", tls.Certificate{}, nil, events.NoopLogger); err == nil {
|
||||
t.Fatal("http is not allowed without noannounce")
|
||||
}
|
||||
|
||||
if _, err := NewGlobal("http://192.0.2.42/?noannounce", tls.Certificate{}, nil); err == nil {
|
||||
if _, err := NewGlobal("http://192.0.2.42/?noannounce", tls.Certificate{}, nil, events.NoopLogger); err == nil {
|
||||
t.Fatal("http is not allowed without insecure")
|
||||
}
|
||||
|
||||
@ -193,7 +194,7 @@ func TestGlobalAnnounce(t *testing.T) {
|
||||
go func() { _ = http.Serve(list, mux) }()
|
||||
|
||||
url := "https://" + list.Addr().String() + "?insecure"
|
||||
disco, err := NewGlobal(url, cert, new(fakeAddressLister))
|
||||
disco, err := NewGlobal(url, cert, new(fakeAddressLister), events.NoopLogger)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -217,7 +218,7 @@ func TestGlobalAnnounce(t *testing.T) {
|
||||
}
|
||||
|
||||
func testLookup(url string) ([]string, error) {
|
||||
disco, err := NewGlobal(url, tls.Certificate{}, nil)
|
||||
disco, err := NewGlobal(url, tls.Certificate{}, nil, events.NoopLogger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ type localClient struct {
|
||||
myID protocol.DeviceID
|
||||
addrList AddressLister
|
||||
name string
|
||||
evLogger events.Logger
|
||||
|
||||
beacon beacon.Interface
|
||||
localBcastStart time.Time
|
||||
@ -46,13 +47,14 @@ const (
|
||||
v13Magic = uint32(0x7D79BC40) // previous version
|
||||
)
|
||||
|
||||
func NewLocal(id protocol.DeviceID, addr string, addrList AddressLister) (FinderService, error) {
|
||||
func NewLocal(id protocol.DeviceID, addr string, addrList AddressLister, evLogger events.Logger) (FinderService, error) {
|
||||
c := &localClient{
|
||||
Supervisor: suture.New("local", suture.Spec{
|
||||
PassThroughPanics: true,
|
||||
}),
|
||||
myID: id,
|
||||
addrList: addrList,
|
||||
evLogger: evLogger,
|
||||
localBcastTick: time.NewTicker(BroadcastInterval).C,
|
||||
forcedBcastTick: make(chan time.Time),
|
||||
localBcastStart: time.Now(),
|
||||
@ -272,7 +274,7 @@ func (c *localClient) registerDevice(src net.Addr, device Announce) bool {
|
||||
})
|
||||
|
||||
if isNewDevice {
|
||||
events.Default.Log(events.DeviceDiscovered, map[string]interface{}{
|
||||
c.evLogger.Log(events.DeviceDiscovered, map[string]interface{}{
|
||||
"device": device.ID.String(),
|
||||
"addrs": validAddresses,
|
||||
})
|
||||
|
@ -11,11 +11,12 @@ import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
func TestLocalInstanceID(t *testing.T) {
|
||||
c, err := NewLocal(protocol.LocalDeviceID, ":0", &fakeAddressLister{})
|
||||
c, err := NewLocal(protocol.LocalDeviceID, ":0", &fakeAddressLister{}, events.NoopLogger)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -38,7 +39,7 @@ func TestLocalInstanceID(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLocalInstanceIDShouldTriggerNew(t *testing.T) {
|
||||
c, err := NewLocal(protocol.LocalDeviceID, ":0", &fakeAddressLister{})
|
||||
c, err := NewLocal(protocol.LocalDeviceID, ":0", &fakeAddressLister{}, events.NoopLogger)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -10,11 +10,11 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
liblogger "github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
dl = logger.DefaultLogger.NewFacility("events", "Event generation and logging")
|
||||
dl = liblogger.DefaultLogger.NewFacility("events", "Event generation and logging")
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -13,7 +13,10 @@ import (
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/thejerf/suture"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
"github.com/syncthing/syncthing/lib/util"
|
||||
)
|
||||
|
||||
type EventType int
|
||||
@ -51,7 +54,10 @@ const (
|
||||
AllEvents = (1 << iota) - 1
|
||||
)
|
||||
|
||||
var runningTests = false
|
||||
var (
|
||||
runningTests = false
|
||||
errNoop = errors.New("method of a noop object called")
|
||||
)
|
||||
|
||||
const eventLogTimeout = 15 * time.Millisecond
|
||||
|
||||
@ -199,13 +205,21 @@ func UnmarshalEventType(s string) EventType {
|
||||
|
||||
const BufferSize = 64
|
||||
|
||||
type Logger struct {
|
||||
subs []*Subscription
|
||||
type Logger interface {
|
||||
suture.Service
|
||||
Log(t EventType, data interface{})
|
||||
Subscribe(mask EventType) Subscription
|
||||
}
|
||||
|
||||
type logger struct {
|
||||
suture.Service
|
||||
subs []*subscription
|
||||
nextSubscriptionIDs []int
|
||||
nextGlobalID int
|
||||
timeout *time.Timer
|
||||
events chan Event
|
||||
funcs chan func()
|
||||
toUnsubscribe chan *subscription
|
||||
stop chan struct{}
|
||||
}
|
||||
|
||||
@ -219,19 +233,17 @@ type Event struct {
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
type Subscription struct {
|
||||
mask EventType
|
||||
events chan Event
|
||||
timeout *time.Timer
|
||||
type Subscription interface {
|
||||
C() <-chan Event
|
||||
Poll(timeout time.Duration) (Event, error)
|
||||
Unsubscribe()
|
||||
}
|
||||
|
||||
var Default = NewLogger()
|
||||
|
||||
func init() {
|
||||
// The default logger never stops. To ensure this we nil out the stop
|
||||
// channel so any attempt to stop it will panic.
|
||||
Default.stop = nil
|
||||
go Default.Serve()
|
||||
type subscription struct {
|
||||
mask EventType
|
||||
events chan Event
|
||||
toUnsubscribe chan *subscription
|
||||
timeout *time.Timer
|
||||
}
|
||||
|
||||
var (
|
||||
@ -239,13 +251,14 @@ var (
|
||||
ErrClosed = errors.New("closed")
|
||||
)
|
||||
|
||||
func NewLogger() *Logger {
|
||||
l := &Logger{
|
||||
func NewLogger() Logger {
|
||||
l := &logger{
|
||||
timeout: time.NewTimer(time.Second),
|
||||
events: make(chan Event, BufferSize),
|
||||
funcs: make(chan func()),
|
||||
stop: make(chan struct{}),
|
||||
toUnsubscribe: make(chan *subscription),
|
||||
}
|
||||
l.Service = util.AsService(l.serve)
|
||||
// Make sure the timer is in the stopped state and hasn't fired anything
|
||||
// into the channel.
|
||||
if !l.timeout.Stop() {
|
||||
@ -254,7 +267,7 @@ func NewLogger() *Logger {
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *Logger) Serve() {
|
||||
func (l *logger) serve(stop chan struct{}) {
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
@ -263,10 +276,13 @@ loop:
|
||||
l.sendEvent(e)
|
||||
|
||||
case fn := <-l.funcs:
|
||||
// Subscriptions etc are handled here.
|
||||
// Subscriptions are handled here.
|
||||
fn()
|
||||
|
||||
case <-l.stop:
|
||||
case s := <-l.toUnsubscribe:
|
||||
l.unsubscribe(s)
|
||||
|
||||
case <-stop:
|
||||
break loop
|
||||
}
|
||||
}
|
||||
@ -279,11 +295,7 @@ loop:
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) Stop() {
|
||||
close(l.stop)
|
||||
}
|
||||
|
||||
func (l *Logger) Log(t EventType, data interface{}) {
|
||||
func (l *logger) Log(t EventType, data interface{}) {
|
||||
l.events <- Event{
|
||||
Time: time.Now(),
|
||||
Type: t,
|
||||
@ -292,7 +304,7 @@ func (l *Logger) Log(t EventType, data interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) sendEvent(e Event) {
|
||||
func (l *logger) sendEvent(e Event) {
|
||||
l.nextGlobalID++
|
||||
dl.Debugln("log", l.nextGlobalID, e.Type, e.Data)
|
||||
|
||||
@ -323,14 +335,15 @@ func (l *Logger) sendEvent(e Event) {
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) Subscribe(mask EventType) *Subscription {
|
||||
res := make(chan *Subscription)
|
||||
func (l *logger) Subscribe(mask EventType) Subscription {
|
||||
res := make(chan Subscription)
|
||||
l.funcs <- func() {
|
||||
dl.Debugln("subscribe", mask)
|
||||
|
||||
s := &Subscription{
|
||||
s := &subscription{
|
||||
mask: mask,
|
||||
events: make(chan Event, BufferSize),
|
||||
toUnsubscribe: l.toUnsubscribe,
|
||||
timeout: time.NewTimer(0),
|
||||
}
|
||||
|
||||
@ -355,9 +368,8 @@ func (l *Logger) Subscribe(mask EventType) *Subscription {
|
||||
return <-res
|
||||
}
|
||||
|
||||
func (l *Logger) Unsubscribe(s *Subscription) {
|
||||
l.funcs <- func() {
|
||||
dl.Debugln("unsubscribe")
|
||||
func (l *logger) unsubscribe(s *subscription) {
|
||||
dl.Debugln("unsubscribe", s.mask)
|
||||
for i, ss := range l.subs {
|
||||
if s == ss {
|
||||
last := len(l.subs) - 1
|
||||
@ -375,12 +387,11 @@ func (l *Logger) Unsubscribe(s *Subscription) {
|
||||
}
|
||||
close(s.events)
|
||||
}
|
||||
}
|
||||
|
||||
// Poll returns an event from the subscription or an error if the poll times
|
||||
// out of the event channel is closed. Poll should not be called concurrently
|
||||
// from multiple goroutines for a single subscription.
|
||||
func (s *Subscription) Poll(timeout time.Duration) (Event, error) {
|
||||
func (s *subscription) Poll(timeout time.Duration) (Event, error) {
|
||||
dl.Debugln("poll", timeout)
|
||||
|
||||
s.timeout.Reset(timeout)
|
||||
@ -409,12 +420,16 @@ func (s *Subscription) Poll(timeout time.Duration) (Event, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Subscription) C() <-chan Event {
|
||||
func (s *subscription) C() <-chan Event {
|
||||
return s.events
|
||||
}
|
||||
|
||||
func (s *subscription) Unsubscribe() {
|
||||
s.toUnsubscribe <- s
|
||||
}
|
||||
|
||||
type bufferedSubscription struct {
|
||||
sub *Subscription
|
||||
sub Subscription
|
||||
buf []Event
|
||||
next int
|
||||
cur int // Current SubscriptionID
|
||||
@ -426,7 +441,7 @@ type BufferedSubscription interface {
|
||||
Since(id int, into []Event, timeout time.Duration) []Event
|
||||
}
|
||||
|
||||
func NewBufferedSubscription(s *Subscription, size int) BufferedSubscription {
|
||||
func NewBufferedSubscription(s Subscription, size int) BufferedSubscription {
|
||||
bs := &bufferedSubscription{
|
||||
sub: s,
|
||||
buf: make([]Event, size),
|
||||
@ -489,3 +504,29 @@ func Error(err error) *string {
|
||||
str := err.Error()
|
||||
return &str
|
||||
}
|
||||
|
||||
type noopLogger struct{}
|
||||
|
||||
var NoopLogger Logger = &noopLogger{}
|
||||
|
||||
func (*noopLogger) Serve() {}
|
||||
|
||||
func (*noopLogger) Stop() {}
|
||||
|
||||
func (*noopLogger) Log(t EventType, data interface{}) {}
|
||||
|
||||
func (*noopLogger) Subscribe(mask EventType) Subscription {
|
||||
return &noopSubscription{}
|
||||
}
|
||||
|
||||
type noopSubscription struct{}
|
||||
|
||||
func (*noopSubscription) C() <-chan Event {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*noopSubscription) Poll(timeout time.Duration) (Event, error) {
|
||||
return Event{}, errNoop
|
||||
}
|
||||
|
||||
func (*noopSubscription) Unsubscribe() {}
|
||||
|
@ -33,7 +33,7 @@ func TestSubscriber(t *testing.T) {
|
||||
go l.Serve()
|
||||
|
||||
s := l.Subscribe(0)
|
||||
defer l.Unsubscribe(s)
|
||||
defer s.Unsubscribe()
|
||||
if s == nil {
|
||||
t.Fatal("Unexpected nil Subscription")
|
||||
}
|
||||
@ -45,7 +45,7 @@ func TestTimeout(t *testing.T) {
|
||||
go l.Serve()
|
||||
|
||||
s := l.Subscribe(0)
|
||||
defer l.Unsubscribe(s)
|
||||
defer s.Unsubscribe()
|
||||
_, err := s.Poll(timeout)
|
||||
if err != ErrTimeout {
|
||||
t.Fatal("Unexpected non-Timeout error:", err)
|
||||
@ -59,7 +59,7 @@ func TestEventBeforeSubscribe(t *testing.T) {
|
||||
|
||||
l.Log(DeviceConnected, "foo")
|
||||
s := l.Subscribe(0)
|
||||
defer l.Unsubscribe(s)
|
||||
defer s.Unsubscribe()
|
||||
|
||||
_, err := s.Poll(timeout)
|
||||
if err != ErrTimeout {
|
||||
@ -73,7 +73,7 @@ func TestEventAfterSubscribe(t *testing.T) {
|
||||
go l.Serve()
|
||||
|
||||
s := l.Subscribe(AllEvents)
|
||||
defer l.Unsubscribe(s)
|
||||
defer s.Unsubscribe()
|
||||
l.Log(DeviceConnected, "foo")
|
||||
|
||||
ev, err := s.Poll(timeout)
|
||||
@ -100,7 +100,7 @@ func TestEventAfterSubscribeIgnoreMask(t *testing.T) {
|
||||
go l.Serve()
|
||||
|
||||
s := l.Subscribe(DeviceDisconnected)
|
||||
defer l.Unsubscribe(s)
|
||||
defer s.Unsubscribe()
|
||||
l.Log(DeviceConnected, "foo")
|
||||
|
||||
_, err := s.Poll(timeout)
|
||||
@ -115,7 +115,7 @@ func TestBufferOverflow(t *testing.T) {
|
||||
go l.Serve()
|
||||
|
||||
s := l.Subscribe(AllEvents)
|
||||
defer l.Unsubscribe(s)
|
||||
defer s.Unsubscribe()
|
||||
|
||||
// The first BufferSize events will be logged pretty much
|
||||
// instantaneously. The next BufferSize events will each block for up to
|
||||
@ -147,7 +147,7 @@ func TestUnsubscribe(t *testing.T) {
|
||||
t.Fatal("Unexpected error:", err)
|
||||
}
|
||||
|
||||
l.Unsubscribe(s)
|
||||
s.Unsubscribe()
|
||||
l.Log(DeviceConnected, "foo")
|
||||
|
||||
_, err = s.Poll(timeout)
|
||||
@ -162,7 +162,7 @@ func TestGlobalIDs(t *testing.T) {
|
||||
go l.Serve()
|
||||
|
||||
s := l.Subscribe(AllEvents)
|
||||
defer l.Unsubscribe(s)
|
||||
defer s.Unsubscribe()
|
||||
l.Log(DeviceConnected, "foo")
|
||||
l.Subscribe(AllEvents)
|
||||
l.Log(DeviceConnected, "bar")
|
||||
@ -194,7 +194,7 @@ func TestSubscriptionIDs(t *testing.T) {
|
||||
go l.Serve()
|
||||
|
||||
s := l.Subscribe(DeviceConnected)
|
||||
defer l.Unsubscribe(s)
|
||||
defer s.Unsubscribe()
|
||||
|
||||
l.Log(DeviceDisconnected, "a")
|
||||
l.Log(DeviceConnected, "b")
|
||||
@ -236,7 +236,7 @@ func TestBufferedSub(t *testing.T) {
|
||||
go l.Serve()
|
||||
|
||||
s := l.Subscribe(AllEvents)
|
||||
defer l.Unsubscribe(s)
|
||||
defer s.Unsubscribe()
|
||||
bs := NewBufferedSubscription(s, 10*BufferSize)
|
||||
|
||||
go func() {
|
||||
@ -267,7 +267,7 @@ func BenchmarkBufferedSub(b *testing.B) {
|
||||
go l.Serve()
|
||||
|
||||
s := l.Subscribe(AllEvents)
|
||||
defer l.Unsubscribe(s)
|
||||
defer s.Unsubscribe()
|
||||
bufferSize := BufferSize
|
||||
bs := NewBufferedSubscription(s, bufferSize)
|
||||
|
||||
@ -323,7 +323,7 @@ func TestSinceUsesSubscriptionId(t *testing.T) {
|
||||
go l.Serve()
|
||||
|
||||
s := l.Subscribe(DeviceConnected)
|
||||
defer l.Unsubscribe(s)
|
||||
defer s.Unsubscribe()
|
||||
bs := NewBufferedSubscription(s, 10*BufferSize)
|
||||
|
||||
l.Log(DeviceConnected, "a") // SubscriptionID = 1
|
||||
@ -390,7 +390,7 @@ func TestUnsubscribeContention(t *testing.T) {
|
||||
defer listenerWg.Done()
|
||||
|
||||
s := l.Subscribe(AllEvents)
|
||||
defer l.Unsubscribe(s)
|
||||
defer s.Unsubscribe()
|
||||
|
||||
for {
|
||||
select {
|
||||
@ -449,7 +449,7 @@ func BenchmarkLogEvent(b *testing.B) {
|
||||
go l.Serve()
|
||||
|
||||
s := l.Subscribe(AllEvents)
|
||||
defer l.Unsubscribe(s)
|
||||
defer s.Unsubscribe()
|
||||
NewBufferedSubscription(s, 1) // runs in the background
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
@ -77,11 +77,11 @@ type puller interface {
|
||||
pull() bool // true when successfull and should not be retried
|
||||
}
|
||||
|
||||
func newFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration) folder {
|
||||
func newFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, evLogger events.Logger) folder {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
return folder{
|
||||
stateTracker: newStateTracker(cfg.ID),
|
||||
stateTracker: newStateTracker(cfg.ID, evLogger),
|
||||
FolderConfiguration: cfg,
|
||||
FolderStatisticsReference: stats.NewFolderStatisticsReference(model.db, cfg.ID),
|
||||
|
||||
@ -630,7 +630,7 @@ func (f *folder) monitorWatch(ctx context.Context) {
|
||||
failTimer.Reset(time.Minute)
|
||||
continue
|
||||
}
|
||||
watchaggregator.Aggregate(eventChan, f.watchChan, f.FolderConfiguration, f.model.cfg, aggrCtx)
|
||||
watchaggregator.Aggregate(eventChan, f.watchChan, f.FolderConfiguration, f.model.cfg, f.evLogger, aggrCtx)
|
||||
l.Debugln("Started filesystem watcher for folder", f.Description())
|
||||
case err = <-errChan:
|
||||
f.setWatchError(err)
|
||||
@ -669,7 +669,7 @@ func (f *folder) setWatchError(err error) {
|
||||
if err != nil {
|
||||
data["to"] = err.Error()
|
||||
}
|
||||
events.Default.Log(events.FolderWatchStateChanged, data)
|
||||
f.evLogger.Log(events.FolderWatchStateChanged, data)
|
||||
}
|
||||
if err == nil {
|
||||
return
|
||||
@ -800,7 +800,7 @@ func (f *folder) updateLocals(fs []protocol.FileInfo) {
|
||||
filenames[i] = file.Name
|
||||
}
|
||||
|
||||
events.Default.Log(events.LocalIndexUpdated, map[string]interface{}{
|
||||
f.evLogger.Log(events.LocalIndexUpdated, map[string]interface{}{
|
||||
"folder": f.ID,
|
||||
"items": len(fs),
|
||||
"filenames": filenames,
|
||||
@ -839,7 +839,7 @@ func (f *folder) emitDiskChangeEvents(fs []protocol.FileInfo, typeOfEvent events
|
||||
}
|
||||
|
||||
// Two different events can be fired here based on what EventType is passed into function
|
||||
events.Default.Log(typeOfEvent, map[string]string{
|
||||
f.evLogger.Log(typeOfEvent, map[string]string{
|
||||
"folder": f.ID,
|
||||
"folderID": f.ID, // incorrect, deprecated, kept for historical compliance
|
||||
"label": f.Label,
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/ignore"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
@ -56,8 +57,8 @@ type receiveOnlyFolder struct {
|
||||
*sendReceiveFolder
|
||||
}
|
||||
|
||||
func newReceiveOnlyFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, ver versioner.Versioner, fs fs.Filesystem) service {
|
||||
sr := newSendReceiveFolder(model, fset, ignores, cfg, ver, fs).(*sendReceiveFolder)
|
||||
func newReceiveOnlyFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, ver versioner.Versioner, fs fs.Filesystem, evLogger events.Logger) service {
|
||||
sr := newSendReceiveFolder(model, fset, ignores, cfg, ver, fs, evLogger).(*sendReceiveFolder)
|
||||
sr.localFlags = protocol.FlagLocalReceiveOnly // gets propagated to the scanner, and set on locally changed files
|
||||
return &receiveOnlyFolder{sr}
|
||||
}
|
||||
|
@ -321,6 +321,7 @@ func setupROFolder() (*model, *sendOnlyFolder) {
|
||||
|
||||
f := &sendOnlyFolder{
|
||||
folder: folder{
|
||||
stateTracker: newStateTracker(fcfg.ID, m.evLogger),
|
||||
fset: m.folderFiles[fcfg.ID],
|
||||
FolderConfiguration: fcfg,
|
||||
},
|
||||
|
@ -9,6 +9,7 @@ package model
|
||||
import (
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/ignore"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
@ -24,9 +25,9 @@ type sendOnlyFolder struct {
|
||||
folder
|
||||
}
|
||||
|
||||
func newSendOnlyFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, _ versioner.Versioner, _ fs.Filesystem) service {
|
||||
func newSendOnlyFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, _ versioner.Versioner, _ fs.Filesystem, evLogger events.Logger) service {
|
||||
f := &sendOnlyFolder{
|
||||
folder: newFolder(model, fset, ignores, cfg),
|
||||
folder: newFolder(model, fset, ignores, cfg, evLogger),
|
||||
}
|
||||
f.folder.puller = f
|
||||
f.folder.Service = util.AsService(f.serve)
|
||||
|
@ -108,9 +108,9 @@ type sendReceiveFolder struct {
|
||||
pullErrorsMut sync.Mutex
|
||||
}
|
||||
|
||||
func newSendReceiveFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, ver versioner.Versioner, fs fs.Filesystem) service {
|
||||
func newSendReceiveFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, ver versioner.Versioner, fs fs.Filesystem, evLogger events.Logger) service {
|
||||
f := &sendReceiveFolder{
|
||||
folder: newFolder(model, fset, ignores, cfg),
|
||||
folder: newFolder(model, fset, ignores, cfg, evLogger),
|
||||
fs: fs,
|
||||
versioner: ver,
|
||||
queue: newJobQueue(),
|
||||
@ -211,7 +211,7 @@ func (f *sendReceiveFolder) pull() bool {
|
||||
// errors preventing us. Flag this with a warning and
|
||||
// wait a bit longer before retrying.
|
||||
if errors := f.Errors(); len(errors) > 0 {
|
||||
events.Default.Log(events.FolderErrors, map[string]interface{}{
|
||||
f.evLogger.Log(events.FolderErrors, map[string]interface{}{
|
||||
"folder": f.folderID,
|
||||
"errors": errors,
|
||||
})
|
||||
@ -544,7 +544,7 @@ func (f *sendReceiveFolder) handleDir(file protocol.FileInfo, dbUpdateChan chan<
|
||||
|
||||
f.resetPullError(file.Name)
|
||||
|
||||
events.Default.Log(events.ItemStarted, map[string]string{
|
||||
f.evLogger.Log(events.ItemStarted, map[string]string{
|
||||
"folder": f.folderID,
|
||||
"item": file.Name,
|
||||
"type": "dir",
|
||||
@ -552,7 +552,7 @@ func (f *sendReceiveFolder) handleDir(file protocol.FileInfo, dbUpdateChan chan<
|
||||
})
|
||||
|
||||
defer func() {
|
||||
events.Default.Log(events.ItemFinished, map[string]interface{}{
|
||||
f.evLogger.Log(events.ItemFinished, map[string]interface{}{
|
||||
"folder": f.folderID,
|
||||
"item": file.Name,
|
||||
"error": events.Error(err),
|
||||
@ -700,7 +700,7 @@ func (f *sendReceiveFolder) handleSymlink(file protocol.FileInfo, dbUpdateChan c
|
||||
|
||||
f.resetPullError(file.Name)
|
||||
|
||||
events.Default.Log(events.ItemStarted, map[string]string{
|
||||
f.evLogger.Log(events.ItemStarted, map[string]string{
|
||||
"folder": f.folderID,
|
||||
"item": file.Name,
|
||||
"type": "symlink",
|
||||
@ -708,7 +708,7 @@ func (f *sendReceiveFolder) handleSymlink(file protocol.FileInfo, dbUpdateChan c
|
||||
})
|
||||
|
||||
defer func() {
|
||||
events.Default.Log(events.ItemFinished, map[string]interface{}{
|
||||
f.evLogger.Log(events.ItemFinished, map[string]interface{}{
|
||||
"folder": f.folderID,
|
||||
"item": file.Name,
|
||||
"error": events.Error(err),
|
||||
@ -782,7 +782,7 @@ func (f *sendReceiveFolder) deleteDir(file protocol.FileInfo, dbUpdateChan chan<
|
||||
// care not declare another err.
|
||||
var err error
|
||||
|
||||
events.Default.Log(events.ItemStarted, map[string]string{
|
||||
f.evLogger.Log(events.ItemStarted, map[string]string{
|
||||
"folder": f.folderID,
|
||||
"item": file.Name,
|
||||
"type": "dir",
|
||||
@ -790,7 +790,7 @@ func (f *sendReceiveFolder) deleteDir(file protocol.FileInfo, dbUpdateChan chan<
|
||||
})
|
||||
|
||||
defer func() {
|
||||
events.Default.Log(events.ItemFinished, map[string]interface{}{
|
||||
f.evLogger.Log(events.ItemFinished, map[string]interface{}{
|
||||
"folder": f.folderID,
|
||||
"item": file.Name,
|
||||
"error": events.Error(err),
|
||||
@ -822,7 +822,7 @@ func (f *sendReceiveFolder) deleteFileWithCurrent(file, cur protocol.FileInfo, h
|
||||
|
||||
f.resetPullError(file.Name)
|
||||
|
||||
events.Default.Log(events.ItemStarted, map[string]string{
|
||||
f.evLogger.Log(events.ItemStarted, map[string]string{
|
||||
"folder": f.folderID,
|
||||
"item": file.Name,
|
||||
"type": "file",
|
||||
@ -833,7 +833,7 @@ func (f *sendReceiveFolder) deleteFileWithCurrent(file, cur protocol.FileInfo, h
|
||||
if err != nil {
|
||||
f.newPullError(file.Name, errors.Wrap(err, "delete file"))
|
||||
}
|
||||
events.Default.Log(events.ItemFinished, map[string]interface{}{
|
||||
f.evLogger.Log(events.ItemFinished, map[string]interface{}{
|
||||
"folder": f.folderID,
|
||||
"item": file.Name,
|
||||
"error": events.Error(err),
|
||||
@ -897,13 +897,13 @@ func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, db
|
||||
// care not declare another err.
|
||||
var err error
|
||||
|
||||
events.Default.Log(events.ItemStarted, map[string]string{
|
||||
f.evLogger.Log(events.ItemStarted, map[string]string{
|
||||
"folder": f.folderID,
|
||||
"item": source.Name,
|
||||
"type": "file",
|
||||
"action": "delete",
|
||||
})
|
||||
events.Default.Log(events.ItemStarted, map[string]string{
|
||||
f.evLogger.Log(events.ItemStarted, map[string]string{
|
||||
"folder": f.folderID,
|
||||
"item": target.Name,
|
||||
"type": "file",
|
||||
@ -911,14 +911,14 @@ func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, db
|
||||
})
|
||||
|
||||
defer func() {
|
||||
events.Default.Log(events.ItemFinished, map[string]interface{}{
|
||||
f.evLogger.Log(events.ItemFinished, map[string]interface{}{
|
||||
"folder": f.folderID,
|
||||
"item": source.Name,
|
||||
"error": events.Error(err),
|
||||
"type": "file",
|
||||
"action": "delete",
|
||||
})
|
||||
events.Default.Log(events.ItemFinished, map[string]interface{}{
|
||||
f.evLogger.Log(events.ItemFinished, map[string]interface{}{
|
||||
"folder": f.folderID,
|
||||
"item": target.Name,
|
||||
"error": events.Error(err),
|
||||
@ -1095,7 +1095,7 @@ func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, copyChan chan<- c
|
||||
// Shuffle the blocks
|
||||
rand.Shuffle(blocks)
|
||||
|
||||
events.Default.Log(events.ItemStarted, map[string]string{
|
||||
f.evLogger.Log(events.ItemStarted, map[string]string{
|
||||
"folder": f.folderID,
|
||||
"item": file.Name,
|
||||
"type": "file",
|
||||
@ -1178,7 +1178,7 @@ func (f *sendReceiveFolder) shortcutFile(file, curFile protocol.FileInfo, dbUpda
|
||||
|
||||
f.resetPullError(file.Name)
|
||||
|
||||
events.Default.Log(events.ItemStarted, map[string]string{
|
||||
f.evLogger.Log(events.ItemStarted, map[string]string{
|
||||
"folder": f.folderID,
|
||||
"item": file.Name,
|
||||
"type": "file",
|
||||
@ -1186,7 +1186,7 @@ func (f *sendReceiveFolder) shortcutFile(file, curFile protocol.FileInfo, dbUpda
|
||||
})
|
||||
|
||||
var err error
|
||||
defer events.Default.Log(events.ItemFinished, map[string]interface{}{
|
||||
defer f.evLogger.Log(events.ItemFinished, map[string]interface{}{
|
||||
"folder": f.folderID,
|
||||
"item": file.Name,
|
||||
"error": events.Error(err),
|
||||
@ -1575,7 +1575,7 @@ func (f *sendReceiveFolder) finisherRoutine(in <-chan *sharedPullerState, dbUpda
|
||||
|
||||
f.model.progressEmitter.Deregister(state)
|
||||
|
||||
events.Default.Log(events.ItemFinished, map[string]interface{}{
|
||||
f.evLogger.Log(events.ItemFinished, map[string]interface{}{
|
||||
"folder": f.folderID,
|
||||
"item": state.file.Name,
|
||||
"error": events.Error(err),
|
||||
|
@ -96,7 +96,7 @@ func setupSendReceiveFolder(files ...protocol.FileInfo) (*model, *sendReceiveFol
|
||||
|
||||
f := &sendReceiveFolder{
|
||||
folder: folder{
|
||||
stateTracker: newStateTracker("default"),
|
||||
stateTracker: newStateTracker("default", model.evLogger),
|
||||
model: model,
|
||||
fset: model.folderFiles[fcfg.ID],
|
||||
initialScanFinished: make(chan struct{}),
|
||||
@ -121,6 +121,12 @@ func setupSendReceiveFolder(files ...protocol.FileInfo) (*model, *sendReceiveFol
|
||||
return model, f
|
||||
}
|
||||
|
||||
func cleanupSRFolder(f *sendReceiveFolder, m *model) {
|
||||
m.evLogger.Stop()
|
||||
os.Remove(m.cfg.ConfigPath())
|
||||
os.Remove(f.Filesystem().URI())
|
||||
}
|
||||
|
||||
// Layout of the files: (indexes from the above array)
|
||||
// 12345678 - Required file
|
||||
// 02005008 - Existing file (currently in the index)
|
||||
@ -137,10 +143,7 @@ func TestHandleFile(t *testing.T) {
|
||||
requiredFile.Blocks = blocks[1:]
|
||||
|
||||
m, f := setupSendReceiveFolder(existingFile)
|
||||
defer func() {
|
||||
os.Remove(m.cfg.ConfigPath())
|
||||
os.Remove(f.Filesystem().URI())
|
||||
}()
|
||||
defer cleanupSRFolder(f, m)
|
||||
|
||||
copyChan := make(chan copyBlocksState, 1)
|
||||
dbUpdateChan := make(chan dbUpdateJob, 1)
|
||||
@ -183,10 +186,7 @@ func TestHandleFileWithTemp(t *testing.T) {
|
||||
requiredFile.Blocks = blocks[1:]
|
||||
|
||||
m, f := setupSendReceiveFolder(existingFile)
|
||||
defer func() {
|
||||
os.Remove(m.cfg.ConfigPath())
|
||||
os.Remove(f.Filesystem().URI())
|
||||
}()
|
||||
defer cleanupSRFolder(f, m)
|
||||
|
||||
if _, err := prepareTmpFile(f.Filesystem()); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -236,10 +236,7 @@ func TestCopierFinder(t *testing.T) {
|
||||
requiredFile.Name = "file2"
|
||||
|
||||
m, f := setupSendReceiveFolder(existingFile)
|
||||
defer func() {
|
||||
os.Remove(m.cfg.ConfigPath())
|
||||
os.Remove(f.Filesystem().URI())
|
||||
}()
|
||||
defer cleanupSRFolder(f, m)
|
||||
|
||||
if _, err := prepareTmpFile(f.Filesystem()); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -302,11 +299,8 @@ func TestCopierFinder(t *testing.T) {
|
||||
func TestWeakHash(t *testing.T) {
|
||||
// Setup the model/pull environment
|
||||
model, fo := setupSendReceiveFolder()
|
||||
defer cleanupSRFolder(fo, model)
|
||||
ffs := fo.Filesystem()
|
||||
defer func() {
|
||||
os.Remove(model.cfg.ConfigPath())
|
||||
os.Remove(ffs.URI())
|
||||
}()
|
||||
|
||||
tempFile := fs.TempName("weakhash")
|
||||
var shift int64 = 10
|
||||
@ -432,10 +426,7 @@ func TestCopierCleanup(t *testing.T) {
|
||||
// Create a file
|
||||
file := setupFile("test", []int{0})
|
||||
m, f := setupSendReceiveFolder(file)
|
||||
defer func() {
|
||||
os.Remove(m.cfg.ConfigPath())
|
||||
os.Remove(f.Filesystem().URI())
|
||||
}()
|
||||
defer cleanupSRFolder(f, m)
|
||||
|
||||
file.Blocks = []protocol.BlockInfo{blocks[1]}
|
||||
file.Version = file.Version.Update(myID.Short())
|
||||
@ -468,13 +459,10 @@ func TestDeregisterOnFailInCopy(t *testing.T) {
|
||||
file := setupFile("filex", []int{0, 2, 0, 0, 5, 0, 0, 8})
|
||||
|
||||
m, f := setupSendReceiveFolder()
|
||||
defer func() {
|
||||
os.Remove(m.cfg.ConfigPath())
|
||||
os.Remove(f.Filesystem().URI())
|
||||
}()
|
||||
defer cleanupSRFolder(f, m)
|
||||
|
||||
// Set up our evet subscription early
|
||||
s := events.Default.Subscribe(events.ItemFinished)
|
||||
s := m.evLogger.Subscribe(events.ItemFinished)
|
||||
|
||||
// queue.Done should be called by the finisher routine
|
||||
f.queue.Push("filex", 0, time.Time{})
|
||||
@ -558,13 +546,10 @@ func TestDeregisterOnFailInPull(t *testing.T) {
|
||||
file := setupFile("filex", []int{0, 2, 0, 0, 5, 0, 0, 8})
|
||||
|
||||
m, f := setupSendReceiveFolder()
|
||||
defer func() {
|
||||
os.Remove(m.cfg.ConfigPath())
|
||||
os.Remove(f.Filesystem().URI())
|
||||
}()
|
||||
defer cleanupSRFolder(f, m)
|
||||
|
||||
// Set up our evet subscription early
|
||||
s := events.Default.Subscribe(events.ItemFinished)
|
||||
s := m.evLogger.Subscribe(events.ItemFinished)
|
||||
|
||||
// queue.Done should be called by the finisher routine
|
||||
f.queue.Push("filex", 0, time.Time{})
|
||||
@ -636,12 +621,9 @@ func TestDeregisterOnFailInPull(t *testing.T) {
|
||||
|
||||
func TestIssue3164(t *testing.T) {
|
||||
m, f := setupSendReceiveFolder()
|
||||
defer cleanupSRFolder(f, m)
|
||||
ffs := f.Filesystem()
|
||||
tmpDir := ffs.URI()
|
||||
defer func() {
|
||||
os.Remove(m.cfg.ConfigPath())
|
||||
os.Remove(tmpDir)
|
||||
}()
|
||||
|
||||
ignDir := filepath.Join("issue3164", "oktodelete")
|
||||
subDir := filepath.Join(ignDir, "foobar")
|
||||
@ -728,11 +710,8 @@ func TestDiffEmpty(t *testing.T) {
|
||||
// in the db.
|
||||
func TestDeleteIgnorePerms(t *testing.T) {
|
||||
m, f := setupSendReceiveFolder()
|
||||
defer cleanupSRFolder(f, m)
|
||||
ffs := f.Filesystem()
|
||||
defer func() {
|
||||
os.Remove(m.cfg.ConfigPath())
|
||||
os.Remove(ffs.URI())
|
||||
}()
|
||||
f.IgnorePerms = true
|
||||
|
||||
name := "deleteIgnorePerms"
|
||||
@ -778,7 +757,7 @@ func TestCopyOwner(t *testing.T) {
|
||||
// filesystem.
|
||||
|
||||
m, f := setupSendReceiveFolder()
|
||||
defer os.Remove(m.cfg.ConfigPath())
|
||||
defer cleanupSRFolder(f, m)
|
||||
f.folder.FolderConfiguration = config.NewFolderConfiguration(m.id, f.ID, f.Label, fs.FilesystemTypeFake, "/TestCopyOwner")
|
||||
f.folder.FolderConfiguration.CopyOwnershipFromParent = true
|
||||
|
||||
@ -867,11 +846,8 @@ func TestCopyOwner(t *testing.T) {
|
||||
// is replaced with a directory and versions are conflicting
|
||||
func TestSRConflictReplaceFileByDir(t *testing.T) {
|
||||
m, f := setupSendReceiveFolder()
|
||||
defer cleanupSRFolder(f, m)
|
||||
ffs := f.Filesystem()
|
||||
defer func() {
|
||||
os.Remove(m.cfg.ConfigPath())
|
||||
os.Remove(ffs.URI())
|
||||
}()
|
||||
|
||||
name := "foo"
|
||||
|
||||
@ -902,11 +878,8 @@ func TestSRConflictReplaceFileByDir(t *testing.T) {
|
||||
// is replaced with a link and versions are conflicting
|
||||
func TestSRConflictReplaceFileByLink(t *testing.T) {
|
||||
m, f := setupSendReceiveFolder()
|
||||
defer cleanupSRFolder(f, m)
|
||||
ffs := f.Filesystem()
|
||||
defer func() {
|
||||
os.Remove(m.cfg.ConfigPath())
|
||||
os.Remove(ffs.URI())
|
||||
}()
|
||||
|
||||
name := "foo"
|
||||
|
||||
|
@ -36,6 +36,7 @@ type folderSummaryService struct {
|
||||
cfg config.Wrapper
|
||||
model Model
|
||||
id protocol.DeviceID
|
||||
evLogger events.Logger
|
||||
immediate chan string
|
||||
|
||||
// For keeping track of folders to recalculate for
|
||||
@ -47,7 +48,7 @@ type folderSummaryService struct {
|
||||
lastEventReqMut sync.Mutex
|
||||
}
|
||||
|
||||
func NewFolderSummaryService(cfg config.Wrapper, m Model, id protocol.DeviceID) FolderSummaryService {
|
||||
func NewFolderSummaryService(cfg config.Wrapper, m Model, id protocol.DeviceID, evLogger events.Logger) FolderSummaryService {
|
||||
service := &folderSummaryService{
|
||||
Supervisor: suture.New("folderSummaryService", suture.Spec{
|
||||
PassThroughPanics: true,
|
||||
@ -55,6 +56,7 @@ func NewFolderSummaryService(cfg config.Wrapper, m Model, id protocol.DeviceID)
|
||||
cfg: cfg,
|
||||
model: m,
|
||||
id: id,
|
||||
evLogger: evLogger,
|
||||
immediate: make(chan string),
|
||||
folders: make(map[string]struct{}),
|
||||
foldersMut: sync.NewMutex(),
|
||||
@ -144,8 +146,8 @@ func (c *folderSummaryService) OnEventRequest() {
|
||||
// listenForUpdates subscribes to the event bus and makes note of folders that
|
||||
// need their data recalculated.
|
||||
func (c *folderSummaryService) listenForUpdates(stop chan struct{}) {
|
||||
sub := events.Default.Subscribe(events.LocalIndexUpdated | events.RemoteIndexUpdated | events.StateChanged | events.RemoteDownloadProgress | events.DeviceConnected | events.FolderWatchStateChanged | events.DownloadProgress)
|
||||
defer events.Default.Unsubscribe(sub)
|
||||
sub := c.evLogger.Subscribe(events.LocalIndexUpdated | events.RemoteIndexUpdated | events.StateChanged | events.RemoteDownloadProgress | events.DeviceConnected | events.FolderWatchStateChanged | events.DownloadProgress)
|
||||
defer sub.Unsubscribe()
|
||||
|
||||
for {
|
||||
// This loop needs to be fast so we don't miss too many events.
|
||||
@ -291,7 +293,7 @@ func (c *folderSummaryService) sendSummary(folder string) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
events.Default.Log(events.FolderSummary, map[string]interface{}{
|
||||
c.evLogger.Log(events.FolderSummary, map[string]interface{}{
|
||||
"folder": folder,
|
||||
"summary": data,
|
||||
})
|
||||
@ -311,6 +313,6 @@ func (c *folderSummaryService) sendSummary(folder string) {
|
||||
comp := c.model.Completion(devCfg.DeviceID, folder).Map()
|
||||
comp["folder"] = folder
|
||||
comp["device"] = devCfg.DeviceID.String()
|
||||
events.Default.Log(events.FolderCompletion, comp)
|
||||
c.evLogger.Log(events.FolderCompletion, comp)
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ func (s folderState) String() string {
|
||||
|
||||
type stateTracker struct {
|
||||
folderID string
|
||||
evLogger events.Logger
|
||||
|
||||
mut sync.Mutex
|
||||
current folderState
|
||||
@ -49,9 +50,10 @@ type stateTracker struct {
|
||||
changed time.Time
|
||||
}
|
||||
|
||||
func newStateTracker(id string) stateTracker {
|
||||
func newStateTracker(id string, evLogger events.Logger) stateTracker {
|
||||
return stateTracker{
|
||||
folderID: id,
|
||||
evLogger: evLogger,
|
||||
mut: sync.NewMutex(),
|
||||
}
|
||||
}
|
||||
@ -83,7 +85,7 @@ func (s *stateTracker) setState(newState folderState) {
|
||||
s.current = newState
|
||||
s.changed = time.Now()
|
||||
|
||||
events.Default.Log(events.StateChanged, eventData)
|
||||
s.evLogger.Log(events.StateChanged, eventData)
|
||||
}
|
||||
s.mut.Unlock()
|
||||
}
|
||||
@ -124,5 +126,5 @@ func (s *stateTracker) setError(err error) {
|
||||
s.err = err
|
||||
s.changed = time.Now()
|
||||
|
||||
events.Default.Log(events.StateChanged, eventData)
|
||||
s.evLogger.Log(events.StateChanged, eventData)
|
||||
}
|
||||
|
@ -128,6 +128,7 @@ type model struct {
|
||||
shortID protocol.ShortID
|
||||
cacheIgnoredFiles bool
|
||||
protectedFiles []string
|
||||
evLogger events.Logger
|
||||
|
||||
clientName string
|
||||
clientVersion string
|
||||
@ -152,7 +153,7 @@ type model struct {
|
||||
foldersRunning int32 // for testing only
|
||||
}
|
||||
|
||||
type folderFactory func(*model, *db.FileSet, *ignore.Matcher, config.FolderConfiguration, versioner.Versioner, fs.Filesystem) service
|
||||
type folderFactory func(*model, *db.FileSet, *ignore.Matcher, config.FolderConfiguration, versioner.Versioner, fs.Filesystem, events.Logger) service
|
||||
|
||||
var (
|
||||
folderFactories = make(map[config.FolderType]folderFactory)
|
||||
@ -175,7 +176,7 @@ var (
|
||||
// NewModel creates and starts a new model. The model starts in read-only mode,
|
||||
// where it sends index information to connected peers and responds to requests
|
||||
// for file data without altering the local folder in any way.
|
||||
func NewModel(cfg config.Wrapper, id protocol.DeviceID, clientName, clientVersion string, ldb *db.Lowlevel, protectedFiles []string) Model {
|
||||
func NewModel(cfg config.Wrapper, id protocol.DeviceID, clientName, clientVersion string, ldb *db.Lowlevel, protectedFiles []string, evLogger events.Logger) Model {
|
||||
m := &model{
|
||||
Supervisor: suture.New("model", suture.Spec{
|
||||
Log: func(line string) {
|
||||
@ -186,11 +187,12 @@ func NewModel(cfg config.Wrapper, id protocol.DeviceID, clientName, clientVersio
|
||||
cfg: cfg,
|
||||
db: ldb,
|
||||
finder: db.NewBlockFinder(ldb),
|
||||
progressEmitter: NewProgressEmitter(cfg),
|
||||
progressEmitter: NewProgressEmitter(cfg, evLogger),
|
||||
id: id,
|
||||
shortID: id.Short(),
|
||||
cacheIgnoredFiles: cfg.Options().CacheIgnoredFiles,
|
||||
protectedFiles: protectedFiles,
|
||||
evLogger: evLogger,
|
||||
clientName: clientName,
|
||||
clientVersion: clientVersion,
|
||||
folderCfgs: make(map[string]config.FolderConfiguration),
|
||||
@ -310,7 +312,7 @@ func (m *model) startFolderLocked(cfg config.FolderConfiguration) {
|
||||
ffs.Hide(".stversions")
|
||||
ffs.Hide(".stignore")
|
||||
|
||||
p := folderFactory(m, fset, m.folderIgnores[folder], cfg, ver, ffs)
|
||||
p := folderFactory(m, fset, m.folderIgnores[folder], cfg, ver, ffs, m.evLogger)
|
||||
|
||||
m.folderRunners[folder] = p
|
||||
|
||||
@ -1023,7 +1025,7 @@ func (m *model) handleIndex(deviceID protocol.DeviceID, folder string, fs []prot
|
||||
}
|
||||
files.Update(deviceID, fs)
|
||||
|
||||
events.Default.Log(events.RemoteIndexUpdated, map[string]interface{}{
|
||||
m.evLogger.Log(events.RemoteIndexUpdated, map[string]interface{}{
|
||||
"device": deviceID.String(),
|
||||
"folder": folder,
|
||||
"items": len(fs),
|
||||
@ -1077,7 +1079,7 @@ func (m *model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
|
||||
}
|
||||
m.cfg.AddOrUpdatePendingFolder(folder.ID, folder.Label, deviceID)
|
||||
changed = true
|
||||
events.Default.Log(events.FolderRejected, map[string]string{
|
||||
m.evLogger.Log(events.FolderRejected, map[string]string{
|
||||
"folder": folder.ID,
|
||||
"folderLabel": folder.Label,
|
||||
"device": deviceID.String(),
|
||||
@ -1180,6 +1182,7 @@ func (m *model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
|
||||
fset: fs,
|
||||
prevSequence: startSequence,
|
||||
dropSymlinks: dropSymlinks,
|
||||
evLogger: m.evLogger,
|
||||
}
|
||||
is.Service = util.AsService(is.serve)
|
||||
// The token isn't tracked as the service stops when the connection
|
||||
@ -1432,7 +1435,7 @@ func (m *model) Closed(conn protocol.Connection, err error) {
|
||||
delete(m.closed, device)
|
||||
|
||||
l.Infof("Connection to %s at %s closed: %v", device, conn.Name(), err)
|
||||
events.Default.Log(events.DeviceDisconnected, map[string]string{
|
||||
m.evLogger.Log(events.DeviceDisconnected, map[string]string{
|
||||
"id": device.String(),
|
||||
"error": err.Error(),
|
||||
})
|
||||
@ -1773,7 +1776,7 @@ func (m *model) OnHello(remoteID protocol.DeviceID, addr net.Addr, hello protoco
|
||||
if !ok {
|
||||
m.cfg.AddOrUpdatePendingDevice(remoteID, hello.DeviceName, addr.String())
|
||||
_ = m.cfg.Save() // best effort
|
||||
events.Default.Log(events.DeviceRejected, map[string]string{
|
||||
m.evLogger.Log(events.DeviceRejected, map[string]string{
|
||||
"name": hello.DeviceName,
|
||||
"device": remoteID.String(),
|
||||
"address": addr.String(),
|
||||
@ -1859,7 +1862,7 @@ func (m *model) AddConnection(conn connections.Connection, hello protocol.HelloR
|
||||
event["addr"] = addr.String()
|
||||
}
|
||||
|
||||
events.Default.Log(events.DeviceConnected, event)
|
||||
m.evLogger.Log(events.DeviceConnected, event)
|
||||
|
||||
l.Infof(`Device %s client is "%s %s" named "%s" at %s`, deviceID, hello.ClientName, hello.ClientVersion, hello.DeviceName, conn)
|
||||
|
||||
@ -1894,7 +1897,7 @@ func (m *model) DownloadProgress(device protocol.DeviceID, folder string, update
|
||||
downloads.Update(folder, updates)
|
||||
state := downloads.GetBlockCounts(folder)
|
||||
|
||||
events.Default.Log(events.RemoteDownloadProgress, map[string]interface{}{
|
||||
m.evLogger.Log(events.RemoteDownloadProgress, map[string]interface{}{
|
||||
"device": device.String(),
|
||||
"folder": folder,
|
||||
"state": state,
|
||||
@ -1926,6 +1929,7 @@ type indexSender struct {
|
||||
fset *db.FileSet
|
||||
prevSequence int64
|
||||
dropSymlinks bool
|
||||
evLogger events.Logger
|
||||
connClosed chan struct{}
|
||||
}
|
||||
|
||||
@ -1941,8 +1945,8 @@ func (s *indexSender) serve(stop chan struct{}) {
|
||||
// Subscribe to LocalIndexUpdated (we have new information to send) and
|
||||
// DeviceDisconnected (it might be us who disconnected, so we should
|
||||
// exit).
|
||||
sub := events.Default.Subscribe(events.LocalIndexUpdated | events.DeviceDisconnected)
|
||||
defer events.Default.Unsubscribe(sub)
|
||||
sub := s.evLogger.Subscribe(events.LocalIndexUpdated | events.DeviceDisconnected)
|
||||
defer sub.Unsubscribe()
|
||||
|
||||
evChan := sub.C()
|
||||
ticker := time.NewTicker(time.Minute)
|
||||
@ -2531,7 +2535,7 @@ func (m *model) CommitConfiguration(from, to config.Configuration) bool {
|
||||
if toCfg.Paused {
|
||||
eventType = events.FolderPaused
|
||||
}
|
||||
events.Default.Log(eventType, map[string]string{"id": toCfg.ID, "label": toCfg.Label})
|
||||
m.evLogger.Log(eventType, map[string]string{"id": toCfg.ID, "label": toCfg.Label})
|
||||
}
|
||||
}
|
||||
|
||||
@ -2559,9 +2563,9 @@ func (m *model) CommitConfiguration(from, to config.Configuration) bool {
|
||||
if toCfg.Paused {
|
||||
l.Infoln("Pausing", deviceID)
|
||||
m.closeConn(deviceID, errDevicePaused)
|
||||
events.Default.Log(events.DevicePaused, map[string]string{"device": deviceID.String()})
|
||||
m.evLogger.Log(events.DevicePaused, map[string]string{"device": deviceID.String()})
|
||||
} else {
|
||||
events.Default.Log(events.DeviceResumed, map[string]string{"device": deviceID.String()})
|
||||
m.evLogger.Log(events.DeviceResumed, map[string]string{"device": deviceID.String()})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ func createTmpWrapper(cfg config.Configuration) config.Wrapper {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
wrapper := config.Wrap(tmpFile.Name(), cfg)
|
||||
wrapper := config.Wrap(tmpFile.Name(), cfg, events.NoopLogger)
|
||||
tmpFile.Close()
|
||||
return wrapper
|
||||
}
|
||||
@ -303,7 +303,7 @@ func TestDeviceRename(t *testing.T) {
|
||||
DeviceID: device1,
|
||||
},
|
||||
}
|
||||
cfg := config.Wrap("testdata/tmpconfig.xml", rawCfg)
|
||||
cfg := config.Wrap("testdata/tmpconfig.xml", rawCfg, events.NoopLogger)
|
||||
|
||||
db := db.OpenMemory()
|
||||
m := newModel(cfg, myID, "syncthing", "dev", db, nil)
|
||||
@ -339,7 +339,7 @@ func TestDeviceRename(t *testing.T) {
|
||||
t.Errorf("Device name got overwritten")
|
||||
}
|
||||
|
||||
cfgw, err := config.Load("testdata/tmpconfig.xml", myID)
|
||||
cfgw, err := config.Load("testdata/tmpconfig.xml", myID, events.NoopLogger)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
@ -3358,12 +3358,12 @@ func TestModTimeWindow(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDevicePause(t *testing.T) {
|
||||
sub := events.Default.Subscribe(events.DevicePaused)
|
||||
defer events.Default.Unsubscribe(sub)
|
||||
|
||||
m, _, fcfg := setupModelWithConnection()
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem().URI())
|
||||
|
||||
sub := m.evLogger.Subscribe(events.DevicePaused)
|
||||
defer sub.Unsubscribe()
|
||||
|
||||
m.pmut.RLock()
|
||||
closed := m.closed[device1]
|
||||
m.pmut.RUnlock()
|
||||
|
@ -29,6 +29,7 @@ type ProgressEmitter struct {
|
||||
connections map[protocol.DeviceID]protocol.Connection
|
||||
foldersByConns map[protocol.DeviceID][]string
|
||||
disabled bool
|
||||
evLogger events.Logger
|
||||
mut sync.Mutex
|
||||
|
||||
timer *time.Timer
|
||||
@ -36,13 +37,14 @@ type ProgressEmitter struct {
|
||||
|
||||
// NewProgressEmitter creates a new progress emitter which emits
|
||||
// DownloadProgress events every interval.
|
||||
func NewProgressEmitter(cfg config.Wrapper) *ProgressEmitter {
|
||||
func NewProgressEmitter(cfg config.Wrapper, evLogger events.Logger) *ProgressEmitter {
|
||||
t := &ProgressEmitter{
|
||||
registry: make(map[string]map[string]*sharedPullerState),
|
||||
timer: time.NewTimer(time.Millisecond),
|
||||
sentDownloadStates: make(map[protocol.DeviceID]*sentDownloadState),
|
||||
connections: make(map[protocol.DeviceID]protocol.Connection),
|
||||
foldersByConns: make(map[protocol.DeviceID][]string),
|
||||
evLogger: evLogger,
|
||||
mut: sync.NewMutex(),
|
||||
}
|
||||
t.Service = util.AsService(t.serve)
|
||||
@ -107,7 +109,7 @@ func (t *ProgressEmitter) sendDownloadProgressEventLocked() {
|
||||
output[folder][name] = puller.Progress()
|
||||
}
|
||||
}
|
||||
events.Default.Log(events.DownloadProgress, output)
|
||||
t.evLogger.Log(events.DownloadProgress, output)
|
||||
l.Debugf("progress emitter: emitting %#v", output)
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ func caller(skip int) string {
|
||||
return fmt.Sprintf("%s:%d", filepath.Base(file), line)
|
||||
}
|
||||
|
||||
func expectEvent(w *events.Subscription, t *testing.T, size int) {
|
||||
func expectEvent(w events.Subscription, t *testing.T, size int) {
|
||||
event, err := w.Poll(timeout)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error:", err, "at", caller(1))
|
||||
@ -44,7 +44,7 @@ func expectEvent(w *events.Subscription, t *testing.T, size int) {
|
||||
}
|
||||
}
|
||||
|
||||
func expectTimeout(w *events.Subscription, t *testing.T) {
|
||||
func expectTimeout(w events.Subscription, t *testing.T) {
|
||||
_, err := w.Poll(timeout)
|
||||
if err != events.ErrTimeout {
|
||||
t.Fatal("Unexpected non-Timeout error:", err, "at", caller(1))
|
||||
@ -52,7 +52,11 @@ func expectTimeout(w *events.Subscription, t *testing.T) {
|
||||
}
|
||||
|
||||
func TestProgressEmitter(t *testing.T) {
|
||||
w := events.Default.Subscribe(events.DownloadProgress)
|
||||
evLogger := events.NewLogger()
|
||||
go evLogger.Serve()
|
||||
defer evLogger.Stop()
|
||||
|
||||
w := evLogger.Subscribe(events.DownloadProgress)
|
||||
|
||||
c := createTmpWrapper(config.Configuration{})
|
||||
defer os.Remove(c.ConfigPath())
|
||||
@ -60,7 +64,7 @@ func TestProgressEmitter(t *testing.T) {
|
||||
ProgressUpdateIntervalS: 0,
|
||||
})
|
||||
|
||||
p := NewProgressEmitter(c)
|
||||
p := NewProgressEmitter(c, evLogger)
|
||||
go p.Serve()
|
||||
p.interval = 0
|
||||
|
||||
@ -112,7 +116,11 @@ func TestSendDownloadProgressMessages(t *testing.T) {
|
||||
|
||||
fc := &fakeConnection{}
|
||||
|
||||
p := NewProgressEmitter(c)
|
||||
evLogger := events.NewLogger()
|
||||
go evLogger.Serve()
|
||||
defer evLogger.Stop()
|
||||
|
||||
p := NewProgressEmitter(c, evLogger)
|
||||
p.temporaryIndexSubscribe(fc, []string{"folder", "folder2"})
|
||||
p.registry["folder"] = make(map[string]*sharedPullerState)
|
||||
p.registry["folder2"] = make(map[string]*sharedPullerState)
|
||||
|
@ -350,8 +350,8 @@ func pullInvalidIgnored(t *testing.T, ft config.FolderType) {
|
||||
}
|
||||
fc.mut.Unlock()
|
||||
|
||||
sub := events.Default.Subscribe(events.FolderErrors)
|
||||
defer events.Default.Unsubscribe(sub)
|
||||
sub := m.evLogger.Subscribe(events.FolderErrors)
|
||||
defer sub.Unsubscribe()
|
||||
|
||||
fc.sendIndexUpdate()
|
||||
|
||||
@ -640,8 +640,8 @@ func TestRequestSymlinkWindows(t *testing.T) {
|
||||
t.Fatalf("timed out before pull was finished")
|
||||
}
|
||||
|
||||
sub := events.Default.Subscribe(events.StateChanged | events.LocalIndexUpdated)
|
||||
defer events.Default.Unsubscribe(sub)
|
||||
sub := m.evLogger.Subscribe(events.StateChanged | events.LocalIndexUpdated)
|
||||
defer sub.Unsubscribe()
|
||||
|
||||
m.ScanFolder("default")
|
||||
|
||||
@ -978,8 +978,8 @@ func TestNeedFolderFiles(t *testing.T) {
|
||||
tmpDir := tfs.URI()
|
||||
defer cleanupModelAndRemoveDir(m, tmpDir)
|
||||
|
||||
sub := events.Default.Subscribe(events.RemoteIndexUpdated)
|
||||
defer events.Default.Unsubscribe(sub)
|
||||
sub := m.evLogger.Subscribe(events.RemoteIndexUpdated)
|
||||
defer sub.Unsubscribe()
|
||||
|
||||
errPreventSync := errors.New("you aren't getting any of this")
|
||||
fc.mut.Lock()
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
@ -117,12 +118,16 @@ func setupModel(w config.Wrapper) *model {
|
||||
}
|
||||
|
||||
func newModel(cfg config.Wrapper, id protocol.DeviceID, clientName, clientVersion string, ldb *db.Lowlevel, protectedFiles []string) *model {
|
||||
return NewModel(cfg, id, clientName, clientVersion, ldb, protectedFiles).(*model)
|
||||
evLogger := events.NewLogger()
|
||||
m := NewModel(cfg, id, clientName, clientVersion, ldb, protectedFiles, evLogger).(*model)
|
||||
go evLogger.Serve()
|
||||
return m
|
||||
}
|
||||
|
||||
func cleanupModel(m *model) {
|
||||
m.Stop()
|
||||
m.db.Close()
|
||||
m.evLogger.Stop()
|
||||
os.Remove(m.cfg.ConfigPath())
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/dialer"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
)
|
||||
@ -455,7 +456,7 @@ func (p *Process) eventLoop() {
|
||||
default:
|
||||
}
|
||||
|
||||
events, err := p.Events(since)
|
||||
evs, err := p.Events(since)
|
||||
if err != nil {
|
||||
if time.Since(start) < 5*time.Second {
|
||||
// The API has probably not started yet, lets give it some time.
|
||||
@ -473,7 +474,7 @@ func (p *Process) eventLoop() {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, ev := range events {
|
||||
for _, ev := range evs {
|
||||
if ev.ID != since+1 {
|
||||
l.Warnln("Event ID jumped", since, "to", ev.ID)
|
||||
}
|
||||
@ -493,7 +494,7 @@ func (p *Process) eventLoop() {
|
||||
p.id = id
|
||||
|
||||
home := data["home"].(string)
|
||||
w, err := config.Load(filepath.Join(home, "config.xml"), protocol.LocalDeviceID)
|
||||
w, err := config.Load(filepath.Join(home, "config.xml"), protocol.LocalDeviceID, events.NoopLogger)
|
||||
if err != nil {
|
||||
log.Println("eventLoop: Starting:", err)
|
||||
continue
|
||||
|
@ -56,6 +56,8 @@ type Config struct {
|
||||
LocalFlags uint32
|
||||
// Modification time is to be considered unchanged if the difference is lower.
|
||||
ModTimeWindow time.Duration
|
||||
// Event logger to which the scan progress events are sent
|
||||
EvLogger events.Logger
|
||||
}
|
||||
|
||||
type CurrentFiler interface {
|
||||
@ -168,7 +170,7 @@ func (w *walker) walk(ctx context.Context) chan ScanResult {
|
||||
current := progress.Total()
|
||||
rate := progress.Rate()
|
||||
l.Debugf("Walk %s %s current progress %d/%d at %.01f MiB/s (%d%%)", w.Folder, w.Subs, current, total, rate/1024/1024, current*100/total)
|
||||
events.Default.Log(events.FolderScanProgress, map[string]interface{}{
|
||||
w.EvLogger.Log(events.FolderScanProgress, map[string]interface{}{
|
||||
"folder": w.Folder,
|
||||
"current": current,
|
||||
"total": total,
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/d4l3k/messagediff"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/ignore"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
@ -66,12 +67,10 @@ func TestWalkSub(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fchan := Walk(context.TODO(), Config{
|
||||
Filesystem: testFs,
|
||||
Subs: []string{"dir2"},
|
||||
Matcher: ignores,
|
||||
Hashers: 2,
|
||||
})
|
||||
cfg := testConfig()
|
||||
cfg.Subs = []string{"dir2"}
|
||||
cfg.Matcher = ignores
|
||||
fchan := Walk(context.TODO(), cfg)
|
||||
var files []protocol.FileInfo
|
||||
for f := range fchan {
|
||||
if f.Err != nil {
|
||||
@ -102,11 +101,9 @@ func TestWalk(t *testing.T) {
|
||||
}
|
||||
t.Log(ignores)
|
||||
|
||||
fchan := Walk(context.TODO(), Config{
|
||||
Filesystem: testFs,
|
||||
Matcher: ignores,
|
||||
Hashers: 2,
|
||||
})
|
||||
cfg := testConfig()
|
||||
cfg.Matcher = ignores
|
||||
fchan := Walk(context.TODO(), cfg)
|
||||
|
||||
var tmp []protocol.FileInfo
|
||||
for f := range fchan {
|
||||
@ -466,15 +463,14 @@ func TestWalkReceiveOnly(t *testing.T) {
|
||||
}
|
||||
|
||||
func walkDir(fs fs.Filesystem, dir string, cfiler CurrentFiler, matcher *ignore.Matcher, localFlags uint32) []protocol.FileInfo {
|
||||
fchan := Walk(context.TODO(), Config{
|
||||
Filesystem: fs,
|
||||
Subs: []string{dir},
|
||||
AutoNormalize: true,
|
||||
Hashers: 2,
|
||||
CurrentFiler: cfiler,
|
||||
Matcher: matcher,
|
||||
LocalFlags: localFlags,
|
||||
})
|
||||
cfg := testConfig()
|
||||
cfg.Filesystem = fs
|
||||
cfg.Subs = []string{dir}
|
||||
cfg.AutoNormalize = true
|
||||
cfg.CurrentFiler = cfiler
|
||||
cfg.Matcher = matcher
|
||||
cfg.LocalFlags = localFlags
|
||||
fchan := Walk(context.TODO(), cfg)
|
||||
|
||||
var tmp []protocol.FileInfo
|
||||
for f := range fchan {
|
||||
@ -576,11 +572,11 @@ func TestStopWalk(t *testing.T) {
|
||||
|
||||
const numHashers = 4
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
fchan := Walk(ctx, Config{
|
||||
Filesystem: fs,
|
||||
Hashers: numHashers,
|
||||
ProgressTickIntervalS: -1, // Don't attempt to build the full list of files before starting to scan...
|
||||
})
|
||||
cfg := testConfig()
|
||||
cfg.Filesystem = fs
|
||||
cfg.Hashers = numHashers
|
||||
cfg.ProgressTickIntervalS = -1 // Don't attempt to build the full list of files before starting to scan...
|
||||
fchan := Walk(ctx, cfg)
|
||||
|
||||
// Receive a few entries to make sure the walker is up and running,
|
||||
// scanning both files and dirs. Do some quick sanity tests on the
|
||||
@ -705,21 +701,17 @@ func TestIssue4841(t *testing.T) {
|
||||
}
|
||||
fd.Close()
|
||||
|
||||
fchan := Walk(context.TODO(), Config{
|
||||
Filesystem: fs,
|
||||
Subs: nil,
|
||||
AutoNormalize: true,
|
||||
Hashers: 2,
|
||||
CurrentFiler: fakeCurrentFiler{
|
||||
"foo": {
|
||||
cfg := testConfig()
|
||||
cfg.Filesystem = fs
|
||||
cfg.AutoNormalize = true
|
||||
cfg.CurrentFiler = fakeCurrentFiler{"foo": {
|
||||
Name: "foo",
|
||||
Type: protocol.FileInfoTypeFile,
|
||||
LocalFlags: protocol.FlagLocalIgnored,
|
||||
Version: protocol.Vector{}.Update(1),
|
||||
},
|
||||
},
|
||||
ShortID: protocol.LocalDeviceID.Short(),
|
||||
})
|
||||
}}
|
||||
cfg.ShortID = protocol.LocalDeviceID.Short()
|
||||
fchan := Walk(context.TODO(), cfg)
|
||||
|
||||
var files []protocol.FileInfo
|
||||
for f := range fchan {
|
||||
@ -745,11 +737,9 @@ func TestNotExistingError(t *testing.T) {
|
||||
t.Fatalf("Lstat returned error %v, while nothing should exist there.", err)
|
||||
}
|
||||
|
||||
fchan := Walk(context.TODO(), Config{
|
||||
Filesystem: testFs,
|
||||
Subs: []string{sub},
|
||||
Hashers: 2,
|
||||
})
|
||||
cfg := testConfig()
|
||||
cfg.Subs = []string{sub}
|
||||
fchan := Walk(context.TODO(), cfg)
|
||||
for f := range fchan {
|
||||
t.Fatalf("Expected no result from scan, got %v", f)
|
||||
}
|
||||
@ -793,3 +783,13 @@ func (fcf fakeCurrentFiler) CurrentFile(name string) (protocol.FileInfo, bool) {
|
||||
f, ok := fcf[name]
|
||||
return f, ok
|
||||
}
|
||||
|
||||
func testConfig() Config {
|
||||
evLogger := events.NewLogger()
|
||||
go evLogger.Serve()
|
||||
return Config{
|
||||
Filesystem: testFs,
|
||||
Hashers: 2,
|
||||
EvLogger: evLogger,
|
||||
}
|
||||
}
|
||||
|
@ -21,13 +21,13 @@ import (
|
||||
type auditService struct {
|
||||
suture.Service
|
||||
w io.Writer // audit destination
|
||||
sub *events.Subscription
|
||||
sub events.Subscription
|
||||
}
|
||||
|
||||
func newAuditService(w io.Writer) *auditService {
|
||||
func newAuditService(w io.Writer, evLogger events.Logger) *auditService {
|
||||
s := &auditService{
|
||||
w: w,
|
||||
sub: events.Default.Subscribe(events.AllEvents),
|
||||
sub: evLogger.Subscribe(events.AllEvents),
|
||||
}
|
||||
s.Service = util.AsService(s.serve)
|
||||
return s
|
||||
@ -50,5 +50,5 @@ func (s *auditService) serve(stop chan struct{}) {
|
||||
// Stop stops the audit service.
|
||||
func (s *auditService) Stop() {
|
||||
s.Service.Stop()
|
||||
events.Default.Unsubscribe(s.sub)
|
||||
s.sub.Unsubscribe()
|
||||
}
|
||||
|
@ -17,15 +17,22 @@ import (
|
||||
|
||||
func TestAuditService(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
evLogger := events.NewLogger()
|
||||
go evLogger.Serve()
|
||||
defer evLogger.Stop()
|
||||
sub := evLogger.Subscribe(events.AllEvents)
|
||||
defer sub.Unsubscribe()
|
||||
|
||||
// Event sent before construction, will not be logged
|
||||
events.Default.Log(events.ConfigSaved, "the first event")
|
||||
// Event sent before start, will not be logged
|
||||
evLogger.Log(events.ConfigSaved, "the first event")
|
||||
// Make sure the event goes through before creating the service
|
||||
<-sub.C()
|
||||
|
||||
service := newAuditService(buf)
|
||||
service := newAuditService(buf, evLogger)
|
||||
go service.Serve()
|
||||
|
||||
// Event that should end up in the audit log
|
||||
events.Default.Log(events.ConfigSaved, "the second event")
|
||||
evLogger.Log(events.ConfigSaved, "the second event")
|
||||
|
||||
// We need to give the events time to arrive, since the channels are buffered etc.
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
@ -33,7 +40,7 @@ func TestAuditService(t *testing.T) {
|
||||
service.Stop()
|
||||
|
||||
// This event should not be logged, since we have stopped.
|
||||
events.Default.Log(events.ConfigSaved, "the third event")
|
||||
evLogger.Log(events.ConfigSaved, "the third event")
|
||||
|
||||
result := buf.String()
|
||||
t.Log(result)
|
||||
|
@ -68,6 +68,7 @@ type App struct {
|
||||
mainService *suture.Supervisor
|
||||
cfg config.Wrapper
|
||||
ll *db.Lowlevel
|
||||
evLogger events.Logger
|
||||
cert tls.Certificate
|
||||
opts Options
|
||||
exitStatus ExitStatus
|
||||
@ -78,10 +79,11 @@ type App struct {
|
||||
stopped chan struct{}
|
||||
}
|
||||
|
||||
func New(cfg config.Wrapper, ll *db.Lowlevel, cert tls.Certificate, opts Options) *App {
|
||||
func New(cfg config.Wrapper, ll *db.Lowlevel, evLogger events.Logger, cert tls.Certificate, opts Options) *App {
|
||||
return &App{
|
||||
cfg: cfg,
|
||||
ll: ll,
|
||||
evLogger: evLogger,
|
||||
opts: opts,
|
||||
cert: cert,
|
||||
stop: make(chan struct{}),
|
||||
@ -120,11 +122,11 @@ func (a *App) startup() error {
|
||||
a.mainService.ServeBackground()
|
||||
|
||||
if a.opts.AuditWriter != nil {
|
||||
a.mainService.Add(newAuditService(a.opts.AuditWriter))
|
||||
a.mainService.Add(newAuditService(a.opts.AuditWriter, a.evLogger))
|
||||
}
|
||||
|
||||
if a.opts.Verbose {
|
||||
a.mainService.Add(newVerboseService())
|
||||
a.mainService.Add(newVerboseService(a.evLogger))
|
||||
}
|
||||
|
||||
errors := logger.NewRecorder(l, logger.LevelWarn, maxSystemErrors, 0)
|
||||
@ -133,8 +135,8 @@ func (a *App) startup() error {
|
||||
// Event subscription for the API; must start early to catch the early
|
||||
// events. The LocalChangeDetected event might overwhelm the event
|
||||
// receiver in some situations so we will not subscribe to it here.
|
||||
defaultSub := events.NewBufferedSubscription(events.Default.Subscribe(api.DefaultEventMask), api.EventSubBufferSize)
|
||||
diskSub := events.NewBufferedSubscription(events.Default.Subscribe(api.DiskEventMask), api.EventSubBufferSize)
|
||||
defaultSub := events.NewBufferedSubscription(a.evLogger.Subscribe(api.DefaultEventMask), api.EventSubBufferSize)
|
||||
diskSub := events.NewBufferedSubscription(a.evLogger.Subscribe(api.DiskEventMask), api.EventSubBufferSize)
|
||||
|
||||
// Attempt to increase the limit on number of open files to the maximum
|
||||
// allowed, in case we have many peers. We don't really care enough to
|
||||
@ -153,7 +155,7 @@ func (a *App) startup() error {
|
||||
|
||||
// Emit the Starting event, now that we know who we are.
|
||||
|
||||
events.Default.Log(events.Starting, map[string]string{
|
||||
a.evLogger.Log(events.Starting, map[string]string{
|
||||
"home": locations.GetBaseDir(locations.ConfigBaseDir),
|
||||
"myID": a.myID.String(),
|
||||
})
|
||||
@ -228,7 +230,7 @@ func (a *App) startup() error {
|
||||
miscDB.PutString("prevVersion", build.Version)
|
||||
}
|
||||
|
||||
m := model.NewModel(a.cfg, a.myID, "syncthing", build.Version, a.ll, protectedFiles)
|
||||
m := model.NewModel(a.cfg, a.myID, "syncthing", build.Version, a.ll, protectedFiles, a.evLogger)
|
||||
|
||||
if a.opts.DeadlockTimeoutS > 0 {
|
||||
m.StartDeadlockDetector(time.Duration(a.opts.DeadlockTimeoutS) * time.Second)
|
||||
@ -265,13 +267,13 @@ func (a *App) startup() error {
|
||||
|
||||
// Start connection management
|
||||
|
||||
connectionsService := connections.NewService(a.cfg, a.myID, m, tlsCfg, cachedDiscovery, bepProtocolName, tlsDefaultCommonName)
|
||||
connectionsService := connections.NewService(a.cfg, a.myID, m, tlsCfg, cachedDiscovery, bepProtocolName, tlsDefaultCommonName, a.evLogger)
|
||||
a.mainService.Add(connectionsService)
|
||||
|
||||
if a.cfg.Options().GlobalAnnEnabled {
|
||||
for _, srv := range a.cfg.GlobalDiscoveryServers() {
|
||||
l.Infoln("Using discovery server", srv)
|
||||
gd, err := discover.NewGlobal(srv, a.cert, connectionsService)
|
||||
gd, err := discover.NewGlobal(srv, a.cert, connectionsService, a.evLogger)
|
||||
if err != nil {
|
||||
l.Warnln("Global discovery:", err)
|
||||
continue
|
||||
@ -286,14 +288,14 @@ func (a *App) startup() error {
|
||||
|
||||
if a.cfg.Options().LocalAnnEnabled {
|
||||
// v4 broadcasts
|
||||
bcd, err := discover.NewLocal(a.myID, fmt.Sprintf(":%d", a.cfg.Options().LocalAnnPort), connectionsService)
|
||||
bcd, err := discover.NewLocal(a.myID, fmt.Sprintf(":%d", a.cfg.Options().LocalAnnPort), connectionsService, a.evLogger)
|
||||
if err != nil {
|
||||
l.Warnln("IPv4 local discovery:", err)
|
||||
} else {
|
||||
cachedDiscovery.Add(bcd, 0, 0)
|
||||
}
|
||||
// v6 multicasts
|
||||
mcd, err := discover.NewLocal(a.myID, a.cfg.Options().LocalAnnMCAddr, connectionsService)
|
||||
mcd, err := discover.NewLocal(a.myID, a.cfg.Options().LocalAnnMCAddr, connectionsService, a.evLogger)
|
||||
if err != nil {
|
||||
l.Warnln("IPv6 local discovery:", err)
|
||||
} else {
|
||||
@ -342,7 +344,7 @@ func (a *App) startup() error {
|
||||
l.Warnln("Syncthing should not run as a privileged or system user. Please consider using a normal user account.")
|
||||
}
|
||||
|
||||
events.Default.Log(events.StartupComplete, map[string]string{
|
||||
a.evLogger.Log(events.StartupComplete, map[string]string{
|
||||
"myID": a.myID.String(),
|
||||
})
|
||||
|
||||
@ -426,10 +428,10 @@ func (a *App) setupGUI(m model.Model, defaultSub, diskSub events.BufferedSubscri
|
||||
cpu := newCPUService()
|
||||
a.mainService.Add(cpu)
|
||||
|
||||
summaryService := model.NewFolderSummaryService(a.cfg, m, a.myID)
|
||||
summaryService := model.NewFolderSummaryService(a.cfg, m, a.myID, a.evLogger)
|
||||
a.mainService.Add(summaryService)
|
||||
|
||||
apiSvc := api.New(a.myID, a.cfg, a.opts.AssetDir, tlsDefaultCommonName, m, defaultSub, diskSub, discoverer, connectionsService, urService, summaryService, errors, systemLog, cpu, &controller{a}, a.opts.NoUpgrade)
|
||||
apiSvc := api.New(a.myID, a.cfg, a.opts.AssetDir, tlsDefaultCommonName, m, defaultSub, diskSub, a.evLogger, discoverer, connectionsService, urService, summaryService, errors, systemLog, cpu, &controller{a}, a.opts.NoUpgrade)
|
||||
a.mainService.Add(apiSvc)
|
||||
|
||||
if err := apiSvc.WaitForStart(); err != nil {
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
@ -19,7 +20,7 @@ func TestShortIDCheck(t *testing.T) {
|
||||
{DeviceID: protocol.DeviceID{8, 16, 24, 32, 40, 48, 56, 0, 0}},
|
||||
{DeviceID: protocol.DeviceID{8, 16, 24, 32, 40, 48, 56, 1, 1}}, // first 56 bits same, differ in the first 64 bits
|
||||
},
|
||||
})
|
||||
}, events.NoopLogger)
|
||||
|
||||
if err := checkShortIDs(cfg); err != nil {
|
||||
t.Error("Unexpected error:", err)
|
||||
@ -30,7 +31,7 @@ func TestShortIDCheck(t *testing.T) {
|
||||
{DeviceID: protocol.DeviceID{8, 16, 24, 32, 40, 48, 56, 64, 0}},
|
||||
{DeviceID: protocol.DeviceID{8, 16, 24, 32, 40, 48, 56, 64, 1}}, // first 64 bits same
|
||||
},
|
||||
})
|
||||
}, events.NoopLogger)
|
||||
|
||||
if err := checkShortIDs(cfg); err == nil {
|
||||
t.Error("Should have gotten an error")
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/locations"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
@ -39,7 +40,7 @@ func LoadOrGenerateCertificate(certFile, keyFile string) (tls.Certificate, error
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
func DefaultConfig(path string, myID protocol.DeviceID, noDefaultFolder bool) (config.Wrapper, error) {
|
||||
func DefaultConfig(path string, myID protocol.DeviceID, evLogger events.Logger, noDefaultFolder bool) (config.Wrapper, error) {
|
||||
newCfg, err := config.NewWithFreePorts(myID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -47,23 +48,23 @@ func DefaultConfig(path string, myID protocol.DeviceID, noDefaultFolder bool) (c
|
||||
|
||||
if noDefaultFolder {
|
||||
l.Infoln("We will skip creation of a default folder on first start")
|
||||
return config.Wrap(path, newCfg), nil
|
||||
return config.Wrap(path, newCfg, evLogger), nil
|
||||
}
|
||||
|
||||
newCfg.Folders = append(newCfg.Folders, config.NewFolderConfiguration(myID, "default", "Default Folder", fs.FilesystemTypeBasic, locations.Get(locations.DefFolder)))
|
||||
l.Infoln("Default folder created and/or linked to new config")
|
||||
return config.Wrap(path, newCfg), nil
|
||||
return config.Wrap(path, newCfg, evLogger), nil
|
||||
}
|
||||
|
||||
// LoadConfigAtStartup loads an existing config. If it doesn't yet exist, it
|
||||
// creates a default one, without the default folder if noDefaultFolder is ture.
|
||||
// Otherwise it checks the version, and archives and upgrades the config if
|
||||
// necessary or returns an error, if the version isn't compatible.
|
||||
func LoadConfigAtStartup(path string, cert tls.Certificate, allowNewerConfig, noDefaultFolder bool) (config.Wrapper, error) {
|
||||
func LoadConfigAtStartup(path string, cert tls.Certificate, evLogger events.Logger, allowNewerConfig, noDefaultFolder bool) (config.Wrapper, error) {
|
||||
myID := protocol.NewDeviceID(cert.Certificate[0])
|
||||
cfg, err := config.Load(path, myID)
|
||||
cfg, err := config.Load(path, myID, evLogger)
|
||||
if fs.IsNotExist(err) {
|
||||
cfg, err = DefaultConfig(path, myID, noDefaultFolder)
|
||||
cfg, err = DefaultConfig(path, myID, evLogger, noDefaultFolder)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to generate default config")
|
||||
}
|
||||
|
@ -19,12 +19,12 @@ import (
|
||||
// verbose format to the console using INFO level.
|
||||
type verboseService struct {
|
||||
suture.Service
|
||||
sub *events.Subscription
|
||||
sub events.Subscription
|
||||
}
|
||||
|
||||
func newVerboseService() *verboseService {
|
||||
func newVerboseService(evLogger events.Logger) *verboseService {
|
||||
s := &verboseService{
|
||||
sub: events.Default.Subscribe(events.AllEvents),
|
||||
sub: evLogger.Subscribe(events.AllEvents),
|
||||
}
|
||||
s.Service = util.AsService(s.serve)
|
||||
return s
|
||||
@ -48,7 +48,7 @@ func (s *verboseService) serve(stop chan struct{}) {
|
||||
// Stop stops the verbose logging service.
|
||||
func (s *verboseService) Stop() {
|
||||
s.Service.Stop()
|
||||
events.Default.Unsubscribe(s.sub)
|
||||
s.sub.Unsubscribe()
|
||||
|
||||
}
|
||||
|
||||
|
@ -125,19 +125,19 @@ func newAggregator(folderCfg config.FolderConfiguration, ctx context.Context) *a
|
||||
return a
|
||||
}
|
||||
|
||||
func Aggregate(in <-chan fs.Event, out chan<- []string, folderCfg config.FolderConfiguration, cfg config.Wrapper, ctx context.Context) {
|
||||
func Aggregate(in <-chan fs.Event, out chan<- []string, folderCfg config.FolderConfiguration, cfg config.Wrapper, evLogger events.Logger, ctx context.Context) {
|
||||
a := newAggregator(folderCfg, ctx)
|
||||
|
||||
// Necessary for unit tests where the backend is mocked
|
||||
go a.mainLoop(in, out, cfg)
|
||||
go a.mainLoop(in, out, cfg, evLogger)
|
||||
}
|
||||
|
||||
func (a *aggregator) mainLoop(in <-chan fs.Event, out chan<- []string, cfg config.Wrapper) {
|
||||
func (a *aggregator) mainLoop(in <-chan fs.Event, out chan<- []string, cfg config.Wrapper, evLogger events.Logger) {
|
||||
a.notifyTimer = time.NewTimer(a.notifyDelay)
|
||||
defer a.notifyTimer.Stop()
|
||||
|
||||
inProgressItemSubscription := events.Default.Subscribe(events.ItemStarted | events.ItemFinished)
|
||||
defer events.Default.Unsubscribe(inProgressItemSubscription)
|
||||
inProgressItemSubscription := evLogger.Subscribe(events.ItemStarted | events.ItemFinished)
|
||||
defer inProgressItemSubscription.Unsubscribe()
|
||||
|
||||
cfg.Subscribe(a)
|
||||
defer cfg.Unsubscribe(a)
|
||||
|
@ -47,7 +47,7 @@ var (
|
||||
}
|
||||
defaultCfg = config.Wrap("", config.Configuration{
|
||||
Folders: []config.FolderConfiguration{defaultFolderCfg},
|
||||
})
|
||||
}, events.NoopLogger)
|
||||
)
|
||||
|
||||
// Represents possibly multiple (different event types) expected paths from
|
||||
@ -151,14 +151,17 @@ func TestAggregate(t *testing.T) {
|
||||
|
||||
// TestInProgress checks that ignoring files currently edited by Syncthing works
|
||||
func TestInProgress(t *testing.T) {
|
||||
evLogger := events.NewLogger()
|
||||
go evLogger.Serve()
|
||||
defer evLogger.Stop()
|
||||
testCase := func(c chan<- fs.Event) {
|
||||
events.Default.Log(events.ItemStarted, map[string]string{
|
||||
evLogger.Log(events.ItemStarted, map[string]string{
|
||||
"item": "inprogress",
|
||||
})
|
||||
sleepMs(100)
|
||||
c <- fs.Event{Name: "inprogress", Type: fs.NonRemove}
|
||||
sleepMs(1000)
|
||||
events.Default.Log(events.ItemFinished, map[string]interface{}{
|
||||
evLogger.Log(events.ItemFinished, map[string]interface{}{
|
||||
"item": "inprogress",
|
||||
})
|
||||
sleepMs(100)
|
||||
@ -170,7 +173,7 @@ func TestInProgress(t *testing.T) {
|
||||
{[][]string{{"notinprogress"}}, 2000, 3500},
|
||||
}
|
||||
|
||||
testScenario(t, "InProgress", testCase, expectedBatches)
|
||||
testScenario(t, "InProgress", testCase, expectedBatches, evLogger)
|
||||
}
|
||||
|
||||
// TestDelay checks that recurring changes to the same path are delayed
|
||||
@ -208,7 +211,7 @@ func TestDelay(t *testing.T) {
|
||||
{[][]string{{delayed}, {delAfter}}, 3600, 7000},
|
||||
}
|
||||
|
||||
testScenario(t, "Delay", testCase, expectedBatches)
|
||||
testScenario(t, "Delay", testCase, expectedBatches, nil)
|
||||
}
|
||||
|
||||
// TestNoDelay checks that no delay occurs if there are no non-remove events
|
||||
@ -225,7 +228,7 @@ func TestNoDelay(t *testing.T) {
|
||||
{[][]string{{mixed}, {del}}, 500, 2000},
|
||||
}
|
||||
|
||||
testScenario(t, "NoDelay", testCase, expectedBatches)
|
||||
testScenario(t, "NoDelay", testCase, expectedBatches, nil)
|
||||
}
|
||||
|
||||
func getEventPaths(dir *eventDir, dirPath string, a *aggregator) []string {
|
||||
@ -277,8 +280,13 @@ func compareBatchToExpectedDirect(t *testing.T, batch []string, expectedPaths []
|
||||
}
|
||||
}
|
||||
|
||||
func testScenario(t *testing.T, name string, testCase func(c chan<- fs.Event), expectedBatches []expectedBatch) {
|
||||
func testScenario(t *testing.T, name string, testCase func(c chan<- fs.Event), expectedBatches []expectedBatch, evLogger events.Logger) {
|
||||
t.Helper()
|
||||
|
||||
if evLogger == nil {
|
||||
evLogger = events.NoopLogger
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
eventChan := make(chan fs.Event)
|
||||
watchChan := make(chan []string)
|
||||
@ -289,7 +297,7 @@ func testScenario(t *testing.T, name string, testCase func(c chan<- fs.Event), e
|
||||
a.notifyTimeout = testNotifyTimeout
|
||||
|
||||
startTime := time.Now()
|
||||
go a.mainLoop(eventChan, watchChan, defaultCfg)
|
||||
go a.mainLoop(eventChan, watchChan, defaultCfg, evLogger)
|
||||
|
||||
sleepMs(20)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user