Explore files in the filesystem with a single stat for each file

This commit is contained in:
emeric
2025-07-07 23:07:51 +02:00
parent 49afdb3db6
commit 1800aaf32e
6 changed files with 32 additions and 107 deletions
@@ -379,7 +379,7 @@ namespace lms::scanner
return db::Advisory::UnSet;
}
db::Track::pointer findMovedTrackBySizeAndMetaData(db::Session& session, const metadata::Track& parsedTrack, size_t fileSize, const std::filesystem::path& relativePath)
db::Track::pointer findMovedTrackBySizeAndMetaData(db::Session& session, const metadata::Track& parsedTrack, const std::filesystem::path& trackPath, size_t fileSize)
{
db::Track::FindParameters params;
// Add as many fields as possible to limit errors
@@ -405,7 +405,7 @@ namespace lms::scanner
if (res)
{
LMS_LOG(DBUPDATER, DEBUG, "Found too many candidates for file move. New file = " << relativePath << ", candidate = " << track->getAbsoluteFilePath() << ", previous candidate = " << res->getAbsoluteFilePath());
LMS_LOG(DBUPDATER, DEBUG, "Found too many candidates for file move. New file = " << trackPath << ", candidate = " << track->getAbsoluteFilePath() << ", previous candidate = " << res->getAbsoluteFilePath());
error = true;
}
res = track;
@@ -598,7 +598,7 @@ namespace lms::scanner
if (!track)
{
// maybe the file just moved?
track = findMovedTrackBySizeAndMetaData(dbSession, *_parsedTrack, getFileSize(), getRelativeFilePath());
track = findMovedTrackBySizeAndMetaData(dbSession, *_parsedTrack, getFilePath(), getFileSize());
if (track)
{
LMS_LOG(DBUPDATER, DEBUG, "Considering track " << getFilePath() << " moved from " << track->getAbsoluteFilePath());
@@ -50,7 +50,6 @@ namespace lms::scanner
const ScannerSettings& getScannerSettings() const { return _settings; }
Wt::WDateTime getLastWriteTime() const { return _file.lastWriteTime; }
std::size_t getFileSize() const { return _file.fileSize; }
const std::filesystem::path& getRelativeFilePath() const { return _file.relativePath; }
template<typename T, typename... CtrArgs>
void addError(CtrArgs&&... args)
@@ -30,7 +30,6 @@ namespace lms::scanner
struct FileToScan
{
std::filesystem::path filePath;
std::filesystem::path relativePath;
MediaLibraryInfo mediaLibrary;
Wt::WDateTime lastWriteTime;
std::size_t fileSize{};
@@ -66,23 +66,6 @@ namespace lms::scanner
std::unique_ptr<IFileScanOperation> _scanOperation;
};
FileToScan retrieveFileInfo(const std::filesystem::path& file, const MediaLibraryInfo& mediaLibrary, std::error_code& ec)
{
FileToScan res;
const core::pathUtils::FileInfo fileInfo{ core::pathUtils::getFileInfo(file, ec) };
if (!ec)
{
res.filePath = file;
res.mediaLibrary = mediaLibrary;
res.relativePath = std::filesystem::relative(file, mediaLibrary.rootDirectory, ec);
res.lastWriteTime = fileInfo.lastWriteTime;
res.fileSize = fileInfo.fileSize;
}
return res;
}
} // namespace
ScanStepScanFiles::ScanStepScanFiles(InitParams& initParams)
@@ -126,9 +109,11 @@ namespace lms::scanner
std::vector<std::unique_ptr<IFileScanOperation>> scanOperations;
core::pathUtils::exploreFilesRecursive(
mediaLibrary.rootDirectory, [&](std::error_code ec, const std::filesystem::path& path) {
mediaLibrary.rootDirectory, [&](std::error_code ec, const std::filesystem::path& path, const core::pathUtils::FileInfo* fileInfo) {
LMS_SCOPED_TRACE_DETAILED("Scanner", "OnExploreFile");
assert((ec && !fileInfo) || (!ec && fileInfo));
if (_abortScan)
return false; // stop iterating
@@ -139,19 +124,17 @@ namespace lms::scanner
}
else if (IFileScanner * scanner{ selectFileScanner(path) })
{
FileToScan fileToScan{ retrieveFileInfo(path, mediaLibrary, ec) };
if (ec)
FileToScan fileToScan;
fileToScan.filePath = path;
fileToScan.mediaLibrary = mediaLibrary;
fileToScan.lastWriteTime.setTime_t(fileInfo->lastWriteTime.toTime_t()); // sec resolution, as stored in the database
fileToScan.fileSize = fileInfo->fileSize;
if (context.scanOptions.fullScan || scanner->needsScan(fileToScan))
{
addError<IOScanError>(context, path, ec);
context.stats.skips++;
}
else
{
if (context.scanOptions.fullScan || scanner->needsScan(fileToScan))
{
auto scanOperation{ scanner->createScanOperation(std::move(fileToScan)) };
queue.push(std::make_unique<FileScanJob>(std::move(scanOperation)));
}
auto scanOperation{ scanner->createScanOperation(std::move(fileToScan)) };
queue.push(std::make_unique<FileScanJob>(std::move(scanOperation)));
}
context.currentStepStats.processedElems++;