Splitting services, begin the switch to a more integrated Wt daemon

This commit is contained in:
epoupon
2015-09-07 12:43:21 +02:00
parent de62abdf0f
commit 614b05105a
13 changed files with 72 additions and 312 deletions
-35
View File
@@ -26,38 +26,3 @@ main = {
}
}
ui = {
resources = {
docroot = "/var/lms/docroot"
approot = "/var/lms/approot"
}
listen-endpoint = {
port = 5081;
addr = "0.0.0.0";
}
ssl-crypto = {
cert = "/var/lms/certs/certUI.pem";
key = "/var/lms/private/privkeyUI.pem";
dh = "/var/lms/dh/dh2048.pem";
}
}
remote = {
nb-threads = 1;
listen-endpoint = {
port = 5080;
addr = "0.0.0.0";
}
ssl-crypto = {
cert = "/var/lms/certs/certRemote.pem";
key = "/var/lms/private/privkeyRemote.pem";
dh = "/var/lms/dh/dh2048.pem";
}
}

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

-1
View File
@@ -28,7 +28,6 @@ lms_SOURCES = \
$(srcdir)/metadata/Utils.cpp \
$(srcdir)/service/ServiceManager.cpp \
$(srcdir)/service/DatabaseUpdateService.cpp \
$(srcdir)/service/UserInterfaceService.cpp \
$(srcdir)/transcode/AvConvTranscoder.cpp \
$(srcdir)/transcode/Format.cpp \
$(srcdir)/transcode/Parameters.cpp \
+3
View File
@@ -79,6 +79,7 @@ Handler::Handler(Wt::Dbo::SqlConnectionPool& connectionPool)
{
_session.setConnectionPool(connectionPool);
_session.mapClass<Database::Artist>("artist");
_session.mapClass<Database::Genre>("genre");
_session.mapClass<Database::Track>("track");
@@ -95,6 +96,8 @@ Handler::Handler(Wt::Dbo::SqlConnectionPool& connectionPool)
_session.mapClass<Database::AuthInfo::AuthTokenType>("auth_token");
try {
Wt::Dbo::Transaction transaction(_session);
_session.createTables();
_session.execute("CREATE INDEX artist_name_idx ON artist(name)");
_session.execute("CREATE INDEX genre_name_idx ON genre(name)");
+13 -13
View File
@@ -81,6 +81,19 @@ Logger::init()
boost::log::register_simple_formatter_factory< Severity, char >("Severity");
if (ConfigReader::instance().getBool("main.logger.console.enable", false))
{
boost::log::add_console_log(std::cout,
boost::log::keywords::format = (
boost::log::expressions::stream
<< boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "[%Y-%m-%d %H:%M:%S]")
<< " [" << boost::log::expressions::attr< Module >("Module") << "]"
<< " [" << boost::log::expressions::attr< Severity >("Severity") << "]"
<< " " << boost::log::expressions::smessage
)
);
}
if (ConfigReader::instance().getBool("main.logger.file.enable", false))
{
boost::log::add_file_log
@@ -99,19 +112,6 @@ Logger::init()
);
}
if (ConfigReader::instance().getBool("main.logger.console.enable", false))
{
boost::log::add_console_log(std::cout,
boost::log::keywords::format = (
boost::log::expressions::stream
<< boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "[%Y-%m-%d %H:%M:%S]")
<< " [" << boost::log::expressions::attr< Module >("Module") << "]"
<< " [" << boost::log::expressions::attr< Severity >("Severity") << "]"
<< " " << boost::log::expressions::smessage
)
);
}
boost::log::core::get()->set_filter
(
boost::log::expressions::attr<Severity>("Severity") <= ConfigReader::instance().getULong("main.logger.level", SEV_DEBUG)
+30 -24
View File
@@ -26,16 +26,18 @@
#include "logger/Logger.hpp"
#include "cover/CoverArtGrabber.hpp"
#include "ui/LmsApplication.hpp"
#include "service/ServiceManager.hpp"
#include "service/DatabaseUpdateService.hpp"
#include "service/UserInterfaceService.hpp"
#if defined HAVE_LMSAPI
#include "service/LmsAPIServerService.hpp"
#endif
#include <Wt/WServer>
int main(int argc, char* argv[])
{
int res = EXIT_FAILURE;
assert(argc > 0);
@@ -43,25 +45,10 @@ int main(int argc, char* argv[])
try
{
// TODO generate a nice command line help with args
// Open configuration file
boost::filesystem::path configFile("/etc/lms.conf"); // TODO
if (argc > 1)
configFile = boost::filesystem::path(argv[1]);
boost::filesystem::path configFilePath("/etc/lms.conf"); // TODO use $confdir from autotools
if ( !boost::filesystem::exists(configFile))
{
std::cerr << "Config file '" << configFile << "' does not exist!" << std::endl;
return EXIT_FAILURE;
}
else if (!boost::filesystem::is_regular(configFile))
{
std::cerr << "Config file '" << configFile << "' is not regular!" << std::endl;
return EXIT_FAILURE;
}
ConfigReader::instance().setFile(configFile);
ConfigReader::instance().setFile(configFilePath);
Logger::instance().init();
CoverArt::Grabber::instance().init();
@@ -76,17 +63,36 @@ int main(int argc, char* argv[])
// 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>(*connectionPool));
serviceManager.startService( std::make_shared<Service::UserInterfaceService>(boost::filesystem::path(argv[0]), *connectionPool));
serviceManager.add( std::make_shared<Service::DatabaseUpdateService>(*connectionPool));
#if defined HAVE_LMSAPI
serviceManager.startService( std::make_shared<Service::LmsAPIService>(*connectionPool));
serviceManager.add( std::make_shared<Service::LmsAPIService>(*connectionPool));
#endif
Wt::WServer server(argv[0]);
server.setServerConfiguration (argc, argv);
// bind entry point
server.addEntryPoint(Wt::Application, boost::bind(UserInterface::LmsApplication::create, _1, boost::ref(*connectionPool)));
LMS_LOG(MOD_MAIN, SEV_NOTICE) << "Now running...";
serviceManager.run();
// Start underlying services
LMS_LOG(MOD_MAIN, SEV_INFO) << "Starting services...";
serviceManager.start();
// Starting the main server
LMS_LOG(MOD_MAIN, SEV_INFO) << "Starting server...";
server.start();
// Waiting for shutdown command
Wt::WServer::waitForShutdown(argv[0]);
LMS_LOG(MOD_MAIN, SEV_INFO) << "Stopping server...";
server.stop();
LMS_LOG(MOD_MAIN, SEV_INFO) << "Stopping services...";
serviceManager.stop();
res = EXIT_SUCCESS;
}
+15 -79
View File
@@ -19,9 +19,6 @@
#include "logger/Logger.hpp"
#include <boost/foreach.hpp>
#include <boost/bind.hpp>
#include "ServiceManager.hpp"
namespace Service {
@@ -34,112 +31,51 @@ ServiceManager::instance()
}
ServiceManager::ServiceManager()
: _signalSet(_ioService)
{
_signalSet.add(SIGINT);
_signalSet.add(SIGTERM);
#if defined(SIGQUIT)
_signalSet.add(SIGQUIT);
#endif // defined(SIGQUIT)
_signalSet.add(SIGHUP);
// Excplicitely ignore SIGCHLD to avoid zombies
// when avconv child processes are being killed
if (::signal(SIGCHLD, SIG_IGN) == SIG_ERR)
throw std::runtime_error("ServiceManager::ServiceManager, signal failed!");
}
ServiceManager::~ServiceManager()
{
LMS_LOG(MOD_SERVICE, SEV_NOTICE) << "Stopping services...";
stopServices();
stop();
}
void
ServiceManager::run()
{
asyncWaitSignals();
LMS_LOG(MOD_SERVICE, SEV_DEBUG) << "ServiceManager: waiting for events...";
try {
// Wait for events
_ioService.run();
}
catch( std::exception& e )
{
LMS_LOG(MOD_SERVICE, SEV_ERROR) << "ServiceManager: exception in ioService::run: " << e.what();
}
// Stopping services
stopServices();
LMS_LOG(MOD_SERVICE, SEV_DEBUG) << "ServiceManager: run complete !";
}
void
ServiceManager::asyncWaitSignals(void)
{
_signalSet.async_wait(boost::bind(&ServiceManager::handleSignal,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::signal_number));
}
void
ServiceManager::startService(Service::pointer service)
ServiceManager::add(Service::pointer service)
{
_services.insert(service);
service->start();
}
void
ServiceManager::stopService(Service::pointer service)
ServiceManager::del(Service::pointer service)
{
_services.erase(service);
service->stop();
_services.erase(service);
}
void
ServiceManager::stopServices(void)
ServiceManager::start(void)
{
BOOST_FOREACH(Service::pointer service, _services)
for (Service::pointer service : _services)
service->start();
}
void
ServiceManager::stop(void)
{
for (Service::pointer service : _services)
service->stop();
}
void
ServiceManager::restartServices(void)
ServiceManager::restart(void)
{
LMS_LOG(MOD_SERVICE, SEV_NOTICE) << "Restarting services...";
BOOST_FOREACH(Service::pointer service, _services)
for (Service::pointer service : _services)
service->restart();
}
void
ServiceManager::handleSignal(boost::system::error_code /*ec*/, int signo)
{
LMS_LOG(MOD_SERVICE, SEV_INFO) << "Received signal " << signo;
switch (signo)
{
case SIGINT:
case SIGTERM:
case SIGQUIT:
stopServices();
// Do not listen for signals, this will make the ioservice.run return
break;
case SIGHUP:
restartServices();
asyncWaitSignals();
break;
default:
LMS_LOG(MOD_SERVICE, SEV_NOTICE) << "Unhandled signal " << signo;
}
}
} // namespace Service
+10 -24
View File
@@ -20,7 +20,6 @@
#ifndef SERVICE_CONTROLER_HPP
#define SERVICE_CONTROLER_HPP
#include <boost/asio.hpp>
#include <set>
#include "Service.hpp"
@@ -35,15 +34,14 @@ class ServiceManager
static ServiceManager& instance();
~ServiceManager();
void stopService(Service::pointer service);
void startService(Service::pointer service);
void add(Service::pointer service);
void del(Service::pointer service);
void stopAllServices();
void start();
void stop();
void restart();
// Return in case of failure/stop by user
void run();
template <class T> typename T::pointer getService();
template <class T> typename T::pointer get();
boost::mutex& mutex() { return _mutex;}
@@ -53,32 +51,20 @@ class ServiceManager
ServiceManager(ServiceManager const&); // Don't Implement
void operator=(ServiceManager const&); // Don't implement
void restartServices(void);
void stopServices(void);
void asyncWaitSignals(void);
void handleSignal(boost::system::error_code error, int signo);
boost::mutex _mutex;
boost::asio::io_service _ioService;
// Listen for interesting signals
boost::asio::signal_set _signalSet;
std::set<Service::pointer> _services;
};
template <class T> typename T::pointer
ServiceManager::getService()
ServiceManager::get()
{
std::set<Service::pointer>::iterator it;
for (std::set<Service::pointer>::iterator it = _services.begin(); it != _services.end(); ++it)
for (Service::pointer service : _services)
{
if (typeid(*(*it)) == typeid(T)) {
return std::dynamic_pointer_cast<T>(*it);
if (typeid(*(service)) == typeid(T)) {
return std::dynamic_pointer_cast<T>(service);
}
}
return std::shared_ptr<T>();
-85
View File
@@ -1,85 +0,0 @@
/*
* Copyright (C) 2013 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/Dbo/SqlConnectionPool>
#include "logger/Logger.hpp"
#include "UserInterfaceService.hpp"
#include "ui/LmsApplication.hpp"
#include "config/ConfigReader.hpp"
namespace Service {
UserInterfaceService::UserInterfaceService( boost::filesystem::path runAppPath, Wt::Dbo::SqlConnectionPool& connectionPool)
: _server(runAppPath.string())
{
std::vector<std::string> args;
args.push_back(runAppPath.string());
args.push_back("--docroot=" + ConfigReader::instance().getString("ui.resources.docroot"));
args.push_back("--approot=" + ConfigReader::instance().getString("ui.resources.approot"));
args.push_back("--https-port=" + std::to_string( ConfigReader::instance().getULong("ui.listen-endpoint.port")));
args.push_back("--https-address=" + ConfigReader::instance().getString("ui.listen-endpoint.addr"));
args.push_back("--ssl-certificate=" + ConfigReader::instance().getString("ui.ssl-crypto.cert"));
args.push_back("--ssl-private-key=" + ConfigReader::instance().getString("ui.ssl-crypto.key"));
args.push_back("--ssl-tmp-dh=" + ConfigReader::instance().getString("ui.ssl-crypto.dh"));
// Construct argc/argv
int argc = args.size();
const char* argv[args.size()];
for (int i = 0; i < argc; ++i)
argv[i] = args[i].c_str();
for(int i = 0; i < argc; ++i)
{
LMS_LOG(MOD_SERVICE, SEV_DEBUG) << "i = " << i << ", arg = '" << argv[i] << "'";
}
_server.setServerConfiguration (argc, const_cast<char**>(argv));
// bind entry point
_server.addEntryPoint(Wt::Application, boost::bind(UserInterface::LmsApplication::create, _1, boost::ref(connectionPool)));
}
void
UserInterfaceService::start(void)
{
_server.start();
LMS_LOG(MOD_SERVICE, SEV_DEBUG) << "UserInterfaceService::start -> Service started...";
}
void
UserInterfaceService::stop(void)
{
LMS_LOG(MOD_SERVICE, SEV_DEBUG) << "UserInterfaceService::stop -> stopping...";
_server.stop();
LMS_LOG(MOD_SERVICE, SEV_DEBUG) << "UserInterfaceService::stop -> stopped!";
}
void
UserInterfaceService::restart(void)
{
}
} // namespace Service
-50
View File
@@ -1,50 +0,0 @@
/*
* Copyright (C) 2013 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WEB_SERVER_SERVICE_HPP
#define WEB_SERVER_SERVICE_HPP
#include <boost/filesystem.hpp>
#include <Wt/WServer>
#include "Service.hpp"
namespace Service {
class UserInterfaceService : public Service
{
public:
UserInterfaceService(boost::filesystem::path runAppPath, Wt::Dbo::SqlConnectionPool& connectionPool);
void start(void);
void stop(void);
void restart(void);
private:
Wt::WServer _server;
};
} //namespace Service
#endif
+1 -1
View File
@@ -107,7 +107,7 @@ Settings::restartDatabaseUpdateService()
// Restarting the update service
boost::lock_guard<boost::mutex> serviceLock (Service::ServiceManager::instance().mutex());
Service::DatabaseUpdateService::pointer service = Service::ServiceManager::instance().getService<Service::DatabaseUpdateService>();
Service::DatabaseUpdateService::pointer service = Service::ServiceManager::instance().get<Service::DatabaseUpdateService>();
if (service)
service->restart();
}