Headless server: simplify system config logger

This commit is contained in:
Felix Kauselmann
2018-01-28 13:32:56 +01:00
commit 2cbbf8d433
1048 changed files with 104347 additions and 0 deletions

View File

@ -0,0 +1,161 @@
TEMPLATE = app
TARGET = YACReaderLibraryServer
QMAKE_TARGET_BUNDLE_PREFIX = "com.yacreader"
CONFIG += console
DEPENDPATH += ../YACReaderLibrary
INCLUDEPATH += ../YACReaderLibrary \
../common \
../YACReaderLibrary/server \
../YACReaderLibrary/db
DEFINES += SERVER_RELEASE NOMINMAX YACREADER_LIBRARY QT_NO_DEBUG_OUTPUT
QMAKE_MAC_SDK = macosx10.12
# load default build flags
# do a basic dependency check
include(headless_config.pri)
include(../dependencies/pdf_backend.pri)
win32 {
LIBS += -loleaut32 -lole32 -lshell32 -luser32
QMAKE_CXXFLAGS_RELEASE += /MP /Ob2 /Oi /Ot /GT /GL
QMAKE_LFLAGS_RELEASE += /LTCG
CONFIG -= embed_manifest_exe
}
macx {
LIBS += -framework Foundation -framework ApplicationServices -framework AppKit
CONFIG += objective_c
}
unix {
CONFIG += c++11
}
unix:haiku {
DEFINES += _BSD_SOURCE
LIBS += -lnetwork -lbsd
}
#CONFIG += release
CONFIG -= flat
QT += core sql network
# Source files
HEADERS += ../YACReaderLibrary/library_creator.h \
../YACReaderLibrary/package_manager.h \
../YACReaderLibrary/bundle_creator.h \
../YACReaderLibrary/db_helper.h \
../YACReaderLibrary/db/data_base_management.h \
../common/comic_db.h \
../common/folder.h \
../common/library_item.h \
../common/comic.h \
../common/pdf_comic.h \
../common/bookmarks.h \
../common/qnaturalsorting.h \
../common/yacreader_global.h \
../YACReaderLibrary/yacreader_local_server.h \
../YACReaderLibrary/comics_remover.h \
../common/http_worker.h \
../YACReaderLibrary/yacreader_libraries.h \
../YACReaderLibrary/comic_files_manager.h \
console_ui_library_creator.h
SOURCES += ../YACReaderLibrary/library_creator.cpp \
../YACReaderLibrary/package_manager.cpp \
../YACReaderLibrary/bundle_creator.cpp \
../YACReaderLibrary/db_helper.cpp \
../YACReaderLibrary/db/data_base_management.cpp \
../common/comic_db.cpp \
../common/folder.cpp \
../common/library_item.cpp \
../common/comic.cpp \
../common/bookmarks.cpp \
../common/qnaturalsorting.cpp \
../YACReaderLibrary/yacreader_local_server.cpp \
../YACReaderLibrary/comics_remover.cpp \
../common/http_worker.cpp \
../common/yacreader_global.cpp \
../YACReaderLibrary/yacreader_libraries.cpp \
../YACReaderLibrary/comic_files_manager.cpp \
console_ui_library_creator.cpp \
main.cpp
include(../YACReaderLibrary/server/server.pri)
CONFIG(7zip) {
include(../compressed_archive/wrapper.pri)
} else:CONFIG(unarr) {
include(../compressed_archive/unarr/unarr-wrapper.pri)
} else {
error(No compression backend specified. Did you mess with the build system?)
}
include(../QsLog/QsLog.pri)
TRANSLATIONS = yacreaderlibraryserver_es.ts \
yacreaderlibraryserver_ru.ts \
yacreaderlibraryserver_pt.ts \
yacreaderlibraryserver_fr.ts \
yacreaderlibraryserver_nl.ts \
yacreaderlibraryserver_tr.ts \
yacreaderlibraryserver_de.ts \
yacreaderlibraryserver_source.ts
RESOURCES += images.qrc
contains(QMAKE_TARGET.arch, x86_64) {
Release:DESTDIR = ../release64
Debug:DESTDIR = ../debug64
} else {
Release:DESTDIR = ../release
Debug:DESTDIR = ../debug
}
unix:!macx {
#set install prefix if it's empty
isEmpty(PREFIX) {
PREFIX = /usr
}
BINDIR = $$PREFIX/bin
LIBDIR = $$PREFIX/lib
DATADIR = $$PREFIX/share
DEFINES += "LIBDIR=\\\"$$LIBDIR\\\"" "DATADIR=\\\"$$DATADIR\\\"" "BINDIR=\\\"$$BINDIR\\\""
#make install
CONFIG(server_standalone) {
INSTALLS += bin server translation systemd
}
else:CONFIG(server_bundled) {
INSTALLS += bin systemd
}
else {
INSTALLS += bin server translation systemd
message("No build type specified. Defaulting to standalone server build (CONFIG+=server_standalone).")
message("If you wish to run YACReaderLibraryServer on a system with an existing install of YACReaderLibrary,\
please specify CONFIG+=server_bundled as an option when running qmake.")
}
bin.path = $$BINDIR
isEmpty(DESTDIR) {
bin.files = YACReaderLibraryServer
} else {
bin.files = $$DESTDIR/YACReaderLibraryServer
}
server.path = $$DATADIR/yacreader
server.files = ../release/server
systemd.path = $$LIBDIR/systemd/user
systemd.files = yacreaderlibraryserver.service
translation.path = $$DATADIR/yacreader/languages
translation.files = ../release/languages/yacreaderlibrary_*
# TODO: We need a manpage for yaclibserver
#manpage.path = $$DATADIR/man/man1
#manpage.files = ../YACReaderLibrary.1
}

