Reduce number of calls to `lstat`.

Should make the scanner a bit faster, specially in networked filesystems
This commit is contained in:
Deluan 2021-07-21 22:17:37 -04:00
parent 86c0b422f6
commit 876dda83f2
1 changed files with 21 additions and 23 deletions

View File

@ -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
}