+54
-6
@@ -59,6 +59,10 @@ type folder struct {
|
||||
|
||||
doInSyncChan chan syncRequest
|
||||
|
||||
forcedRescanRequested chan struct{}
|
||||
forcedRescanPaths map[string]struct{}
|
||||
forcedRescanPathsMut sync.Mutex
|
||||
|
||||
watchCancel context.CancelFunc
|
||||
watchChan chan []string
|
||||
restartWatchChan chan struct{}
|
||||
@@ -99,6 +103,10 @@ func newFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg conf
|
||||
|
||||
doInSyncChan: make(chan syncRequest),
|
||||
|
||||
forcedRescanRequested: make(chan struct{}, 1),
|
||||
forcedRescanPaths: make(map[string]struct{}),
|
||||
forcedRescanPathsMut: sync.NewMutex(),
|
||||
|
||||
watchCancel: func() {},
|
||||
restartWatchChan: make(chan struct{}, 1),
|
||||
watchMut: sync.NewMutex(),
|
||||
@@ -170,6 +178,9 @@ func (f *folder) serve(ctx context.Context) {
|
||||
pullFailTimer.Reset(pause)
|
||||
}
|
||||
|
||||
case <-f.forcedRescanRequested:
|
||||
f.handleForcedRescans()
|
||||
|
||||
case <-f.scanTimer.C:
|
||||
l.Debugln(f, "Scanning due to timer")
|
||||
f.scanTimerFired()
|
||||
@@ -841,13 +852,16 @@ func (f *folder) Errors() []FileError {
|
||||
return append([]FileError{}, f.scanErrors...)
|
||||
}
|
||||
|
||||
// ForceRescan marks the file such that it gets rehashed on next scan and then
|
||||
// immediately executes that scan.
|
||||
func (f *folder) ForceRescan(file protocol.FileInfo) error {
|
||||
file.SetMustRescan(f.shortID)
|
||||
f.fset.Update(protocol.LocalDeviceID, []protocol.FileInfo{file})
|
||||
// ScheduleForceRescan marks the file such that it gets rehashed on next scan, and schedules a scan.
|
||||
func (f *folder) ScheduleForceRescan(path string) {
|
||||
f.forcedRescanPathsMut.Lock()
|
||||
f.forcedRescanPaths[path] = struct{}{}
|
||||
f.forcedRescanPathsMut.Unlock()
|
||||
|
||||
return f.Scan([]string{file.Name})
|
||||
select {
|
||||
case f.forcedRescanRequested <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
func (f *folder) updateLocalsFromScanning(fs []protocol.FileInfo) {
|
||||
@@ -921,6 +935,40 @@ func (f *folder) emitDiskChangeEvents(fs []protocol.FileInfo, typeOfEvent events
|
||||
}
|
||||
}
|
||||
|
||||
func (f *folder) handleForcedRescans() {
|
||||
f.forcedRescanPathsMut.Lock()
|
||||
paths := make([]string, 0, len(f.forcedRescanPaths))
|
||||
for path := range f.forcedRescanPaths {
|
||||
paths = append(paths, path)
|
||||
}
|
||||
f.forcedRescanPaths = make(map[string]struct{})
|
||||
f.forcedRescanPathsMut.Unlock()
|
||||
|
||||
batch := newFileInfoBatch(func(fs []protocol.FileInfo) error {
|
||||
f.fset.Update(protocol.LocalDeviceID, fs)
|
||||
return nil
|
||||
})
|
||||
|
||||
snap := f.fset.Snapshot()
|
||||
|
||||
for _, path := range paths {
|
||||
_ = batch.flushIfFull()
|
||||
|
||||
fi, ok := snap.Get(protocol.LocalDeviceID, path)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
fi.SetMustRescan(f.shortID)
|
||||
batch.append(fi)
|
||||
}
|
||||
|
||||
snap.Release()
|
||||
|
||||
_ = batch.flush()
|
||||
|
||||
_ = f.scanSubdirs(paths)
|
||||
}
|
||||
|
||||
// The exists function is expected to return true for all known paths
|
||||
// (excluding "" and ".")
|
||||
func unifySubs(dirs []string, exists func(dir string) bool) []string {
|
||||
|
||||
Reference in New Issue
Block a user