ddl/mapping/engine/mapping_engine.cpp
2019-12-12 14:41:47 +01:00

424 lines
12 KiB
C++

/**
* @file
*
* @copyright
* @verbatim
Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved.
This Source Code Form is subject to the terms of the Mozilla
Public License, v. 2.0. If a copy of the MPL was not distributed
with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular file, then
You may include the notice in a location (such as a LICENSE file in a
relevant directory) where a recipient would be likely to look for such a notice.
You may add additional accurate notices of copyright ownership.
@endverbatim
*/
#include "mapping_engine.h"
#include "a_util/result/error_def.h"
#include "legacy_error_macros.h"
namespace mapping
{
namespace rt
{
//define all needed error types and values locally
_MAKE_RESULT(-4, ERR_POINTER)
_MAKE_RESULT(-5, ERR_INVALID_ARG)
_MAKE_RESULT(-16, ERR_NOT_IMPL)
_MAKE_RESULT(-40, ERR_INVALID_STATE)
_MAKE_RESULT(-42, ERR_INVALID_TYPE)
}
}
using namespace mapping;
using namespace mapping::rt;
MappingEngine::MappingEngine(IMappingEnvironment& oEnv):
_env(oEnv), _map_config(NULL), _running(false)
{
}
MappingEngine::~MappingEngine()
{
stop();
unmapAll();
}
a_util::result::Result MappingEngine::setConfiguration(const oo::MapConfiguration& oConfig)
{
_map_config = oConfig;
return a_util::result::SUCCESS;
}
a_util::result::Result MappingEngine::Map(const std::string& strTargetName, handle_t& hMappedSignal)
{
a_util::result::Result nRes = a_util::result::SUCCESS;
// If the target is already in the List, return invalid error
if(_targets.find(strTargetName) != _targets.end())
{
nRes = ERR_INVALID_ARG;
}
const oo::MapTarget* pMapTarget = NULL;
std::string strTargetDesc;
if (isOk(nRes))
{
pMapTarget = _map_config.getTarget(strTargetName);
// If the target is not found in the mapping configuration, return invalid error
if(pMapTarget == NULL)
{
nRes = ERR_INVALID_ARG;
}
else
{
const char* desc = 0;
if (isFailed(_env.resolveType(pMapTarget->getType().c_str(), desc)))
{
nRes = ERR_INVALID_TYPE;
}
// save a copy, never know how long the environment holds the memory
strTargetDesc = desc;
}
}
// Backup storage for error cleanup
SourceMap oSourceCleanup;
TriggerMap oTriggerCleanup;
if (isOk(nRes))
{
// Create sources
const oo::MapSourceNameList& lstSources = pMapTarget->getReferencedSources();
for (oo::MapSourceNameList::const_iterator it = lstSources.begin();
it != lstSources.end(); ++it)
{
const oo::MapSource* pMapSource = _map_config.getSource(*it);
if (_sources.find(pMapSource->getName()) == _sources.end())
{
const char* strSourceDesc = 0;
nRes = _env.resolveType(pMapSource->getType().c_str(), strSourceDesc);
if (isFailed(nRes))
{
break;
}
Source* pSrc = new Source(_env);
nRes = pSrc->create(*pMapSource, strSourceDesc);
if (isFailed(nRes))
{
delete pSrc;
break;
}
_sources[pMapSource->getName()] = pSrc;
oSourceCleanup[pMapSource->getName()] = pSrc;
}
}
}
Target* pTarget = NULL;
if (isOk(nRes))
{
// Create Target
pTarget = new Target(_env);
nRes = pTarget->create(_map_config, *pMapTarget, strTargetDesc, _sources);
if (isFailed(nRes))
{
delete pTarget;
pTarget = NULL;
}
else
{
_targets[strTargetName] = pTarget;
}
}
if (isOk(nRes))
{
//Create Triggers
const oo::MapTriggerList& oTriggerList = pMapTarget->getTriggerList();
for(oo::MapTriggerList::const_iterator it = oTriggerList.begin();
it != oTriggerList.end(); it++)
{
const oo::MapPeriodicTrigger* pMapPTrigger =
dynamic_cast<const oo::MapPeriodicTrigger*>(*it);
const oo::MapSignalTrigger* pMapSigTrigger =
dynamic_cast<const oo::MapSignalTrigger*>(*it);
const oo::MapDataTrigger* pMapDataTrigger =
dynamic_cast<const oo::MapDataTrigger*>(*it);
if(!pMapPTrigger && !pMapSigTrigger && !pMapDataTrigger)
{
nRes = ERR_NOT_IMPL;
break;
}
if (pMapPTrigger)
{
std::string strTrigName;
if(pMapPTrigger->getPeriod() == 0)
{
strTrigName = "ini";
}
else
{
strTrigName = a_util::strings::toString(pMapPTrigger->getPeriod()) + "ms";
}
if(_triggers.find(strTrigName) == _triggers.end())
{
PeriodicTrigger* pTrigger = new PeriodicTrigger(_env, strTrigName,
pMapPTrigger->getPeriod());
nRes = pTrigger->create();
if (isFailed(nRes))
{
delete pTrigger;
break;
}
_triggers[strTrigName] = pTrigger;
oTriggerCleanup[strTrigName] = pTrigger;
}
_triggers[strTrigName]->addTarget(pTarget);
}
if (pMapSigTrigger)
{
std::string strSourceName = pMapSigTrigger->getVariable();
TriggerMap::iterator iter = _triggers.find(strSourceName);
if(iter == _triggers.end())
{
SignalTrigger* pTrigger = new SignalTrigger(_env, strSourceName);
std::pair<TriggerMap::iterator, bool> oNewElem =
_triggers.insert(std::make_pair(strSourceName, pTrigger));
iter = oNewElem.first;
oTriggerCleanup[strSourceName] = pTrigger;
}
iter->second->addTarget(pTarget);
_sources[strSourceName]->addTrigger(_map_config, iter->second);
}
if (pMapDataTrigger)
{
std::string name = pMapDataTrigger->getSource() + "." + pMapDataTrigger->getVariable()
+ pMapDataTrigger->getOperator();
name.append(a_util::strings::format("%f", pMapDataTrigger->getValue()));
TriggerMap::iterator iter = _triggers.find(name);
if(_triggers.find(name) == _triggers.end())
{
DataTrigger* pTrigger = new DataTrigger(_env, name,
pMapDataTrigger->getVariable(), pMapDataTrigger->getOperator(),
pMapDataTrigger->getValue());
std::pair<TriggerMap::iterator, bool> oNewElem =
_triggers.insert(std::make_pair(name, pTrigger));
iter = oNewElem.first;
oTriggerCleanup[name] = pTrigger;
}
iter->second->addTarget(pTarget);
_sources[pMapDataTrigger->getSource()]->addTrigger(_map_config, iter->second);
}
}
}
// cleanup on error
if (isFailed(nRes))
{
for (SourceMap::iterator it = oSourceCleanup.begin();
it != oSourceCleanup.end(); ++it)
{
_sources.erase(it->first);
delete it->second;
}
for (TriggerMap::iterator it = _triggers.begin();
it != _triggers.end(); ++it)
{
it->second->removeTarget(pTarget);
}
for (TriggerMap::iterator it = oTriggerCleanup.begin();
it != oTriggerCleanup.end(); ++it)
{
_triggers.erase(it->first);
delete it->second;
}
}
if(isOk(nRes))
{
hMappedSignal = reinterpret_cast<handle_t>(pTarget);
_env.targetMapped(strTargetName.c_str(), pTarget->getType().c_str(), hMappedSignal, pTarget->getSize());
}
return nRes;
}
a_util::result::Result MappingEngine::reset()
{
if (_running)
{
return ERR_INVALID_STATE;
}
// Reset the target buffers
for(TargetMap::iterator it = _targets.begin(); it != _targets.end(); it++)
{
RETURN_IF_FAILED(it->second->reset(_map_config));
}
return a_util::result::SUCCESS;
}
a_util::result::Result MappingEngine::start()
{
if (_running)
{
return ERR_INVALID_STATE;
}
_running = true;
// start the triggers in order to send targets
for(TriggerMap::iterator it = _triggers.begin(); it != _triggers.end(); it++)
{
it->second->start();
}
return a_util::result::SUCCESS;
}
bool MappingEngine::hasTriggers(handle_t mapped_signal) const
{
Target* target_signal = reinterpret_cast<Target*>(mapped_signal);
if (!target_signal)
{
return false;
}
bool has_trigger = false;
for (const auto& trigga : _triggers)
{
if (has_trigger)
{
break;
}
const auto& target_list = trigga.second->getTargetList();
for (const auto& target : target_list)
{
if (target == target_signal)
{
has_trigger = true;
break;
}
}
}
return has_trigger;
}
a_util::result::Result MappingEngine::stop()
{
if (!_running)
{
return ERR_INVALID_STATE;
}
_running = false;
// stop the triggers in order to send targets
for(TriggerMap::iterator it = _triggers.begin(); it != _triggers.end(); it++)
{
it->second->stop();
}
return a_util::result::SUCCESS;
}
a_util::result::Result MappingEngine::unmap(handle_t hMappedSignal)
{
if (_running)
{
return ERR_INVALID_STATE;
}
Target* pTarget = reinterpret_cast<Target*>(hMappedSignal);
if (!pTarget) { return ERR_POINTER; }
std::vector<TriggerMap::iterator> vecEraseTrig;
for(TriggerMap::iterator it = _triggers.begin(); it != _triggers.end(); ++it)
{
it->second->removeTarget(pTarget);
if (it->second->getTargetList().empty())
{
delete it->second;
vecEraseTrig.push_back(it);
}
}
for (std::vector<TriggerMap::iterator>::iterator it = vecEraseTrig.begin();
it != vecEraseTrig.end(); ++it)
{
_triggers.erase(*it);
}
std::vector<SourceMap::iterator> vecEraseSrc;
for(SourceMap::iterator it = _sources.begin(); it != _sources.end(); ++it)
{
it->second->removeAssignmentsFor(pTarget);
if (it->second->getAssigmentList().empty())
{
delete it->second;
vecEraseSrc.push_back(it);
}
}
for (std::vector<SourceMap::iterator>::iterator it = vecEraseSrc.begin();
it != vecEraseSrc.end(); ++it)
{
_sources.erase(*it);
}
_env.targetUnmapped(pTarget->getName().c_str(), hMappedSignal);
_targets.erase(pTarget->getName());
delete pTarget;
return a_util::result::SUCCESS;
}
a_util::result::Result MappingEngine::unmapAll()
{
if (_running)
{
return ERR_INVALID_STATE;
}
while (!_targets.empty())
{
unmap(reinterpret_cast<handle_t>(_targets.begin()->second));
}
return a_util::result::SUCCESS;
}
a_util::result::Result MappingEngine::getCurrentData(handle_t hMappedSignal,
void* pTargetBuffer, size_t szTargetBuffer) const
{
Target* pTarget = reinterpret_cast<Target*>(hMappedSignal);
if (!pTarget) { return ERR_POINTER; }
if (!pTargetBuffer) { return ERR_POINTER; }
return pTarget->getCurrentBuffer(pTargetBuffer, szTargetBuffer);
}
// empty definitions of mapping environment destruktors
ISignalListener::~ISignalListener() {}
IPeriodicListener::~IPeriodicListener() {}
IMappingEnvironment::~IMappingEnvironment() {}