Browse Source

lib/model: Optimize rename detection in scanner (#7315)

Simon Frei 4 years ago
parent
commit
249bcb3a01
1 changed files with 15 additions and 6 deletions
  1. 15 6
      lib/model/folder.go

+ 15 - 6
lib/model/folder.go

@@ -549,7 +549,7 @@ func (f *folder) scanSubdirs(subDirs []string) error {
 	}
 
 	f.clearScanErrors(subDirs)
-	alreadyUsed := make(map[string]struct{})
+	alreadyUsedOrExisting := make(map[string]struct{})
 	for res := range fchan {
 		if res.Err != nil {
 			f.newScanError(res.Path, res.Err)
@@ -571,7 +571,7 @@ func (f *folder) scanSubdirs(subDirs []string) error {
 		switch f.Type {
 		case config.FolderTypeReceiveOnly, config.FolderTypeReceiveEncrypted:
 		default:
-			if nf, ok := f.findRename(snap, res.File, alreadyUsed); ok {
+			if nf, ok := f.findRename(snap, res.File, alreadyUsedOrExisting); ok {
 				batchAppend(nf, snap)
 				changes++
 			}
@@ -582,6 +582,10 @@ func (f *folder) scanSubdirs(subDirs []string) error {
 		return err
 	}
 
+	// Might have grown large, isn't used anymore and this function may keep
+	// running for some time.
+	alreadyUsedOrExisting = nil
+
 	if len(subDirs) == 0 {
 		// If we have no specific subdirectories to traverse, set it to one
 		// empty prefix so we traverse the entire folder contents once.
@@ -728,7 +732,7 @@ func (f *folder) scanSubdirs(subDirs []string) error {
 	return nil
 }
 
-func (f *folder) findRename(snap *db.Snapshot, file protocol.FileInfo, alreadyUsed map[string]struct{}) (protocol.FileInfo, bool) {
+func (f *folder) findRename(snap *db.Snapshot, file protocol.FileInfo, alreadyUsedOrExisting map[string]struct{}) (protocol.FileInfo, bool) {
 	if len(file.Blocks) == 0 || file.Size == 0 {
 		return protocol.FileInfo{}, false
 	}
@@ -745,7 +749,12 @@ func (f *folder) findRename(snap *db.Snapshot, file protocol.FileInfo, alreadyUs
 		default:
 		}
 
-		if _, ok := alreadyUsed[fi.Name]; ok {
+		if fi.Name == file.Name {
+			alreadyUsedOrExisting[fi.Name] = struct{}{}
+			return true
+		}
+
+		if _, ok := alreadyUsedOrExisting[fi.Name]; ok {
 			return true
 		}
 
@@ -764,12 +773,12 @@ func (f *folder) findRename(snap *db.Snapshot, file protocol.FileInfo, alreadyUs
 			return true
 		}
 
+		alreadyUsedOrExisting[fi.Name] = struct{}{}
+
 		if !osutil.IsDeleted(f.mtimefs, fi.Name) {
 			return true
 		}
 
-		alreadyUsed[fi.Name] = struct{}{}
-
 		nf = fi
 		nf.SetDeleted(f.shortID)
 		nf.LocalFlags = f.localFlags