325 lines
10 KiB
C++
Executable File
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
|