View File

@ -0,0 +1,148 @@
#include "console_ui_library_creator.h"
#include <iostream>
#include "library_creator.h"
#include "yacreader_libraries.h"
ConsoleUILibraryCreator::ConsoleUILibraryCreator(QObject *parent) :
QObject(parent), numComicsProcessed(0)
{
}
void ConsoleUILibraryCreator::createLibrary(const QString & name, const QString & path)
{
QEventLoop eventLoop;
LibraryCreator * libraryCreator = new LibraryCreator();
QDir pathDir(path);
if (!pathDir.exists())
{
std::cout << "Directory not found." << std::endl;
return;
}
QString cleanPath = QDir::cleanPath(pathDir.absolutePath());
YACReaderLibraries yacreaderLibraries;
yacreaderLibraries.load();
if (yacreaderLibraries.contains(name))
{
std::cout << "A Library named \"" << name.toUtf8().constData() << "\" already exists in database." << std::endl;
return;
}
libraryCreator->createLibrary(cleanPath,QDir::cleanPath(pathDir.absolutePath()+"/.yacreaderlibrary"));
connect(libraryCreator, &LibraryCreator::finished, this, &ConsoleUILibraryCreator::done);
connect(libraryCreator, &LibraryCreator::comicAdded, this, &ConsoleUILibraryCreator::newComic);
connect(libraryCreator, &LibraryCreator::failedCreatingDB, this, &ConsoleUILibraryCreator::manageCreatingError);
connect(libraryCreator, &LibraryCreator::finished, &eventLoop, &QEventLoop::quit);
std::cout << "Processing comics";
libraryCreator->start();
eventLoop.exec();
yacreaderLibraries.addLibrary(name, cleanPath);
yacreaderLibraries.save();
}
void ConsoleUILibraryCreator::updateLibrary(const QString & path)
{
QEventLoop eventLoop;
LibraryCreator * libraryCreator = new LibraryCreator();
QDir pathDir(path);
if (!pathDir.exists())
{
std::cout << "Directory not found." << std::endl;
return;
}
QString cleanPath = QDir::cleanPath(pathDir.absolutePath());
libraryCreator->updateLibrary(cleanPath,QDir::cleanPath(pathDir.absolutePath()+"/.yacreaderlibrary"));
connect(libraryCreator, &LibraryCreator::finished, this, &ConsoleUILibraryCreator::done);
connect(libraryCreator, &LibraryCreator::comicAdded, this, &ConsoleUILibraryCreator::newComic);
connect(libraryCreator, &LibraryCreator::failedOpeningDB, this, &ConsoleUILibraryCreator::manageUpdatingError);
connect(libraryCreator, &LibraryCreator::finished, &eventLoop, &QEventLoop::quit);
std::cout << "Processing comics";
libraryCreator->start();
eventLoop.exec();
}
void ConsoleUILibraryCreator::addExistingLibrary(const QString & name, const QString & path)
{
QDir pathDir(path);
if (!pathDir.exists())
{
std::cout << "Directory not found." << std::endl;
return;
}
QString cleanPath = QDir::cleanPath(pathDir.absolutePath());
if (!QDir(cleanPath + "/.yacreaderlibrary").exists())
{
std::cout << "No library database found in directory." << std::endl;
return;
}
YACReaderLibraries yacreaderLibraries;
yacreaderLibraries.load();
if (yacreaderLibraries.contains(name))
{
std::cout << "A Library named \"" << name.toUtf8().constData() << "\" already exists in the database." << std::endl;
return;
}
yacreaderLibraries.addLibrary(name, cleanPath);
yacreaderLibraries.save();
std::cout << "Library added : " << name.toUtf8().constData() << " at " << cleanPath.toUtf8().constData() << std::endl;
}
void ConsoleUILibraryCreator::removeLibrary(const QString & name)
{
//TODO add error handling
YACReaderLibraries yacreaderLibraries;
yacreaderLibraries.load();
if (!yacreaderLibraries.contains(name))
{
std::cout << "No Library named \"" << name.toUtf8().constData() << "\" in database." << std::endl;
return;
}
yacreaderLibraries.remove(name);
yacreaderLibraries.save();
std::cout << "Library removed : " << name.toUtf8().constData() << std::endl;
}
void ConsoleUILibraryCreator::newComic(const QString & /*relativeComicPath*/, const QString & /*coverPath*/)
{
numComicsProcessed++;
std::cout << ".";
}
void ConsoleUILibraryCreator::manageCreatingError(const QString & error)
{
std::cout << std::endl << "Error creating library! " << error.toUtf8().constData() << std::endl;
}
void ConsoleUILibraryCreator::manageUpdatingError(const QString & error)
{
std::cout << std::endl << "Error updating library! " << error.toUtf8().constData() << std::endl;
}
void ConsoleUILibraryCreator::done()
{
std::cout << "Done!" << std::endl;
if(numComicsProcessed > 0)
std::cout << "Number of comics processed = " << numComicsProcessed << std::endl;
}

