add control processes and so on

This commit is contained in:
Evgenii Alekseev 2017-03-08 05:33:52 +03:00
parent 20578996b7
commit 2701e44119
15 changed files with 403 additions and 92 deletions

View File

@ -17,12 +17,15 @@
#include "QueuedApplicationInterface.h"
#include <QCoreApplication>
#include <unistd.h>
#include "queued/Queued.h"
#include "QueuedApplication.h"
extern "C" {
#include <unistd.h>
}
QueuedApplicationInterface::QueuedApplicationInterface(
QueuedApplication *parent)
@ -54,8 +57,8 @@ void QueuedApplicationInterface::Close() const
QStringList QueuedApplicationInterface::UIDs() const
{
QStringList uids;
uids.append(QString::number(getuid()));
uids.append(QString::number(geteuid()));
uids.append(QString::number(::getuid()));
uids.append(QString::number(::geteuid()));
return uids;
}

View File

@ -24,6 +24,10 @@
#include "QueuedApplication.h"
#include "version.h"
extern "C" {
#include <unistd.h>
}
bool existingSessionOperation(const QString &operation)
{
@ -38,7 +42,13 @@ bool existingSessionOperation(const QString &operation)
int main(int argc, char *argv[])
{
// daemon(0, 0);
// HACK preparse arguments to find out if --daemon is set
for (int i = 0; i < argc; i++) {
if (std::string(argv[i]) != "--daemon")
continue;
::daemon(0, 0);
}
QCoreApplication app(argc, argv);
app.setApplicationName(NAME);
@ -50,22 +60,40 @@ int main(int argc, char *argv[])
"Daemon for starting jobs to queue of calculations");
parser.addHelpOption();
parser.addVersionOption();
// info
QCommandLineOption infoOption(QStringList() << "i"
<< "info",
"Show additional info.");
parser.addOption(infoOption);
// configuration option
QCommandLineOption configOption(QStringList() << "c"
<< "config",
"Read initial configuration from file",
"Read initial configuration from file.",
"config", QueuedSettings::defaultPath());
parser.addOption(configOption);
// debug mode
QCommandLineOption debugOption(QStringList() << "d"
<< "debug",
"Print debug information");
"Print debug information.");
parser.addOption(debugOption);
// daemon mode
QCommandLineOption daemonOption(QStringList() << "daemon",
"Start detached.");
parser.addOption(daemonOption);
parser.process(app);
// show info and exit
if (parser.isSet(infoOption)) {
QueuedDebug::enableDebug();
auto metadata = QueuedDebug::getBuildData();
for (auto &string : metadata)
qCInfo(LOG_APP) << string;
}
// check if exists
if (existingSessionOperation(QString("Active"))) {
qCWarning(LOG_APP) << "Another session is active";

View File

@ -40,6 +40,7 @@
#include "QueuedProcessManager.h"
#include "QueuedReportManager.h"
#include "QueuedSettings.h"
#include "QueuedSystemInfo.h"
#include "QueuedTokenManager.h"
#include "QueuedUser.h"
#include "QueuedUserManager.h"

View File

@ -77,24 +77,26 @@ typedef struct {
} QueuedDBSetup;
/**
* @ingroup QueuedCfg
* @enum Settings
* @enum QueuedSettings
* @brief settings keys enum
* @var Settigns::Invalid
* @var QueuedSettings::Invalid
* unknown key
* @var Settings::DatabaseInterval
* @var QueuedSettings::DatabaseInterval
* database actions interval in msecs
* @var Settings::DefaultLimits
* @var QueuedSettings::DefaultLimits
* default limits value
* @var Settings::KeepTasks
* @var QueuedSettings::KeepTasks
* keep ended tasks in msecs
* @var Settings::KeepUsers
* @var QueuedSettings::KeepUsers
* keep users last logged in msecs
* @var Settings::OnExitAction
* @var QueuedSettings::OnExitAction
* on queued exit action enum
* @var Settings::TokenExpiration
* @var QueuedSettings::TokenExpiration
* token expiration value in days
* @var Settings::DatabaseVersion
* @var QueuedSettings::DatabaseVersion
* internal field to control current database version
* @var QueuedSettings::ProcessCommandLine
* control process command line
*/
enum class QueuedSettings {
Invalid = 1 << 0,
@ -104,7 +106,8 @@ enum class QueuedSettings {
KeepUsers = 1 << 4,
OnExitAction = 1 << 5,
TokenExpiration = 1 << 6,
DatabaseVersion = 1 << 7
DatabaseVersion = 1 << 7,
ProcessCommandLine = 1 << 8,
};
/**
* @ingroup QueuedCfg
@ -140,7 +143,11 @@ const QueuedSettingsDefaultMap QueuedSettingsDefaults = {
{"OnExitAction", {QueuedSettings::OnExitAction, 2}},
{"TokenExpiration", {QueuedSettings::TokenExpiration, 30}},
{"DatabaseVersion",
{QueuedSettings::DatabaseVersion, QueuedConfig::DATABASE_VERSION}}};
{QueuedSettings::DatabaseVersion, QueuedConfig::DATABASE_VERSION}},
{"ProcessCommandLine",
{QueuedSettings::ProcessCommandLine,
"systemd-run\x01--scope\x01--unit={name}\x01--uid={uid}\x01--gid={gid}"
"\x01-p\x01CPUQuota={cpu}%\x01-p\x01MemoryHigh={memory}\x01{app}"}}};
};
#endif /* QUEUEDCONFIGURATION_H */

View File

@ -55,17 +55,11 @@ QVariantList sendRequest(const QString &_service, const QString &_path,
/**
* @ingroup QueuedCoreAdaptor
* @brief additional method to avoid conversion from DBus type to native ones
* @tparam T
* type to which DBus data should be converted
* @param _data
* source data
* @return converted value
*/
template <class T> T toNativeType(const QVariant &_data)
{
return qdbus_cast<T>(
_data.value<QDBusVariant>().variant().value<QDBusArgument>());
};
QVariant toNativeType(const QVariant &_data);
}

View File

@ -28,32 +28,29 @@
/**
* @brief database operation exception
* @brief generic exception class
*/
class QueuedDatabaseException : public QException
class QueuedException : public QException
{
public:
/**
* @brief QueuedDatabaseException class constructor
* @brief QueuedException class constructor
* @param message
* exception message
*/
QueuedDatabaseException(const QString &message)
QueuedException(const QString &message)
: m_message(message){};
/**
* @brief clone QueuedDatabaseException
* @brief clone QueuedException
*/
QueuedDatabaseException *clone() const
{
return new QueuedDatabaseException(*this);
};
QueuedException *clone() const { return new QueuedException(*this); };
/**
* @brief message of this exception
* @return message for logging, etc
*/
QString message() const { return m_message; };
/**
* @brief raise QueuedDatabaseException
* @brief raise QueuedException
*/
void raise() const { throw * this; }
@ -65,10 +62,42 @@ private:
};
/**
* @brief configuration related exception
*/
class QueuedConfigurationException : public QueuedException
{
public:
/**
* @brief QueuedConfigurationException class constructor
* @param message
* exception message
*/
QueuedConfigurationException(const QString &message)
: QueuedException(message){};
};
/**
* @brief database operation exception
*/
class QueuedDatabaseException : public QueuedException
{
public:
/**
* @brief QueuedDatabaseException class constructor
* @param message
* exception message
*/
QueuedDatabaseException(const QString &message)
: QueuedException(message){};
};
/**
* @brief DBus operation exception
*/
class QueuedDBusException : public QException
class QueuedDBusException : public QueuedException
{
public:
/**
@ -77,29 +106,7 @@ public:
* exception message
*/
QueuedDBusException(const QString &message)
: m_message(message){};
/**
* @brief clone QueuedDBusException
*/
QueuedDBusException *clone() const
{
return new QueuedDBusException(*this);
};
/**
* @brief message of this exception
* @return message for logging, etc
*/
QString message() const { return m_message; };
/**
* @brief raise QueuedDBusException
*/
void raise() const { throw * this; }
private:
/**
* @brief exception message
*/
QString m_message;
: QueuedException(message){};
};

View File

@ -48,6 +48,7 @@ class QueuedProcess : public QProcess
Q_PROPERTY(QString limits READ limits WRITE setLimits)
Q_PROPERTY(QueuedLimits::Limits nativeLimtis READ nativeLimits)
Q_PROPERTY(uint nice READ nice WRITE setNice)
Q_PROPERTY(QString processLine READ processLine WRITE setProcessLine)
Q_PROPERTY(QueuedEnums::ProcessState pstate READ pstate WRITE setPState)
Q_PROPERTY(QDateTime startTime READ startTime WRITE setStartTime)
Q_PROPERTY(uint uid READ uid WRITE setUid)
@ -111,6 +112,11 @@ public:
* @brief QueuedProcess class destructor
*/
virtual ~QueuedProcess();
/**
* @brief update command arguments
*/
void updateArguments();
// properties
/**
* @brief index of process
* @return assigned index of process
@ -157,6 +163,11 @@ public:
* @return process nice
*/
uint nice() const;
/**
* @brief process line
* @return process line as is in configuration
*/
QString processLine() const;
/**
* @brief process state
* @return process defined state
@ -217,6 +228,13 @@ public:
* new process nice
*/
void setNice(const uint _nice);
/**
* @brief set process line
* @param _processLine
* original process line
* @remark the following values will be replaced
*/
void setProcessLine(const QString &_processLine);
/**
* @brief set process state
* @param _limits
@ -255,12 +273,6 @@ public:
*/
bool operator==(const QueuedProcess &_other);
protected:
/**
* @brief additional method with sets rules for QProcess
*/
void setupChildProcess();
private:
/**
* @brief process definitions
@ -270,6 +282,10 @@ private:
* @brief index of process
*/
long long m_index = -1;
/**
* @brief process line to launch
*/
QString m_processLine;
};

View File

@ -38,12 +38,13 @@ class QueuedProcessManager : public QObject
{
Q_OBJECT
Q_PROPERTY(OnExitAction onExit READ onExit WRITE setOnExitAction)
Q_PROPERTY(QString processLine READ processLine WRITE setProcessLine)
public:
/**
* @typedef QueuedProcessMap
* map of indices to QueuedProcess pointers
*/
* @typedef QueuedProcessMap
* map of indices to QueuedProcess pointers
*/
typedef QHash<long long, QueuedProcess *> QueuedProcessMap;
/**
* @typedef QueuedProcessConnectionMap
@ -51,7 +52,6 @@ public:
*/
typedef QHash<long long, QMetaObject::Connection>
QueuedProcessConnectionMap;
/**
* @enum OnExitAction
* @brief action with child process on destruction
@ -66,10 +66,13 @@ public:
* @brief QueuedProcessManager class constructor
* @param parent
* pointer to parent item
* @param processLine
* command line pattern
* @param onExit
* default action on exit
*/
explicit QueuedProcessManager(QObject *parent, const OnExitAction onExit);
explicit QueuedProcessManager(QObject *parent, const QString &processLine,
const OnExitAction onExit);
/**
* @brief QueuedProcessManager class destructor
*/
@ -136,12 +139,23 @@ public:
* @return default action from possible ones
*/
OnExitAction onExit() const;
/**
* @brief process command line
* @return current command line
*/
QString processLine() const;
/**
* @brief set on exit action
* @param _action
* new on exit action
*/
void setOnExitAction(const OnExitAction _action);
/**
* @brief set command line
* @param _commandLine
* new command line
*/
void setProcessLine(const QString _processLine);
signals:
/**
@ -188,6 +202,10 @@ private:
* @brief processes list
*/
QueuedProcessMap m_processes;
/**
* @brief command line
*/
QString m_processLine;
};

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2016 Evgeniy Alekseev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
*
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
/**
* @file QueuedSystemInfo.h
* Header of Queued library
* @author Evgeniy Alekseev
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDSYSTEMINFO_H
#define QUEUEDSYSTEMINFO_H
/**
* @defgroup QueuedSystemInfo
* @brief system information methods
*/
namespace QueuedSystemInfo
{
/**
* @ingroup QueuedSystemInfo
* @brief system CPU count
* @return system CPU count
*/
long long cpuCount();
/**
* @ingroup QueuedSystemInfo
* @brief weight of specified CPU count
* @param _cpu
* CPU count to get weight
* @return weight as proportion
*/
double cpuWeight(const long long _cpu);
/**
* @ingroup QueuedSystemInfo
* @brief system memory count
* @return system memory count in bytes
*/
long long memoryCount();
/**
* @ingroup QueuedSystemInfo
* @brief weight of specified memory count
* @param _memory
* memory in bytes to get weight
* @return weight as proportion
*/
double memoryWeight(const long long _memory);
}
#endif /* QUEUEDSYSTEMINFO_H */

View File

@ -500,6 +500,9 @@ void QueuedCore::updateSettings(const QueuedCfg::QueuedSettings _key,
m_processes->setOnExitAction(
static_cast<QueuedProcessManager::OnExitAction>(_value.toInt()));
break;
case QueuedCfg::QueuedSettings::ProcessCommandLine:
m_processes->setProcessLine(_value.toString());
break;
case QueuedCfg::QueuedSettings::TokenExpiration:
m_users->setTokenExpiration(_value.toLongLong());
break;
@ -607,8 +610,11 @@ void QueuedCore::initProcesses()
auto onExitAction = static_cast<QueuedProcessManager::OnExitAction>(
m_advancedSettings->get(QueuedCfg::QueuedSettings::OnExitAction)
.toInt());
auto processLine
= m_advancedSettings->get(QueuedCfg::QueuedSettings::ProcessCommandLine)
.toString();
m_processes = new QueuedProcessManager(this, onExitAction);
m_processes = new QueuedProcessManager(this, processLine, onExitAction);
auto dbProcesses = m_database->get(
QueuedDB::TASKS_TABLE,
QString("WHERE state != %1")

View File

@ -55,3 +55,12 @@ QVariantList QueuedCoreAdaptor::sendRequest(const QString &_service,
return arguments;
}
/**
* @fn toNativeType
*/
QVariant QueuedCoreAdaptor::toNativeType(const QVariant &_data)
{
return _data.value<QDBusVariant>().variant();
}

View File

@ -21,13 +21,9 @@
*/
#include "queued/Queued.h"
#include <queued/Queued.h>
extern "C" {
#include <unistd.h>
}
#include <QMetaProperty>
/**
@ -46,9 +42,13 @@ QueuedProcess::QueuedProcess(QObject *parent,
qCDebug(LOG_LIB) << __PRETTY_FUNCTION__;
// update QProcess related values as well
// TODO configuration
setCommand(m_definitions.command);
setCommandArguments(m_definitions.arguments);
setWorkDirectory(m_definitions.workingDirectory);
setStandardErrorFile(QString("%1-err.log").arg(name()), QIODevice::Append);
setStandardOutputFile(QString("%1-out.log").arg(name()), QIODevice::Append);
}
@ -61,6 +61,47 @@ QueuedProcess::~QueuedProcess()
}
/**
* @fn updateArguments
*/
void QueuedProcess::updateArguments()
{
QString application = processLine();
// replace generic properties first
auto meta = metaObject();
int count = meta->propertyCount();
for (int i = 0; i < count; i++) {
QMetaProperty prop = meta->property(i);
auto name = prop.name();
// replace string now
application.replace(QString("{%1}").arg(name),
property(name).toString());
}
// replace limits now
application.replace(
"{cpu}", QString("%1").arg(
QueuedSystemInfo::cpuWeight(nativeLimits().cpu) * 100.0, 0,
'f', 0));
application.replace(
"{memory}",
QString("%1").arg(QueuedSystemInfo::memoryWeight(nativeLimits().memory)
* QueuedSystemInfo::memoryCount(),
0, 'f', 0));
// command line
QString commandLine = command() + "\x01" + commandArguments().join('\x01');
application.replace("{app}", commandLine);
QStringList arguments = application.split('\x01');
// set QProcess properties
setProgram(arguments.takeFirst());
setCommandArguments(arguments);
}
/**
* @fn index
*/
@ -75,7 +116,7 @@ long long QueuedProcess::index() const
*/
QString QueuedProcess::name() const
{
return QString("queued-%1").arg(index());
return QString("queued-task-%1").arg(index());
}
@ -142,6 +183,15 @@ uint QueuedProcess::nice() const
}
/**
* @fn processLine
*/
QString QueuedProcess::processLine() const
{
return m_processLine;
}
/**
* @fn pstate
*/
@ -195,7 +245,7 @@ void QueuedProcess::setCommand(const QString &_command)
qCDebug(LOG_LIB) << "Set command to" << _command;
m_definitions.command = _command;
setProgram(_command);
updateArguments();
}
@ -207,7 +257,7 @@ void QueuedProcess::setCommandArguments(const QStringList &_commandArguments)
qCDebug(LOG_LIB) << "Set command line arguments to" << _commandArguments;
m_definitions.arguments = _commandArguments;
setArguments(_commandArguments);
updateArguments();
}
@ -230,6 +280,7 @@ void QueuedProcess::setGid(const uint _gid)
qCDebug(LOG_LIB) << "Set process GID to" << _gid;
m_definitions.gid = _gid;
updateArguments();
}
@ -241,6 +292,7 @@ void QueuedProcess::setLimits(const QString &_limits)
qCDebug(LOG_LIB) << "Set process limits" << _limits;
m_definitions.limits = _limits;
updateArguments();
}
@ -255,6 +307,18 @@ void QueuedProcess::setNice(const uint _nice)
}
/**
* @fn setProcessLine
*/
void QueuedProcess::setProcessLine(const QString &_processLine)
{
qCDebug(LOG_LIB) << "Set process line to" << _processLine;
m_processLine = _processLine;
updateArguments();
}
/**
* @fn setPState
*/
@ -285,6 +349,7 @@ void QueuedProcess::setUid(const uint _uid)
qCDebug(LOG_LIB) << "Set process UID to" << _uid;
m_definitions.uid = _uid;
updateArguments();
}
@ -318,13 +383,3 @@ bool QueuedProcess::operator==(const QueuedProcess &_other)
{
return name() == _other.name();
}
/**
* @fn setupChildProcess
*/
void QueuedProcess::setupChildProcess()
{
::setgid(m_definitions.gid);
::setuid(m_definitions.uid);
}

