Files
qt5-legatus-legacy/Lts/Services/ServiceManagement/group_handler.cpp
T
2026-08-13 18:33:10 +02:00

325 lines
10 KiB
C++
Executable File

/**
* The GroupHandler class handles all group related classes and writes the groups state to DDS.
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-02-15
*/
#include "group_handler.h"
#include "group.h"
#include "heartbeat_listener.h"
#include "service_donator.h"
namespace ServiceManagement
{
GroupHandler::GroupHandler(const std::shared_ptr<DdsHandler> &ddsHandler,
const std::shared_ptr<ServiceDonator> &donator)
: QObject()
, Interface::Fts::StartGroupRequestHandler(ddsHandler->fts())
, Interface::Fts::StopGroupRequestHandler(ddsHandler->fts())
, Interface::Fts::RestartGroupRequestHandler(ddsHandler->fts())
, m_serviceDonator(donator)
, m_ddsHandler(ddsHandler)
, m_heartbeatListener(new HeartbeatListener(ddsHandler->connector(), donator))
, m_logger(getLogger("GroupHandler"))
{
}
GroupHandler::~GroupHandler()
{
qDeleteAll(m_groups);
m_groups.clear();
qDeleteAll(m_groupSchemes);
m_groupSchemes.clear();
delete m_heartbeatListener;
}
bool GroupHandler::init(int32_t coreDomain)
{
DEBUG_LOG(m_logger) << "Initializing GroupHandler ...";
bool bAllPartsInitialized = m_heartbeatListener->init() &&
startGroupCore(coreDomain);
if (bAllPartsInitialized)
DEBUG_LOG(m_logger) << "GroupHandler successfully initialized.";
else
ERROR_LOG(m_logger) << "GroupHandler initialization failed.";
return bAllPartsInitialized;
}
void GroupHandler::addServiceLink(int serviceId, Core::ServiceGroupType groupType)
{
groupSchemeFromType(groupType)->addServiceId(serviceId);
}
QVector<Group *> GroupHandler::groups() const
{
return m_groups;
}
GroupScheme *GroupHandler::groupSchemeFromType(Core::ServiceGroupType type)
{
for (GroupScheme *scheme : qAsConst(m_groupSchemes))
{
if (scheme->groupType == type)
return scheme;
}
// TODO: make generic ...
QMap<Core::ServiceGroupType, QString> groupNameMapping;
groupNameMapping.insert(Core::ServiceGroupType_def::Master, QLatin1String("Master"));
groupNameMapping.insert(Core::ServiceGroupType_def::Core, QLatin1String("Core"));
groupNameMapping.insert(Core::ServiceGroupType_def::ExercisePreparation, QLatin1String("ExercisePreparation"));
groupNameMapping.insert(Core::ServiceGroupType_def::ExerciseExecution, QLatin1String("ExerciseExecution"));
groupNameMapping.insert(Core::ServiceGroupType_def::ExercisePaused, QLatin1String("ExercisePaused"));
groupNameMapping.insert(Core::ServiceGroupType_def::ExerciseAfterActionReview, QLatin1String("ExerciseAfterActionReview"));
groupNameMapping.insert(Core::ServiceGroupType_def::Playback, QLatin1String("Playback"));
// if no scheme with type type exists, it will be newly generated and added
GroupScheme *newScheme = new GroupScheme(type, groupNameMapping.value(type));
m_groupSchemes.append(newScheme);
return newScheme;
}
Group *GroupHandler::getGroup(const GroupRequest &groupToFind) const
{
for (Group *group : m_groups)
{
if (group->type() == groupToFind.type() &&
group->exercisePartitionId() == groupToFind.exercisePartitionId() &&
group->domainId() == groupToFind.domainId() &&
group->replayPartitionId() == groupToFind.replayPartitionId())
return group;
}
return nullptr;
}
Group *GroupHandler::getSimilarGroup(const GroupRequest &groupToFind) const
{
const std::vector<Core::ServiceGroupType> possibleTypes = {Core::ServiceGroupType::ExercisePreparation,
Core::ServiceGroupType::ExerciseExecution,
Core::ServiceGroupType::ExercisePaused,
Core::ServiceGroupType::ExerciseAfterActionReview};
bool bSimilar = false;
for (const auto &type : possibleTypes)
{
if (type != groupToFind.type())
continue;
bSimilar = true;
break;
}
if (!bSimilar)
return nullptr;
for(auto type : possibleTypes)
{
// don't find ourself ...
if (type == groupToFind.type())
continue;
GroupRequest similarGroup(groupToFind);
similarGroup.type(type);
Group *groupFound = getGroup(similarGroup);
if (groupFound)
return groupFound;
}
return nullptr;
}
bool GroupHandler::startGroupCore(int32_t domainId)
{
if (domainId != m_ddsHandler->connector()->getDomainId())
{
ERROR_LOG(m_logger) << "Could not start group Core for domain "
<< domainId
<< ", this ServiceManagement instance only supports domain "
<< m_ddsHandler->connector()->getDomainId();
return false;
}
DEBUG_LOG(m_logger) << "Starting core group ...";
GroupRequest groupToSearch;
groupToSearch.type(Core::ServiceGroupType::Core);
groupToSearch.domainId(domainId);
Group *coreGroup = getGroup(groupToSearch);
if (coreGroup == nullptr)
{
GroupScheme *coreScheme = groupSchemeFromType(groupToSearch.type());
if (coreScheme == nullptr)
{
ERROR_LOG(m_logger) << "Could not start core group because there are no services linked to it";
return false;
}
coreGroup = new Group(m_ddsHandler, m_serviceDonator, groupToSearch, coreScheme, this);
m_groups.append(coreGroup);
}
coreGroup->start();
return true;
}
void GroupHandler::onStartGroupRequest(const rti::core::SampleIdentity &cookie, const GroupRequest &request)
{
auto ret = onStartGroup(request);
if (ret.error())
WARNING_LOG(m_logger) << ret();
m_ddsHandler->fts()->startGroupReply(cookie, ret);
}
void GroupHandler::slotStartGroupRequest(const GroupRequest &request)
{
auto ret = onStartGroup(request);
if (ret.error())
WARNING_LOG(m_logger) << ret();
emit startGroupReply(ret);
}
Core::FunctionReplyObject GroupHandler::onStartGroup(const GroupRequest &request)
{
DEBUG_LOG(m_logger) << "New StartGroupRequest: " << request;
if (request.domainId() != m_ddsHandler->connector()->getDomainId())
return Core::FunctionReplyObject(request.requestId(),
tr_lts("dds", "This instance of ServiceManagement only allows to start a group in domain %1. Domain %2 was provided"))
.arg(m_ddsHandler->connector()->getDomainId())
.arg(request.domainId());
// special case: request.type == Master, ExerciseId != 0 -> stopp all
if (request.type() == Core::ServiceGroupType::Master && request.exercisePartitionId() != 0)
return onStopAllForExercise(request.domainId(), request.exercisePartitionId());
Group *existingGroup = getGroup(request);
// check if it's a Exercise group and search a group with the same exercise/domain -id
// if the group does not exist, it is newly created (normal case)
if (existingGroup == nullptr)
{
GroupScheme *scheme = groupSchemeFromType(request.type());
if (scheme == nullptr)
return Core::FunctionReplyObject(request.requestId(),
tr_lts("dds", "Starting attempt of non existing group: %1")).arg(request.type().underlying());
existingGroup = new Group(m_ddsHandler, m_serviceDonator, request, scheme, this);
m_groups.append(existingGroup);
}
Group *similarGroup = getSimilarGroup(request);
// if there is a similar group, we should take the services from there (to avoid restarting services on exeuction -> pause or pause -> resume)
if (similarGroup)
{
DEBUG_LOG(m_logger) << "Taking existing services from group " << similarGroup->type()
<< " to " << existingGroup->type();
existingGroup->takeServicesFromGroup(similarGroup);
similarGroup->stop();
m_groups.removeAll(similarGroup);
similarGroup->deleteLater();
similarGroup = nullptr;
}
existingGroup->start();
return Core::FunctionReplyObject(request.requestId());
}
Core::FunctionReplyObject GroupHandler::onStopAllForExercise(int domainId, int exercisePartitionId)
{
DEBUG_LOG(m_logger) << "Stopping all proces for domain " << domainId << ", partition " << exercisePartitionId;
QVector<Group *> stillAliveGroups;
int cntStopped = 0;
int cntAlive = 0;
for (Group *group : qAsConst(m_groups))
{
if (group->exercisePartitionId() == exercisePartitionId &&
group->domainId() == domainId)
{
group->stop();
group->deleteLater();
++cntStopped;
}
else
{
stillAliveGroups += group;
++cntAlive;
}
}
m_groups = stillAliveGroups;
DEBUG_LOG(m_logger) << "Stopping all proces for domain " << domainId << ", partition " << exercisePartitionId
<< " - done. Stopped " << cntStopped << " groups"
<< ", still alive: " << cntAlive;
return Core::FunctionReplyObject(exercisePartitionId);
}
void GroupHandler::onStopGroupRequest(const rti::core::SampleIdentity &cookie, const GroupRequest &request)
{
auto ret = onStopGroup(request);
if (ret.error())
WARNING_LOG(m_logger) << ret();
m_ddsHandler->fts()->stopGroupReply(cookie, ret);
}
void GroupHandler::slotStopGroupRequest(const GroupRequest &request)
{
auto ret = onStopGroup(request);
if (ret.error())
WARNING_LOG(m_logger) << ret();
emit stopGroupReply(ret);
}
Core::FunctionReplyObject GroupHandler::onStopGroup(const GroupRequest &request)
{
DEBUG_LOG(m_logger) << "New StopGroupRequest: " << request;
Group *existingGroup = getGroup(request);
if (existingGroup == nullptr)
return Core::FunctionReplyObject(request.requestId(),
tr_lts("dds", "Could not stop Group, because it does not exist"));
existingGroup->stop();
// delete this group since no longer needed
m_groups.removeAll(existingGroup);
delete existingGroup;
return Core::FunctionReplyObject(request.requestId());
}
void GroupHandler::onRestartGroupRequest(const rti::core::SampleIdentity &cookie,
const GroupRequest &request)
{
auto ret = onRestartGroup(request);
if (ret.error())
WARNING_LOG(m_logger) << ret();
m_ddsHandler->fts()->restartGroupReply(cookie, ret);
}
Core::FunctionReplyObject GroupHandler::onRestartGroup(const GroupRequest &request)
{
DEBUG_LOG(m_logger) << "New RestartGroupRequest: " << request;
Group *existingGroup = getGroup(request);
if (existingGroup == nullptr)
return Core::FunctionReplyObject(tr_lts("dds", "Could not restart Group, because it does not exist"));
existingGroup->restart();
return Core::FunctionReplyObject(existingGroup->id());
}
} // namespace ServiceManagement