Auto reformatted the base, ref #470
This commit is contained in:
@@ -43,4 +43,4 @@ namespace lms::scanner
|
||||
};
|
||||
virtual void process(ScanContext& context) = 0;
|
||||
};
|
||||
}
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -22,40 +22,42 @@
|
||||
#include <functional>
|
||||
|
||||
#include "services/scanner/ScannerStats.hpp"
|
||||
|
||||
#include "IScanStep.hpp"
|
||||
#include "ScannerSettings.hpp"
|
||||
|
||||
namespace lms::db
|
||||
{
|
||||
class Db;
|
||||
class Db;
|
||||
}
|
||||
|
||||
namespace lms::scanner
|
||||
{
|
||||
class ScanStepBase : public IScanStep
|
||||
{
|
||||
public:
|
||||
static inline const std::filesystem::path excludeDirFileName {".lmsignore"};
|
||||
using ProgressCallback = std::function<void(const ScanStepStats& stats)>;
|
||||
class ScanStepBase : public IScanStep
|
||||
{
|
||||
public:
|
||||
static inline const std::filesystem::path excludeDirFileName{ ".lmsignore" };
|
||||
using ProgressCallback = std::function<void(const ScanStepStats& stats)>;
|
||||
|
||||
struct InitParams
|
||||
{
|
||||
const ScannerSettings& settings;
|
||||
ProgressCallback progressCallback;
|
||||
bool& abortScan;
|
||||
db::Db& db;
|
||||
};
|
||||
ScanStepBase(InitParams& initParams)
|
||||
: _settings {initParams.settings}
|
||||
, _progressCallback {initParams.progressCallback}
|
||||
, _abortScan {initParams.abortScan}
|
||||
, _db {initParams.db}
|
||||
{}
|
||||
struct InitParams
|
||||
{
|
||||
const ScannerSettings& settings;
|
||||
ProgressCallback progressCallback;
|
||||
bool& abortScan;
|
||||
db::Db& db;
|
||||
};
|
||||
ScanStepBase(InitParams& initParams)
|
||||
: _settings{ initParams.settings }
|
||||
, _progressCallback{ initParams.progressCallback }
|
||||
, _abortScan{ initParams.abortScan }
|
||||
, _db{ initParams.db }
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
const ScannerSettings& _settings;
|
||||
ProgressCallback _progressCallback;
|
||||
bool& _abortScan;
|
||||
db::Db& _db;
|
||||
};
|
||||
}
|
||||
protected:
|
||||
const ScannerSettings& _settings;
|
||||
ProgressCallback _progressCallback;
|
||||
bool& _abortScan;
|
||||
db::Db& _db;
|
||||
};
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
|
||||
#include "ScanStepCheckDuplicatedDbFiles.hpp"
|
||||
|
||||
#include "core/ILogger.hpp"
|
||||
#include "database/Db.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "database/Track.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
|
||||
namespace lms::scanner
|
||||
{
|
||||
@@ -33,8 +33,8 @@ namespace lms::scanner
|
||||
if (_abortScan)
|
||||
return;
|
||||
|
||||
Session& session {_db.getTLSSession()};
|
||||
auto transaction {session.createReadTransaction()};
|
||||
Session& session{ _db.getTLSSession() };
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
|
||||
const RangeResults<TrackId> tracks = Track::findIdsTrackMBIDDuplicates(session);
|
||||
for (const TrackId trackId : tracks.results)
|
||||
@@ -54,4 +54,4 @@ namespace lms::scanner
|
||||
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Found " << context.currentStepStats.processedElems << " duplicated audio files");
|
||||
}
|
||||
}
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
|
||||
namespace lms::scanner
|
||||
{
|
||||
class ScanStepCheckDuplicatedDbFiles : public ScanStepBase
|
||||
{
|
||||
public:
|
||||
using ScanStepBase::ScanStepBase;
|
||||
class ScanStepCheckDuplicatedDbFiles : public ScanStepBase
|
||||
{
|
||||
public:
|
||||
using ScanStepBase::ScanStepBase;
|
||||
|
||||
private:
|
||||
core::LiteralString getStepName() const override { return "Check for duplicated files"; }
|
||||
ScanStep getStep() const override { return ScanStep::CheckForDuplicateFiles; }
|
||||
void process(ScanContext& context) override;
|
||||
};
|
||||
}
|
||||
private:
|
||||
core::LiteralString getStepName() const override { return "Check for duplicated files"; }
|
||||
ScanStep getStep() const override { return ScanStep::CheckForDuplicateFiles; }
|
||||
void process(ScanContext& context) override;
|
||||
};
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -30,4 +30,4 @@ namespace lms::scanner
|
||||
if (context.scanOptions.compact)
|
||||
_db.getTLSSession().vacuum();
|
||||
}
|
||||
}
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
|
||||
namespace lms::scanner
|
||||
{
|
||||
class ScanStepCompact : public ScanStepBase
|
||||
{
|
||||
public:
|
||||
using ScanStepBase::ScanStepBase;
|
||||
class ScanStepCompact : public ScanStepBase
|
||||
{
|
||||
public:
|
||||
using ScanStepBase::ScanStepBase;
|
||||
|
||||
private:
|
||||
ScanStep getStep() const override { return ScanStep::Compact; }
|
||||
core::LiteralString getStepName() const override { return "Compact"; }
|
||||
void process(ScanContext& context) override;
|
||||
};
|
||||
}
|
||||
private:
|
||||
ScanStep getStep() const override { return ScanStep::Compact; }
|
||||
core::LiteralString getStepName() const override { return "Compact"; }
|
||||
void process(ScanContext& context) override;
|
||||
};
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
*/
|
||||
|
||||
#include "ScanStepComputeClusterStats.hpp"
|
||||
#include "database/Db.hpp"
|
||||
#include "database/Cluster.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
#include "core/Path.hpp"
|
||||
#include "database/Cluster.hpp"
|
||||
#include "database/Db.hpp"
|
||||
#include "database/Session.hpp"
|
||||
|
||||
namespace lms::scanner
|
||||
{
|
||||
@@ -38,53 +38,51 @@ namespace lms::scanner
|
||||
const std::size_t clusterCount{ [&] {
|
||||
auto transaction{ dbSession.createReadTransaction() };
|
||||
return Cluster::getCount(dbSession);
|
||||
}() };
|
||||
}() };
|
||||
|
||||
context.currentStepStats.totalElems = clusterCount;
|
||||
|
||||
foreachSubRange(Range{ 0, clusterCount }, 100, [&](Range range)
|
||||
foreachSubRange(Range{ 0, clusterCount }, 100, [&](Range range) {
|
||||
const std::vector<ClusterId> clusterIds{ [&] {
|
||||
Cluster::FindParameters params;
|
||||
params.setRange(range);
|
||||
|
||||
{
|
||||
auto transaction{ dbSession.createReadTransaction() };
|
||||
return std::move(Cluster::findIds(dbSession, params).results);
|
||||
}
|
||||
}() };
|
||||
|
||||
for (const ClusterId clusterId : clusterIds)
|
||||
{
|
||||
const std::vector<ClusterId> clusterIds{ [&]
|
||||
if (_abortScan)
|
||||
break;
|
||||
|
||||
std::size_t trackCount;
|
||||
std::size_t releaseCount;
|
||||
|
||||
{
|
||||
Cluster::FindParameters params;
|
||||
params.setRange(range);
|
||||
auto transaction{ dbSession.createReadTransaction() };
|
||||
|
||||
{
|
||||
auto transaction{ dbSession.createReadTransaction() };
|
||||
return std::move(Cluster::findIds(dbSession, params).results);
|
||||
}
|
||||
}() };
|
||||
|
||||
for (const ClusterId clusterId : clusterIds)
|
||||
{
|
||||
if (_abortScan)
|
||||
break;
|
||||
|
||||
std::size_t trackCount;
|
||||
std::size_t releaseCount;
|
||||
|
||||
{
|
||||
auto transaction{ dbSession.createReadTransaction() };
|
||||
|
||||
trackCount = Cluster::computeTrackCount(dbSession, clusterId);
|
||||
releaseCount = Cluster::computeReleaseCount(dbSession, clusterId);
|
||||
}
|
||||
|
||||
{
|
||||
auto transaction{ dbSession.createWriteTransaction() };
|
||||
|
||||
auto cluster{ Cluster::find(dbSession, clusterId) };
|
||||
cluster.modify()->setTrackCount(trackCount);
|
||||
cluster.modify()->setReleaseCount(releaseCount);
|
||||
}
|
||||
|
||||
context.currentStepStats.processedElems++;
|
||||
_progressCallback(context.currentStepStats);
|
||||
trackCount = Cluster::computeTrackCount(dbSession, clusterId);
|
||||
releaseCount = Cluster::computeReleaseCount(dbSession, clusterId);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
{
|
||||
auto transaction{ dbSession.createWriteTransaction() };
|
||||
|
||||
auto cluster{ Cluster::find(dbSession, clusterId) };
|
||||
cluster.modify()->setTrackCount(trackCount);
|
||||
cluster.modify()->setReleaseCount(releaseCount);
|
||||
}
|
||||
|
||||
context.currentStepStats.processedElems++;
|
||||
_progressCallback(context.currentStepStats);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Recomputed stats for " << context.currentStepStats.processedElems << " clusters!");
|
||||
}
|
||||
}
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -33,4 +33,4 @@ namespace lms::scanner
|
||||
core::LiteralString getStepName() const override { return "Compute cluster stats"; }
|
||||
void process(ScanContext& context) override;
|
||||
};
|
||||
}
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -31,8 +31,8 @@ namespace lms::scanner
|
||||
for (const ScannerSettings::MediaLibraryInfo& mediaLibrary : _settings.mediaLibraries)
|
||||
{
|
||||
std::size_t currentDirectoryProcessElemsCount{};
|
||||
core::pathUtils::exploreFilesRecursive(mediaLibrary.rootDirectory, [&](std::error_code ec, const std::filesystem::path& path)
|
||||
{
|
||||
core::pathUtils::exploreFilesRecursive(
|
||||
mediaLibrary.rootDirectory, [&](std::error_code ec, const std::filesystem::path& path) {
|
||||
if (_abortScan)
|
||||
return false;
|
||||
|
||||
@@ -44,7 +44,8 @@ namespace lms::scanner
|
||||
}
|
||||
|
||||
return true;
|
||||
}, &excludeDirFileName);
|
||||
},
|
||||
&excludeDirFileName);
|
||||
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Discovered " << currentDirectoryProcessElemsCount << " files in '" << mediaLibrary.rootDirectory << "'");
|
||||
}
|
||||
@@ -53,4 +54,4 @@ namespace lms::scanner
|
||||
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Discovered " << context.stats.filesScanned << " files in all directories");
|
||||
}
|
||||
}
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
|
||||
namespace lms::scanner
|
||||
{
|
||||
class ScanStepDiscoverFiles : public ScanStepBase
|
||||
{
|
||||
public:
|
||||
using ScanStepBase::ScanStepBase;
|
||||
class ScanStepDiscoverFiles : public ScanStepBase
|
||||
{
|
||||
public:
|
||||
using ScanStepBase::ScanStepBase;
|
||||
|
||||
private:
|
||||
ScanStep getStep() const override { return ScanStep::DiscoverFiles; }
|
||||
core::LiteralString getStepName() const override { return "Discover files"; }
|
||||
void process(ScanContext& context) override;
|
||||
};
|
||||
}
|
||||
private:
|
||||
ScanStep getStep() const override { return ScanStep::DiscoverFiles; }
|
||||
core::LiteralString getStepName() const override { return "Discover files"; }
|
||||
void process(ScanContext& context) override;
|
||||
};
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -53,4 +53,4 @@ namespace lms::scanner
|
||||
LMS_LOG(DBUPDATER, INFO, "Database analyze complete");
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
|
||||
namespace lms::scanner
|
||||
{
|
||||
class ScanStepOptimize : public ScanStepBase
|
||||
{
|
||||
public:
|
||||
using ScanStepBase::ScanStepBase;
|
||||
class ScanStepOptimize : public ScanStepBase
|
||||
{
|
||||
public:
|
||||
using ScanStepBase::ScanStepBase;
|
||||
|
||||
private:
|
||||
ScanStep getStep() const override { return ScanStep::Optimize; }
|
||||
core::LiteralString getStepName() const override { return "Optimize"; }
|
||||
void process(ScanContext& context) override;
|
||||
};
|
||||
}
|
||||
private:
|
||||
ScanStep getStep() const override { return ScanStep::Optimize; }
|
||||
core::LiteralString getStepName() const override { return "Optimize"; }
|
||||
void process(ScanContext& context) override;
|
||||
};
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
|
||||
#include "ScanStepRemoveOrphanDbFiles.hpp"
|
||||
|
||||
#include "core/ILogger.hpp"
|
||||
#include "core/Path.hpp"
|
||||
#include "database/Artist.hpp"
|
||||
#include "database/Cluster.hpp"
|
||||
#include "database/Db.hpp"
|
||||
#include "database/Release.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "database/Track.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
#include "core/Path.hpp"
|
||||
|
||||
namespace lms::scanner
|
||||
{
|
||||
@@ -36,7 +36,7 @@ namespace lms::scanner
|
||||
{
|
||||
constexpr std::size_t batchSize = 100;
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
void removeOrphanEntries(Session& session, bool& abortScan)
|
||||
{
|
||||
using IdType = typename T::IdType;
|
||||
@@ -68,7 +68,7 @@ namespace lms::scanner
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void ScanStepRemoveOrphanDbFiles::process(ScanContext& context)
|
||||
{
|
||||
@@ -110,15 +110,14 @@ namespace lms::scanner
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
|
||||
endReached = true;
|
||||
Track::find(session, lastCheckedTrackID, batchSize, [&](const Track::pointer& track)
|
||||
{
|
||||
endReached = false;
|
||||
Track::find(session, lastCheckedTrackID, batchSize, [&](const Track::pointer& track) {
|
||||
endReached = false;
|
||||
|
||||
if (!checkFile(track->getAbsoluteFilePath()))
|
||||
tracksToRemove.push_back(track);
|
||||
if (!checkFile(track->getAbsoluteFilePath()))
|
||||
tracksToRemove.push_back(track);
|
||||
|
||||
context.currentStepStats.processedElems++;
|
||||
});
|
||||
context.currentStepStats.processedElems++;
|
||||
});
|
||||
}
|
||||
|
||||
if (!tracksToRemove.empty())
|
||||
@@ -175,10 +174,9 @@ namespace lms::scanner
|
||||
}
|
||||
|
||||
if (std::none_of(std::cbegin(_settings.mediaLibraries), std::cend(_settings.mediaLibraries),
|
||||
[&](const ScannerSettings::MediaLibraryInfo& libraryInfo)
|
||||
{
|
||||
return core::pathUtils::isPathInRootPath(p, libraryInfo.rootDirectory, &excludeDirFileName);
|
||||
}))
|
||||
[&](const ScannerSettings::MediaLibraryInfo& libraryInfo) {
|
||||
return core::pathUtils::isPathInRootPath(p, libraryInfo.rootDirectory, &excludeDirFileName);
|
||||
}))
|
||||
{
|
||||
LMS_LOG(DBUPDATER, INFO, "Removing '" << p.string() << "': out of media directory");
|
||||
return false;
|
||||
@@ -198,4 +196,4 @@ namespace lms::scanner
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -25,21 +25,21 @@
|
||||
|
||||
namespace lms::scanner
|
||||
{
|
||||
class ScanStepRemoveOrphanDbFiles : public ScanStepBase
|
||||
{
|
||||
public:
|
||||
using ScanStepBase::ScanStepBase;
|
||||
class ScanStepRemoveOrphanDbFiles : public ScanStepBase
|
||||
{
|
||||
public:
|
||||
using ScanStepBase::ScanStepBase;
|
||||
|
||||
private:
|
||||
core::LiteralString getStepName() const override { return "Check orphaned entries"; }
|
||||
ScanStep getStep() const override { return ScanStep::CheckForMissingFiles; }
|
||||
void process(ScanContext& context) override;
|
||||
private:
|
||||
core::LiteralString getStepName() const override { return "Check orphaned entries"; }
|
||||
ScanStep getStep() const override { return ScanStep::CheckForMissingFiles; }
|
||||
void process(ScanContext& context) override;
|
||||
|
||||
void removeOrphanTracks(ScanContext& context);
|
||||
void removeOrphanClusters();
|
||||
void removeOrphanClusterTypes();
|
||||
void removeOrphanArtists();
|
||||
void removeOrphanReleases();
|
||||
bool checkFile(const std::filesystem::path& p);
|
||||
};
|
||||
}
|
||||
void removeOrphanTracks(ScanContext& context);
|
||||
void removeOrphanClusters();
|
||||
void removeOrphanClusterTypes();
|
||||
void removeOrphanArtists();
|
||||
void removeOrphanReleases();
|
||||
bool checkFile(const std::filesystem::path& p);
|
||||
};
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
|
||||
#include "ScanStepScanFiles.hpp"
|
||||
|
||||
#include "core/Exception.hpp"
|
||||
#include "core/IConfig.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
#include "core/ITraceLogger.hpp"
|
||||
#include "core/Path.hpp"
|
||||
#include "database/Artist.hpp"
|
||||
#include "database/Cluster.hpp"
|
||||
#include "database/Db.hpp"
|
||||
@@ -26,15 +31,10 @@
|
||||
#include "database/Release.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "database/Track.hpp"
|
||||
#include "database/TrackFeatures.hpp"
|
||||
#include "database/TrackArtistLink.hpp"
|
||||
#include "database/TrackFeatures.hpp"
|
||||
#include "metadata/Exception.hpp"
|
||||
#include "metadata/IParser.hpp"
|
||||
#include "core/Exception.hpp"
|
||||
#include "core/IConfig.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
#include "core/Path.hpp"
|
||||
#include "core/ITraceLogger.hpp"
|
||||
|
||||
namespace lms::scanner
|
||||
{
|
||||
@@ -249,8 +249,7 @@ namespace lms::scanner
|
||||
{
|
||||
std::vector<Cluster::pointer> clusters;
|
||||
|
||||
auto getOrCreateClusters{ [&](std::string tag, std::span<const std::string> values)
|
||||
{
|
||||
auto getOrCreateClusters{ [&](std::string tag, std::span<const std::string> values) {
|
||||
auto clusterType = ClusterType::find(session, tag);
|
||||
if (!clusterType)
|
||||
clusterType = session.create<ClusterType>(tag);
|
||||
@@ -306,7 +305,8 @@ namespace lms::scanner
|
||||
: _metadataParser{ parser }
|
||||
, _scanContextRunner{ _scanContext, threadCount, "ScannerMetadata" }
|
||||
, _abort{ abort }
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void ScanStepScanFiles::MetadataScanQueue::pushScanRequest(const std::filesystem::path& path)
|
||||
{
|
||||
@@ -315,38 +315,37 @@ namespace lms::scanner
|
||||
_ongoingScanCount += 1;
|
||||
}
|
||||
|
||||
_scanContext.post([=, this]
|
||||
_scanContext.post([=, this] {
|
||||
LMS_SCOPED_TRACE_OVERVIEW("Scanner", "AudioFileParseJob");
|
||||
|
||||
std::unique_ptr<metadata::Track> track;
|
||||
|
||||
if (_abort)
|
||||
{
|
||||
LMS_SCOPED_TRACE_OVERVIEW("Scanner", "AudioFileParseJob");
|
||||
std::scoped_lock lock{ _mutex };
|
||||
_ongoingScanCount -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
track = _metadataParser.parse(path);
|
||||
}
|
||||
catch (const metadata::Exception& e)
|
||||
{
|
||||
LMS_LOG(DBUPDATER, INFO, "Failed to parse '" << path.string() << "'");
|
||||
}
|
||||
|
||||
std::unique_ptr<metadata::Track> track;
|
||||
|
||||
if (_abort)
|
||||
{
|
||||
std::scoped_lock lock{ _mutex };
|
||||
|
||||
_scanResults.emplace_back(MetaDataScanResult{ std::move(path), std::move(track) });
|
||||
_ongoingScanCount -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
track = _metadataParser.parse(path);
|
||||
}
|
||||
catch (const metadata::Exception& e)
|
||||
{
|
||||
LMS_LOG(DBUPDATER, INFO, "Failed to parse '" << path.string() << "'");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::scoped_lock lock{ _mutex };
|
||||
|
||||
_scanResults.emplace_back(MetaDataScanResult{ std::move(path), std::move(track) });
|
||||
_ongoingScanCount -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
_condVar.notify_all();
|
||||
});
|
||||
_condVar.notify_all();
|
||||
});
|
||||
}
|
||||
|
||||
std::size_t ScanStepScanFiles::MetadataScanQueue::getResultsCount() const
|
||||
@@ -407,8 +406,8 @@ namespace lms::scanner
|
||||
|
||||
for (const ScannerSettings::MediaLibraryInfo& mediaLibrary : _settings.mediaLibraries)
|
||||
{
|
||||
core::pathUtils::exploreFilesRecursive(mediaLibrary.rootDirectory, [&](std::error_code ec, const std::filesystem::path& path)
|
||||
{
|
||||
core::pathUtils::exploreFilesRecursive(
|
||||
mediaLibrary.rootDirectory, [&](std::error_code ec, const std::filesystem::path& path) {
|
||||
LMS_SCOPED_TRACE_DETAILED("Scanner", "OnExploreFile");
|
||||
|
||||
if (_abortScan)
|
||||
@@ -437,7 +436,8 @@ namespace lms::scanner
|
||||
_metadataScanQueue.wait(scanQueueMaxScanRequestCount);
|
||||
|
||||
return true;
|
||||
}, &excludeDirFileName);
|
||||
},
|
||||
&excludeDirFileName);
|
||||
|
||||
_metadataScanQueue.wait();
|
||||
|
||||
@@ -469,8 +469,7 @@ namespace lms::scanner
|
||||
|
||||
if (track
|
||||
&& track->getLastWriteTime().toTime_t() == lastWriteTime.toTime_t()
|
||||
&& track->getScanVersion() == _settings.scanVersion
|
||||
)
|
||||
&& track->getScanVersion() == _settings.scanVersion)
|
||||
{
|
||||
// this file may have been moved from one library to another, then we just need to update the media library id instead of a full rescan
|
||||
const auto trackMediaLibrary{ track->getMediaLibrary() };
|
||||
@@ -568,10 +567,9 @@ namespace lms::scanner
|
||||
|
||||
// Skip if duplicate files no longer in media root: as it will be removed later, we will end up with no file
|
||||
if (std::none_of(std::cbegin(_settings.mediaLibraries), std::cend(_settings.mediaLibraries),
|
||||
[&](const ScannerSettings::MediaLibraryInfo& libraryInfo)
|
||||
{
|
||||
return core::pathUtils::isPathInRootPath(file, libraryInfo.rootDirectory, &excludeDirFileName);
|
||||
}))
|
||||
[&](const ScannerSettings::MediaLibraryInfo& libraryInfo) {
|
||||
return core::pathUtils::isPathInRootPath(file, libraryInfo.rootDirectory, &excludeDirFileName);
|
||||
}))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -723,4 +721,4 @@ namespace lms::scanner
|
||||
stats.updates++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -27,8 +27,9 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "metadata/IParser.hpp"
|
||||
#include "core/IOContextRunner.hpp"
|
||||
#include "metadata/IParser.hpp"
|
||||
|
||||
#include "ScanStepBase.hpp"
|
||||
|
||||
namespace lms::scanner
|
||||
@@ -52,36 +53,36 @@ namespace lms::scanner
|
||||
void processMetaDataScanResults(ScanContext& context, std::span<const MetaDataScanResult> scanResults, const ScannerSettings::MediaLibraryInfo& libraryInfo);
|
||||
void processFileMetaData(ScanContext& context, const std::filesystem::path& file, const metadata::Track& trackMetadata, const ScannerSettings::MediaLibraryInfo& libraryInfo);
|
||||
|
||||
std::unique_ptr<metadata::IParser> _metadataParser;
|
||||
const std::vector<std::string> _extraTagsToParse;
|
||||
std::unique_ptr<metadata::IParser> _metadataParser;
|
||||
const std::vector<std::string> _extraTagsToParse;
|
||||
|
||||
class MetadataScanQueue
|
||||
{
|
||||
public:
|
||||
MetadataScanQueue(metadata::IParser& parser, std::size_t threadCount, bool& abort);
|
||||
public:
|
||||
MetadataScanQueue(metadata::IParser& parser, std::size_t threadCount, bool& abort);
|
||||
|
||||
std::size_t getThreadCount() const { return _scanContextRunner.getThreadCount(); }
|
||||
std::size_t getThreadCount() const { return _scanContextRunner.getThreadCount(); }
|
||||
|
||||
void pushScanRequest(const std::filesystem::path& path);
|
||||
void pushScanRequest(const std::filesystem::path& path);
|
||||
|
||||
std::size_t getResultsCount() const;
|
||||
size_t popResults(std::vector<MetaDataScanResult>& results, std::size_t maxCount);
|
||||
std::size_t getResultsCount() const;
|
||||
size_t popResults(std::vector<MetaDataScanResult>& results, std::size_t maxCount);
|
||||
|
||||
void wait(std::size_t maxScanRequestCount = 0); // wait until ongoing scan request count <= maxScanRequestCount
|
||||
void wait(std::size_t maxScanRequestCount = 0); // wait until ongoing scan request count <= maxScanRequestCount
|
||||
|
||||
private:
|
||||
metadata::IParser& _metadataParser;
|
||||
boost::asio::io_context _scanContext;
|
||||
core::IOContextRunner _scanContextRunner;
|
||||
private:
|
||||
metadata::IParser& _metadataParser;
|
||||
boost::asio::io_context _scanContext;
|
||||
core::IOContextRunner _scanContextRunner;
|
||||
|
||||
mutable std::mutex _mutex ;
|
||||
std::size_t _ongoingScanCount{};
|
||||
std::deque<MetaDataScanResult> _scanResults;
|
||||
std::condition_variable _condVar;
|
||||
bool& _abort;
|
||||
mutable std::mutex _mutex;
|
||||
std::size_t _ongoingScanCount{};
|
||||
std::deque<MetaDataScanResult> _scanResults;
|
||||
std::condition_variable _condVar;
|
||||
bool& _abort;
|
||||
};
|
||||
MetadataScanQueue _metadataScanQueue;
|
||||
|
||||
std::deque<MetaDataScanResult> _metaDataScanResults;
|
||||
};
|
||||
}
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -21,14 +21,14 @@
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include "database/MediaLibrary.hpp"
|
||||
#include "database/TrackFeatures.hpp"
|
||||
#include "database/ScanSettings.hpp"
|
||||
#include "core/Exception.hpp"
|
||||
#include "core/Path.hpp"
|
||||
#include "core/IConfig.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
#include "core/ITraceLogger.hpp"
|
||||
#include "core/Path.hpp"
|
||||
#include "database/MediaLibrary.hpp"
|
||||
#include "database/ScanSettings.hpp"
|
||||
#include "database/TrackFeatures.hpp"
|
||||
|
||||
#include "ScanStepCheckDuplicatedDbFiles.hpp"
|
||||
#include "ScanStepCompact.hpp"
|
||||
@@ -91,13 +91,12 @@ namespace lms::scanner
|
||||
{
|
||||
std::scoped_lock lock{ _controlMutex };
|
||||
|
||||
_ioService.post([this]
|
||||
{
|
||||
if (_abortScan)
|
||||
return;
|
||||
_ioService.post([this] {
|
||||
if (_abortScan)
|
||||
return;
|
||||
|
||||
scheduleNextScan();
|
||||
});
|
||||
scheduleNextScan();
|
||||
});
|
||||
|
||||
_ioService.start();
|
||||
}
|
||||
@@ -139,25 +138,23 @@ namespace lms::scanner
|
||||
void ScannerService::requestImmediateScan(const ScanOptions& scanOptions)
|
||||
{
|
||||
abortScan();
|
||||
_ioService.post([this, scanOptions]
|
||||
{
|
||||
if (_abortScan)
|
||||
return;
|
||||
_ioService.post([this, scanOptions] {
|
||||
if (_abortScan)
|
||||
return;
|
||||
|
||||
scheduleScan(scanOptions);
|
||||
});
|
||||
scheduleScan(scanOptions);
|
||||
});
|
||||
}
|
||||
|
||||
void ScannerService::requestReload()
|
||||
{
|
||||
abortScan();
|
||||
_ioService.post([this]()
|
||||
{
|
||||
if (_abortScan)
|
||||
return;
|
||||
_ioService.post([this]() {
|
||||
if (_abortScan)
|
||||
return;
|
||||
|
||||
scheduleNextScan();
|
||||
});
|
||||
scheduleNextScan();
|
||||
});
|
||||
}
|
||||
|
||||
ScannerService::Status ScannerService::getStatus() const
|
||||
@@ -229,8 +226,7 @@ namespace lms::scanner
|
||||
|
||||
void ScannerService::scheduleScan(const ScanOptions& scanOptions, const Wt::WDateTime& dateTime)
|
||||
{
|
||||
auto cb{ [this, scanOptions](boost::system::error_code ec)
|
||||
{
|
||||
auto cb{ [this, scanOptions](boost::system::error_code ec) {
|
||||
if (ec)
|
||||
return;
|
||||
|
||||
@@ -270,7 +266,7 @@ namespace lms::scanner
|
||||
|
||||
refreshScanSettings();
|
||||
|
||||
IScanStep::ScanContext scanContext{ scanOptions, ScanStats {}, ScanStepStats {} };
|
||||
IScanStep::ScanContext scanContext{ scanOptions, ScanStats{}, ScanStepStats{} };
|
||||
ScanStats& stats{ scanContext.stats };
|
||||
stats.startTime = Wt::WDateTime::currentDateTime();
|
||||
|
||||
@@ -329,13 +325,11 @@ namespace lms::scanner
|
||||
|
||||
_settings = std::move(newSettings);
|
||||
|
||||
auto cbFunc{ [this](const ScanStepStats& stats)
|
||||
{
|
||||
notifyInProgressIfNeeded(stats);
|
||||
} };
|
||||
auto cbFunc{ [this](const ScanStepStats& stats) {
|
||||
notifyInProgressIfNeeded(stats);
|
||||
} };
|
||||
|
||||
ScanStepBase::InitParams params
|
||||
{
|
||||
ScanStepBase::InitParams params{
|
||||
_settings,
|
||||
cbFunc,
|
||||
_abortScan,
|
||||
@@ -373,14 +367,13 @@ namespace lms::scanner
|
||||
[](const std::filesystem::path& extension) { return std::filesystem::path{ core::stringUtils::stringToLower(extension.string()) }; });
|
||||
}
|
||||
|
||||
MediaLibrary::find(_db.getTLSSession(), [&](const MediaLibrary::pointer& mediaLibrary)
|
||||
{
|
||||
newSettings.mediaLibraries.push_back(ScannerSettings::MediaLibraryInfo{ mediaLibrary->getId(), mediaLibrary->getPath().lexically_normal() });
|
||||
});
|
||||
MediaLibrary::find(_db.getTLSSession(), [&](const MediaLibrary::pointer& mediaLibrary) {
|
||||
newSettings.mediaLibraries.push_back(ScannerSettings::MediaLibraryInfo{ mediaLibrary->getId(), mediaLibrary->getPath().lexically_normal() });
|
||||
});
|
||||
|
||||
{
|
||||
const auto& tags{ scanSettings->getExtraTagsToScan() };
|
||||
std::transform(std::cbegin(tags), std::cend(tags), std::back_inserter(newSettings.extraTags), [](std::string_view tag) { return std::string{ tag };});
|
||||
std::transform(std::cbegin(tags), std::cend(tags), std::back_inserter(newSettings.extraTags), [](std::string_view tag) { return std::string{ tag }; });
|
||||
}
|
||||
|
||||
newSettings.artistTagDelimiters = scanSettings->getArtistTagDelimiters();
|
||||
|
||||
@@ -20,23 +20,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <shared_mutex>
|
||||
#include <optional>
|
||||
#include <shared_mutex>
|
||||
#include <vector>
|
||||
|
||||
#include <Wt/WDateTime.h>
|
||||
#include <Wt/WIOService.h>
|
||||
#include <Wt/WSignal.h>
|
||||
|
||||
#include <boost/asio/system_timer.hpp>
|
||||
|
||||
#include "IScanStep.hpp"
|
||||
#include "ScannerSettings.hpp"
|
||||
#include "core/Path.hpp"
|
||||
#include "database/Db.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "database/Types.hpp"
|
||||
#include "services/scanner/IScannerService.hpp"
|
||||
#include "core/Path.hpp"
|
||||
#include "IScanStep.hpp"
|
||||
#include "ScannerSettings.hpp"
|
||||
|
||||
namespace lms::scanner
|
||||
{
|
||||
@@ -53,7 +52,7 @@ namespace lms::scanner
|
||||
void requestReload() override;
|
||||
void requestImmediateScan(const ScanOptions& scanOptions) override;
|
||||
|
||||
Status getStatus() const override;
|
||||
Status getStatus() const override;
|
||||
Events& getEvents() override { return _events; }
|
||||
|
||||
private:
|
||||
@@ -78,23 +77,22 @@ namespace lms::scanner
|
||||
void notifyInProgressIfNeeded(const ScanStepStats& stats);
|
||||
void notifyInProgress(const ScanStepStats& stats);
|
||||
|
||||
std::vector<std::unique_ptr<IScanStep>> _scanSteps;
|
||||
std::vector<std::unique_ptr<IScanStep>> _scanSteps;
|
||||
|
||||
std::mutex _controlMutex;
|
||||
bool _abortScan{};
|
||||
Wt::WIOService _ioService;
|
||||
boost::asio::system_timer _scheduleTimer{ _ioService };
|
||||
Events _events;
|
||||
std::chrono::system_clock::time_point _lastScanInProgressEmit{};
|
||||
std::mutex _controlMutex;
|
||||
bool _abortScan{};
|
||||
Wt::WIOService _ioService;
|
||||
boost::asio::system_timer _scheduleTimer{ _ioService };
|
||||
Events _events;
|
||||
std::chrono::system_clock::time_point _lastScanInProgressEmit{};
|
||||
db::Db& _db;
|
||||
|
||||
mutable std::shared_mutex _statusMutex;
|
||||
State _curState{ State::NotScheduled };
|
||||
std::optional<ScanStats> _lastCompleteScanStats;
|
||||
std::optional<ScanStepStats> _currentScanStepStats;
|
||||
Wt::WDateTime _nextScheduledScan;
|
||||
mutable std::shared_mutex _statusMutex;
|
||||
State _curState{ State::NotScheduled };
|
||||
std::optional<ScanStats> _lastCompleteScanStats;
|
||||
std::optional<ScanStepStats> _currentScanStepStats;
|
||||
Wt::WDateTime _nextScheduledScan;
|
||||
|
||||
ScannerSettings _settings;
|
||||
ScannerSettings _settings;
|
||||
};
|
||||
} // Scanner
|
||||
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <Wt/WDateTime.h>
|
||||
|
||||
#include "database/MediaLibraryId.hpp"
|
||||
#include "database/ScanSettings.hpp"
|
||||
|
||||
@@ -30,14 +32,14 @@ namespace lms::scanner
|
||||
{
|
||||
struct ScannerSettings
|
||||
{
|
||||
std::size_t scanVersion{};
|
||||
Wt::WTime startTime;
|
||||
db::ScanSettings::UpdatePeriod updatePeriod{ db::ScanSettings::UpdatePeriod::Never };
|
||||
std::vector<std::filesystem::path> supportedExtensions;
|
||||
bool skipDuplicateMBID{};
|
||||
std::vector<std::string> extraTags;
|
||||
std::vector<std::string> artistTagDelimiters;
|
||||
std::vector<std::string> defaultTagDelimiters;
|
||||
std::size_t scanVersion{};
|
||||
Wt::WTime startTime;
|
||||
db::ScanSettings::UpdatePeriod updatePeriod{ db::ScanSettings::UpdatePeriod::Never };
|
||||
std::vector<std::filesystem::path> supportedExtensions;
|
||||
bool skipDuplicateMBID{};
|
||||
std::vector<std::string> extraTags;
|
||||
std::vector<std::string> artistTagDelimiters;
|
||||
std::vector<std::string> defaultTagDelimiters;
|
||||
|
||||
struct MediaLibraryInfo
|
||||
{
|
||||
@@ -46,8 +48,8 @@ namespace lms::scanner
|
||||
|
||||
auto operator<=>(const MediaLibraryInfo& other) const = default;
|
||||
};
|
||||
std::vector<MediaLibraryInfo> mediaLibraries;
|
||||
std::vector<MediaLibraryInfo> mediaLibraries;
|
||||
|
||||
bool operator==(const ScannerSettings& rhs) const = default;
|
||||
};
|
||||
}
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
namespace lms::scanner
|
||||
{
|
||||
ScanError::ScanError(const std::filesystem::path& _file, ScanErrorType _error, const std::string& _systemError)
|
||||
: file{ _file },
|
||||
error{ _error },
|
||||
systemError{ _systemError }
|
||||
: file{ _file }
|
||||
, error{ _error }
|
||||
, systemError{ _systemError }
|
||||
{
|
||||
}
|
||||
|
||||
@@ -43,4 +43,3 @@ namespace lms::scanner
|
||||
return (processedElems / static_cast<float>(totalElems ? totalElems : 1)) * 100;
|
||||
}
|
||||
} // namespace lms::scanner
|
||||
|
||||
|
||||
Reference in New Issue
Block a user