Reworked the database session creation

This commit is contained in:
emeric
2019-11-20 12:58:44 +01:00
parent b69e0c0c3d
commit 6d69fc043b
15 changed files with 113 additions and 107 deletions
+5 -4
View File
@@ -33,6 +33,7 @@
#include "database/Cluster.hpp" #include "database/Cluster.hpp"
#include "database/Db.hpp" #include "database/Db.hpp"
#include "database/Release.hpp" #include "database/Release.hpp"
#include "database/Session.hpp"
#include "database/Track.hpp" #include "database/Track.hpp"
#include "database/TrackList.hpp" #include "database/TrackList.hpp"
#include "database/User.hpp" #include "database/User.hpp"
@@ -128,7 +129,7 @@ struct RequestContext
std::string userName; std::string userName;
}; };
using SessionMap = std::map<Db*, std::unique_ptr<Session>>; using SessionMap = std::map<Db*, Session>;
static std::map<std::thread::id, SessionMap> dbSessions; static std::map<std::thread::id, SessionMap> dbSessions;
static static
@@ -146,14 +147,14 @@ getOrCreateDbSession(Db& db)
auto it {sessionMap->find(&db)}; auto it {sessionMap->find(&db)};
if (it != std::end(*sessionMap)) if (it != std::end(*sessionMap))
return *it->second; return it->second;
auto res { sessionMap->try_emplace(&db, db.createSession())}; auto res { sessionMap->try_emplace(&db, db)};
assert(res.second); assert(res.second);
LMS_LOG(API_SUBSONIC, DEBUG) << "Created db session"; LMS_LOG(API_SUBSONIC, DEBUG) << "Created db session";
return *res.first->second; return res.first->second;
} }
static static
-12
View File
@@ -40,18 +40,6 @@ Db::Db(const std::filesystem::path& dbPath)
connectionPool->setTimeout(std::chrono::seconds(10)); connectionPool->setTimeout(std::chrono::seconds(10));
_connectionPool = std::move(connectionPool); _connectionPool = std::move(connectionPool);
{
auto session {createSession()};
session->prepareTables();
}
}
std::unique_ptr<Session>
Db::createSession()
{
return std::unique_ptr<Session>(new Session {_sharedMutex, *_connectionPool.get()});
} }
} // namespace Database } // namespace Database
+5 -4
View File
@@ -24,8 +24,6 @@
#include <Wt/Dbo/SqlConnectionPool.h> #include <Wt/Dbo/SqlConnectionPool.h>
#include "Session.hpp"
namespace Database { namespace Database {
// Session living class handling the database and the login // Session living class handling the database and the login
@@ -35,9 +33,12 @@ class Db
Db(const std::filesystem::path& dbPath); Db(const std::filesystem::path& dbPath);
std::unique_ptr<Session> createSession();
private: private:
friend class Session;
std::shared_mutex& getMutex() { return _sharedMutex; }
Wt::Dbo::SqlConnectionPool& getConnectionPool() { return *_connectionPool; }
std::shared_mutex _sharedMutex; std::shared_mutex _sharedMutex;
std::unique_ptr<Wt::Dbo::SqlConnectionPool> _connectionPool; std::unique_ptr<Wt::Dbo::SqlConnectionPool> _connectionPool;
}; };
+8 -7
View File
@@ -24,6 +24,7 @@
#include "Artist.hpp" #include "Artist.hpp"
#include "Cluster.hpp" #include "Cluster.hpp"
#include "Db.hpp"
#include "Release.hpp" #include "Release.hpp"
#include "ScanSettings.hpp" #include "ScanSettings.hpp"
#include "SimilaritySettings.hpp" #include "SimilaritySettings.hpp"
@@ -116,10 +117,10 @@ Session::doDatabaseMigrationIfNeeded()
VersionInfo::get(*this).modify()->setVersion(LMS_DATABASE_VERSION); VersionInfo::get(*this).modify()->setVersion(LMS_DATABASE_VERSION);
} }
Session::Session(std::shared_mutex& mutex, Wt::Dbo::SqlConnectionPool& connectionPool) Session::Session(Db& db)
: _mutex {mutex} : _db {db}
{ {
_session.setConnectionPool(connectionPool); _session.setConnectionPool(_db.getConnectionPool());
_session.mapClass<VersionInfo>("version_info"); _session.mapClass<VersionInfo>("version_info");
_session.mapClass<Artist>("artist"); _session.mapClass<Artist>("artist");
@@ -179,25 +180,25 @@ SharedTransaction::~SharedTransaction()
void void
Session::checkUniqueLocked() Session::checkUniqueLocked()
{ {
assert(lockDebug[&_mutex] == OwnedLock::Unique); assert(lockDebug[&_db.getMutex()] == OwnedLock::Unique);
} }
void void
Session::checkSharedLocked() Session::checkSharedLocked()
{ {
assert(lockDebug[&_mutex] != OwnedLock::None); assert(lockDebug[&_db.getMutex()] != OwnedLock::None);
} }
UniqueTransaction UniqueTransaction
Session::createUniqueTransaction() Session::createUniqueTransaction()
{ {
return UniqueTransaction{_mutex, _session}; return UniqueTransaction{_db.getMutex(), _session};
} }
SharedTransaction SharedTransaction
Session::createSharedTransaction() Session::createSharedTransaction()
{ {
return SharedTransaction{_mutex, _session}; return SharedTransaction{_db.getMutex(), _session};
} }
void void
+6 -4
View File
@@ -54,9 +54,12 @@ class SharedTransaction
Wt::Dbo::Transaction _transaction; Wt::Dbo::Transaction _transaction;
}; };
class Db;
class Session class Session
{ {
public: public:
Session (Db& database);
Session(const Session&) = delete; Session(const Session&) = delete;
Session(Session&&) = delete; Session(Session&&) = delete;
Session& operator=(const Session&) = delete; Session& operator=(const Session&) = delete;
@@ -70,17 +73,16 @@ class Session
void optimize(); void optimize();
void prepareTables(); // need to run only once at startup
Wt::Dbo::Session& getDboSession() { return _session; } Wt::Dbo::Session& getDboSession() { return _session; }
private: private:
friend class Db;
Session(std::shared_mutex& mutex, Wt::Dbo::SqlConnectionPool& connectionPool); Session(std::shared_mutex& mutex, Wt::Dbo::SqlConnectionPool& connectionPool);
void doDatabaseMigrationIfNeeded(); void doDatabaseMigrationIfNeeded();
void prepareTables(); // need to run only once at startup
std::shared_mutex& _mutex; Db& _db;
Wt::Dbo::Session _session; Wt::Dbo::Session _session;
}; };
+6 -2
View File
@@ -134,15 +134,19 @@ int main(int argc, char* argv[])
// Initializing a connection pool to the database that will be shared along services // Initializing a connection pool to the database that will be shared along services
Database::Db database {ServiceProvider<Config>::get()->getPath("working-dir") / "lms.db"}; Database::Db database {ServiceProvider<Config>::get()->getPath("working-dir") / "lms.db"};
{
Database::Session session {database};
session.prepareTables();
}
UserInterface::LmsApplicationGroupContainer appGroups; UserInterface::LmsApplicationGroupContainer appGroups;
// Service initialization order is important // Service initialization order is important
ServiceProvider<Auth::AuthTokenService>::create(ServiceProvider<Config>::get()->getULong("login-throttler-max-entriees", 10000)); ServiceProvider<Auth::AuthTokenService>::create(ServiceProvider<Config>::get()->getULong("login-throttler-max-entriees", 10000));
ServiceProvider<Auth::PasswordService>::create(ServiceProvider<Config>::get()->getULong("login-throttler-max-entriees", 10000)); ServiceProvider<Auth::PasswordService>::create(ServiceProvider<Config>::get()->getULong("login-throttler-max-entriees", 10000));
Scanner::MediaScanner& mediaScanner {ServiceProvider<Scanner::MediaScanner>::create(database.createSession())}; Scanner::MediaScanner& mediaScanner {ServiceProvider<Scanner::MediaScanner>::create(database)};
Similarity::FeaturesScannerAddon similarityFeaturesScannerAddon {database.createSession()}; Similarity::FeaturesScannerAddon similarityFeaturesScannerAddon {database};
mediaScanner.setAddon(similarityFeaturesScannerAddon); mediaScanner.setAddon(similarityFeaturesScannerAddon);
+28 -28
View File
@@ -191,8 +191,8 @@ getOrCreateClusters(Session& session, const MetaData::Clusters& clustersNames)
namespace Scanner { namespace Scanner {
MediaScanner::MediaScanner(std::unique_ptr<Database::Session> dbSession) MediaScanner::MediaScanner(Database::Db& db)
: _dbSession {std::move(dbSession)} : _dbSession {db}
{ {
_ioService.setThreadCount(1); _ioService.setThreadCount(1);
@@ -444,7 +444,7 @@ MediaScanner::scan(boost::system::error_code err)
} }
LMS_LOG(DBUPDATER, INFO) << "Optimizing db..."; LMS_LOG(DBUPDATER, INFO) << "Optimizing db...";
_dbSession->optimize(); _dbSession.optimize();
LMS_LOG(DBUPDATER, INFO) << "Optimize db done!"; LMS_LOG(DBUPDATER, INFO) << "Optimize db done!";
} }
@@ -452,9 +452,9 @@ void
MediaScanner::refreshScanSettings() MediaScanner::refreshScanSettings()
{ {
{ {
auto transaction {_dbSession->createSharedTransaction()}; auto transaction {_dbSession.createSharedTransaction()};
ScanSettings::pointer scanSettings {ScanSettings::get(*_dbSession)}; ScanSettings::pointer scanSettings {ScanSettings::get(_dbSession)};
LMS_LOG(DBUPDATER, INFO) << "Using scan settings version " << scanSettings->getScanVersion(); LMS_LOG(DBUPDATER, INFO) << "Using scan settings version " << scanSettings->getScanVersion();
@@ -521,9 +521,9 @@ MediaScanner::scanAudioFile(const std::filesystem::path& file, bool forceScan, S
if (!forceScan) if (!forceScan)
{ {
// Skip file if last write is the same // Skip file if last write is the same
auto transaction {_dbSession->createSharedTransaction()}; auto transaction {_dbSession.createSharedTransaction()};
const Track::pointer track {Track::getByPath(*_dbSession, file)}; const Track::pointer track {Track::getByPath(_dbSession, file)};
if (track && track->getLastWriteTime().toTime_t() == lastWriteTime.toTime_t() if (track && track->getLastWriteTime().toTime_t() == lastWriteTime.toTime_t()
&& track->getScanVersion() == _scanVersion) && track->getScanVersion() == _scanVersion)
@@ -542,9 +542,9 @@ MediaScanner::scanAudioFile(const std::filesystem::path& file, bool forceScan, S
stats.scans++; stats.scans++;
auto uniqueTransaction {_dbSession->createUniqueTransaction()}; auto uniqueTransaction {_dbSession.createUniqueTransaction()};
Track::pointer track {Track::getByPath(*_dbSession, file) }; Track::pointer track {Track::getByPath(_dbSession, file) };
// We estimate this is an audio file if: // We estimate this is an audio file if:
// - we found a least one audio stream // - we found a least one audio stream
@@ -588,25 +588,25 @@ MediaScanner::scanAudioFile(const std::filesystem::path& file, bool forceScan, S
} }
// ***** Clusters // ***** Clusters
std::vector<Cluster::pointer> clusters {getOrCreateClusters(*_dbSession, trackInfo->clusters)}; std::vector<Cluster::pointer> clusters {getOrCreateClusters(_dbSession, trackInfo->clusters)};
// ***** Artists // ***** Artists
std::vector<Artist::pointer> artists {getOrCreateArtists(*_dbSession, trackInfo->artists)}; std::vector<Artist::pointer> artists {getOrCreateArtists(_dbSession, trackInfo->artists)};
// ***** Release artists // ***** Release artists
std::vector<Artist::pointer> releaseArtists {getOrCreateArtists(*_dbSession, trackInfo->albumArtists)}; std::vector<Artist::pointer> releaseArtists {getOrCreateArtists(_dbSession, trackInfo->albumArtists)};
// ***** Release // ***** Release
Release::pointer release; Release::pointer release;
if (trackInfo->album) if (trackInfo->album)
release = getOrCreateRelease(*_dbSession, *trackInfo->album); release = getOrCreateRelease(_dbSession, *trackInfo->album);
// If file already exist, update data // If file already exist, update data
// Otherwise, create it // Otherwise, create it
if (!track) if (!track)
{ {
// Create a new song // Create a new song
track = Track::create(*_dbSession, file); track = Track::create(_dbSession, file);
LMS_LOG(DBUPDATER, INFO) << "Adding '" << file.string() << "'"; LMS_LOG(DBUPDATER, INFO) << "Adding '" << file.string() << "'";
stats.additions++; stats.additions++;
} }
@@ -629,10 +629,10 @@ MediaScanner::scanAudioFile(const std::filesystem::path& file, bool forceScan, S
track.modify()->clearArtistLinks(); track.modify()->clearArtistLinks();
for (const auto& artist : artists) for (const auto& artist : artists)
track.modify()->addArtistLink(Database::TrackArtistLink::create(*_dbSession, track, artist, Database::TrackArtistLink::Type::Artist)); track.modify()->addArtistLink(Database::TrackArtistLink::create(_dbSession, track, artist, Database::TrackArtistLink::Type::Artist));
for (const auto& releaseArtist : releaseArtists) for (const auto& releaseArtist : releaseArtists)
track.modify()->addArtistLink(Database::TrackArtistLink::create(*_dbSession, track, releaseArtist, Database::TrackArtistLink::Type::ReleaseArtist)); track.modify()->addArtistLink(Database::TrackArtistLink::create(_dbSession, track, releaseArtist, Database::TrackArtistLink::Type::ReleaseArtist));
track.modify()->setScanVersion(_scanVersion); track.modify()->setScanVersion(_scanVersion);
track.modify()->setRelease(release); track.modify()->setRelease(release);
@@ -733,8 +733,8 @@ MediaScanner::removeMissingTracks(ScanStats& stats)
{ {
std::vector<std::filesystem::path> trackPaths; std::vector<std::filesystem::path> trackPaths;
{ {
auto transaction {_dbSession->createSharedTransaction()}; auto transaction {_dbSession.createSharedTransaction()};
trackPaths = Track::getAllPaths(*_dbSession);; trackPaths = Track::getAllPaths(_dbSession);;
} }
LMS_LOG(DBUPDATER, DEBUG) << "Checking tracks..."; LMS_LOG(DBUPDATER, DEBUG) << "Checking tracks...";
@@ -745,9 +745,9 @@ MediaScanner::removeMissingTracks(ScanStats& stats)
if (!checkFile(trackPath, _mediaDirectory, _fileExtensions)) if (!checkFile(trackPath, _mediaDirectory, _fileExtensions))
{ {
auto transaction {_dbSession->createUniqueTransaction()}; auto transaction {_dbSession.createUniqueTransaction()};
Track::pointer track {Track::getByPath(*_dbSession, trackPath)}; Track::pointer track {Track::getByPath(_dbSession, trackPath)};
if (track) if (track)
{ {
track.remove(); track.remove();
@@ -762,10 +762,10 @@ MediaScanner::removeOrphanEntries()
{ {
LMS_LOG(DBUPDATER, DEBUG) << "Checking orphan clusters..."; LMS_LOG(DBUPDATER, DEBUG) << "Checking orphan clusters...";
{ {
auto transaction {_dbSession->createUniqueTransaction()}; auto transaction {_dbSession.createUniqueTransaction()};
// Now process orphan Cluster (no track) // Now process orphan Cluster (no track)
auto clusters {Cluster::getAllOrphans(*_dbSession)}; auto clusters {Cluster::getAllOrphans(_dbSession)};
for (auto& cluster : clusters) for (auto& cluster : clusters)
{ {
LMS_LOG(DBUPDATER, DEBUG) << "Removing orphan cluster '" << cluster->getName() << "'"; LMS_LOG(DBUPDATER, DEBUG) << "Removing orphan cluster '" << cluster->getName() << "'";
@@ -775,9 +775,9 @@ MediaScanner::removeOrphanEntries()
LMS_LOG(DBUPDATER, DEBUG) << "Checking orphan artists..."; LMS_LOG(DBUPDATER, DEBUG) << "Checking orphan artists...";
{ {
auto transaction {_dbSession->createUniqueTransaction()}; auto transaction {_dbSession.createUniqueTransaction()};
auto artists {Artist::getAllOrphans(*_dbSession)}; auto artists {Artist::getAllOrphans(_dbSession)};
for (auto& artist : artists) for (auto& artist : artists)
{ {
LMS_LOG(DBUPDATER, DEBUG) << "Removing orphan artist '" << artist->getName() << "'"; LMS_LOG(DBUPDATER, DEBUG) << "Removing orphan artist '" << artist->getName() << "'";
@@ -787,9 +787,9 @@ MediaScanner::removeOrphanEntries()
LMS_LOG(DBUPDATER, DEBUG) << "Checking orphan releases..."; LMS_LOG(DBUPDATER, DEBUG) << "Checking orphan releases...";
{ {
auto transaction {_dbSession->createUniqueTransaction()}; auto transaction {_dbSession.createUniqueTransaction()};
auto releases {Release::getAllOrphans(*_dbSession)}; auto releases {Release::getAllOrphans(_dbSession)};
for (auto& release : releases) for (auto& release : releases)
{ {
LMS_LOG(DBUPDATER, DEBUG) << "Removing orphan release '" << release->getName() << "'"; LMS_LOG(DBUPDATER, DEBUG) << "Removing orphan release '" << release->getName() << "'";
@@ -805,9 +805,9 @@ MediaScanner::checkDuplicatedAudioFiles(ScanStats& stats)
{ {
LMS_LOG(DBUPDATER, INFO) << "Checking duplicated audio files"; LMS_LOG(DBUPDATER, INFO) << "Checking duplicated audio files";
auto transaction {_dbSession->createSharedTransaction()}; auto transaction {_dbSession.createSharedTransaction()};
const std::vector<Track::pointer> tracks = Database::Track::getMBIDDuplicates(*_dbSession); const std::vector<Track::pointer> tracks = Database::Track::getMBIDDuplicates(_dbSession);
for (const Track::pointer& track : tracks) for (const Track::pointer& track : tracks)
{ {
LMS_LOG(DBUPDATER, INFO) << "Found duplicated MBID [" << track->getMBID() << "], file: " << track->getPath().string() << " - " << track->getName(); LMS_LOG(DBUPDATER, INFO) << "Found duplicated MBID [" << track->getMBID() << "], file: " << track->getPath().string() << " - " << track->getName();
+2 -2
View File
@@ -41,7 +41,7 @@ namespace Scanner {
class MediaScanner class MediaScanner
{ {
public: public:
MediaScanner(std::unique_ptr<Database::Session> dbSession); MediaScanner(Database::Db& db);
void setAddon(MediaScannerAddon& addon); void setAddon(MediaScannerAddon& addon);
@@ -110,7 +110,7 @@ class MediaScanner
Wt::Signal<ScanProgressStats> _sigScanInProgress; Wt::Signal<ScanProgressStats> _sigScanInProgress;
std::chrono::system_clock::time_point _lastScanInProgressEmit {}; std::chrono::system_clock::time_point _lastScanInProgressEmit {};
Wt::Signal<Wt::WDateTime> _sigScheduled; Wt::Signal<Wt::WDateTime> _sigScheduled;
std::unique_ptr<Database::Session> _dbSession; Database::Session _dbSession;
MetaData::TagLibParser _metadataParser; MetaData::TagLibParser _metadataParser;
std::vector<MediaScannerAddon*> _addons; std::vector<MediaScannerAddon*> _addons;
@@ -72,13 +72,13 @@ getTracksWithMBIDAndMissingFeatures(Database::Session& dbSession)
return res; return res;
} }
FeaturesScannerAddon::FeaturesScannerAddon(std::unique_ptr<Database::Session> dbSession) FeaturesScannerAddon::FeaturesScannerAddon(Database::Db& db)
: _dbSession {std::move(dbSession)} : _dbSession {db}
{ {
std::optional<Similarity::FeaturesCache> cache {Similarity::FeaturesCache::read()}; std::optional<Similarity::FeaturesCache> cache {Similarity::FeaturesCache::read()};
if (cache) if (cache)
{ {
auto searcher {std::make_shared<Similarity::FeaturesSearcher>(*_dbSession.get(), *cache, [&]() { return _stopRequested; })}; auto searcher {std::make_shared<Similarity::FeaturesSearcher>(_dbSession, *cache, [&]() { return _stopRequested; })};
if (searcher->isValid()) if (searcher->isValid())
std::atomic_store(&_searcher, searcher); std::atomic_store(&_searcher, searcher);
} }
@@ -99,9 +99,9 @@ FeaturesScannerAddon::requestStop()
void void
FeaturesScannerAddon::trackUpdated(Database::IdType trackId) FeaturesScannerAddon::trackUpdated(Database::IdType trackId)
{ {
auto uniqueTransaction {_dbSession->createUniqueTransaction()}; auto uniqueTransaction {_dbSession.createUniqueTransaction()};
auto track {Database::Track::getById(*_dbSession, trackId)}; auto track {Database::Track::getById(_dbSession, trackId)};
if (!track) if (!track)
return; return;
@@ -112,9 +112,9 @@ void
FeaturesScannerAddon::preScanComplete() FeaturesScannerAddon::preScanComplete()
{ {
{ {
auto transaction {_dbSession->createSharedTransaction()}; auto transaction {_dbSession.createSharedTransaction()};
if (Database::SimilaritySettings::get(*_dbSession)->getEngineType() != Database::SimilaritySettings::EngineType::Features) if (Database::SimilaritySettings::get(_dbSession)->getEngineType() != Database::SimilaritySettings::EngineType::Features)
{ {
LMS_LOG(DBUPDATER, INFO) << "Do not fetch features since the engine type does not make use of them"; LMS_LOG(DBUPDATER, INFO) << "Do not fetch features since the engine type does not make use of them";
return; return;
@@ -122,7 +122,7 @@ FeaturesScannerAddon::preScanComplete()
} }
LMS_LOG(DBUPDATER, DEBUG) << "Getting tracks with missing Features..."; LMS_LOG(DBUPDATER, DEBUG) << "Getting tracks with missing Features...";
const std::vector<TrackInfo> tracksInfo {getTracksWithMBIDAndMissingFeatures(*_dbSession)}; const std::vector<TrackInfo> tracksInfo {getTracksWithMBIDAndMissingFeatures(_dbSession)};
LMS_LOG(DBUPDATER, DEBUG) << "Getting tracks with missing Features DONE (found " << tracksInfo.size() << ")"; LMS_LOG(DBUPDATER, DEBUG) << "Getting tracks with missing Features DONE (found " << tracksInfo.size() << ")";
if (!tracksInfo.empty()) if (!tracksInfo.empty())
@@ -144,16 +144,16 @@ FeaturesScannerAddon::updateSearcher()
{ {
LMS_LOG(SIMILARITY, INFO) << "Updating searcher..."; LMS_LOG(SIMILARITY, INFO) << "Updating searcher...";
if (hasAtLeastOneTrackWithFeatures(*_dbSession)) if (hasAtLeastOneTrackWithFeatures(_dbSession))
{ {
LMS_LOG(DBUPDATER, INFO) << "No track suitable for features similarity clustering"; LMS_LOG(DBUPDATER, INFO) << "No track suitable for features similarity clustering";
std::atomic_store(&_searcher, std::shared_ptr<FeaturesSearcher>{}); std::atomic_store(&_searcher, std::shared_ptr<FeaturesSearcher>{});
return; return;
} }
const auto features {getFeatureSettings(*_dbSession)}; const auto features {getFeatureSettings(_dbSession)};
auto searcher {std::make_shared<Similarity::FeaturesSearcher>(*_dbSession, features, [&]() { return _stopRequested; })}; auto searcher {std::make_shared<Similarity::FeaturesSearcher>(_dbSession, features, [&]() { return _stopRequested; })};
if (searcher->isValid()) if (searcher->isValid())
{ {
std::atomic_store(&_searcher, searcher); std::atomic_store(&_searcher, searcher);
@@ -183,13 +183,13 @@ FeaturesScannerAddon::fetchFeatures(Database::IdType trackId, const std::string&
} }
{ {
auto uniqueTransaction {_dbSession->createUniqueTransaction()}; auto uniqueTransaction {_dbSession.createUniqueTransaction()};
Wt::Dbo::ptr<Database::Track> track {Database::Track::getById(*_dbSession, trackId)}; Wt::Dbo::ptr<Database::Track> track {Database::Track::getById(_dbSession, trackId)};
if (!track) if (!track)
return false; return false;
Database::TrackFeatures::create(*_dbSession, track, data); Database::TrackFeatures::create(_dbSession, track, data);
} }
return true; return true;
@@ -24,13 +24,17 @@
#include "SimilarityFeaturesSearcher.hpp" #include "SimilarityFeaturesSearcher.hpp"
namespace Database {
class Db;
}
namespace Similarity { namespace Similarity {
class FeaturesScannerAddon final : public Scanner::MediaScannerAddon class FeaturesScannerAddon final : public Scanner::MediaScannerAddon
{ {
public: public:
FeaturesScannerAddon(std::unique_ptr<Database::Session> dbSession); FeaturesScannerAddon(Database::Db& db);
std::shared_ptr<FeaturesSearcher> getSearcher(); std::shared_ptr<FeaturesSearcher> getSearcher();
@@ -48,7 +52,7 @@ class FeaturesScannerAddon final : public Scanner::MediaScannerAddon
void updateSearcher(); void updateSearcher();
std::unique_ptr<Database::Session> _dbSession; Database::Session _dbSession;
std::shared_ptr<FeaturesSearcher> _searcher; std::shared_ptr<FeaturesSearcher> _searcher;
bool _stopRequested {}; bool _stopRequested {};
}; };
+14 -14
View File
@@ -60,7 +60,7 @@ namespace UserInterface {
std::unique_ptr<Wt::WApplication> std::unique_ptr<Wt::WApplication>
LmsApplication::create(const Wt::WEnvironment& env, Database::Db& db, LmsApplicationGroupContainer& appGroups) LmsApplication::create(const Wt::WEnvironment& env, Database::Db& db, LmsApplicationGroupContainer& appGroups)
{ {
return std::make_unique<LmsApplication>(env, db.createSession(), appGroups); return std::make_unique<LmsApplication>(env, db, appGroups);
} }
LmsApplication* LmsApplication*
@@ -70,12 +70,12 @@ LmsApplication::instance()
} }
Wt::Dbo::ptr<Database::User> Wt::Dbo::ptr<Database::User>
LmsApplication::getUser() const LmsApplication::getUser()
{ {
if (!_userId) if (!_userId)
return {}; return {};
return Database::User::getById(*_dbSession, *_userId); return Database::User::getById(_dbSession, *_userId);
} }
bool bool
@@ -85,34 +85,34 @@ LmsApplication::isUserAuthStrong() const
} }
bool bool
LmsApplication::isUserAdmin() const LmsApplication::isUserAdmin()
{ {
auto transaction {_dbSession->createSharedTransaction()}; auto transaction {_dbSession.createSharedTransaction()};
return getUser()->isAdmin(); return getUser()->isAdmin();
} }
bool bool
LmsApplication::isUserDemo() const LmsApplication::isUserDemo()
{ {
auto transaction {_dbSession->createSharedTransaction()}; auto transaction {_dbSession.createSharedTransaction()};
return getUser()->isDemo(); return getUser()->isDemo();
} }
std::string std::string
LmsApplication::getUserLoginName() const LmsApplication::getUserLoginName()
{ {
auto transaction {_dbSession->createSharedTransaction()}; auto transaction {_dbSession.createSharedTransaction()};
return getUser()->getLoginName(); return getUser()->getLoginName();
} }
LmsApplication::LmsApplication(const Wt::WEnvironment& env, LmsApplication::LmsApplication(const Wt::WEnvironment& env,
std::unique_ptr<Database::Session> dbSession, Database::Db& db,
LmsApplicationGroupContainer& appGroups) LmsApplicationGroupContainer& appGroups)
: Wt::WApplication {env}, : Wt::WApplication {env},
_dbSession {std::move(dbSession)}, _dbSession {db},
_appGroups {appGroups} _appGroups {appGroups}
{ {
auto bootstrapTheme = std::make_unique<Wt::WBootstrapTheme>(); auto bootstrapTheme = std::make_unique<Wt::WBootstrapTheme>();
@@ -165,8 +165,8 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env,
// If here is no account in the database, launch the first connection wizard // If here is no account in the database, launch the first connection wizard
bool firstConnection {}; bool firstConnection {};
{ {
auto transaction {_dbSession->createSharedTransaction()}; auto transaction {_dbSession.createSharedTransaction()};
firstConnection = Database::User::getAll(*_dbSession).empty(); firstConnection = Database::User::getAll(_dbSession).empty();
} }
LMS_LOG(UI, DEBUG) << "Creating root widget. First connection = " << firstConnection; LMS_LOG(UI, DEBUG) << "Creating root widget. First connection = " << firstConnection;
@@ -368,7 +368,7 @@ LmsApplication::handleUserLoggedOut()
LMS_LOG(UI, INFO) << "User '" << getUserLoginName() << " 'logged out"; LMS_LOG(UI, INFO) << "User '" << getUserLoginName() << " 'logged out";
{ {
auto transaction {_dbSession->createUniqueTransaction()}; auto transaction {_dbSession.createUniqueTransaction()};
getUser().modify()->clearAuthTokens(); getUser().modify()->clearAuthTokens();
} }
+9 -7
View File
@@ -23,6 +23,8 @@
#include <Wt/WApplication.h> #include <Wt/WApplication.h>
#include "database/Db.hpp"
#include "database/Session.hpp"
#include "scanner/MediaScanner.hpp" #include "scanner/MediaScanner.hpp"
#include "LmsApplicationGroup.hpp" #include "LmsApplicationGroup.hpp"
@@ -73,7 +75,7 @@ enum class MsgType
class LmsApplication : public Wt::WApplication class LmsApplication : public Wt::WApplication
{ {
public: public:
LmsApplication(const Wt::WEnvironment& env, std::unique_ptr<Database::Session> dbSession, LmsApplicationGroupContainer& appGroups); LmsApplication(const Wt::WEnvironment& env, Database::Db& db, LmsApplicationGroupContainer& appGroups);
static std::unique_ptr<Wt::WApplication> create(const Wt::WEnvironment& env, Database::Db& db, LmsApplicationGroupContainer& appGroups); static std::unique_ptr<Wt::WApplication> create(const Wt::WEnvironment& env, Database::Db& db, LmsApplicationGroupContainer& appGroups);
static LmsApplication* instance(); static LmsApplication* instance();
@@ -81,13 +83,13 @@ class LmsApplication : public Wt::WApplication
// Session application data // Session application data
std::shared_ptr<ImageResource> getImageResource() { return _imageResource; } std::shared_ptr<ImageResource> getImageResource() { return _imageResource; }
std::shared_ptr<AudioResource> getAudioResource() { return _audioResource; } std::shared_ptr<AudioResource> getAudioResource() { return _audioResource; }
Database::Session& getDbSession() { return *_dbSession.get();} Database::Session& getDbSession() { return _dbSession;}
Wt::Dbo::ptr<Database::User> getUser() const; Wt::Dbo::ptr<Database::User> getUser();
bool isUserAuthStrong() const; // user must be logged in prior this call bool isUserAuthStrong() const; // user must be logged in prior this call
bool isUserAdmin() const; // user must be logged in prior this call bool isUserAdmin(); // user must be logged in prior this call
bool isUserDemo() const; // user must be logged in prior this call bool isUserDemo(); // user must be logged in prior this call
std::string getUserLoginName() const; // user must be logged in prior this call std::string getUserLoginName(); // user must be logged in prior this call
Events& getEvents() { return _events; } Events& getEvents() { return _events; }
@@ -121,7 +123,7 @@ class LmsApplication : public Wt::WApplication
void createHome(); void createHome();
Wt::Signal<> _preQuit; Wt::Signal<> _preQuit;
std::unique_ptr<Database::Session> _dbSession; Database::Session _dbSession;
LmsApplicationGroupContainer& _appGroups; LmsApplicationGroupContainer& _appGroups;
Events _events; Events _events;
std::optional<Database::IdType> _userId; std::optional<Database::IdType> _userId;
+6 -4
View File
@@ -25,9 +25,10 @@
#include "database/Artist.hpp" #include "database/Artist.hpp"
#include "database/Cluster.hpp" #include "database/Cluster.hpp"
#include "database/Db.hpp" #include "database/Db.hpp"
#include "database/TrackList.hpp"
#include "database/Release.hpp" #include "database/Release.hpp"
#include "database/Session.hpp"
#include "database/Track.hpp" #include "database/Track.hpp"
#include "database/TrackList.hpp"
#include "database/User.hpp" #include "database/User.hpp"
#include "utils/StreamLogger.hpp" #include "utils/StreamLogger.hpp"
@@ -1266,13 +1267,14 @@ int main()
for (std::size_t i = 0; i < 2; ++i) for (std::size_t i = 0; i < 2; ++i)
{ {
Database::Db db {tmpFile}; Database::Db db {tmpFile};
std::unique_ptr<Session> session {db.createSession()}; Database::Session session {db};
session.prepareTables();
auto runTest = [&session](const std::string& name, std::function<void(Session&)> testFunc) auto runTest = [&session](const std::string& name, std::function<void(Session&)> testFunc)
{ {
std::cout << "Running test '" << name << "'..." << std::endl; std::cout << "Running test '" << name << "'..." << std::endl;
testFunc(*session); testFunc(session);
testDatabaseEmpty(*session); testDatabaseEmpty(session);
std::cout << "Running test '" << name << "': SUCCESS" << std::endl; std::cout << "Running test '" << name << "': SUCCESS" << std::endl;
}; };
@@ -4,6 +4,7 @@
#include <string> #include <string>
#include "database/Db.hpp" #include "database/Db.hpp"
#include "database/Session.hpp"
#include "utils/Config.hpp" #include "utils/Config.hpp"
#include "utils/Service.hpp" #include "utils/Service.hpp"
#include "utils/StreamLogger.hpp" #include "utils/StreamLogger.hpp"
@@ -23,7 +24,7 @@ int main(int argc, char *argv[])
ServiceProvider<Config>::create(configFilePath); ServiceProvider<Config>::create(configFilePath);
Database::Db db {ServiceProvider<Config>::get()->getPath("working-dir") / "lms.db"}; Database::Db db {ServiceProvider<Config>::get()->getPath("working-dir") / "lms.db"};
auto session {db.createSession()}; Database::Session session {db};
/* const FeatureSettings /* const FeatureSettings
{ {
+2 -2
View File
@@ -39,13 +39,13 @@ int main(int argc, char *argv[])
ServiceProvider<Config>::create(configFilePath); ServiceProvider<Config>::create(configFilePath);
Database::Db db {ServiceProvider<Config>::get()->getPath("working-dir") / "lms.db"}; Database::Db db {ServiceProvider<Config>::get()->getPath("working-dir") / "lms.db"};
auto session {db.createSession()}; Database::Session session {db};
std::cout << "Getting all features..." << std::endl; std::cout << "Getting all features..." << std::endl;
std::cout << "Classifying tracks..." << std::endl; std::cout << "Classifying tracks..." << std::endl;
// may be long... // may be long...
FeaturesSearcher searcher {*session, featuresSettings}; FeaturesSearcher searcher {session, featuresSettings};
std::cout << "Classifying tracks DONE" << std::endl; std::cout << "Classifying tracks DONE" << std::endl;
} }