mirror of
https://github.com/octoleo/syncthing.git
synced 2025-02-02 11:58:28 +00:00
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`.
This commit is contained in:
parent
d64d954721
commit
370a3549e7
@ -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 {
|
||||
|
@ -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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user