From 876dda83f2ff9f4dddf06733d5d14d38ab8f320a Mon Sep 17 00:00:00 2001 From: Deluan Date: Wed, 21 Jul 2021 22:17:37 -0400 Subject: [PATCH] Reduce number of calls to `lstat`. Should make the scanner a bit faster, specially in networked filesystems --- scanner/tag_scanner.go | 44 ++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/scanner/tag_scanner.go b/scanner/tag_scanner.go index 2f8dabeff..598a132b4 100644 --- a/scanner/tag_scanner.go +++ b/scanner/tag_scanner.go @@ -2,6 +2,7 @@ package scanner import ( "context" + "io/fs" "os" "path/filepath" "sort" @@ -249,7 +250,7 @@ func (s *TagScanner) processChangedDir(ctx context.Context, dir string, fullScan currentTracks[t.Path] = t } - // Load tracks FileInfo from the folder + // Load track list from the folder files, err := loadAllAudioFiles(dir) if err != nil { return err @@ -268,15 +269,21 @@ func (s *TagScanner) processChangedDir(ctx context.Context, dir string, fullScan // If track from folder is newer than the one in DB, select for update/insert in DB log.Trace(ctx, "Processing changed folder", "dir", dir, "tracksInDB", len(currentTracks), "tracksInFolder", len(files)) var filesToUpdate []string - for filePath, info := range files { - c, ok := currentTracks[filePath] - if !ok { + for filePath, entry := range files { + c, inDB := currentTracks[filePath] + if !inDB || fullScan { filesToUpdate = append(filesToUpdate, filePath) s.cnt.added++ - } - if ok && (info.ModTime().After(c.UpdatedAt) || fullScan) { - filesToUpdate = append(filesToUpdate, filePath) - s.cnt.updated++ + } else { + info, err := entry.Info() + if err != nil { + log.Error("Could not stat file", "filePath", filePath, err) + continue + } + if info.ModTime().After(c.UpdatedAt) { + filesToUpdate = append(filesToUpdate, filePath) + s.cnt.updated++ + } } // Force a refresh of the album and artist, to cater for cover art files @@ -311,7 +318,7 @@ func (s *TagScanner) processChangedDir(ctx context.Context, dir string, fullScan err = buffer.flush() log.Info(ctx, "Finished processing changed folder", "dir", dir, "updated", numUpdatedTracks, - "purged", numPurgedTracks, "elapsed", time.Since(start)) + "deleted", numPurgedTracks, "elapsed", time.Since(start)) return err } @@ -393,16 +400,12 @@ func (s *TagScanner) withAdminUser(ctx context.Context) context.Context { return request.WithUser(ctx, *u) } -func loadAllAudioFiles(dirPath string) (map[string]os.FileInfo, error) { - dir, err := os.Open(dirPath) +func loadAllAudioFiles(dirPath string) (map[string]fs.DirEntry, error) { + files, err := fs.ReadDir(os.DirFS(dirPath), ".") if err != nil { return nil, err } - files, err := dir.Readdir(-1) - if err != nil { - return nil, err - } - audioFiles := make(map[string]os.FileInfo) + fileInfos := make(map[string]fs.DirEntry) for _, f := range files { if f.IsDir() { continue @@ -414,13 +417,8 @@ func loadAllAudioFiles(dirPath string) (map[string]os.FileInfo, error) { if !utils.IsAudioFile(filePath) { continue } - fi, err := os.Stat(filePath) - if err != nil { - log.Error("Could not stat file", "filePath", filePath, err) - } else { - audioFiles[filePath] = fi - } + fileInfos[filePath] = f } - return audioFiles, nil + return fileInfos, nil }