[DB] Use a single shared pool of connections to the database

This commit is contained in:
emeric
2015-08-19 13:31:50 +02:00
parent 4b35e03ef8
commit e18221689f
23 changed files with 89 additions and 62 deletions
+8 -9
View File
@@ -19,7 +19,6 @@
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/thread.hpp>
#include <boost/asio/placeholders.hpp>
@@ -73,7 +72,7 @@ isFileSupported(const boost::filesystem::path& file, const std::vector<boost::fi
boost::filesystem::path fileExtension = file.extension();
BOOST_FOREACH(const boost::filesystem::path extension, extensions)
for (auto extension : extensions)
{
if (extension == fileExtension)
return true;
@@ -88,7 +87,7 @@ getRootDirectoriesByType(Wt::Dbo::Session& session, Database::MediaDirectory::Ty
std::vector<boost::filesystem::path> res;
std::vector<Database::MediaDirectory::pointer> rootDirs = Database::MediaDirectory::getByType(session, type);
BOOST_FOREACH(Database::MediaDirectory::pointer rootDir, rootDirs)
for (auto rootDir : rootDirs)
res.push_back(rootDir->getPath());
return res;
@@ -102,10 +101,10 @@ namespace DatabaseUpdater {
using namespace Database;
Updater::Updater(boost::filesystem::path dbPath, MetaData::Parser& parser)
Updater::Updater(Wt::Dbo::SqlConnectionPool &connectionPool, MetaData::Parser& parser)
: _running(false),
_scheduleTimer(_ioService),
_db(dbPath),
_db(connectionPool),
_metadataParser(parser)
{
_ioService.setThreadCount(1);
@@ -114,14 +113,14 @@ _metadataParser(parser)
void
Updater::setAudioExtensions(const std::vector<std::string>& extensions)
{
BOOST_FOREACH(const std::string& extension, extensions)
for (const std::string& extension : extensions)
_audioExtensions.push_back("." + extension);
}
void
Updater::setVideoExtensions(const std::vector<std::string>& extensions)
{
BOOST_FOREACH(const std::string& extension, extensions)
for (const std::string& extension : extensions)
_videoExtensions.push_back("." + extension);
}
@@ -226,7 +225,7 @@ Updater::process(boost::system::error_code err)
{
Wt::Dbo::Transaction transaction(_db.getSession());
std::vector<MediaDirectory::pointer> mediaDirectories = MediaDirectory::getAll(_db.getSession());
BOOST_FOREACH(MediaDirectory::pointer directory, mediaDirectories)
for (MediaDirectory::pointer directory : mediaDirectories)
rootDirectories.push_back( std::make_pair( directory->getPath(), directory->getType() ));
}
@@ -604,7 +603,7 @@ Updater::checkFile(const boost::filesystem::path& p, const std::vector<boost::fi
else
{
bool foundRoot = false;
BOOST_FOREACH(const boost::filesystem::path& rootDir, rootDirs)
for (auto rootDir : rootDirs)
{
if (p.string().find( rootDir.string() ) != std::string::npos)
{
+1 -1
View File
@@ -32,7 +32,7 @@ namespace DatabaseUpdater {
class Updater
{
public:
Updater(boost::filesystem::path db, MetaData::Parser& parser);
Updater(Wt::Dbo::SqlConnectionPool& connectionPool, MetaData::Parser& parser);
void setAudioExtensions(const std::vector<std::string>& extensions);
void setVideoExtensions(const std::vector<std::string>& extensions);
+21 -10
View File
@@ -17,6 +17,9 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/Dbo/FixedSqlConnectionPool>
#include <Wt/Dbo/backend/Sqlite3>
#include <Wt/Auth/Dbo/AuthInfo>
#include <Wt/Auth/Dbo/UserDatabase>
#include <Wt/Auth/AuthService>
@@ -72,11 +75,10 @@ Handler::getPasswordService()
}
Handler::Handler(boost::filesystem::path db)
:
_dbBackend( db.string() )
Handler::Handler(Wt::Dbo::SqlConnectionPool& connectionPool)
{
_session.setConnection(_dbBackend);
_session.setConnectionPool(connectionPool);
_session.mapClass<Database::Artist>("artist");
_session.mapClass<Database::Genre>("genre");
_session.mapClass<Database::Track>("track");
@@ -94,17 +96,15 @@ _dbBackend( db.string() )
try {
_session.createTables();
_dbBackend.executeSql("CREATE INDEX artist_name_idx ON artist(name)");
_dbBackend.executeSql("CREATE INDEX genre_name_idx ON genre(name)");
_dbBackend.executeSql("CREATE INDEX release_name_idx ON release(name)");
_dbBackend.executeSql("CREATE INDEX track_name_idx ON track(name)");
_session.execute("CREATE INDEX artist_name_idx ON artist(name)");
_session.execute("CREATE INDEX genre_name_idx ON genre(name)");
_session.execute("CREATE INDEX release_name_idx ON release(name)");
_session.execute("CREATE INDEX track_name_idx ON track(name)");
}
catch(std::exception& e) {
LMS_LOG(MOD_DB, SEV_ERROR) << "Cannot create tables: " << e.what();
}
_dbBackend.executeSql("pragma journal_mode=WAL");
_users = new UserDatabase(_session);
}
@@ -149,5 +149,16 @@ Handler::getUser(const Wt::Auth::User& authUser)
return user;
}
Wt::Dbo::SqlConnectionPool*
Handler::createConnectionPool(boost::filesystem::path p)
{
Wt::Dbo::backend::Sqlite3 *connection = new Wt::Dbo::backend::Sqlite3(p.string());
connection->executeSql("pragma journal_mode=WAL");
// connection->setProperty("show-queries", "true");
return new Wt::Dbo::FixedSqlConnectionPool(connection, 10);
}
} // namespace Database
+4 -4
View File
@@ -23,7 +23,8 @@
#include <boost/filesystem.hpp>
#include <Wt/Dbo/Dbo>
#include <Wt/Dbo/backend/Sqlite3>
#include <Wt/Dbo/SqlConnectionPool>
#include <Wt/Auth/Dbo/UserDatabase>
#include <Wt/Auth/Login>
#include <Wt/Auth/PasswordService>
@@ -39,7 +40,7 @@ class Handler
{
public:
Handler(boost::filesystem::path db);
Handler(Wt::Dbo::SqlConnectionPool& connectionPool);
~Handler();
Wt::Dbo::Session& getSession() { return _session; }
@@ -56,12 +57,11 @@ class Handler
static const Wt::Auth::AuthService& getAuthService();
static const Wt::Auth::PasswordService& getPasswordService();
static Wt::Dbo::SqlConnectionPool* createConnectionPool(boost::filesystem::path db);
private:
Wt::Dbo::backend::Sqlite3 _dbBackend;
Wt::Dbo::Session _session;
UserDatabase* _users;
Wt::Auth::Login _login;
+2 -2
View File
@@ -39,11 +39,11 @@ namespace Server {
Connection::Connection(boost::asio::io_service& ioService,
boost::asio::ssl::context& context,
ConnectionManager& manager,
const boost::filesystem::path& dbPath)
Wt::Dbo::SqlConnectionPool& connectionPool)
: _closing(false),
_socket(ioService, context),
_connectionManager(manager),
_requestHandler(dbPath)
_requestHandler(connectionPool)
{
LMS_LOG(MOD_REMOTE, SEV_DEBUG) << "Server::Connection::Connection, Creating connection";
}
+1 -1
View File
@@ -50,7 +50,7 @@ class Connection : public std::enable_shared_from_this<Connection>
/// Construct a connection with the given io_service.
explicit Connection(boost::asio::io_service& ioService, boost::asio::ssl::context& context,
ConnectionManager& manager,
const boost::filesystem::path& dbPath);
Wt::Dbo::SqlConnectionPool& connectionPool);
ssl_socket::lowest_layer_type& getSocket() {return _socket.lowest_layer();}
+2 -2
View File
@@ -24,8 +24,8 @@
namespace LmsAPI {
namespace Server {
RequestHandler::RequestHandler(boost::filesystem::path dbPath)
: _db( dbPath ),
RequestHandler::RequestHandler(Wt::Dbo::SqlConnectionPool &connectionPool)
: _db( connectionPool ),
_authRequestHandler(_db),
_audioCollectionRequestHandler(_db),
_mediaRequestHandler(_db)
+2 -2
View File
@@ -20,7 +20,7 @@
#ifndef REMOTE_REQUEST_HANDLER
#define REMOTE_REQUEST_HANDLER
#include <boost/filesystem.hpp>
#include <Wt/Dbo/SqlConnectionPool>
#include "messages.pb.h"
@@ -37,7 +37,7 @@ class RequestHandler
{
public:
RequestHandler(boost::filesystem::path dbPath);
RequestHandler(Wt::Dbo::SqlConnectionPool& connectionPool);
~RequestHandler();
bool process(const ClientMessage& request, ServerMessage& response);
+3 -3
View File
@@ -34,12 +34,12 @@ Server::Server(const endpoint_type& bindEndpoint,
boost::filesystem::path certPath,
boost::filesystem::path privKeyPath,
boost::filesystem::path dhPath,
boost::filesystem::path dbPath)
Wt::Dbo::SqlConnectionPool& connectionPool)
:
_acceptor(_ioService, bindEndpoint, true /*SO_REUSEADDR*/),
_connectionManager(),
_context(boost::asio::ssl::context::tlsv1_server),
_dbPath(dbPath)
_connectionPool(connectionPool)
{
_ioService.setThreadCount(1); // TODO parametrize
@@ -68,7 +68,7 @@ Server::start()
void
Server::asyncAccept()
{
std::shared_ptr<Connection> newConnection = std::make_shared<Connection>(_ioService, _context, _connectionManager, _dbPath);
std::shared_ptr<Connection> newConnection = std::make_shared<Connection>(_ioService, _context, _connectionManager, _connectionPool);
_acceptor.async_accept(newConnection->getSocket(),
boost::bind(&Server::handleAccept, this, newConnection, boost::asio::placeholders::error));
+3 -2
View File
@@ -21,6 +21,7 @@
#define REMOTE_SERVER_HPP
#include <Wt/WIOService>
#include <Wt/Dbo/SqlConnectionPool>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
@@ -49,7 +50,7 @@ class Server
boost::filesystem::path certPath,
boost::filesystem::path privKeyPath,
boost::filesystem::path dhPath,
boost::filesystem::path dbPath);
Wt::Dbo::SqlConnectionPool& connectionPool);
// Run the server's io_service loop.
void start();
@@ -72,7 +73,7 @@ class Server
boost::asio::ssl::context _context;
/// The database to be used for requests
boost::filesystem::path _dbPath;
Wt::Dbo::SqlConnectionPool& _connectionPool;
};
} // namespace Server
+6 -4
View File
@@ -73,12 +73,15 @@ int main(int argc, char* argv[])
Transcode::AvConvTranscoder::init();
Database::Handler::configureAuth();
// Initializing a connection pool to the database that will be shared along services
std::unique_ptr<Wt::Dbo::SqlConnectionPool> connectionPool( Database::Handler::createConnectionPool( ConfigReader::instance().getString("main.database.path") ));
LMS_LOG(MOD_MAIN, SEV_INFO) << "Starting services...";
serviceManager.startService( std::make_shared<Service::DatabaseUpdateService>() );
serviceManager.startService( std::make_shared<Service::UserInterfaceService>(boost::filesystem::path(argv[0])));
serviceManager.startService( std::make_shared<Service::DatabaseUpdateService>(*connectionPool));
serviceManager.startService( std::make_shared<Service::UserInterfaceService>(boost::filesystem::path(argv[0]), *connectionPool));
#if defined HAVE_LMSAPI
serviceManager.startService( std::make_shared<Service::LmsAPIService>( ));
serviceManager.startService( std::make_shared<Service::LmsAPIService>(*connectionPool));
#endif
LMS_LOG(MOD_MAIN, SEV_NOTICE) << "Now running...";
@@ -86,7 +89,6 @@ int main(int argc, char* argv[])
serviceManager.run();
res = EXIT_SUCCESS;
}
// TODO catch setting not found exception
catch( libconfig::ParseException& e)
+2 -3
View File
@@ -38,10 +38,9 @@ static std::vector<std::string> splitStrings(const std::string& source)
namespace Service {
DatabaseUpdateService::DatabaseUpdateService()
DatabaseUpdateService::DatabaseUpdateService(Wt::Dbo::SqlConnectionPool &connectionPool)
: _metadataParser(),
_databaseUpdater( ConfigReader::instance().getString("main.database.path"),
_metadataParser)
_databaseUpdater( connectionPool, _metadataParser)
{
_databaseUpdater.setAudioExtensions(splitStrings(ConfigReader::instance().getString("main.database.audio_extensions")));
_databaseUpdater.setVideoExtensions(splitStrings(ConfigReader::instance().getString("main.database.video_extensions")));
+1 -1
View File
@@ -36,7 +36,7 @@ class DatabaseUpdateService : public Service
typedef std::shared_ptr<DatabaseUpdateService> pointer;
DatabaseUpdateService();
DatabaseUpdateService(Wt::Dbo::SqlConnectionPool &connectionPool);
// Service interface
void start(void);
+2 -2
View File
@@ -26,7 +26,7 @@
namespace Service {
LmsAPIService::LmsAPIService()
LmsAPIService::LmsAPIService(Wt::Dbo::SqlConnectionPool& connectionPool)
: _server(
boost::asio::ip::tcp::endpoint(
boost::asio::ip::address::from_string(ConfigReader::instance().getString("remote.listen-endpoint.addr")),
@@ -34,7 +34,7 @@ LmsAPIService::LmsAPIService()
ConfigReader::instance().getString("remote.ssl-crypto.cert"),
ConfigReader::instance().getString("remote.ssl-crypto.key"),
ConfigReader::instance().getString("remote.ssl-crypto.dh"),
ConfigReader::instance().getString("main.database.path"))
connectionPool)
{
}
+2 -2
View File
@@ -20,7 +20,7 @@
#ifndef REMOTE_SERVER_SERVICE_HPP
#define REMOTE_SERVER_SERVICE_HPP
#include <boost/filesystem.hpp>
#include <Wt/Dbo/SqlConnectionPool>
#include "config/config.h"
@@ -34,7 +34,7 @@ class LmsAPIService : public Service
{
public:
LmsAPIService();
LmsAPIService(Wt::Dbo::SqlConnectionPool& connectionPool);
void start(void);
void stop(void);
+4 -2
View File
@@ -17,6 +17,8 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/Dbo/SqlConnectionPool>
#include "logger/Logger.hpp"
#include "UserInterfaceService.hpp"
@@ -26,7 +28,7 @@
namespace Service {
UserInterfaceService::UserInterfaceService( boost::filesystem::path runAppPath)
UserInterfaceService::UserInterfaceService( boost::filesystem::path runAppPath, Wt::Dbo::SqlConnectionPool& connectionPool)
: _server(runAppPath.string())
{
std::vector<std::string> args;
@@ -54,7 +56,7 @@ UserInterfaceService::UserInterfaceService( boost::filesystem::path runAppPath)
_server.setServerConfiguration (argc, const_cast<char**>(argv));
// bind entry point
_server.addEntryPoint(Wt::Application, boost::bind(UserInterface::LmsApplication::create, _1, ConfigReader::instance().getString("main.database.path")));
_server.addEntryPoint(Wt::Application, boost::bind(UserInterface::LmsApplication::create, _1, boost::ref(connectionPool)));
}
+1 -1
View File
@@ -32,7 +32,7 @@ class UserInterfaceService : public Service
{
public:
UserInterfaceService(boost::filesystem::path runAppPath);
UserInterfaceService(boost::filesystem::path runAppPath, Wt::Dbo::SqlConnectionPool& connectionPool);
void start(void);
void stop(void);
+5 -4
View File
@@ -63,13 +63,13 @@ bool agentIsMobile()
namespace UserInterface {
Wt::WApplication*
LmsApplication::create(const Wt::WEnvironment& env, boost::filesystem::path dbPath)
LmsApplication::create(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool)
{
/*
* You could read information from the environment to decide whether
* the user has permission to start a new application
*/
return new LmsApplication(env, dbPath);
return new LmsApplication(env, connectionPool);
}
LmsApplication*
@@ -84,9 +84,9 @@ LmsApplication::instance()
* constructor so it is typically also an argument for your custom
* application constructor.
*/
LmsApplication::LmsApplication(const Wt::WEnvironment& env, boost::filesystem::path dbPath)
LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool)
: Wt::WApplication(env),
_db(dbPath),
_db(connectionPool),
_coverResource(nullptr)
{
@@ -182,6 +182,7 @@ LmsApplication::handleAuthEvent(void)
Wt::WStackedWidget *contentsStack = new Wt::WStackedWidget();
contentsStack->setOverflow(Wt::WContainerWidget::OverflowAuto);
contentsStack->addStyleClass("contents");
// Setup a Left-aligned menu.
Wt::WMenu *leftMenu = new Wt::WMenu(contentsStack);
+4 -2
View File
@@ -23,6 +23,8 @@
#include <boost/filesystem.hpp>
#include <Wt/WApplication>
#include <Wt/Dbo/SqlConnectionPool>
#include "database/DatabaseHandler.hpp"
#include "resource/CoverResource.hpp"
@@ -31,10 +33,10 @@ namespace UserInterface {
class LmsApplication : public Wt::WApplication
{
public:
static Wt::WApplication *create(const Wt::WEnvironment& env, boost::filesystem::path dbPath);
static Wt::WApplication *create(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool);
static LmsApplication* instance();
LmsApplication(const Wt::WEnvironment& env, boost::filesystem::path dbPath);
LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool);
// Session application data
CoverResource* getCoverResource() { return _coverResource; }