| 465 | } |
| 466 | |
| 467 | func (f *folder) scanSubdirs(ctx context.Context, subDirs []string) error { |
| 468 | f.sl.DebugContext(ctx, "Scanning") |
| 469 | |
| 470 | oldHash := f.ignores.Hash() |
| 471 | |
| 472 | err := f.getHealthErrorAndLoadIgnores() |
| 473 | if err != nil { |
| 474 | return err |
| 475 | } |
| 476 | f.setError(ctx, nil) |
| 477 | |
| 478 | // Check on the way out if the ignore patterns changed as part of scanning |
| 479 | // this folder. If they did we should schedule a pull of the folder so that |
| 480 | // we request things we might have suddenly become unignored and so on. |
| 481 | defer func() { |
| 482 | if f.ignores.Hash() != oldHash { |
| 483 | f.sl.DebugContext(ctx, "Ignore patterns change detected while scanning; triggering puller") |
| 484 | f.ignoresUpdated() |
| 485 | f.SchedulePull() |
| 486 | } |
| 487 | }() |
| 488 | |
| 489 | f.setState(FolderScanWaiting) |
| 490 | defer f.setState(FolderIdle) |
| 491 | |
| 492 | if err := f.ioLimiter.TakeWithContext(ctx, 1); err != nil { |
| 493 | return err |
| 494 | } |
| 495 | defer f.ioLimiter.Give(1) |
| 496 | |
| 497 | metricFolderScans.WithLabelValues(f.ID).Inc() |
| 498 | scanCtx, cancel := context.WithCancel(ctx) |
| 499 | defer cancel() |
| 500 | go addTimeUntilCancelled(scanCtx, metricFolderScanSeconds.WithLabelValues(f.ID)) |
| 501 | |
| 502 | for i := range subDirs { |
| 503 | sub := osutil.NativeFilename(subDirs[i]) |
| 504 | |
| 505 | if sub == "" { |
| 506 | // A blank subdirs means to scan the entire folder. We can trim |
| 507 | // the subDirs list and go on our way. |
| 508 | subDirs = nil |
| 509 | break |
| 510 | } |
| 511 | |
| 512 | subDirs[i] = sub |
| 513 | } |
| 514 | |
| 515 | // Clean the list of subitems to ensure that we start at a known |
| 516 | // directory, and don't scan subdirectories of things we've already |
| 517 | // scanned. |
| 518 | subDirs = unifySubs(subDirs, func(file string) bool { |
| 519 | _, ok, err := f.db.GetDeviceFile(f.folderID, protocol.LocalDeviceID, file) |
| 520 | return err == nil && ok |
| 521 | }) |
| 522 | |
| 523 | f.setState(FolderScanning) |
| 524 | f.clearScanErrors(subDirs) |