View File

@ -0,0 +1,29 @@
#ifndef CONSOLE_UI_LIBRARY_CREATOR_H
#define CONSOLE_UI_LIBRARY_CREATOR_H
#include <QtCore>
class ConsoleUILibraryCreator : public QObject
{
Q_OBJECT
public:
explicit ConsoleUILibraryCreator(QObject *parent = 0);
void createLibrary(const QString & name, const QString & path);
void updateLibrary(const QString & path);
void addExistingLibrary(const QString & name, const QString & path);
void removeLibrary(const QString & name);
private:
uint numComicsProcessed;
signals:
public slots:
protected slots:
void newComic(const QString & relativeComicPath, const QString & coverPath);
void manageCreatingError(const QString & error);
void manageUpdatingError(const QString & error);
void done();
};
#endif // CONSOLE_UI_LIBRARY_CREATOR_H

View File

@ -0,0 +1,37 @@
# functions to automatically initialize some of YACReaderLibraryServer's build
# options to default values if they're not set at build time
# for a more detailed description, see INSTALL.TXT
include (../config.pri)
unix!macx {
!contains(QT_CONFIG, no-pkg-config) {
packagesExist(Qt5Core) {
message("Found Qt5Core")
} else: {
message("Missing dependency: Qt5Core")
}
packagesExist(Qt5Gui) {
message("Found Qt5Gui")
} else: {
message("Missing dependency: Qt5Gui")
}
packagesExist(Qt5Network) {
message("Found Qt5Network")
} else: {
message("Missing dependency: Qt5Network")
}
packagesExist(Qt5Sql) {
message("Found Qt5Sql")
} else: {
message("Missing dependency: Qt5Sql")
}
packagesExist(sqlite3) {
message("Found sqlite3")
} else: {
message("Missing dependency: sqlite3")
}
} else {
message("Qmake was compiled without support for pkg-config. Skipping dependency checks.")
}
}

