From 370a3549e7e8a6a9b6cae84f56b7e49d122c77c5 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Mon, 21 May 2018 08:45:05 +0200 Subject: [PATCH] lib/model: Refactor folderScanner into folder The functionality was anyway mostly implemented there and not isolated in the folderScanner type. The attempt to refactor it out in the other direction wouldn't work given that the event loop and stuff is on `folder`. --- lib/model/folder.go | 54 +++++++++++++++++++++++++++------- lib/model/folderscanner.go | 59 -------------------------------------- 2 files changed, 43 insertions(+), 70 deletions(-) delete mode 100644 lib/model/folderscanner.go diff --git a/lib/model/folder.go b/lib/model/folder.go index df35aeab2..c90b9e3b6 100644 --- a/lib/model/folder.go +++ b/lib/model/folder.go @@ -9,6 +9,7 @@ package model import ( "context" "errors" + "math/rand" "time" "github.com/syncthing/syncthing/lib/config" @@ -18,7 +19,7 @@ import ( "github.com/syncthing/syncthing/lib/watchaggregator" ) -var errWatchNotStarted error = errors.New("not started") +var errWatchNotStarted = errors.New("not started") type folder struct { stateTracker @@ -29,7 +30,10 @@ type folder struct { ctx context.Context cancel context.CancelFunc - scan folderScanner + scanInterval time.Duration + scanTimer *time.Timer + scanNow chan rescanRequest + scanDelay chan time.Duration initialScanFinished chan struct{} pullScheduled chan struct{} @@ -43,6 +47,11 @@ type folder struct { puller puller } +type rescanRequest struct { + subdirs []string + err chan error +} + type puller interface { pull() bool // true when successfull and should not be retried } @@ -59,7 +68,10 @@ func newFolder(model *Model, cfg config.FolderConfiguration) folder { ctx: ctx, cancel: cancel, - scan: newFolderScanner(cfg), + scanInterval: time.Duration(cfg.RescanIntervalS) * time.Second, + scanTimer: time.NewTimer(time.Millisecond), // The first scan should be done immediately. + scanNow: make(chan rescanRequest), + scanDelay: make(chan time.Duration), initialScanFinished: make(chan struct{}), pullScheduled: make(chan struct{}, 1), // This needs to be 1-buffered so that we queue a pull if we're busy when it comes. @@ -75,7 +87,7 @@ func (f *folder) Serve() { defer l.Debugln(f, "exiting") defer func() { - f.scan.timer.Stop() + f.scanTimer.Stop() f.setState(FolderIdle) }() @@ -133,15 +145,15 @@ func (f *folder) Serve() { // The reason for running the scanner from within the puller is that // this is the easiest way to make sure we are not doing both at the // same time. - case <-f.scan.timer.C: + case <-f.scanTimer.C: l.Debugln(f, "Scanning subdirectories") f.scanTimerFired() - case req := <-f.scan.now: + case req := <-f.scanNow: req.err <- f.scanSubdirs(req.subdirs) - case next := <-f.scan.delay: - f.scan.timer.Reset(next) + case next := <-f.scanDelay: + f.scanTimer.Reset(next) case fsEvents := <-f.watchChan: l.Debugln(f, "filesystem notification rescan") @@ -156,7 +168,7 @@ func (f *folder) Serve() { func (f *folder) BringToFront(string) {} func (f *folder) DelayScan(next time.Duration) { - f.scan.Delay(next) + f.Delay(next) } func (f *folder) IgnoresUpdated() { @@ -182,7 +194,27 @@ func (f *folder) Jobs() ([]string, []string) { func (f *folder) Scan(subdirs []string) error { <-f.initialScanFinished - return f.scan.Scan(subdirs) + req := rescanRequest{ + subdirs: subdirs, + err: make(chan error), + } + f.scanNow <- req + return <-req.err +} + +func (f *folder) Reschedule() { + if f.scanInterval == 0 { + return + } + // Sleep a random time between 3/4 and 5/4 of the configured interval. + sleepNanos := (f.scanInterval.Nanoseconds()*3 + rand.Int63n(2*f.scanInterval.Nanoseconds())) / 4 + interval := time.Duration(sleepNanos) * time.Nanosecond + l.Debugln(f, "next rescan in", interval) + f.scanTimer.Reset(interval) +} + +func (f *folder) Delay(next time.Duration) { + f.scanDelay <- next } func (f *folder) Stop() { @@ -242,7 +274,7 @@ func (f *folder) scanTimerFired() { close(f.initialScanFinished) } - f.scan.Reschedule() + f.Reschedule() } func (f *folder) WatchError() error { diff --git a/lib/model/folderscanner.go b/lib/model/folderscanner.go deleted file mode 100644 index 003a10d86..000000000 --- a/lib/model/folderscanner.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (C) 2016 The Syncthing Authors. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at https://mozilla.org/MPL/2.0/. - -package model - -import ( - "github.com/syncthing/syncthing/lib/config" - "math/rand" - "time" -) - -type rescanRequest struct { - subdirs []string - err chan error -} - -// bundle all folder scan activity -type folderScanner struct { - interval time.Duration - timer *time.Timer - now chan rescanRequest - delay chan time.Duration -} - -func newFolderScanner(config config.FolderConfiguration) folderScanner { - return folderScanner{ - interval: time.Duration(config.RescanIntervalS) * time.Second, - timer: time.NewTimer(time.Millisecond), // The first scan should be done immediately. - now: make(chan rescanRequest), - delay: make(chan time.Duration), - } -} - -func (f *folderScanner) Reschedule() { - if f.interval == 0 { - return - } - // Sleep a random time between 3/4 and 5/4 of the configured interval. - sleepNanos := (f.interval.Nanoseconds()*3 + rand.Int63n(2*f.interval.Nanoseconds())) / 4 - interval := time.Duration(sleepNanos) * time.Nanosecond - l.Debugln(f, "next rescan in", interval) - f.timer.Reset(interval) -} - -func (f *folderScanner) Scan(subdirs []string) error { - req := rescanRequest{ - subdirs: subdirs, - err: make(chan error), - } - f.now <- req - return <-req.err -} - -func (f *folderScanner) Delay(next time.Duration) { - f.delay <- next -}