Merge pull request 'partially migrate to IndexedTimer' (#225) from v1_master into v1_release
Some checks failed
SHS Gitea/SHS/pipeline/head There was a failure building this commit

Reviewed-on: #225
This commit was merged in pull request #225.
This commit is contained in:
2024-07-12 12:31:08 +03:00
5 changed files with 435 additions and 389 deletions

View File

@@ -11,7 +11,7 @@ if("${SHS_QT_VERSION}" STREQUAL "")
set(SHS_QT_VERSION 5 CACHE STRING "Qt version")
endif()
find_package(PIP 3.15 REQUIRED)
find_package(PIP 3.21 REQUIRED)
find_package(QAD 2.8.4 REQUIRED)
qad_find_qt(Qt${SHS_QT_VERSION} Core Gui Widgets)
set(TARGET_SUFFIX_Qt${SHS_QT_VERSION} "")
@@ -33,7 +33,7 @@ endif()
set_version(SHS
MAJOR 1
MINOR 2
REVISION 3
REVISION 4
BUILD "${BUILD_NUMBER}"
SUFFIX ""
OUTPUT "${SHS_VERSION_FILE}")

View File

@@ -3,13 +3,14 @@
#include "SH_network_types.h"
#include "SH_packages.h"
#include "ccm_SHS_shared.h"
#include "piqt.h"
#include "server.h"
#include <QCryptographicHash>
#include <QDebug>
#include <QMetaObject>
#include <piethernet.h>
#include <piliterals_time.h>
#include <piqt.h>
ServerClient::ServerClient(ServerCore * s, SHNetworkTypes::ChannelType c): PIThread(), server(s), channel_type(c) {
@@ -44,10 +45,13 @@ void ServerClient::destroy() {
PIThread::stop();
// piCout << "~ServerClient stop";
if (device) device->stop();
if (!PIThread::waitForFinish(10000)) PIThread::terminate();
if (!PIThread::waitForFinish(5_s)) PIThread::terminate();
if (device) {
device->stopAndWait(10000);
if (device->isThreadedRead()) piCout << "[ServerClient::destroy]" << device << "can`t stop ...";
device->stopAndWait(5_s);
if (device->isThreadedRead()) {
piCout << "[ServerClient::destroy]" << device << "can`t stop ...";
device->terminateThreadedRead();
}
}
// piCout << "~ServerClient stop done";
piDeleteSafety(tcp);
@@ -208,6 +212,7 @@ void ServerClient::recGraphicsRequest(PIStringList gl) {
void ServerClient::packetRec(PIByteArray data) {
if (closing) return;
// piCout << "packetRec" << data.toHex() << "...";
if (diag) diag->received(data.size_s());
// piCout << "packetRec" << data.toHex();

View File

@@ -1,25 +1,36 @@
#include "server_core.h"
#include "piqt.h"
#include "SH_packages.h"
#include "SH_network_types.h"
#include "SH_packages.h"
#include "SH_plugins_manager.h"
#include <QDebug>
#include <QMetaEnum>
#include <QCryptographicHash>
#include <QResource>
#include <qad_locations.h>
#include <piethernet.h>
#include "ccm_SHS_shared.h"
//const double keepAliveInterval_s = 2.;
#include <QCryptographicHash>
#include <QDebug>
#include <QMetaEnum>
#include <QResource>
#include <piethernet.h>
#include <piliterals_time.h>
#include <piqt.h>
#include <qad_locations.h>
// const double keepAliveInterval_s = 2.;
enum TimerRole {
trSaveState,
trAdmin,
trServerSync,
trClients
};
ServerCore::ServerCore(bool reservation): QObject(), SHMulticast(), eth_tcp(PIEthernet::TCP_Server) {
PACKAGES;
file_ui_state = QAD::userPath(QAD::ltCache, "ui_state" );
file_ui_state = QAD::userPath(QAD::ltCache, "ui_state");
file_ui_state_new = QAD::userPath(QAD::ltCache, "ui_state_new");
with_reservation = reservation;
auto il = PIEthernet::interfaces();
with_reservation = reservation;
auto il = PIEthernet::interfaces();
for (const auto & i: il) {
piCout << i.name << i.address;
if (!i.isLoopback() && !i.address.isEmpty() && i.address != "0.0.0.0") {
@@ -27,17 +38,27 @@ ServerCore::ServerCore(bool reservation): QObject(), SHMulticast(), eth_tcp(PIEt
break;
}
}
seed = generateID();//PINetworkAddress(my_ip, 0).ip();
seed = generateID(); // PINetworkAddress(my_ip, 0).ip();
addressesChanged();
piCoutObj << PICoutManipulators::Hex << seed << PINetworkAddress(seed, 0);
connect(&engine, SIGNAL(variableHistoryAdded(QString,QPair<QDateTime,double>)), this, SLOT(variableHistoryAdded(QString,QPair<QDateTime,double>)), Qt::DirectConnection);
connect(&engine,
SIGNAL(variableHistoryAdded(QString, QPair<QDateTime, double>)),
this,
SLOT(variableHistoryAdded(QString, QPair<QDateTime, double>)),
Qt::DirectConnection);
connect(&engine, SIGNAL(debug(QString)), this, SLOT(scriptDebug(QString)), Qt::DirectConnection);
CONNECTU(&eth_tcp, newConnection, this, newTCPConnection);
CONNECTU(&cloud_server, newConnection, this, newCloudConnection);
bindIndexedTimer(trSaveState, [this] { saveUIState(); });
bindIndexedTimer(trAdmin, [this] { sendAdminData(); });
bindIndexedTimer(trServerSync, [this] { syncServers(); });
bindIndexedTimer(trClients, [this] { procClients(); });
delete_clients_thread.start([this] { deleteOldClients(); }, 2_Hz);
}
ServerCore::~ServerCore() {
piCoutObj << "~ServerCore";
cloud_server.close();
cloud_server.stop();
engine.remove();
@@ -45,25 +66,29 @@ ServerCore::~ServerCore() {
PIByteArray sba = SHNetworkTypes::makeHeader(SHNetworkTypes::ServerRemove);
sba << seed;
piCoutObj << "send ServerRemove seed =" << seed;
send(sba);
killTimer(timer_save_state);
killTimer(timer_admin);
killTimer(timer_sync);
killTimer(timer);
stopRead();
PIVector<ServerClient * > rl = remotes.values();
send(sba);
stopIndexedTimer(trSaveState);
stopIndexedTimer(trAdmin);
stopIndexedTimer(trServerSync);
stopIndexedTimer(trClients);
delete_clients_thread.stopAndWait();
deleteOldClients();
PIVector<ServerClient *> rl = remotes.values();
for (ServerClient * r: rl)
if (r) {
piCoutObj << "delete" << (uintptr_t)r << "...";
r->destroy();
delete r->device;
delete r;
piCoutObj << "delete" << (uintptr_t)r << "done";
}
remotes.clear();
eth_tcp.stop();
for (auto * c: eth_tcp.clients())
c->stop();
piDeleteSafety(form);
if (bqr_content.data())
QResource::unregisterResource((uchar*)bqr_content.data());
if (bqr_content.data()) QResource::unregisterResource((uchar *)bqr_content.data());
}
@@ -78,8 +103,8 @@ void ServerCore::startEth() {
cloud_server.startThreadedRead();
log(QString("Connect to cloud %1@%2").arg(sa.server, PI2QString(cloud_server.serverName())));
}
timer_sync = startTimer(100);
timer_admin = startTimer(1000);
startIndexedTimer(trServerSync, 10_Hz);
startIndexedTimer(trAdmin, 1_Hz);
SHMulticast::startRead();
}
@@ -100,10 +125,10 @@ void ServerCore::loadRCC(const QString & p) {
return;
}
bqr_content = Q2PIByteArray(f.readAll());
rcc_hash = bqr_content.hash();
rcc_hash = bqr_content.hash();
f.close();
if(bqr_content.isEmpty()) return;
if (!QResource::registerResource((uchar*)bqr_content.data())) {
if (bqr_content.isEmpty()) return;
if (!QResource::registerResource((uchar *)bqr_content.data())) {
log("Can`t open resource \"" + QFileInfo(f).absoluteFilePath() + "\"!", SHServer::LogWarning);
return;
}
@@ -126,10 +151,10 @@ void ServerCore::loadUI(const QString & p) {
}
f.seek(0);
ui_content = Q2PIByteArray(f.readAll());
ui_hash = ui_content.hash();
ui_hash = ui_content.hash();
ui_content = Q2PIByteArray(qCompress(PI2QByteArray(ui_content)));
sync.assign(&ui_loader, true);
RUNTIME->json_ui = sync.json_ui;
RUNTIME->json_ui = sync.json_ui;
RUNTIME->widget_list = ui_loader.loaded_widgets;
form->setWindowTitle(QFileInfo(p).baseName());
ui_loader.adjust(form);
@@ -149,12 +174,12 @@ void ServerCore::loadQS(const QString & p) {
return;
}
log("Loaded script \"" + QFileInfo(f).absoluteFilePath() + "\"", SHServer::LogSuccess);
script_dir = QFileInfo(f).absoluteDir();
//script = QString::fromUtf8(f.readAll());
script_dir = QFileInfo(f).absoluteDir();
// script = QString::fromUtf8(f.readAll());
file_script = f.fileName();
QObject::connect(&engine, SIGNAL(error(int,QString,QString,QString)), this, SLOT(scriptError(int,QString,QString,QString)));
QObject::connect(&engine, SIGNAL(log(QString,int)), this, SLOT(scriptLog(QString,int)));
QObject::connect(&engine, SIGNAL(message(QString,int)), this, SLOT(scriptMessage(QString,int)));
QObject::connect(&engine, SIGNAL(error(int, QString, QString, QString)), this, SLOT(scriptError(int, QString, QString, QString)));
QObject::connect(&engine, SIGNAL(log(QString, int)), this, SLOT(scriptLog(QString, int)));
QObject::connect(&engine, SIGNAL(message(QString, int)), this, SLOT(scriptMessage(QString, int)));
QObject::connect(&engine, SIGNAL(logIO(QString)), this, SLOT(IOLog(QString)));
}
@@ -171,7 +196,7 @@ void ServerCore::loadDAT(const QString & p) {
}
log("Loaded database \"" + QFileInfo(f).absoluteFilePath() + "\"", SHServer::LogSuccess);
RUNTIME->setServerData(loadFromFile<SHS::ServerData>(p));
server_key_ = Q2PIString(RUNTIME->server_data.project.propertyValueByName("key" ).toString());
server_key_ = Q2PIString(RUNTIME->server_data.project.propertyValueByName("key").toString());
server_name_ = Q2PIString(RUNTIME->server_data.project.propertyValueByName("name").toString());
piCout << "key" << server_key_;
loadedDAT();
@@ -186,7 +211,7 @@ void ServerCore::loadCM(const QString & p) {
}
log("Loaded connection \"" + QFileInfo(f).absoluteFilePath() + "\"", SHServer::LogSuccess);
RUNTIME->connection.loadFromCMFile(p);
connect(&RUNTIME->connection, SIGNAL(qDataReceivedEvent(QString,QByteArray)), this, SLOT(connDataReceivedEvent(QString,QByteArray)));
connect(&RUNTIME->connection, SIGNAL(qDataReceivedEvent(QString, QByteArray)), this, SLOT(connDataReceivedEvent(QString, QByteArray)));
loadedCM();
}
@@ -204,29 +229,28 @@ void ServerCore::loadVAR(const QString & p) {
void ServerCore::loadBAF(const PIString & p) {
piCout << "loadBAF" << p;
baf_path = p;
baf_path = p;
RUNTIME->server_project = SHS::ServerProject();
if (baf_path.isEmpty()) return;
RUNTIME->server_data.setRootPath(QDir::tempPath());
RUNTIME->modules_dir = RUNTIME->server_data.modulePath();
QStringList fl = ass.unpack(PI2QString(baf_path)), qspl;
QStringList fl = ass.unpack(PI2QString(baf_path)), qspl;
QString bqrp, uip, dbp, cmp, varp, sdpp;
for (const auto & s: fl) {
if (s.endsWith(".rcc")) bqrp = s;
if (s.endsWith(".uip")) uip = s;
if (s.endsWith(".uip")) uip = s;
if (s.endsWith(".dat") && !s.endsWith(QString(SHFileSuffix) + ".dat")) dbp = s;
if (s.endsWith(".qs")) qspl << s;
if (s.endsWith(".cm")) cmp = s;
if (s.endsWith(".qs")) qspl << s;
if (s.endsWith(".cm")) cmp = s;
if (s.endsWith(".var")) varp = s;
if (s.endsWith(".sdp")) sdpp = s;
}
if (!bqrp.isEmpty()) loadRCC(bqrp);
loadUI(uip);
if (!cmp.isEmpty()) loadCM(cmp);
if (!dbp.isEmpty()) loadDAT(dbp);
if (!cmp.isEmpty()) loadCM(cmp);
if (!dbp.isEmpty()) loadDAT(dbp);
RUNTIME->server_data.setRootPath(QDir::tempPath());
if (!varp.isEmpty())
loadVAR(varp);
if (!varp.isEmpty()) loadVAR(varp);
if (!sdpp.isEmpty())
loadProject(sdpp);
else if (qspl.size() == 1) {
@@ -259,221 +283,9 @@ void ServerCore::loadProject(const QString & p) {
}
void ServerCore::timerEvent(QTimerEvent * e) {
if (e->timerId() == timer_save_state) {
saveUIState();
return;
}
if (e->timerId() == timer_sync) {
if (with_reservation) {
smutex.lock();
if (server_state > ServerCore::ssSync) {
for (int i = 0; i < servers.size_s(); ++i) {
servers[i].missed++;
if (servers[i].missed > 10) {
piCoutObj << "remove by timeout" << servers[i].seed;
if (servers[i].seed == seed_main)
selectNewMain();
servers.remove(i);
i--;
}
}
}
smutex.unlock();
if (sync_skip > 0) {
sync_skip--;
return;
}
switch (server_state) {
case ServerCore::ssStart: {
PIByteArray sba = SHNetworkTypes::makeHeader(SHNetworkTypes::ServerNew);
sba << seed;
piCoutObj << "send ServerNew seed =" << seed << ", ip =" << my_ip;
send(sba);
selectNewMain();
} break;
case ServerCore::ssSync:
if (seed_main == 0) {
int mseed = seed;
int mi = -1;
smutex.lock();
for (int i = 0; i < servers.size_s(); ++i) {
if (mseed > servers[i].seed) {
mseed = servers[i].seed;
mi = i;
}
}
smutex.unlock();
seed_main = mseed;
main_ip = PINetworkAddress(mseed, 0).ipString();
if (mi < 0)
startAsMain();
else
startAsReserve();
}
break;
case ServerCore::ssWorkReserve:
main_missed++;
if (main_missed > 10) {
main_missed = 0;
selectNewMain();
}
case ServerCore::ssWorkMain:
{
PIByteArray sba = SHNetworkTypes::makeHeader(SHNetworkTypes::ServerPing);
sba << seed;
//piCoutObj << "send ServerPing seed =" << seed;
send(sba);
}
break;
}
} else startAsMain();
return;
}
if (e->timerId() == timer_admin) {
lmutex.lock();
PacketServerLog pck_log, pck_log_hist;
pck_log.entries = std::move(admin_log);
admin_log.clear();
auto mq = std::move(message_queue);
message_queue.clear();
lmutex.unlock();
rmutex.lock();
state_dynamic.clients.clear();
PIVector<ServerClient * > rl = remotes.values();
for (ServerClient * r: rl) {
if (!r) continue;
r->updateInfo();
state_dynamic.clients << r->info;
}
state_dynamic.devices.clear();
PIVector<PIIODevice * > devs = RUNTIME->connection.boundedDevices();
for (PIIODevice * d: devs) {
if (!d) continue;
ServerDeviceInfo di;
di.classname = QLatin1String(d->className());
di.path = PI2QString(d->path());
di.mode = d->mode();
PIDiagnostics * diag = RUNTIME->connection.diagnostic(d);
if (diag) {
di.sended_bytes = diag->state().sended_bytes;
di.received_bytes = diag->state().received_bytes;
di.send_speed = PI2QString(diag->sendSpeed());
di.receive_speed = PI2QString(diag->receiveSpeed());
}
state_dynamic.devices << di;
}
for (auto & v: state_dynamic.variables) {
auto val = engine.getVariableValue(v.name);
v.changed = val.first;
v.value = val.second;
}
PIByteArray msg_state;
msg_state = SHNetworkTypes::makeHeader(SHNetworkTypes::AdminDynamicState);
msg_state << state_dynamic;
for (ServerClient * r: rl) {
if (!r) continue;
if (r->info.role == SHServer::RoleMessages) {
for (const auto & m: mq) {
PIByteArray ba = SHNetworkTypes::makeHeader(SHNetworkTypes::Message);
ba << m;
r->queueSend(ba);
}
}
if (r->info.role == SHServer::RoleAdmin) {
if (!r->log_sended) {
r->log_sended = true;
pck_log_hist.entries = admin_log_history;
PIByteArray msg = SHNetworkTypes::makeHeader(SHNetworkTypes::AdminLog);
msg << pck_log_hist;
r->queueSend(msg);
}
if (!msg_state.isEmpty())
r->queueSend(msg_state);
if (!pck_log.entries.isEmpty() || !r->admin_io_log.isEmpty()) {
PacketServerLog pckt;
pckt.entries << pck_log.entries << r->admin_io_log;
pckt.entries.sort([](const LogEntry & t0, const LogEntry & t1){return t0.time < t1.time;});
r->admin_io_log.clear();
PIByteArray msg = SHNetworkTypes::makeHeader(SHNetworkTypes::AdminLog);
msg << pckt;
r->queueSend(msg);
}
}
}
rmutex.unlock();
for (const auto & e: pck_log.entries) {
admin_log_cur_size += e.text.size();
admin_log_history << e;
while (admin_log_cur_size > admin_log_max_size)
admin_log_cur_size -= admin_log_history.take_front().text.size();
}
return;
}
rmutex.lock();
sync.buildDiffForRoles();
PIVector<ServerClient * > rl = remotes.values(), to_remove;
for (ServerClient * r: rl) {
bool disconn = !r->isConnected();
if (r) {if (r->tcp->wasError()) disconn = true;}
if (disconn) {
log("Client " + PI2QString(r->device->path()) + " disconnected", SHServer::LogInfo);
//piCout << "disconn ...";
r->close();
//piCout << "disconn close";
if (df_client == r) {
df_client = 0;
df_device.clear();
engine.connection()->setInactive(false);
}
to_remove << r;
//piCout << "disconn done";
}
r->maybeCallQueuedEvents();
r->updateInfo();
if (!r->tcp || !r->active || (r->info.role != SHServer::RoleGui)) continue;
PIByteArray diff;
if (r->role_changed) {
diff = Q2PIByteArray(sync.buildTransitionDiff(r->user_role, r->new_user_role));
//qDebug() << "send transitional diff" << r->user_role << "->" << r->new_user_role << diff.size();
r->newRoleDone();
if (!diff.isEmpty()) {
diff.insert(0, SHNetworkTypes::makeHeader(SHNetworkTypes::GuiSyncDiff));
r->queueSend(diff);
}
diff.clear();
}
diff = sync.diffForRole(r->user_role);
if (!diff.isEmpty()) {
diff.insert(0, SHNetworkTypes::makeHeader(SHNetworkTypes::GuiSyncDiff));
r->queueSend(diff);
}
//piCout << "diff role" << r->user_role << diff.size();
}
for (ServerClient * r: to_remove) {
remotes.remove(r->device);
r->destroy();
delete r->device;
delete r;
}
rmutex.unlock();
}
bool ServerCore::hasServer(const PIString & ip) const {
for (const auto & s: servers)
if (s.ip == ip)
return true;
if (s.ip == ip) return true;
return false;
}
@@ -504,10 +316,8 @@ void ServerCore::startAsMain() {
if (server_state == ServerCore::ssWorkMain) return;
piCoutObj << "startAsMain";
server_state = ServerCore::ssWorkMain;
if (timer > 0) killTimer(timer);
timer = startTimer(100);
if (timer_save_state > 0) killTimer(timer_save_state);
timer_save_state = startTimer(10000);
startIndexedTimer(trSaveState, 10_s);
startIndexedTimer(trClients, 10_Hz);
sync_skip = 0;
start();
engine.setDir(script_dir);
@@ -531,8 +341,7 @@ void ServerCore::startAsReserve() {
if (server_state == ServerCore::ssWorkReserve) return;
piCoutObj << "startAsReserve";
server_state = ServerCore::ssWorkReserve;
if (timer > 0) killTimer(timer);
timer = 0;
stopIndexedTimer(trClients);
sync_skip = 0;
start();
startedAsReserve();
@@ -541,9 +350,9 @@ void ServerCore::startAsReserve() {
void ServerCore::selectNewMain() {
piCoutObj << "selectNewMain";
seed_main = 0;
seed_main = 0;
server_state = ServerCore::ssSync;
sync_skip = 10;
sync_skip = 10;
}
@@ -566,8 +375,7 @@ void ServerCore::restoreUIState() {
QFile f(file_ui_state);
if (!f.open(QIODevice::ReadOnly)) {
f.setFileName(file_ui_state_new);
if (!f.open(QIODevice::ReadOnly))
return;
if (!f.open(QIODevice::ReadOnly)) return;
}
if (f.size() < 8) return;
QDataStream s(&f);
@@ -577,7 +385,7 @@ void ServerCore::restoreUIState() {
s >> v >> data;
if (v == SHUISync::Version3) {
data = sync.convertFromVersion3(data);
v = SHUISync::CurrentVersion;
v = SHUISync::CurrentVersion;
piCoutObj << "UI state converted from version" << SHUISync::Version3;
}
if (v != SHUISync::CurrentVersion) {
@@ -630,7 +438,7 @@ void ServerCore::gatherVariables() {
vars = engine.getVariables();
for (const auto & v: vars) {
ServerVariable sv;
sv.name = v.name;
sv.name = v.name;
sv.store = v.store;
state_dynamic.variables << sv;
}
@@ -644,9 +452,230 @@ void ServerCore::gatherFixedState() {
PIString server = Q2PIString(RUNTIME->server_data.project.propertyValueByName("cloud_address").toString()) + "@";
server += getThisCloudName();
state_fixed.cloud_address = PI2QString(server);
state_fixed.cloud_href = QString("https://") + SHServerURL + "/pult/?address=" + QString(QUrl::toPercentEncoding(PI2QString(server + getThisCloudName())));
state_fixed.cloud_href = QString("https://") + SHServerURL +
"/pult/?address=" + QString(QUrl::toPercentEncoding(PI2QString(server + getThisCloudName())));
}
}
void ServerCore::sendAdminData() {
lmutex.lock();
PacketServerLog pck_log, pck_log_hist;
pck_log.entries = std::move(admin_log);
admin_log.clear();
auto mq = std::move(message_queue);
message_queue.clear();
lmutex.unlock();
rmutex.lock();
state_dynamic.clients.clear();
PIVector<ServerClient *> rl = remotes.values();
for (ServerClient * r: rl) {
if (!r) continue;
r->updateInfo();
state_dynamic.clients << r->info;
}
state_dynamic.devices.clear();
PIVector<PIIODevice *> devs = RUNTIME->connection.boundedDevices();
for (PIIODevice * d: devs) {
if (!d) continue;
ServerDeviceInfo di;
di.classname = QLatin1String(d->className());
di.path = PI2QString(d->path());
di.mode = d->mode();
PIDiagnostics * diag = RUNTIME->connection.diagnostic(d);
if (diag) {
di.sended_bytes = diag->state().sended_bytes;
di.received_bytes = diag->state().received_bytes;
di.send_speed = PI2QString(diag->sendSpeed());
di.receive_speed = PI2QString(diag->receiveSpeed());
}
state_dynamic.devices << di;
}
for (auto & v: state_dynamic.variables) {
auto val = engine.getVariableValue(v.name);
v.changed = val.first;
v.value = val.second;
}
PIByteArray msg_state;
msg_state = SHNetworkTypes::makeHeader(SHNetworkTypes::AdminDynamicState);
msg_state << state_dynamic;
for (ServerClient * r: rl) {
if (!r) continue;
if (r->info.role == SHServer::RoleMessages) {
for (const auto & m: mq) {
PIByteArray ba = SHNetworkTypes::makeHeader(SHNetworkTypes::Message);
ba << m;
r->queueSend(ba);
}
}
if (r->info.role == SHServer::RoleAdmin) {
if (!r->log_sended) {
r->log_sended = true;
pck_log_hist.entries = admin_log_history;
PIByteArray msg = SHNetworkTypes::makeHeader(SHNetworkTypes::AdminLog);
msg << pck_log_hist;
r->queueSend(msg);
}
if (!msg_state.isEmpty()) r->queueSend(msg_state);
if (!pck_log.entries.isEmpty() || !r->admin_io_log.isEmpty()) {
PacketServerLog pckt;
pckt.entries << pck_log.entries << r->admin_io_log;
pckt.entries.sort([](const LogEntry & t0, const LogEntry & t1) { return t0.time < t1.time; });
r->admin_io_log.clear();
PIByteArray msg = SHNetworkTypes::makeHeader(SHNetworkTypes::AdminLog);
msg << pckt;
r->queueSend(msg);
}
}
}
rmutex.unlock();
for (const auto & e: pck_log.entries) {
admin_log_cur_size += e.text.size();
admin_log_history << e;
while (admin_log_cur_size > admin_log_max_size)
admin_log_cur_size -= admin_log_history.take_front().text.size();
}
}
void ServerCore::syncServers() {
if (with_reservation) {
smutex.lock();
if (server_state > ServerCore::ssSync) {
for (int i = 0; i < servers.size_s(); ++i) {
servers[i].missed++;
if (servers[i].missed > 10) {
piCoutObj << "remove by timeout" << servers[i].seed;
if (servers[i].seed == seed_main) selectNewMain();
servers.remove(i);
i--;
}
}
}
smutex.unlock();
if (sync_skip > 0) {
sync_skip--;
return;
}
switch (server_state) {
case ServerCore::ssStart: {
PIByteArray sba = SHNetworkTypes::makeHeader(SHNetworkTypes::ServerNew);
sba << seed;
piCoutObj << "send ServerNew seed =" << seed << ", ip =" << my_ip;
send(sba);
selectNewMain();
} break;
case ServerCore::ssSync:
if (seed_main == 0) {
int mseed = seed;
int mi = -1;
smutex.lock();
for (int i = 0; i < servers.size_s(); ++i) {
if (mseed > servers[i].seed) {
mseed = servers[i].seed;
mi = i;
}
}
smutex.unlock();
seed_main = mseed;
main_ip = PINetworkAddress(mseed, 0).ipString();
if (mi < 0)
startAsMain();
else
startAsReserve();
}
break;
case ServerCore::ssWorkReserve:
main_missed++;
if (main_missed > 10) {
main_missed = 0;
selectNewMain();
}
case ServerCore::ssWorkMain: {
PIByteArray sba = SHNetworkTypes::makeHeader(SHNetworkTypes::ServerPing);
sba << seed;
// piCoutObj << "send ServerPing seed =" << seed;
send(sba);
} break;
}
} else
startAsMain();
}
void ServerCore::procClients() {
PIMutexLocker ml(rmutex);
sync.buildDiffForRoles();
PIVector<ServerClient *> rl = remotes.values(), to_remove;
for (ServerClient * r: rl) {
bool disconn = !r->isConnected();
if (r) {
if (r->tcp->wasError()) disconn = true;
}
if (disconn) {
log("Client " + PI2QString(r->device->path()) + " disconnected", SHServer::LogInfo);
// piCout << "disconn ...";
r->close();
// piCout << "disconn close";
if (df_client == r) {
df_client = 0;
df_device.clear();
engine.connection()->setInactive(false);
}
to_remove << r;
// piCout << "disconn done";
}
r->maybeCallQueuedEvents();
r->updateInfo();
if (!r->tcp || !r->active || (r->info.role != SHServer::RoleGui)) continue;
PIByteArray diff;
if (r->role_changed) {
diff = Q2PIByteArray(sync.buildTransitionDiff(r->user_role, r->new_user_role));
// qDebug() << "send transitional diff" << r->user_role << "->" << r->new_user_role << diff.size();
r->newRoleDone();
if (!diff.isEmpty()) {
diff.insert(0, SHNetworkTypes::makeHeader(SHNetworkTypes::GuiSyncDiff));
r->queueSend(diff);
}
diff.clear();
}
diff = sync.diffForRole(r->user_role);
if (!diff.isEmpty()) {
diff.insert(0, SHNetworkTypes::makeHeader(SHNetworkTypes::GuiSyncDiff));
r->queueSend(diff);
}
// piCout << "diff role" << r->user_role << diff.size();
}
for (ServerClient * r: to_remove) {
remotes.remove(r->device);
r->close();
rcq_mutex.lock();
delete_clients_queue.enqueue(r);
rcq_mutex.unlock();
}
}
void ServerCore::deleteOldClients() {
rcq_mutex.lock();
auto del_queue = delete_clients_queue;
delete_clients_queue.clear();
rcq_mutex.unlock();
for (auto * r: del_queue) {
piCoutObj << "delete" << (uintptr_t)r << "...";
r->destroy();
delete r->device;
delete r;
piCoutObj << "delete" << (uintptr_t)r << "done";
}
}
@@ -668,14 +697,14 @@ void ServerCore::connDataReceivedEvent(QString from, QByteArray data) {
void ServerCore::variableHistoryAdded(QString vname, QPair<QDateTime, double> value) {
//qDebug() << "history add" << vname;
// qDebug() << "history add" << vname;
SHS::PacketGraphicData gd(vname);
ullong time = value.first.toMSecsSinceEpoch();
gd.data << PIPair<ullong, double>(time, value.second);
PIByteArray ba = SHNetworkTypes::makeHeader(SHNetworkTypes::GraphicData);
ba << gd;
PIMutexLocker _ml(rmutex);
PIVector<ServerClient * > rl = remotes.values();
PIVector<ServerClient *> rl = remotes.values();
for (auto * r: rl)
if (r->tcp && r->active && r->info.role == SHServer::RoleGraphics) {
if (r->graphics.contains(vname)) {
@@ -687,14 +716,14 @@ void ServerCore::variableHistoryAdded(QString vname, QPair<QDateTime, double> va
void ServerCore::receivedSH(PIByteArray data, uint rec_id) {
//piCout << "received" << data;
// piCout << "received" << data;
PacketHeader hdr = SHNetworkTypes::takeHeader(data);
if (hdr.type < 0) return;
//piCout << "received type" << hdr.type << rec_id << data.size();
// piCout << "received type" << hdr.type << rec_id << data.size();
int _seed;
PIString _ip;
PIByteArray ba;
//piCout << "received" << type;
// piCout << "received" << type;
if (with_reservation) {
switch ((SHNetworkTypes::MulticastType)hdr.type) {
case SHNetworkTypes::ServerNew:
@@ -729,8 +758,7 @@ void ServerCore::receivedSH(PIByteArray data, uint rec_id) {
smutex.lock();
for (int i = 0; i < servers.size_s(); ++i)
if (servers[i].seed == _seed) {
if (seed_main == _seed)
selectNewMain();
if (seed_main == _seed) selectNewMain();
servers.remove(i);
i--;
}
@@ -745,23 +773,21 @@ void ServerCore::receivedSH(PIByteArray data, uint rec_id) {
break;
case SHNetworkTypes::ServerPing:
data >> _seed;
if (seed_main == _seed)
main_missed = 0;
if (seed_main == _seed) main_missed = 0;
smutex.lock();
for (int i = 0; i < servers.size_s(); ++i)
if (servers[i].seed == _seed)
servers[i].missed = 0;
if (servers[i].seed == _seed) servers[i].missed = 0;
smutex.unlock();
//seed_main = _seed;
//piCoutObj << "recv ServerPing seed =" << _seed;
// seed_main = _seed;
// piCoutObj << "recv ServerPing seed =" << _seed;
break;
default: break;
}
}
if (server_state != ServerCore::ssWorkMain) return;
//piCout << "received type" << type << rec_id << data.size();
// piCout << "received type" << type << rec_id << data.size();
if (hdr.type == SHNetworkTypes::Request) {
//PIMutexLocker locker(mcast_mutex);
// PIMutexLocker locker(mcast_mutex);
PIStringList addresses;
data >> addresses;
PIString addr;
@@ -772,17 +798,16 @@ void ServerCore::receivedSH(PIByteArray data, uint rec_id) {
break;
}
}
if (!addr.isEmpty())
break;
if (!addr.isEmpty()) break;
}
//piCout << "return address" << addr;
// piCout << "return address" << addr;
PacketServerInfo info;
info.identify = PacketIdentification::makeLocal(0, SHS_NETWORK_VERSION, SHS_UISYNC_VERSION);
info.identify.hashes.hash_ui = ui_hash;
info.identify = PacketIdentification::makeLocal(0, SHS_NETWORK_VERSION, SHS_UISYNC_VERSION);
info.identify.hashes.hash_ui = ui_hash;
info.identify.hashes.hash_rcc = rcc_hash;
info.connect_address = addr;
info.name = server_name_;
PIByteArray sba = SHNetworkTypes::makeHeader(SHNetworkTypes::Reply);
info.connect_address = addr;
info.name = server_name_;
PIByteArray sba = SHNetworkTypes::makeHeader(SHNetworkTypes::Reply);
sba << info;
send(sba, rec_id);
}
@@ -799,36 +824,36 @@ void ServerCore::addressesChanged() {
void ServerCore::newTCPConnection(PIEthernet * client) {
//piCout << "newConnection" << client;
// piCout << "newConnection" << client;
log("Client connected from " + PI2QString(client->path()) + " (TCP)", SHServer::LogInfo);
client->setDebug(false);
client->setReadTimeout(60000.);
client->setWriteTimeout(60000.);
client->setParameter(PIEthernet::DisonnectOnTimeout, false);
ServerClient * r = new ServerClient(this, SHNetworkTypes::TCP);
//CONNECTU(r, packetReceived, this, packetReceived)
// CONNECTU(r, packetReceived, this, packetReceived)
r->init(client);
//piCout << "newConnection lock ...";
// piCout << "newConnection lock ...";
rmutex.lock();
remotes[client] = r;
rmutex.unlock();
client->startThreadedRead();
//piCout << "newConnection lock done";
// piCout << "newConnection lock done";
}
void ServerCore::newCloudConnection(PICloudServer::Client * client) {
piCout << "newCloudConnection" << client;
log("Client connected from " + PI2QString(client->path()) + " (Cloud)", SHServer::LogInfo);
//client->setDebug(false);
// client->setDebug(false);
ServerClient * r = new ServerClient(this, SHNetworkTypes::Cloud);
//CONNECTU(r, packetReceived, this, packetReceived)
// CONNECTU(r, packetReceived, this, packetReceived)
r->init(client);
//piCout << "newConnection lock ...";
// piCout << "newConnection lock ...";
rmutex.lock();
remotes[client] = r;
rmutex.unlock();
//piCout << "newConnection lock done";
// piCout << "newConnection lock done";
client->startThreadedRead();
}
@@ -837,15 +862,15 @@ void ServerCore::receivedIdentification(ServerClient * r, PIByteArray data) {
PIByteArray ba;
PacketIdentification p;
data >> p;
r->id = r->tcp->lastRecID();
r->info.id = r->id;
r->info.OS_type = (SHPlatform::OSType)p.os_type;
r->info.OS_arch = PI2QString(p.arch);
r->id = r->tcp->lastRecID();
r->info.id = r->id;
r->info.OS_type = (SHPlatform::OSType)p.os_type;
r->info.OS_arch = PI2QString(p.arch);
r->info.OS_version = PI2QString(p.os_version);
r->info.hostname = PI2QString(p.hostname);
r->info.role = (SHServer::ClientRole)p.role;
r->info.hostname = PI2QString(p.hostname);
r->info.role = (SHServer::ClientRole)p.role;
r->net_version = p.net_version;
r->net_version = p.net_version;
if (r->net_version != SHS_NETWORK_VERSION) {
qDebug() << "invalid network version" << r->net_version;
log(tr("Client \"%1\" invalid network version: %2!").arg(r->info.hostname).arg(r->net_version), SHServer::LogWarning);
@@ -879,13 +904,13 @@ void ServerCore::receivedIdentification(ServerClient * r, PIByteArray data) {
sendInitialAdminData(r);
}
//piCoutObj << "my" << ui_hash << rcc_hash;
//piCoutObj << "cl" << p.hashes.hash_ui << p.hashes.hash_rcc;
r->upload_ui = (p.hashes.hash_ui != ui_hash);
// piCoutObj << "my" << ui_hash << rcc_hash;
// piCoutObj << "cl" << p.hashes.hash_ui << p.hashes.hash_rcc;
r->upload_ui = (p.hashes.hash_ui != ui_hash);
r->upload_rcc = (p.hashes.hash_rcc != rcc_hash);
r->tcp->setCheckHeader(true);
r->tcp->setID(r->id);
//qDebug() << "ident" << int(r->info.OS_type) << r->info.OS_arch << r->info.OS_version;
// qDebug() << "ident" << int(r->info.OS_type) << r->info.OS_arch << r->info.OS_version;
}
@@ -903,16 +928,15 @@ void ServerCore::receivedKey(ServerClient * r, PIByteArray data) {
PIString key;
data >> key;
bool ok = (key == server_key_);
ba = SHNetworkTypes::makeHeader(SHNetworkTypes::KeyProbeResult);
ba = SHNetworkTypes::makeHeader(SHNetworkTypes::KeyProbeResult);
ba << uchar(ok ? 1 : 0);
piCout << "received key" << key;
r->tcp->send(ba);
if (ok) {
if (r->upload_rcc) {
ba = SHNetworkTypes::makeHeader(SHNetworkTypes::GuiSyncRCC);
ba.append(bqr_content);
//qDebug() << "send rcc" << int(SHNetworkTypes::GuiSyncRCC) << bqr_content.size();
// qDebug() << "send rcc" << int(SHNetworkTypes::GuiSyncRCC) << bqr_content.size();
} else {
ba = SHNetworkTypes::makeHeader(SHNetworkTypes::GuiRestoreRCC);
}
@@ -924,11 +948,11 @@ void ServerCore::receivedKey(ServerClient * r, PIByteArray data) {
} else {
ba = SHNetworkTypes::makeHeader(SHNetworkTypes::GuiRestoreUI);
}
//qDebug() << "send ui" << int(SHNetworkTypes::GuiSyncUI) << ba.size();
// qDebug() << "send ui" << int(SHNetworkTypes::GuiSyncUI) << ba.size();
r->queueSend(ba);
ba = Q2PIByteArray(sync.buildFullDiffForRole(r->user_role));
//qDebug() << "send init diff" << r->user_role << ba.size();
// qDebug() << "send init diff" << r->user_role << ba.size();
if (!ba.isEmpty()) {
PIByteArray hdr = SHNetworkTypes::makeHeader(SHNetworkTypes::GuiSyncDiff);
ba.insert(0, hdr);
@@ -938,14 +962,14 @@ void ServerCore::receivedKey(ServerClient * r, PIByteArray data) {
ba = SHNetworkTypes::makeHeader(SHNetworkTypes::ConnectingDone);
r->queueSend(ba);
//r->active = true;
// r->active = true;
}
}
void ServerCore::sendToAll(const PIByteArray & data, SHServer::ClientRole role, bool no_check) {
PIMutexLocker _ml(rmutex);
PIVector<ServerClient * > rl = remotes.values();
PIVector<ServerClient *> rl = remotes.values();
for (ServerClient * r: rl) {
qDebug() << r << r->tcp << r->active << r->info.role;
if (!r->tcp || r->info.role != role) continue;
@@ -967,7 +991,7 @@ void ServerCore::sendInitialAdminData(ServerClient * r) {
while (it.next()) {
if (it.value().isLoaded()) {
PacketServerPlugin plugin;
plugin.name = it.key();
plugin.name = it.key();
plugin.version = it.value().manifest.fullVersion();
plugins << plugin;
}
@@ -1009,14 +1033,14 @@ void ServerCore::message(const QString & text, int type) {
void ServerCore::scriptError(int line, QString file, QString message, QString stack) {
if (lqs_err_line == line && lqs_err_msg == message) return;
lqs_err_line = line;
lqs_err_msg = message;
lqs_err_msg = message;
log(QString("Script error, %1:%2: %3\n%4").arg(file).arg(line).arg(message, stack), SHServer::LogError);
PIByteArray msg = SHNetworkTypes::makeHeader(SHNetworkTypes::AdminScriptError);
PacketScriptError se;
se.message = message;
se.stack = stack;
se.file = file;
se.line = line;
se.stack = stack;
se.file = file;
se.line = line;
se.project = PI2QString(server_name_);
msg << se;
sendToAll(msg, SHServer::RoleAdmin, true);
@@ -1040,7 +1064,7 @@ void ServerCore::IOLog(QString text) {
e.text = text;
e.type = SHServer::LogIO;
rmutex.lock();
PIVector<ServerClient * > rl = remotes.values();
PIVector<ServerClient *> rl = remotes.values();
for (ServerClient * r: rl) {
if (!r) continue;
if ((r->info.role != SHServer::RoleAdmin) || !r->admin_log_io) continue;

View File

@@ -1,49 +1,54 @@
#ifndef SERVER_CORE_H
#define SERVER_CORE_H
#include "SH_assembly.h"
#include "SH_ui_loader.h"
#include "SH_ui_sync.h"
#include "script_engine.h"
#include "server_client.h"
#include <QTimer>
#include <picli.h>
#include <picloudserver.h>
#include <piliterals_bytes.h>
#include "script_engine.h"
#include "server_client.h"
#include "SH_assembly.h"
#include "SH_ui_loader.h"
#include "SH_ui_sync.h"
#include <qad_timers.h>
class Server;
class ServerClient;
class ServerStarter;
class ServerCore: public QObject, public SHMulticast {
class ServerCore
: public QObject
, public SHMulticast
, public IndexedTimer<> {
Q_OBJECT
PIOBJECT_SUBCLASS(ServerCore, SHMulticast)
friend class Server;
friend class ServerClient;
friend class ServerStarter;
public:
ServerCore(bool reservation = false);
~ServerCore();
void loadRCC(const QString & p);
void loadUI (const QString & p);
void loadQS (const QString & p);
void loadUI(const QString & p);
void loadQS(const QString & p);
void loadDAT(const QString & p);
void loadCM (const QString & p);
void loadCM(const QString & p);
void loadVAR(const QString & p);
void loadBAF(const PIString & p);
void loadProject(const QString & p);
void startEth();
void start();
bool isPluginsLoaded() const {return plugins_ok;}
bool isPluginsLoaded() const { return plugins_ok; }
SHSScriptEngine engine;
PIByteArray admin_password;
uint admin_log_max_size = 65_KiB;
private:
void timerEvent(QTimerEvent *) override;
void receivedSH(PIByteArray data, uint rec_id) override;
void addressesChanged() override;
void sendToAll(const PIByteArray & data, SHServer::ClientRole role, bool no_check = false);
@@ -64,12 +69,21 @@ private:
void updatePlugins(const QStringList & names, ServerClient * r);
void gatherVariables();
void gatherFixedState();
void sendAdminData();
void syncServers();
void procClients();
void deleteOldClients();
PacketParameterList adminParameters() const;
EVENT_HANDLER1(void, newTCPConnection, PIEthernet * , client);
EVENT_HANDLER1(void, newCloudConnection, PICloudServer::Client * , client);
EVENT_HANDLER1(void, newTCPConnection, PIEthernet *, client);
EVENT_HANDLER1(void, newCloudConnection, PICloudServer::Client *, client);
enum ServerState {
ssStart,
ssSync,
ssWorkMain,
ssWorkReserve
};
enum ServerState {ssStart, ssSync, ssWorkMain, ssWorkReserve};
struct ServerSync {
int seed;
ServerState state;
@@ -84,56 +98,57 @@ private:
};
typedef PIPair<PIString, PIString> PISSPair;
QWidget * form = nullptr;
SHUISync sync;
SHAssembly ass;
PIEthernet eth_tcp;
PICloudServer cloud_server;
PIMutex rmutex, lmutex, smutex;
PIMutex rmutex, lmutex, smutex, rcq_mutex;
QQueue<LogEntry> log_queue;
PIThread delete_clients_thread;
PIDeque<LogEntry> admin_log, admin_log_history;
QQueue<PacketMessage> message_queue;
PIVector<PIEthernet*> eth_mcast;
PIVector<PIEthernet *> eth_mcast;
PIByteArray ui_content, bqr_content;
PacketServerDynamicState state_dynamic;
PacketServerFixedState state_fixed;
PIMap<PIIODevice * , ServerClient * > remotes;
PIMap<PIIODevice *, ServerClient *> remotes;
PIQueue<ServerClient *> delete_clients_queue;
QDir script_dir;
QString lqs_err_msg, script, file_ui_state, file_ui_state_new, file_script;
QList<SHS::ScriptVariable> vars;
PIVector<ServerSync> servers;
PIVector<PISSPair> addresses_server;
PIString my_ip = "127.0.0.1", main_ip, baf_path, df_device, server_name_, server_key_;
PIString my_ip = "127.0.0.1", main_ip, baf_path, df_device, server_name_, server_key_;
ServerState server_state = ServerCore::ssStart;
ServerClient * df_client = nullptr;
SHSUiLoader ui_loader;
uint ui_hash = 0, rcc_hash = 0;
uint admin_log_cur_size = 0;
int timer = 0, timer_sync = 0, timer_admin = 0, timer_save_state = 0, lqs_err_line = -1, sync_skip = 0, main_missed = 0;
int seed = 0 , seed_main = 0;
int timer = 0, lqs_err_line = -1, sync_skip = 0, main_missed = 0;
int seed = 0, seed_main = 0;
bool with_reservation = false, plugins_ok = false;
private slots:
void connDataReceivedEvent(QString from, QByteArray data);
void variableHistoryAdded(QString vname, QPair<QDateTime, double> value);
void scriptError(int line, QString file, QString message, QString stack);
void scriptLog(QString text, int type) {log(text, (SHServer::LogEntryType)type);}
void scriptLog(QString text, int type) { log(text, (SHServer::LogEntryType)type); }
void scriptDebug(QString text);
void scriptMessage(QString text, int type) {message(text, type);}
void scriptMessage(QString text, int type) { message(text, type); }
void IOLog(QString text);
signals:
void restart(QString baf_path);
void loadedUI ();
void loadedUI();
void loadedDAT();
void loadedCM ();
void loadedCM();
void loadedVAR();
void startedAsMain();
void startedAsReserve();
void zeroFailure();
void updatePluginsRequest(QStringList);
};
#endif // SERVER_CORE_H

View File

@@ -1,8 +1,9 @@
#include "server_starter.h"
#include "SH_base.h"
#include "SH_plugins_manager.h"
#include <qad_locations.h>
#include <qad_locations.h>
ServerStarter::ServerStarter(): QObject() {
@@ -13,31 +14,30 @@ ServerStarter::ServerStarter(): QObject() {
if (QFile::exists(confpath)) {
QPIConfig conf(confpath, QIODevice::ReadOnly);
QString baf = conf.getValue("baf_path", "").toString().trimmed();
if (!baf.isEmpty())
baf_path = baf;
if (!baf.isEmpty()) baf_path = baf;
max_failures = conf.getValue("max_failures", max_failures).toInt();
log_add_time = conf.getValue("log_add_time", log_add_time).toBool();
log_add_dev = conf.getValue("log_add_dev", log_add_dev).toBool();
log_io = conf.getValue("log_io", log_io).toBool();
max_log_kb = conf.getValue("max_log_kb", max_log_kb).toDouble();
reservation = conf.getValue("reservation", reservation).toBool();
ph = conf.getValue("admin_passwd").toString();
log_add_dev = conf.getValue("log_add_dev", log_add_dev).toBool();
log_io = conf.getValue("log_io", log_io).toBool();
max_log_kb = conf.getValue("max_log_kb", max_log_kb).toDouble();
reservation = conf.getValue("reservation", reservation).toBool();
ph = conf.getValue("admin_passwd").toString();
}
if (ph.isEmpty())
admin_password = passwordHash("");
else
admin_password = PIByteArray::fromHex(Q2PIString(ph));
//piCout << "last admin_passwd" << admin_passwd.toHex();
// piCout << "last admin_passwd" << admin_passwd.toHex();
}
ServerStarter::~ServerStarter() {
destroy();
// destroy();
}
void ServerStarter::writePassword(const PIByteArray & ph) {
//piCout << " set admin_passwd" << ph.toHex();
// piCout << " set admin_passwd" << ph.toHex();
QPIConfig conf(confpath, QIODevice::ReadWrite);
conf.setValue("admin_passwd", PI2QString(ph.toHex()));
}
@@ -46,12 +46,11 @@ void ServerStarter::writePassword(const PIByteArray & ph) {
void ServerStarter::init() {
destroy();
checkConfig();
server = new Server(reservation);
server = new Server(reservation);
server->core.admin_log_max_size = piRound(max_log_kb * 1024);
server->core.admin_password = admin_password;
server->core.admin_password = admin_password;
connect(server, SIGNAL(restartRequest()), this, SLOT(restart()));
if (no_graphics)
server->disableGraphics();
if (no_graphics) server->disableGraphics();
server->core.engine.connection()->setLogAddTime(log_add_time);
server->core.engine.connection()->setLogAddDevice(log_add_dev);
server->core.engine.connection()->setLogIO(log_io);
@@ -75,8 +74,7 @@ void ServerStarter::start() {
RUNTIME->connection.start();
}
server->core.startEth();
if (!no_graphics)
server->show();
if (!no_graphics) server->show();
QTimer::singleShot(10000, &(server->core), SIGNAL(zeroFailure()));
}
@@ -90,8 +88,7 @@ bool ServerStarter::checkFailure() {
}
int fails = 0;
QTextStream s(&f);
if (f.size() >= 1)
s >> fails;
if (f.size() >= 1) s >> fails;
if (fails >= max_failures) {
qDebug() << "[ServerStarter] Error: too many failures, standby ...";
return true;
@@ -104,7 +101,8 @@ bool ServerStarter::checkFailure() {
}
#define CHECK_CONF(e) if (!conf.isEntryExists(#e)) s << #e << " = " << e << "\n";
#define CHECK_CONF(e) \
if (!conf.isEntryExists(#e)) s << #e << " = " << e << "\n";
void ServerStarter::checkConfig() {
QPIConfig conf(confpath, QIODevice::ReadOnly);
@@ -117,13 +115,13 @@ void ServerStarter::checkConfig() {
f.seek(f.size());
QTextStream s(&f);
auto baf_path = src_baf_path;
CHECK_CONF(baf_path );
CHECK_CONF(baf_path);
CHECK_CONF(max_failures);
CHECK_CONF(log_add_time);
CHECK_CONF(log_add_dev );
CHECK_CONF(log_io );
CHECK_CONF(reservation );
CHECK_CONF(max_log_kb );
CHECK_CONF(log_add_dev);
CHECK_CONF(log_io);
CHECK_CONF(reservation);
CHECK_CONF(max_log_kb);
}
#undef CHECK_CONF
@@ -150,13 +148,17 @@ void ServerStarter::updatePlugins(QStringList names) {
return;
}
RUNTIME->plugins_manager->updateInfo();
qDebug() << "[ServerStarter::updatePlugins]" << "Got info from server, shutdown server ...";
qDebug() << "[ServerStarter::updatePlugins]"
<< "Got info from server, shutdown server ...";
destroy();
qDebug() << "[ServerStarter::updatePlugins]" << "Update plugins ...";
qDebug() << "[ServerStarter::updatePlugins]"
<< "Update plugins ...";
RUNTIME->plugins_manager->update(names);
qDebug() << "[ServerStarter::updatePlugins]" << "Update done, start server ...";
qDebug() << "[ServerStarter::updatePlugins]"
<< "Update done, start server ...";
restart({});
qDebug() << "[ServerStarter::updatePlugins]" << "Restarted";
qDebug() << "[ServerStarter::updatePlugins]"
<< "Restarted";
}