Splitting services, begin the switch to a more integrated Wt daemon
This commit is contained in:
@@ -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 |
@@ -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 \
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
service->stop();
|
||||
_services.erase(service);
|
||||
service->stop();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user