View File

@ -29,12 +29,14 @@
* @fn QueuedProcessManager
*/
QueuedProcessManager::QueuedProcessManager(QObject *parent,
const QString &processLine,
const OnExitAction onExit)
: QObject(parent)
{
qCDebug(LOG_LIB) << __PRETTY_FUNCTION__;
setOnExitAction(onExit);
setProcessLine(processLine);
}
@ -160,7 +162,6 @@ void QueuedProcessManager::remove(const long long _index)
pr->kill();
break;
case OnExitAction::Terminate:
default:
pr->terminate();
break;
}
@ -204,7 +205,6 @@ void QueuedProcessManager::stop(const long long _index)
pr->kill();
break;
case OnExitAction::Terminate:
default:
pr->terminate();
break;
}
@ -220,6 +220,15 @@ QueuedProcessManager::OnExitAction QueuedProcessManager::onExit() const
}
/**
* @fn processLine
*/
QString QueuedProcessManager::processLine() const
{
return m_processLine;
}
/**
* @fn setOnExitAction
*/
@ -231,6 +240,19 @@ void QueuedProcessManager::setOnExitAction(const OnExitAction _action)
}
/**
* @fn setProcessLine
*/
void QueuedProcessManager::setProcessLine(const QString _processLine)
{
qCDebug(LOG_LIB) << "Set process line to" << _processLine;
m_processLine = _processLine;
for (auto process : m_processes.values())
process->setProcessLine(processLine());
}
/**
* @fn taskFinished
*/

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2016 Evgeniy Alekseev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
*
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
/**
* @file QueuedSystemInfo.cpp
* Source code of queued library
* @author Evgeniy Alekseev
* @copyright GPLv3
* @bug https://github.com/arcan1s/queued/issues
*/
#include "queued/Queued.h"
#include <QThread>
extern "C" {
#include <sys/sysinfo.h>
}
/**
* @fn cpuCount
*/
long long QueuedSystemInfo::cpuCount()
{
return QThread::idealThreadCount();
}
/**
* @fn cpuWeight
*/
double QueuedSystemInfo::cpuWeight(const long long _cpu)
{
qCDebug(LOG_LIB) << "Get CPU weight for" << _cpu;
if ((_cpu > 0) && (_cpu < cpuCount()))
return static_cast<double>(_cpu) / static_cast<double>(cpuCount());
else
return 1.0;
}
/**
* @fn memoryCount
*/
long long QueuedSystemInfo::memoryCount()
{
struct sysinfo info;
if (::sysinfo(&info) != 0)
throw QueuedConfigurationException("Count not get memory information");
return info.totalram;
}
/**
* @fn memoryWeight
*/
double QueuedSystemInfo::memoryWeight(const long long _memory)
{
qCDebug(LOG_LIB) << "Get memory weight for" << _memory;
if ((_memory > 0) && (_memory < memoryCount()))
return static_cast<double>(_memory)
/ static_cast<double>(memoryCount());
else
return 1.0;
}

View File

@ -27,7 +27,6 @@
extern "C" {
#include <pwd.h>
#include <sys/types.h>
}
@ -107,7 +106,7 @@ QPair<uint, uint> QueuedUser::ids()
{
QPair<uint, uint> system = {1, 1};
auto pwd = getpwnam(name().toLocal8Bit().constData());
auto pwd = ::getpwnam(name().toLocal8Bit().constData());
if (!pwd) {
qCWarning(LOG_LIB) << "No user found by name" << name();
return system;