From 8a84a078be409793286f6e1609a71ec31b9a3554 Mon Sep 17 00:00:00 2001 From: emeric Date: Mon, 31 Aug 2020 14:15:10 +0200 Subject: [PATCH] Fixed regression on recommendation engine --- CMakeLists.txt | 2 +- src/libs/database/impl/Db.cpp | 7 ++++ src/libs/database/include/database/Db.hpp | 6 +++ src/libs/recommendation/impl/Engine.cpp | 17 ++++++-- src/libs/recommendation/impl/Engine.hpp | 11 +++++- .../include/recommendation/IEngine.hpp | 3 +- src/libs/scanner/impl/MediaScanner.cpp | 2 + src/libs/scanner/impl/MediaScanner.hpp | 5 ++- .../scanner/include/scanner/IMediaScanner.hpp | 4 -- src/lms/main.cpp | 1 + src/tools/recommendation/CMakeLists.txt | 1 + .../recommendation/LmsRecommendation.cpp | 39 ++++++++++++++----- 12 files changed, 74 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d84e7d3..6099f285 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ find_package(PkgConfig REQUIRED) find_package(Filesystem REQUIRED) find_package(FFMPEGAV REQUIRED) find_package(Taglib REQUIRED) -find_package(Boost REQUIRED COMPONENTS system) +find_package(Boost REQUIRED COMPONENTS system program_options) find_package(PStreams REQUIRED) find_package(PAM) pkg_check_modules(GRAPHICSMAGICKXX REQUIRED GraphicsMagick++) diff --git a/src/libs/database/impl/Db.cpp b/src/libs/database/impl/Db.cpp index 4d745877..d06eb38b 100644 --- a/src/libs/database/impl/Db.cpp +++ b/src/libs/database/impl/Db.cpp @@ -43,6 +43,13 @@ Db::Db(const std::filesystem::path& dbPath) _connectionPool = std::move(connectionPool); } +Db::~Db() +{ + LMS_LOG(DB, DEBUG) << "Optimizing db..."; + executeSql("pragma optimize"); + LMS_LOG(DB, DEBUG) << "Optimizing db DONE"; +} + void Db::executeSql(const std::string& sql) { diff --git a/src/libs/database/include/database/Db.hpp b/src/libs/database/include/database/Db.hpp index 58345405..565ffcd6 100644 --- a/src/libs/database/include/database/Db.hpp +++ b/src/libs/database/include/database/Db.hpp @@ -32,6 +32,12 @@ class Db public: Db(const std::filesystem::path& dbPath); + ~Db(); + + Db(const Db&) = delete; + Db(Db&&) = delete; + Db& operator=(const Db&) = delete; + Db& operator=(Db&&) = delete; private: friend class Session; diff --git a/src/libs/recommendation/impl/Engine.cpp b/src/libs/recommendation/impl/Engine.cpp index 072c3d48..26caf31b 100644 --- a/src/libs/recommendation/impl/Engine.cpp +++ b/src/libs/recommendation/impl/Engine.cpp @@ -38,6 +38,12 @@ createEngine(Database::Db& db) Engine::Engine(Database::Db& db) : _dbSession {db} { + start(); +} + +Engine::~Engine() +{ + stop(); } void @@ -45,9 +51,6 @@ Engine::start() { assert(!_running); _running = true; - - requestReloadInternal(false); - _ioService.start(); } @@ -62,6 +65,12 @@ Engine::stop() _ioService.stop(); } +void +Engine::requestLoad() +{ + requestReloadInternal(false); +} + void Engine::requestReload() { @@ -254,7 +263,7 @@ void Engine::cancelPendingClassifiers() { std::unique_lock lock {_classifiersMutex}; - + for (IClassifier* classifier : _pendingClassifiers) classifier->requestCancelInit(); } diff --git a/src/libs/recommendation/impl/Engine.hpp b/src/libs/recommendation/impl/Engine.hpp index 4fab63f1..fd2f91fb 100644 --- a/src/libs/recommendation/impl/Engine.hpp +++ b/src/libs/recommendation/impl/Engine.hpp @@ -35,12 +35,19 @@ namespace Recommendation { public: Engine(Database::Db& db); + ~Engine(); + + Engine(const Engine&) = delete; + Engine(Engine&&) = delete; + Engine& operator=(const Engine&) = delete; + Engine& operator=(Engine&&) = delete; private: - void start() override; - void stop() override; + void start(); + void stop(); + void requestLoad() override; void requestReload() override; Wt::Signal<>& reloaded() override { return _sigReloaded; } diff --git a/src/libs/recommendation/include/recommendation/IEngine.hpp b/src/libs/recommendation/include/recommendation/IEngine.hpp index 37f7cb8c..7cf196e8 100644 --- a/src/libs/recommendation/include/recommendation/IEngine.hpp +++ b/src/libs/recommendation/include/recommendation/IEngine.hpp @@ -40,8 +40,7 @@ namespace Recommendation public: virtual ~IEngine() = default; - virtual void start() = 0; - virtual void stop() = 0; + virtual void requestLoad() = 0; virtual void requestReload() = 0; virtual Wt::Signal<>& reloaded() = 0; diff --git a/src/libs/scanner/impl/MediaScanner.cpp b/src/libs/scanner/impl/MediaScanner.cpp index e463f518..7b7d60cb 100644 --- a/src/libs/scanner/impl/MediaScanner.cpp +++ b/src/libs/scanner/impl/MediaScanner.cpp @@ -254,6 +254,8 @@ MediaScanner::MediaScanner(Database::Db& db) _ioService.setThreadCount(1); refreshScanSettings(); + + start(); } MediaScanner::~MediaScanner() diff --git a/src/libs/scanner/impl/MediaScanner.hpp b/src/libs/scanner/impl/MediaScanner.hpp index 0ff66730..88cbc27c 100644 --- a/src/libs/scanner/impl/MediaScanner.hpp +++ b/src/libs/scanner/impl/MediaScanner.hpp @@ -50,8 +50,6 @@ class MediaScanner : public IMediaScanner MediaScanner& operator=(const MediaScanner&) = delete; MediaScanner& operator=(MediaScanner&&) = delete; - void start() override; - void stop() override; void requestReload() override; void requestImmediateScan(bool force) override; @@ -64,6 +62,9 @@ class MediaScanner : public IMediaScanner private: + void start(); + void stop(); + // Job handling void scheduleNextScan(); void scheduleScan(bool force, const Wt::WDateTime& dateTime = {}); diff --git a/src/libs/scanner/include/scanner/IMediaScanner.hpp b/src/libs/scanner/include/scanner/IMediaScanner.hpp index 83e675fb..5a0afbdc 100644 --- a/src/libs/scanner/include/scanner/IMediaScanner.hpp +++ b/src/libs/scanner/include/scanner/IMediaScanner.hpp @@ -38,14 +38,10 @@ class IMediaScanner public: virtual ~IMediaScanner() = default; - virtual void start() = 0; - virtual void stop() = 0; - // Async requests virtual void requestReload() = 0; virtual void requestImmediateScan(bool force) = 0; - enum class State { NotScheduled, diff --git a/src/lms/main.cpp b/src/lms/main.cpp index c70f5ca3..657cd868 100644 --- a/src/lms/main.cpp +++ b/src/lms/main.cpp @@ -171,6 +171,7 @@ int main(int argc, char* argv[]) Service coverArtService {CoverArt::createGrabber(argv[0])}; coverArtService->setDefaultCover(server.appRoot() + "/images/unknown-cover.jpg"); Service recommendationEngineService {Recommendation::createEngine(database)}; + recommendationEngineService->requestLoad(); Service mediaScannerService {Scanner::createMediaScanner(database)}; mediaScannerService->scanComplete().connect([&]() diff --git a/src/tools/recommendation/CMakeLists.txt b/src/tools/recommendation/CMakeLists.txt index 75b3e5d0..12f20ef0 100644 --- a/src/tools/recommendation/CMakeLists.txt +++ b/src/tools/recommendation/CMakeLists.txt @@ -6,6 +6,7 @@ add_executable(lms-recommendation target_link_libraries(lms-recommendation PRIVATE lmsdatabase lmsrecommendation + Boost::program_options ) install(TARGETS lms-recommendation DESTINATION bin) diff --git a/src/tools/recommendation/LmsRecommendation.cpp b/src/tools/recommendation/LmsRecommendation.cpp index ecb625f8..9991a596 100644 --- a/src/tools/recommendation/LmsRecommendation.cpp +++ b/src/tools/recommendation/LmsRecommendation.cpp @@ -22,6 +22,8 @@ #include #include +#include + #include "database/Artist.hpp" #include "database/Cluster.hpp" #include "database/Db.hpp" @@ -130,14 +132,30 @@ int main(int argc, char *argv[]) { try { + namespace po = boost::program_options; + // log to stdout Service logger {std::make_unique(std::cout)}; - std::filesystem::path configFilePath {"/etc/lms.conf"}; - if (argc >= 2) - configFilePath = std::string(argv[1], 0, 256); + po::options_description desc{"Allowed options"}; + desc.add_options() + ("help,h", "print usage message") + ("conf,c", po::value()->default_value("/etc/lms.conf"), "LMS config file") + ("artists,a", "Display recommendation for artists") + ("releases,r", "Display recommendation for releases") + ("tracks,t", "Display recommendation for tracks") + ; - Service config {createConfig(configFilePath)}; + po::variables_map vm; + po::store(po::parse_command_line(argc, argv, desc), vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return EXIT_SUCCESS; + } + + Service config {createConfig(vm["conf"].as())}; Database::Db db {config->getPath("working-dir") / "lms.db"}; Database::Session session {db}; @@ -153,17 +171,20 @@ int main(int argc, char *argv[]) sem.notify(); }); - engine->start(); + engine->requestLoad(); std::cout << "Waiting for the recommendation engine to be loaded..." << std::endl; sem.wait(); std::cout << "Recommendation engine loaded!" << std::endl; - dumpTracksRecommendation(db, *engine); - dumpReleasesRecommendation(db, *engine); - dumpArtistsRecommendation(db, *engine); + if (vm.count("tracks")) + dumpTracksRecommendation(db, *engine); - engine->stop(); + if (vm.count("releases")) + dumpReleasesRecommendation(db, *engine); + + if (vm.count("artists")) + dumpArtistsRecommendation(db, *engine); } catch( std::exception& e) {