UI: Straightforward RPC.

This commit is contained in:
Nodir Temirkhodjaev 2021-04-29 09:43:19 +03:00
parent 1c16d3b5d0
commit 21f302dbdf
11 changed files with 115 additions and 181 deletions

View File

@ -104,7 +104,6 @@ SOURCES += \
task/taskworker.cpp \
task/taskzonedownloader.cpp \
translationmanager.cpp \
util/classutil.cpp \
util/conf/addressrange.cpp \
util/conf/confutil.cpp \
util/dateutil.cpp \
@ -240,7 +239,6 @@ HEADERS += \
task/taskzonedownloader.h \
translationmanager.h \
util/classhelpers.h \
util/classutil.h \
util/conf/addressrange.h \
util/conf/confappswalker.h \
util/conf/confutil.h \

View File

@ -5,16 +5,17 @@
namespace Control {
enum Command : qint8 { CommandNone = 0, CommandConf, CommandProg, CommandRpc };
enum RpcObject : qint8 {
Rpc_None = 0,
Rpc_AppInfoManager,
Rpc_ConfManager,
Rpc_DriverManager,
Rpc_QuotaManager,
Rpc_StatManager,
Rpc_TaskManager,
enum Command : qint8 {
CommandNone = 0,
Conf,
Prog,
Rpc_AppInfoManager_lookupAppInfo,
Rpc_AppInfoManager_checkLookupFinished,
Rpc_ConfManager_,
Rpc_DriverManager_,
Rpc_QuotaManager_alert,
Rpc_StatManager_,
Rpc_TaskManager_,
};
}

View File

@ -64,9 +64,9 @@ bool ControlManager::postCommand()
{
Control::Command command;
if (settings()->controlCommand() == "conf") {
command = Control::CommandConf;
command = Control::Conf;
} else if (settings()->controlCommand() == "prog") {
command = Control::CommandProg;
command = Control::Prog;
} else {
logWarning() << "Unknown control command:" << settings()->controlCommand();
return false;
@ -91,7 +91,7 @@ bool ControlManager::postCommand()
if (args.isEmpty())
return false;
return worker.sendCommand(command, Control::Rpc_None, 0, args) && worker.waitForSent();
return worker.sendCommand(command, args) && worker.waitForSent();
}
void ControlManager::onNewConnection()
@ -115,35 +115,31 @@ void ControlManager::onNewConnection()
}
}
bool ControlManager::processRequest(Control::Command command, Control::RpcObject rpcObj,
qint16 methodIndex, const QVariantList &args)
bool ControlManager::processRequest(Control::Command command, const QVariantList &args)
{
QString errorMessage;
if (!processCommand(command, rpcObj, methodIndex, args, errorMessage)) {
if (!processCommand(command, args, errorMessage)) {
logWarning() << "Bad control command" << errorMessage << ':' << command << args;
return false;
}
return true;
}
bool ControlManager::processCommand(Control::Command command, Control::RpcObject rpcObj,
qint16 methodIndex, const QVariantList &args, QString &errorMessage)
bool ControlManager::processCommand(
Control::Command command, const QVariantList &args, QString &errorMessage)
{
switch (command) {
case Control::CommandConf:
case Control::Conf:
if (processCommandConf(args, errorMessage))
return true;
break;
case Control::CommandProg:
case Control::Prog:
if (processCommandProg(args, errorMessage))
return true;
break;
case Control::CommandRpc:
if (rpcManager()->processCommandRpc(rpcObj, methodIndex, args, errorMessage))
return true;
break;
default:
errorMessage = "Unknown command";
if (rpcManager()->processCommandRpc(command, args, errorMessage))
return true;
}
if (errorMessage.isEmpty()) {

View File

@ -36,17 +36,15 @@ public:
bool postCommand();
signals:
void rpcRequestReady(Control::RpcObject rpcObj, qint16 methodIndex, const QVariantList &args);
void rpcRequestReady(Control::Command command, const QVariantList &args);
private slots:
void onNewConnection();
bool processRequest(Control::Command command, Control::RpcObject rpcObj, qint16 methodIndex,
const QVariantList &args);
bool processRequest(Control::Command command, const QVariantList &args);
private:
bool processCommand(Control::Command command, Control::RpcObject rpcObj, qint16 methodIndex,
const QVariantList &args, QString &errorMessage);
bool processCommand(Control::Command command, const QVariantList &args, QString &errorMessage);
bool processCommandConf(const QVariantList &args, QString &errorMessage);
bool processCommandProg(const QVariantList &args, QString &errorMessage);

View File

@ -76,14 +76,13 @@ void ControlWorker::abort()
socket()->close();
}
bool ControlWorker::sendCommand(Control::Command command, Control::RpcObject rpcObj,
int methodIndex, const QVariantList &args)
bool ControlWorker::sendCommand(Control::Command command, const QVariantList &args)
{
QByteArray buffer;
if (!buildArgsData(buffer, args))
return false;
RequestHeader request(command, rpcObj, methodIndex, buffer.size());
RequestHeader request(command, buffer.size());
socket()->write((const char *) &request, sizeof(RequestHeader));
@ -138,12 +137,10 @@ bool ControlWorker::readRequest()
return false;
const Control::Command command = m_requestHeader.command();
const Control::RpcObject rpcObj = m_requestHeader.rpcObj();
const qint16 methodIndex = m_requestHeader.methodIndex();
clearRequest();
emit requestReady(command, rpcObj, methodIndex, args);
emit requestReady(command, args);
return true;
}

View File

@ -22,16 +22,14 @@ public:
void setupForAsync();
bool sendCommand(Control::Command command, Control::RpcObject rpcObj, int methodIndex,
const QVariantList &args);
bool sendCommand(Control::Command command, const QVariantList &args);
bool waitForSent(int msecs = 1000) const;
static QVariantList buildArgs(const QStringList &list);
signals:
void requestReady(Control::Command command, Control::RpcObject rpcObj, qint16 methodIndex,
const QVariantList &args);
void requestReady(Control::Command command, const QVariantList &args);
public slots:
void abort();
@ -48,31 +46,23 @@ private:
private:
struct RequestHeader
{
RequestHeader(Control::Command command = Control::CommandNone,
Control::RpcObject rpcObj = Control::Rpc_None, qint16 methodIndex = 0,
quint32 dataSize = 0) :
m_command(command), m_rpcObj(rpcObj), m_methodIndex(methodIndex), m_dataSize(dataSize)
RequestHeader(Control::Command command = Control::CommandNone, quint32 dataSize = 0) :
m_command(command), m_dataSize(dataSize)
{
}
Control::Command command() const { return m_command; }
Control::RpcObject rpcObj() const { return m_rpcObj; }
qint16 methodIndex() const { return m_methodIndex; }
Control::Command command() const { return static_cast<Control::Command>(m_command); }
quint32 dataSize() const { return m_dataSize; }
void clear()
{
m_command = Control::CommandNone;
m_rpcObj = Control::Rpc_None;
m_methodIndex = 0;
m_dataSize = 0;
}
private:
Control::Command m_command;
Control::RpcObject m_rpcObj;
qint16 m_methodIndex;
quint32 m_dataSize;
quint32 m_command : 8;
quint32 m_dataSize : 24;
};
bool m_isServiceClient = false;

View File

@ -4,7 +4,6 @@
#include "../fortmanager.h"
#include "../rpc/rpcmanager.h"
#include "../util/classutil.h"
AppInfoManagerRpc::AppInfoManagerRpc(
const QString &filePath, FortManager *fortManager, QObject *parent) :
@ -19,8 +18,7 @@ RpcManager *AppInfoManagerRpc::rpcManager() const
void AppInfoManagerRpc::lookupAppInfo(const QString &appPath)
{
static const int methodIndex = ClassUtil::indexOfMethod(&AppInfoManager::lookupAppInfo);
rpcManager()->invokeOnServer(Control::Rpc_AppInfoManager, methodIndex, { appPath });
rpcManager()->invokeOnServer(Control::Rpc_AppInfoManager_lookupAppInfo, { appPath });
}
void AppInfoManagerRpc::updateAppAccessTime(const QString & /*appPath*/) { }

View File

@ -10,7 +10,6 @@
#include "../rpc/quotamanagerrpc.h"
#include "../rpc/statmanagerrpc.h"
#include "../rpc/taskmanagerrpc.h"
#include "../util/classutil.h"
RpcManager::RpcManager(FortManager *fortManager, QObject *parent) :
QObject(parent), m_fortManager(fortManager)
@ -27,6 +26,36 @@ ControlManager *RpcManager::controlManager() const
return fortManager()->controlManager();
}
AppInfoManager *RpcManager::appInfoManager() const
{
return fortManager()->appInfoManager();
}
ConfManager *RpcManager::confManager() const
{
return fortManager()->confManager();
}
DriverManager *RpcManager::driverManager() const
{
return fortManager()->driverManager();
}
QuotaManager *RpcManager::quotaManager() const
{
return fortManager()->quotaManager();
}
StatManager *RpcManager::statManager() const
{
return fortManager()->statManager();
}
TaskManager *RpcManager::taskManager() const
{
return fortManager()->taskManager();
}
void RpcManager::initialize()
{
if (settings()->isService()) {
@ -34,18 +63,6 @@ void RpcManager::initialize()
}
}
bool RpcManager::processCommandRpc(
Control::RpcObject rpcObj, int methodIndex, const QVariantList &args, QString &errorMessage)
{
QObject *o = getRpcObject(rpcObj);
if (!o) {
errorMessage = "Bad RPC: No object";
return false;
}
return ClassUtil::invokeMethod(o, methodIndex, args);
}
void RpcManager::setupServerSignals()
{
setupAppInfoManagerSignals();
@ -54,62 +71,62 @@ void RpcManager::setupServerSignals()
void RpcManager::setupAppInfoManagerSignals()
{
constexpr Control::RpcObject rpcObj = Control::Rpc_AppInfoManager;
auto o = fortManager()->appInfoManager();
connect(o, &AppInfoManager::lookupFinished, this,
connect(appInfoManager(), &AppInfoManager::lookupFinished, this,
[&](const QString &appPath, const AppInfo & /*appInfo*/) {
static const int methodIndex =
ClassUtil::indexOfMethod(&AppInfoManager::checkLookupFinished);
invokeOnClients(rpcObj, methodIndex, { appPath });
invokeOnClients(Control::Rpc_AppInfoManager_checkLookupFinished, { appPath });
});
}
void RpcManager::setupQuotaManagerSignals()
{
constexpr Control::RpcObject rpcObj = Control::Rpc_QuotaManager;
auto o = fortManager()->quotaManager();
connect(o, &QuotaManager::alert, this, [&](qint8 alertType) {
static const int methodIndex = ClassUtil::indexOfSignal(&QuotaManager::alert);
invokeOnClients(rpcObj, methodIndex, { alertType });
connect(quotaManager(), &QuotaManager::alert, this, [&](qint8 alertType) {
invokeOnClients(Control::Rpc_QuotaManager_alert, { alertType });
});
}
void RpcManager::invokeOnServer(
Control::RpcObject rpcObj, int methodIndex, const QVariantList &args)
void RpcManager::invokeOnServer(Control::Command cmd, const QVariantList &args)
{
m_client->sendCommand(Control::CommandRpc, rpcObj, methodIndex, args);
m_client->sendCommand(cmd, args);
}
void RpcManager::invokeOnClients(
Control::RpcObject rpcObj, int methodIndex, const QVariantList &args)
void RpcManager::invokeOnClients(Control::Command cmd, const QVariantList &args)
{
const auto clients = controlManager()->clients();
for (ControlWorker *w : clients) {
if (!w->isServiceClient())
continue;
w->sendCommand(Control::CommandRpc, rpcObj, methodIndex, args);
w->sendCommand(cmd, args);
}
}
QObject *RpcManager::getRpcObject(Control::RpcObject rpcObj) const
bool RpcManager::processCommandRpc(
Control::Command cmd, const QVariantList &args, QString &errorMessage)
{
switch (rpcObj) {
case Control::Rpc_AppInfoManager:
return fortManager()->appInfoManager();
case Control::Rpc_ConfManager:
return fortManager()->confManager();
case Control::Rpc_DriverManager:
return fortManager()->driverManager();
case Control::Rpc_QuotaManager:
return fortManager()->quotaManager();
case Control::Rpc_StatManager:
return fortManager()->statManager();
case Control::Rpc_TaskManager:
return fortManager()->taskManager();
switch (cmd) {
case Control::Rpc_AppInfoManager_lookupAppInfo:
appInfoManager()->lookupAppInfo(args.value(0).toString());
return true;
case Control::Rpc_AppInfoManager_checkLookupFinished:
appInfoManager()->checkLookupFinished(args.value(0).toString());
return true;
case Control::Rpc_ConfManager_:
confManager();
return true;
case Control::Rpc_DriverManager_:
driverManager();
return true;
case Control::Rpc_QuotaManager_alert:
quotaManager();
return true;
case Control::Rpc_StatManager_:
statManager();
return true;
case Control::Rpc_TaskManager_:
taskManager();
return true;
default:
return nullptr;
errorMessage = "Unknown command";
return false;
}
}

View File

@ -6,10 +6,16 @@
#include "../control/control.h"
class AppInfoManager;
class ConfManager;
class ControlManager;
class ControlWorker;
class DriverManager;
class FortManager;
class FortSettings;
class QuotaManager;
class StatManager;
class TaskManager;
class RpcManager : public QObject
{
@ -21,22 +27,25 @@ public:
FortManager *fortManager() const { return m_fortManager; }
FortSettings *settings() const;
ControlManager *controlManager() const;
AppInfoManager *appInfoManager() const;
ConfManager *confManager() const;
DriverManager *driverManager() const;
QuotaManager *quotaManager() const;
StatManager *statManager() const;
TaskManager *taskManager() const;
void initialize();
bool processCommandRpc(Control::RpcObject rpcObj, int methodIndex, const QVariantList &args,
QString &errorMessage);
void invokeOnServer(Control::Command cmd, const QVariantList &args);
void invokeOnServer(Control::RpcObject rpcObj, int methodIndex, const QVariantList &args);
bool processCommandRpc(Control::Command cmd, const QVariantList &args, QString &errorMessage);
private:
void setupServerSignals();
void setupAppInfoManagerSignals();
void setupQuotaManagerSignals();
void invokeOnClients(Control::RpcObject rpcObj, int methodIndex, const QVariantList &args);
QObject *getRpcObject(Control::RpcObject rpcObj) const;
void invokeOnClients(Control::Command cmd, const QVariantList &args);
private:
FortManager *m_fortManager = nullptr;

View File

@ -1,38 +0,0 @@
#include "classutil.h"
bool ClassUtil::invokeMethod(
QObject *object, int methodIndex, const QVariantList &args, QVariant *result)
{
const QMetaMethod metaMethod = object->metaObject()->method(methodIndex);
constexpr int maxArgsCount = 5;
Q_ASSERT(metaMethod.parameterTypes().size() == args.size() && args.size() <= maxArgsCount);
QVector<QGenericArgument> arguments(maxArgsCount);
for (const auto &arg : args) {
void *data = const_cast<void *>(arg.constData()); // data() detaches it
arguments.append(QGenericArgument(arg.typeName(), data));
}
QVariant returnValue(metaMethod.returnMetaType(), nullptr);
QGenericReturnArgument returnArgument(
metaMethod.typeName(), const_cast<void *>(returnValue.constData()));
if (!metaMethod.invoke(object, Qt::DirectConnection, returnArgument, arguments.value(0),
arguments.value(1), arguments.value(2), arguments.value(3), arguments.value(4)))
return false;
if (result) {
*result = returnValue;
}
return true;
}
int ClassUtil::getIndexOfMethod(const QMetaObject &metaObject, void **method)
{
int i = -1;
void *args[] = { &i, method };
metaObject.static_metacall(QMetaObject::IndexOfMethod, 0, args);
return i;
}

View File

@ -1,32 +0,0 @@
#ifndef CLASSUTIL_H
#define CLASSUTIL_H
#include <QMetaMethod>
#include <QVariant>
class ClassUtil
{
public:
static bool invokeMethod(QObject *object, int methodIndex, const QVariantList &args = {},
QVariant *result = nullptr);
template<typename PointerToMemberFunction>
static int indexOfSignal(PointerToMemberFunction signal)
{
const QMetaMethod method = QMetaMethod::fromSignal(signal);
return method.methodIndex();
}
template<typename PointerToMemberFunction>
static int indexOfMethod(PointerToMemberFunction method)
{
using MemberFunctionType = QtPrivate::FunctionPointer<PointerToMemberFunction>;
return getIndexOfMethod(
MemberFunctionType::Object::staticMetaObject, reinterpret_cast<void **>(&method));
}
private:
static int getIndexOfMethod(const QMetaObject &metaObject, void **method);
};
#endif // CLASSUTIL_H