lib/model: Do Revert/Override synchronously (#6460)

This commit is contained in:
Simon Frei 2020-03-27 13:05:09 +01:00 committed by GitHub
parent c7cf3ef899
commit 79a758be3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 13 deletions

View File

@ -50,7 +50,6 @@ type folder struct {
scanInterval time.Duration
scanTimer *time.Timer
scanNow chan rescanRequest
scanDelay chan time.Duration
initialScanFinished chan struct{}
scanErrors []FileError
@ -58,6 +57,8 @@ type folder struct {
pullScheduled chan struct{}
doInSyncChan chan syncRequest
watchCancel context.CancelFunc
watchChan chan []string
restartWatchChan chan struct{}
@ -67,8 +68,8 @@ type folder struct {
puller puller
}
type rescanRequest struct {
subdirs []string
type syncRequest struct {
fn func() error
err chan error
}
@ -90,13 +91,14 @@ func newFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg conf
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{}),
scanErrorsMut: sync.NewMutex(),
pullScheduled: make(chan struct{}, 1), // This needs to be 1-buffered so that we queue a pull if we're busy when it comes.
doInSyncChan: make(chan syncRequest),
watchCancel: func() {},
restartWatchChan: make(chan struct{}, 1),
watchMut: sync.NewMutex(),
@ -172,9 +174,9 @@ func (f *folder) serve(ctx context.Context) {
l.Debugln(f, "Scanning due to timer")
f.scanTimerFired()
case req := <-f.scanNow:
l.Debugln(f, "Scanning due to request")
req.err <- f.scanSubdirs(req.subdirs)
case req := <-f.doInSyncChan:
l.Debugln(f, "Running something due to request")
req.err <- req.fn()
case next := <-f.scanDelay:
l.Debugln(f, "Delaying scan")
@ -224,13 +226,19 @@ func (f *folder) Jobs(_, _ int) ([]string, []string, int) {
func (f *folder) Scan(subdirs []string) error {
<-f.initialScanFinished
req := rescanRequest{
subdirs: subdirs,
err: make(chan error),
return f.doInSync(func() error { return f.scanSubdirs(subdirs) })
}
// doInSync allows to run functions synchronously in folder.serve from exported,
// asynchronously called methods.
func (f *folder) doInSync(fn func() error) error {
req := syncRequest{
fn: fn,
err: make(chan error, 1),
}
select {
case f.scanNow <- req:
case f.doInSyncChan <- req:
return <-req.err
case <-f.ctx.Done():
return f.ctx.Err()

View File

@ -64,6 +64,10 @@ func newReceiveOnlyFolder(model *model, fset *db.FileSet, ignores *ignore.Matche
}
func (f *receiveOnlyFolder) Revert() {
f.doInSync(func() error { f.revert(); return nil })
}
func (f *receiveOnlyFolder) revert() {
l.Infof("Reverting folder %v", f.Description)
f.setState(FolderScanning)

View File

@ -97,9 +97,15 @@ func (f *sendOnlyFolder) pull() bool {
}
func (f *sendOnlyFolder) Override() {
f.doInSync(func() error { f.override(); return nil })
}
func (f *sendOnlyFolder) override() {
l.Infof("Overriding global state on folder %v", f.Description)
f.setState(FolderScanning)
defer f.setState(FolderIdle)
batch := make([]protocol.FileInfo, 0, maxBatchSizeFiles)
batchSizeBytes := 0
snap := f.fset.Snapshot()
@ -134,5 +140,4 @@ func (f *sendOnlyFolder) Override() {
if len(batch) > 0 {
f.updateLocalsFromScanning(batch)
}
f.setState(FolderIdle)
}