View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/">
<file>../images/f_overlayed.png</file>
<file>../images/f_overlayed_retina.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,251 @@
#include <QtCore>
#include "comic_db.h"
#include "db_helper.h"
#include "startup.h"
#include "yacreader_global.h"
#include "yacreader_libraries.h"
#include "yacreader_local_server.h"
#include "console_ui_library_creator.h"
#include "QsLog.h"
#include "QsLogDest.h"
using namespace QsLogging;
void logSystemAndConfig()
{
QLOG_INFO() << "---------- System & configuration ----------";
QLOG_INFO() << "OS: " + QSysInfo::prettyProductName() + ", Version: " + QSysInfo::productVersion();
QLOG_INFO() << "Kernel: " + QSysInfo::kernelType() + " " + QSysInfo::kernelVersion() + " Architecture: " + QSysInfo::currentCpuArchitecture();
/* TODO: qrencode could be helpfull for showing a qr code in the web client for client devices
#if defined Q_OS_UNIX && !defined Q_OS_MAC
if(QFileInfo(QString(BINDIR)+"/qrencode").exists())
#else
if(QFileInfo(QCoreApplication::applicationDirPath()+"/utils/qrencode.exe").exists() || QFileInfo("./util/qrencode").exists())
#endif
QLOG_INFO() << "qrencode : found";
else
QLOG_INFO() << "qrencode : not found";
*/
QLOG_INFO() << "Libraries: " << DBHelper::getLibraries().getLibraries();
QLOG_INFO() << "--------------------------------------------";
}
int main( int argc, char ** argv )
{
QCoreApplication *app = new QCoreApplication(argc, argv);
app->setApplicationName("YACReaderLibrary");
app->setOrganizationName("YACReader");
app->setApplicationVersion(VERSION);
QTextStream qout(stdout);
//general help
QCommandLineParser parser;
parser.setApplicationDescription(QCoreApplication::tr("\nYACReaderLibraryServer is the headless (no gui) version of YACReaderLibrary"));
parser.addHelpOption();
parser.addVersionOption();
parser.addPositionalArgument("command", "The command to execute. [start, create-library, update-library, add-library, remove-library, list-libraries]");
parser.parse(QCoreApplication::arguments());
const QStringList args = parser.positionalArguments();
const QString command = args.isEmpty() ? QString() : args.first();
if(command == "start")
{
QString destLog = YACReader::getSettingsPath()+"/yacreaderlibrary.log";
QDir().mkpath(YACReader::getSettingsPath());
Logger& logger = Logger::instance();
logger.setLoggingLevel(QsLogging::InfoLevel);
DestinationPtr fileDestination(DestinationFactory::MakeFileDestination(
destLog, EnableLogRotation, MaxSizeBytes(1048576), MaxOldLogCount(2)));
DestinationPtr debugDestination(DestinationFactory::MakeDebugOutputDestination());
logger.addDestination(debugDestination);
logger.addDestination(fileDestination);
QTranslator translator;
QString sufix = QLocale::system().name();
#if defined Q_OS_UNIX && !defined Q_OS_MAC
translator.load(QString(DATADIR)+"/yacreader/languages/yacreaderlibrary_"+sufix);
#else
translator.load(QCoreApplication::applicationDirPath()+"/languages/yacreaderlibrary_"+sufix);
#endif
app->installTranslator(&translator);
QTranslator viewerTranslator;
#if defined Q_OS_UNIX && !defined Q_OS_MAC
viewerTranslator.load(QString(DATADIR)+"/yacreader/languages/yacreader_"+sufix);
#else
viewerTranslator.load(QCoreApplication::applicationDirPath()+"/languages/yacreader_"+sufix);
#endif
app->installTranslator(&viewerTranslator);
qRegisterMetaType<ComicDB>("ComicDB");
QSettings * settings = new QSettings(YACReader::getSettingsPath()+"/"+QCoreApplication::applicationName()+".ini",QSettings::IniFormat);
settings->beginGroup("libraryConfig");
//server
Startup *s = new Startup();
s->start();
QLOG_INFO() << "YACReaderLibraryServer attempting to start";
logSystemAndConfig();
if(YACReaderLocalServer::isRunning()) //s�lo se permite una instancia de YACReaderLibrary
{
QLOG_WARN() << "another instance of YACReaderLibrary is running";
QsLogging::Logger::destroyInstance();
return 0;
}
QLOG_INFO() << "YACReaderLibrary starting";
YACReaderLocalServer * localServer = new YACReaderLocalServer();
int ret = app->exec();
QLOG_INFO() << "YACReaderLibrary closed with exit code :" << ret;
//shutdown
s->stop();
delete s;
localServer->close();
delete localServer;
QsLogging::Logger::destroyInstance();
return ret;
}
else if(command == "create-library")
{
//QCommandLineParser parser;
//parser.addHelpOption();
//parser.parse(QCoreApplication::arguments());
parser.clearPositionalArguments();
parser.addPositionalArgument("create-library", "Creates a library named \"name\" in the specified destination <path>");
parser.addPositionalArgument("name", "Library name", "\"name\"");
parser.addPositionalArgument("path", "Path to the folder where the library will be created", "<path>");
parser.process(*app);
const QStringList args = parser.positionalArguments();
if(args.length() != 3)
{
parser.showHelp();
return 0;
}
const QStringList createArgs = parser.positionalArguments();
ConsoleUILibraryCreator * libraryCreatorUI = new ConsoleUILibraryCreator;
libraryCreatorUI->createLibrary(createArgs.at(1), createArgs.at(2));
return 0;
}
else if(command == "update-library")
{
//QCommandLineParser parser;
//parser.addHelpOption();
//parser.parse(QCoreApplication::arguments());
parser.clearPositionalArguments();
parser.addPositionalArgument("update-library", "Updates an existing library at <path>");
parser.addPositionalArgument("path", "Path to the library to be updated", "<path>");
parser.process(*app);
const QStringList args = parser.positionalArguments();
if(args.length() != 2)
{
parser.showHelp();
return 0;
}
const QStringList updateArgs = parser.positionalArguments();
ConsoleUILibraryCreator * libraryCreatorUI = new ConsoleUILibraryCreator;
libraryCreatorUI->updateLibrary(updateArgs.at(1));
return 0;
}
else if(command == "add-library")
{
//QCommandLineParser parser;
//parser.addHelpOption();
//parser.parse(QCoreApplication::arguments());
parser.clearPositionalArguments();
parser.addPositionalArgument("add-library", "Adds an exiting library named \"name\" at the specified origin <path>");
parser.addPositionalArgument("name", "Library name", "\"name\"");
parser.addPositionalArgument("path", "Path to the folder where the library is", "<path>");
parser.process(*app);
const QStringList args = parser.positionalArguments();
if(args.length() != 3)
{
parser.showHelp();
return 0;
}
const QStringList addArgs = parser.positionalArguments();
ConsoleUILibraryCreator * libraryCreatorUI = new ConsoleUILibraryCreator;
libraryCreatorUI->addExistingLibrary(addArgs.at(1), addArgs.at(2));
return 0;
}
else if(command == "remove-library")
{
//QCommandLineParser parser;
//parser.addHelpOption();
//parser.parse(QCoreApplication::arguments());
parser.clearPositionalArguments();
parser.addPositionalArgument("remove-library", "Removes a library named \"name\" from the list of libraries");
parser.addPositionalArgument("name", "Library name", "\"name\"");
parser.process(*app);
const QStringList args = parser.positionalArguments();
if(args.length() != 2)
{
parser.showHelp();
return 0;
}
const QStringList removeArgs = parser.positionalArguments();
ConsoleUILibraryCreator * libraryCreatorUI = new ConsoleUILibraryCreator;
libraryCreatorUI->removeLibrary(removeArgs.at(1));
return 0;
}
else if(command == "list-libraries")
{
YACReaderLibraries libraries = DBHelper::getLibraries();
for(QString libraryName : libraries.getNames())
qout << libraryName << " : " << libraries.getPath(libraryName) << endl;
return 0;
}
else //error
{
parser.showHelp();
return 0;
}
}

