lib/model: Mark initial scan as finished even if failed and refactor (fixes #4103)

The mechanism to disallow manual scans before the initial scan completed
(#3996) , had the side effect, that if the initial scan failed, no further
scans are allowed. So this marks the initial scan as finished regardless of
whether it succeeded or not.

There was also redundant code in rofolder and a pointless check for folder
health in scanSubsIfHealthy (happens in internalScanFolderSubdirs as well).
This also moves logging from folder.go to ro/rw-folder.go to include the
information about whether it is send-only or send-receive

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4104
This commit is contained in:
Simon Frei
2017-04-20 00:20:34 +00:00
committed by Jakob Borg
parent 57e3f9e64b
commit 6b188ebcf3
4 changed files with 41 additions and 55 deletions

View File

@@ -11,10 +11,10 @@ import "time"
type folder struct { type folder struct {
stateTracker stateTracker
scan folderScanner scan folderScanner
model *Model model *Model
stop chan struct{} stop chan struct{}
initialScanCompleted chan struct{} initialScanFinished chan struct{}
} }
func (f *folder) IndexUpdated() { func (f *folder) IndexUpdated() {
@@ -25,7 +25,7 @@ func (f *folder) DelayScan(next time.Duration) {
} }
func (f *folder) Scan(subdirs []string) error { func (f *folder) Scan(subdirs []string) error {
<-f.initialScanCompleted <-f.initialScanFinished
return f.scan.Scan(subdirs) return f.scan.Scan(subdirs)
} }
func (f *folder) Stop() { func (f *folder) Stop() {
@@ -38,12 +38,7 @@ func (f *folder) Jobs() ([]string, []string) {
func (f *folder) BringToFront(string) {} func (f *folder) BringToFront(string) {}
func (f *folder) scanSubdirsIfHealthy(subDirs []string) error { func (f *folder) scanSubdirs(subDirs []string) error {
if err := f.model.CheckFolderHealth(f.folderID); err != nil {
l.Infoln("Skipping folder", f.folderID, "scan due to folder error:", err)
return err
}
l.Debugln(f, "Scanning subdirectories")
if err := f.model.internalScanFolderSubdirs(f.folderID, subDirs); err != nil { if err := f.model.internalScanFolderSubdirs(f.folderID, subDirs); err != nil {
// Potentially sets the error twice, once in the scanner just // Potentially sets the error twice, once in the scanner just
// by doing a check, and once here, if the error returned is // by doing a check, and once here, if the error returned is

View File

@@ -26,11 +26,11 @@ type sendOnlyFolder struct {
func newSendOnlyFolder(model *Model, cfg config.FolderConfiguration, _ versioner.Versioner, _ *fs.MtimeFS) service { func newSendOnlyFolder(model *Model, cfg config.FolderConfiguration, _ versioner.Versioner, _ *fs.MtimeFS) service {
return &sendOnlyFolder{ return &sendOnlyFolder{
folder: folder{ folder: folder{
stateTracker: newStateTracker(cfg.ID), stateTracker: newStateTracker(cfg.ID),
scan: newFolderScanner(cfg), scan: newFolderScanner(cfg),
stop: make(chan struct{}), stop: make(chan struct{}),
model: model, model: model,
initialScanCompleted: make(chan struct{}), initialScanFinished: make(chan struct{}),
}, },
FolderConfiguration: cfg, FolderConfiguration: cfg,
} }
@@ -50,29 +50,18 @@ func (f *sendOnlyFolder) Serve() {
return return
case <-f.scan.timer.C: case <-f.scan.timer.C:
if err := f.model.CheckFolderHealth(f.folderID); err != nil { l.Debugln(f, "Scanning subdirectories")
l.Infoln("Skipping scan of", f.Description(), "due to folder error:", err) err := f.scanSubdirs(nil)
f.scan.Reschedule()
continue
}
l.Debugln(f, "rescan")
if err := f.model.internalScanFolderSubdirs(f.folderID, 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
// duplicate set is handled by setError.
f.setError(err)
f.scan.Reschedule()
continue
}
select { select {
case <-f.initialScanCompleted: case <-f.initialScanFinished:
default: default:
l.Infoln("Completed initial scan (ro) of", f.Description()) status := "Completed"
close(f.initialScanCompleted) if err != nil {
status = "Failed"
}
l.Infoln(status, "initial scan (ro) of", f.Description())
close(f.initialScanFinished)
} }
if f.scan.HasNoInterval() { if f.scan.HasNoInterval() {
@@ -82,7 +71,7 @@ func (f *sendOnlyFolder) Serve() {
f.scan.Reschedule() f.scan.Reschedule()
case req := <-f.scan.now: case req := <-f.scan.now:
req.err <- f.scanSubdirsIfHealthy(req.subdirs) req.err <- f.scanSubdirs(req.subdirs)
case next := <-f.scan.delay: case next := <-f.scan.delay:
f.scan.timer.Reset(next) f.scan.timer.Reset(next)

View File

@@ -101,11 +101,11 @@ type sendReceiveFolder struct {
func newSendReceiveFolder(model *Model, cfg config.FolderConfiguration, ver versioner.Versioner, mtimeFS *fs.MtimeFS) service { func newSendReceiveFolder(model *Model, cfg config.FolderConfiguration, ver versioner.Versioner, mtimeFS *fs.MtimeFS) service {
f := &sendReceiveFolder{ f := &sendReceiveFolder{
folder: folder{ folder: folder{
stateTracker: newStateTracker(cfg.ID), stateTracker: newStateTracker(cfg.ID),
scan: newFolderScanner(cfg), scan: newFolderScanner(cfg),
stop: make(chan struct{}), stop: make(chan struct{}),
model: model, model: model,
initialScanCompleted: make(chan struct{}), initialScanFinished: make(chan struct{}),
}, },
FolderConfiguration: cfg, FolderConfiguration: cfg,
@@ -181,7 +181,7 @@ func (f *sendReceiveFolder) Serve() {
case <-f.pullTimer.C: case <-f.pullTimer.C:
select { select {
case <-f.initialScanCompleted: case <-f.initialScanFinished:
default: default:
// We don't start pulling files until a scan has been completed. // We don't start pulling files until a scan has been completed.
l.Debugln(f, "skip (initial)") l.Debugln(f, "skip (initial)")
@@ -275,20 +275,22 @@ func (f *sendReceiveFolder) Serve() {
// this is the easiest way to make sure we are not doing both at the // this is the easiest way to make sure we are not doing both at the
// same time. // same time.
case <-f.scan.timer.C: case <-f.scan.timer.C:
err := f.scanSubdirsIfHealthy(nil) l.Debugln(f, "Scanning subdirectories")
err := f.scanSubdirs(nil)
f.scan.Reschedule() f.scan.Reschedule()
if err != nil {
continue
}
select { select {
case <-f.initialScanCompleted: case <-f.initialScanFinished:
default: default:
l.Infoln("Completed initial scan (rw) of", f.Description()) close(f.initialScanFinished)
close(f.initialScanCompleted) status := "Completed"
if err != nil {
status = "Failed"
}
l.Infoln(status, "initial scan (rw) of", f.Description())
} }
case req := <-f.scan.now: case req := <-f.scan.now:
req.err <- f.scanSubdirsIfHealthy(req.subdirs) req.err <- f.scanSubdirs(req.subdirs)
case next := <-f.scan.delay: case next := <-f.scan.delay:
f.scan.timer.Reset(next) f.scan.timer.Reset(next)

View File

@@ -80,9 +80,9 @@ func setUpModel(file protocol.FileInfo) *Model {
func setUpSendReceiveFolder(model *Model) *sendReceiveFolder { func setUpSendReceiveFolder(model *Model) *sendReceiveFolder {
f := &sendReceiveFolder{ f := &sendReceiveFolder{
folder: folder{ folder: folder{
stateTracker: newStateTracker("default"), stateTracker: newStateTracker("default"),
model: model, model: model,
initialScanCompleted: make(chan struct{}), initialScanFinished: make(chan struct{}),
}, },
mtimeFS: fs.NewMtimeFS(fs.DefaultFilesystem, db.NewNamespacedKV(model.db, "mtime")), mtimeFS: fs.NewMtimeFS(fs.DefaultFilesystem, db.NewNamespacedKV(model.db, "mtime")),
@@ -93,7 +93,7 @@ func setUpSendReceiveFolder(model *Model) *sendReceiveFolder {
} }
// Folders are never actually started, so no initial scan will be done // Folders are never actually started, so no initial scan will be done
close(f.initialScanCompleted) close(f.initialScanFinished)
return f return f
} }