Serialize scans and pulls (fixes #1391)
This commit is contained in:
@@ -32,7 +32,7 @@ import (
|
||||
const (
|
||||
pauseIntv = 60 * time.Second
|
||||
nextPullIntv = 10 * time.Second
|
||||
shortPullIntv = 5 * time.Second
|
||||
shortPullIntv = time.Second
|
||||
)
|
||||
|
||||
// A pullBlockState is passed to the puller routine for each block that needs
|
||||
@@ -90,6 +90,7 @@ type rwFolder struct {
|
||||
scanTimer *time.Timer
|
||||
pullTimer *time.Timer
|
||||
delayScan chan time.Duration
|
||||
scanNow chan rescanRequest
|
||||
remoteIndex chan struct{} // An index update was received, we should re-evaluate needs
|
||||
}
|
||||
|
||||
@@ -118,6 +119,7 @@ func newRWFolder(m *Model, shortID uint64, cfg config.FolderConfiguration) *rwFo
|
||||
pullTimer: time.NewTimer(shortPullIntv),
|
||||
scanTimer: time.NewTimer(time.Millisecond), // The first scan should be done immediately.
|
||||
delayScan: make(chan time.Duration),
|
||||
scanNow: make(chan rescanRequest),
|
||||
remoteIndex: make(chan struct{}, 1), // This needs to be 1-buffered so that we queue a notification if we're busy doing a pull when it comes.
|
||||
}
|
||||
}
|
||||
@@ -278,7 +280,7 @@ func (p *rwFolder) Serve() {
|
||||
l.Debugln(p, "rescan")
|
||||
}
|
||||
|
||||
if err := p.model.ScanFolder(p.folder); err != nil {
|
||||
if err := p.model.internalScanFolderSubs(p.folder, nil); err != nil {
|
||||
// Potentially sets the error twice, once in the scanner just
|
||||
// by doing a check, and once here, if the error returned is
|
||||
// the same one as returned by CheckFolderHealth, though
|
||||
@@ -296,6 +298,29 @@ func (p *rwFolder) Serve() {
|
||||
initialScanCompleted = true
|
||||
}
|
||||
|
||||
case req := <-p.scanNow:
|
||||
if err := p.model.CheckFolderHealth(p.folder); err != nil {
|
||||
l.Infoln("Skipping folder", p.folder, "scan due to folder error:", err)
|
||||
req.err <- err
|
||||
continue
|
||||
}
|
||||
|
||||
if debug {
|
||||
l.Debugln(p, "forced rescan")
|
||||
}
|
||||
|
||||
if err := p.model.internalScanFolderSubs(p.folder, req.subs); err != nil {
|
||||
// Potentially sets the error twice, once in the scanner just
|
||||
// by doing a check, and once here, if the error returned is
|
||||
// the same one as returned by CheckFolderHealth, though
|
||||
// duplicate set is handled by setError.
|
||||
p.setError(err)
|
||||
req.err <- err
|
||||
continue
|
||||
}
|
||||
|
||||
req.err <- nil
|
||||
|
||||
case next := <-p.delayScan:
|
||||
p.scanTimer.Reset(next)
|
||||
}
|
||||
@@ -317,6 +342,15 @@ func (p *rwFolder) IndexUpdated() {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *rwFolder) Scan(subs []string) error {
|
||||
req := rescanRequest{
|
||||
subs: subs,
|
||||
err: make(chan error),
|
||||
}
|
||||
p.scanNow <- req
|
||||
return <-req.err
|
||||
}
|
||||
|
||||
func (p *rwFolder) String() string {
|
||||
return fmt.Sprintf("rwFolder/%s@%p", p.folder, p)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user