View File

@ -0,0 +1,32 @@
Starting with YACReader 9.0.0 we supply a systemd service file for use with
YACReaderLibraryServer. To make use of it, follow these instructions:
1. Open yacreaderlibraryserver.service in a text editor of your choice.
Change the path used in the ExecStart variable to the location where your headless
server binary resides. If yacreaderlibraryserver was installed as part of a
package you can probably skip this step.
2. Copy the service file into ~/.local/share/systemd/user
3. Enable the service file by running:
"systemctl --user enable yacreaderlibraryserver"
4. Start the server by running:
"systemctl --user start yacreaderlibraryserver"
5. Check the server status by running:
"systemctl --user status yacreaderlibraryserver"
Important: Don't run this as root. None of these steps require root privileges.
By the default, the service is configured to restart yacreaderlibraryserver in
case of a crash and will automatically restart even after a kill or reboot.
This might give you some trouble when running YACReaderLibrary on the same machine.
To temporarily disable the server, run systemctl with the stop command:
"systemctl --user stop yacreaderlibraryserver"
To permanently disable it, use the "disable" command:
"systemctl --user disable yacreaderlibraryserver"

View File

@ -0,0 +1,11 @@
[Unit]
Description= YACReaderLibrary headless server
After=network.target
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/YACReaderLibraryServer start
[Install]
WantedBy=default.target