Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Executable
+377
@@ -0,0 +1,377 @@
|
||||
/**
|
||||
* The Group class represents a group which was already startet.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hannes Baeuerle, SLSE, 2016-02-15
|
||||
*/
|
||||
|
||||
#include "group.h"
|
||||
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtAlgorithms>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "group_handler.h"
|
||||
#include "service_handler.h"
|
||||
#include "service_process.h"
|
||||
#include "service_donator.h"
|
||||
|
||||
#include <ServiceManagement/scm.hpp>
|
||||
|
||||
namespace ServiceManagement
|
||||
{
|
||||
|
||||
int32_t Group::s_idCounter = 0;
|
||||
|
||||
Group::Group(const std::shared_ptr<DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<ServiceDonator> &serviceDonator,
|
||||
const GroupRequest &groupData,
|
||||
GroupScheme *scheme,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_serviceDonator(serviceDonator)
|
||||
, m_scheme(scheme)
|
||||
, m_groupId(s_idCounter++)
|
||||
, m_groupData(groupData)
|
||||
, m_completeCoreTimeout(0)
|
||||
, m_logger(getLogger("Group"))
|
||||
{
|
||||
INFO_LOG(m_logger) << "Group "
|
||||
<< m_scheme->groupType
|
||||
<< " for partition "
|
||||
<< groupData
|
||||
<< " created.";
|
||||
m_elapsedTimer.start();
|
||||
}
|
||||
|
||||
Group::~Group()
|
||||
{
|
||||
setRunningState(Core::RunningState::StoppedNormally);
|
||||
for (ServiceProcess *serviceProc :qAsConst(m_serviceProcs))
|
||||
m_ddsHandler->dts()->removeServiceInformationByKey(serviceProc->serviceProcessId());
|
||||
qDeleteAll(m_serviceProcs); // in Service they are removed via ServiceProcess::destroyed signal
|
||||
m_ddsHandler->dts()->removeGroupInformationByKey(m_groupId);
|
||||
}
|
||||
|
||||
void Group::init()
|
||||
{
|
||||
for (int serviceId : qAsConst(m_scheme->services))
|
||||
{
|
||||
if (m_serviceProcs.contains(serviceId))
|
||||
continue;
|
||||
|
||||
ServiceProcess *proc = m_serviceDonator->getProcess(serviceId, m_groupData);
|
||||
if (proc != nullptr)
|
||||
{
|
||||
connect(proc, &ServiceProcess::newServiceInformation,
|
||||
this, &Group::onNewServiceInfo);
|
||||
m_serviceProcs.insert(serviceId, proc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Group::setRunningState(Core::RunningState newState)
|
||||
{
|
||||
INFO_LOG(m_logger) << "Setting RunningState of group "
|
||||
<< m_scheme->groupType
|
||||
<< " in exercisePartition "
|
||||
<< m_groupData.exercisePartitionId()
|
||||
<< ", replayPartition "
|
||||
<< m_groupData.replayPartitionId()
|
||||
<< " to "
|
||||
<< newState;
|
||||
|
||||
switch (newState.underlying())
|
||||
{
|
||||
case Core::RunningState::Running:
|
||||
case Core::RunningState::Starting:
|
||||
// make sure all services are there
|
||||
init();
|
||||
for (ServiceProcess *serviceProc : qAsConst(m_serviceProcs))
|
||||
serviceProc->start();
|
||||
return true;
|
||||
case Core::RunningState::StoppedNormally:
|
||||
for (ServiceProcess *serviceProc : qAsConst(m_serviceProcs))
|
||||
serviceProc->terminate();
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Group::startCore()
|
||||
{
|
||||
if (m_scheme->groupType != Core::ServiceGroupType::Core)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "startCore() was invoked on a non Core Group object";
|
||||
return;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "Starting Core";
|
||||
|
||||
// make sure all services are there
|
||||
init();
|
||||
|
||||
// ExerciseManagement must be started ...
|
||||
for (ServiceProcess *proc : qAsConst(m_serviceProcs))
|
||||
{
|
||||
if (proc->serviceName() == QLatin1String("ExerciseManagement"))
|
||||
{
|
||||
if ( proc->prio() == m_actPrio)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "startCore proc->start() "
|
||||
<< proc->serviceName()
|
||||
<< " prio=" << proc->prio()
|
||||
<< " m_actPrio=" <<m_actPrio;
|
||||
|
||||
proc->start();
|
||||
}
|
||||
// waiting 15 secs for EXM startup
|
||||
m_completeCoreTimeout = QDateTime::currentMSecsSinceEpoch() + 15000;
|
||||
|
||||
onCompleteCoreTick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Group::getNextPrio(QList <int> &prioList)
|
||||
{
|
||||
if ( m_actPrio == 0)
|
||||
return -1;
|
||||
std::sort(prioList.begin(), prioList.end());
|
||||
for ( int i = 0; i < prioList.size(); i++)
|
||||
{
|
||||
if ( m_actPrio < prioList.at(i))
|
||||
return prioList.at(i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Group::start()
|
||||
{
|
||||
QList <int> prioList;
|
||||
DEBUG_LOG(m_logger) << "Group::start() m_actPrio=" << m_actPrio
|
||||
<< " groupId=" << m_groupId;
|
||||
// make sure all services are there
|
||||
init();
|
||||
// get list of prio
|
||||
for (ServiceProcess *proc : qAsConst(m_serviceProcs))
|
||||
{
|
||||
if ( !prioList.contains(proc->prio()))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "prioList.append " << proc->prio()
|
||||
<< " m_actPrio=" << m_actPrio
|
||||
<< " groupId=" << m_groupId;
|
||||
prioList.append(proc->prio());
|
||||
}
|
||||
}
|
||||
|
||||
//if ( !prioList.contains(m_actPrio))
|
||||
//{
|
||||
// m_actPrio = getNextPrio(prioList);
|
||||
//}
|
||||
|
||||
for (ServiceProcess *proc : qAsConst(m_serviceProcs))
|
||||
{
|
||||
if ( m_actPrio == proc->prio())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Group::start(): proc->start() "
|
||||
<< proc->serviceName()
|
||||
<< " prio=" << proc->prio()
|
||||
<< " m_actPrio=" << m_actPrio
|
||||
<< " exId=" << proc->exercisePartitionId()
|
||||
<< " lastHeartbeat=" << proc->lastHeartbeatMSec();
|
||||
proc->start();
|
||||
}
|
||||
}
|
||||
if ( m_actPrio > 0)
|
||||
{
|
||||
m_actPrio= getNextPrio(prioList);
|
||||
QTimer::singleShot(1000, this, &Group::start);
|
||||
}
|
||||
}
|
||||
|
||||
void Group::stop()
|
||||
{
|
||||
for (ServiceProcess *proc : qAsConst(m_serviceProcs))
|
||||
{
|
||||
if (proc->state() != QProcess::NotRunning)
|
||||
proc->stopFromRequest();
|
||||
}
|
||||
}
|
||||
|
||||
void Group::restart()
|
||||
{
|
||||
// make sure all services are there
|
||||
init();
|
||||
for (ServiceProcess *proc : qAsConst(m_serviceProcs))
|
||||
proc->restart();
|
||||
}
|
||||
|
||||
void Group::takeServicesFromGroup(Group *otherGroup)
|
||||
{
|
||||
auto otherServiceProcs = otherGroup->m_serviceProcs;
|
||||
for (auto it = otherServiceProcs.begin(); it != otherServiceProcs.end(); ++it)
|
||||
{
|
||||
int serviceId = it.key();
|
||||
// already there? -> skip
|
||||
if (m_serviceProcs.contains(serviceId))
|
||||
continue;
|
||||
// not in our scheme? -> skip
|
||||
if (!m_scheme->services.contains(serviceId))
|
||||
continue;
|
||||
ServiceProcess *proc = it.value();
|
||||
|
||||
// remove from otherGroup
|
||||
otherGroup->m_serviceProcs.remove(serviceId);
|
||||
proc->disconnect(otherGroup);
|
||||
|
||||
// add to ourself
|
||||
m_serviceProcs.insert(serviceId, proc);
|
||||
connect(proc, &ServiceProcess::newServiceInformation,
|
||||
this, &Group::onNewServiceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Core::ServiceGroupType Group::type() const
|
||||
{
|
||||
return m_scheme->groupType;
|
||||
}
|
||||
|
||||
qint64 Group::lastHeartbeatMSec() const
|
||||
{
|
||||
qint64 result = 0;
|
||||
|
||||
for (ServiceProcess *proc : m_serviceProcs)
|
||||
{
|
||||
if (proc->lastHeartbeatMSec() > result)
|
||||
result = proc->lastHeartbeatMSec();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QMap<int, ServiceProcess *> Group::serviceProcs() const
|
||||
{
|
||||
return m_serviceProcs;
|
||||
}
|
||||
|
||||
void Group::onNewServiceInfo()
|
||||
{
|
||||
if (m_elapsedTimer.elapsed() < 2 * 1000)
|
||||
return;
|
||||
m_elapsedTimer.start();
|
||||
std::vector<int32_t> serviceIds;
|
||||
serviceIds.reserve(m_serviceProcs.size());
|
||||
for (ServiceProcess *proc : qAsConst(m_serviceProcs))
|
||||
serviceIds.push_back(proc->serviceProcessId());
|
||||
|
||||
GroupInformation info(m_groupId,
|
||||
lastHeartbeatMSec(),
|
||||
m_scheme->groupType,
|
||||
m_groupData.domainId(),
|
||||
m_groupData.exercisePartitionId(),
|
||||
m_groupData.replayPartitionId(),
|
||||
serviceIds);
|
||||
|
||||
TRACE_LOG(m_logger) << "Publishing new GroupInformation: " << info;
|
||||
|
||||
m_ddsHandler->dts()->publish(info);
|
||||
}
|
||||
|
||||
void Group::onCompleteCoreTick()
|
||||
{
|
||||
QList <int> prioList;
|
||||
if (QDateTime::currentMSecsSinceEpoch() > m_completeCoreTimeout)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not start group Core, because no Heartbeat for EXM with RunningState 'Running' was received.";
|
||||
return;
|
||||
}
|
||||
|
||||
ServiceProcess *exmProc = nullptr;
|
||||
|
||||
// get EXM proc
|
||||
for (ServiceProcess *proc : qAsConst(m_serviceProcs))
|
||||
{
|
||||
if (proc->serviceName() == QLatin1String("ExerciseManagement"))
|
||||
{
|
||||
exmProc = proc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (exmProc == nullptr)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not find Process for EXM";
|
||||
return;
|
||||
}
|
||||
|
||||
// check if EXM got RunningState from Heartbeat
|
||||
if (exmProc->runningState() == Core::RunningState::Running)
|
||||
{
|
||||
// get list of prio
|
||||
for (ServiceProcess *proc : qAsConst(m_serviceProcs))
|
||||
{
|
||||
if ( !prioList.contains(proc->prio()))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "prioList.append " << proc->prio()
|
||||
<< " m_actPrio=" << m_actPrio
|
||||
<< " groupId=" << m_groupId;
|
||||
prioList.append(proc->prio());
|
||||
}
|
||||
}
|
||||
|
||||
// start rest of group core
|
||||
for (ServiceProcess *proc : qAsConst(m_serviceProcs))
|
||||
{
|
||||
if (proc->state() != QProcess::Running && proc->prio() == m_actPrio)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onCompleteCoreTick proc->start() "
|
||||
<< proc->serviceName()
|
||||
<< " prio=" << proc->prio();
|
||||
proc->start();
|
||||
}
|
||||
}
|
||||
m_actPrio = getNextPrio(prioList);
|
||||
if (-1 != m_actPrio)
|
||||
{
|
||||
QTimer::singleShot(1000, this, &Group::onCompleteCoreTick);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "EXM has runningState " << exmProc->runningState();
|
||||
// start next completion attemp
|
||||
QTimer::singleShot(1000, this, &Group::onCompleteCoreTick);
|
||||
}
|
||||
|
||||
ServiceProcess *Group::procFromPid(Q_PID pid)
|
||||
{
|
||||
for (ServiceProcess *proc :qAsConst(m_serviceProcs))
|
||||
{
|
||||
if (proc->pid() == pid)
|
||||
return proc;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "Searched for not existing process with PID "
|
||||
<< pid;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Group::allProcsStopped() const
|
||||
{
|
||||
for (ServiceProcess *proc : m_serviceProcs)
|
||||
{
|
||||
if (proc->state() != QProcess::NotRunning)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ServiceManagement
|
||||
Reference in new issue
Block a user