Commit a2b7c5a9 by amir

Add state name and flow prefix to StateIndex

 and validate on handle event
parent 7d05b37c
......@@ -3,15 +3,17 @@
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/defs/retstat.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/defs/constants.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/defs/Logger.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/defs/seh_types.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/defs/enums.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/defs/seh_types.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/defs/Logger.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/defs/constants.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/seh/JsonCallFlowBuilder.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/seh/seh_engine.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/seh/seh_engine.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/seh/JsonCallFlowBuilder.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/seh/XMLCallFlowBuilder.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/seh/seh_engine.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/seh/XMLCallFlowBuilder.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/CMakeLists.txt" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/test_seh.cpp" isTestSource="false" />
......
......@@ -7,7 +7,7 @@ set (seh_VERSION_MINOR 1)
set (seh_VERSION_PATCH 0)
set(seh_VERSION_STRING ${seh_VERSION_MAJOR}.${seh_VERSION_MINOR}.${seh_VERSION_PATCH})
set(CMAKE_BUILD_TYPE Release)
#set(CMAKE_BUILD_TYPE Release)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
......@@ -15,7 +15,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
link_directories( ../3party/lib )
include_directories(SYSTEM ../3party/rapidjson-0.11/include/rapidjson)
set(SOURCE_FILES src/defs/constants.h src/defs/enums.h src/defs/retstat.h src/defs/seh_types.h src/defs/seh_types.cpp src/seh/seh_engine.cpp src/seh/seh_engine.h src/seh/JsonCallFlowBuilder.cpp src/seh/JsonCallFlowBuilder.h src/seh/XMLCallFlowBuilder.cpp src/seh/XMLCallFlowBuilder.h)
set(SOURCE_FILES src/defs/constants.h src/defs/enums.h src/defs/retstat.h src/defs/seh_types.h src/defs/seh_types.cpp src/seh/seh_engine.cpp src/seh/seh_engine.h src/seh/JsonCallFlowBuilder.cpp src/seh/JsonCallFlowBuilder.h src/seh/XMLCallFlowBuilder.cpp src/seh/XMLCallFlowBuilder.h src/defs/Logger.cpp src/defs/Logger.h)
add_library(seh SHARED ${SOURCE_FILES})
#target_link_libraries(seh ${PROJECT_LINK_LIBS} )
set_target_properties(seh PROPERTIES VERSION ${seh_VERSION_STRING}
......
//
// Created by amir on 19/09/16.
//
#include "Logger.h"
// Global static pointer used to ensure a single instance of the class.
Logger* Logger::m_pInstance = nullptr;
/** This function is called to create an instance of the class.
Calling the constructor publicly is not allowed. The constructor
is private and is only called by this Instance function.
*/
Logger* Logger::Instance()
{
if (!m_pInstance) // Only allow one instance of class to be generated.
m_pInstance = new Logger;
return m_pInstance;
}
void Logger::EnableLogging(bool enableLogging) {
Logger::enableLogging = enableLogging;
}
//
// Created by amir on 19/09/16.
//
#ifndef SEH_LOGGER_H
#define SEH_LOGGER_H
//using namespace std;
#include <ostream>
class Logger{
public:
static Logger* Instance();
void EnableLogging(bool enableLogging);
template <typename Arg, typename... Args>
void Log(std::ostream& out, Arg&& arg, Args&&... args)
{
if (enableLogging)
{
out << std::forward<Arg>(arg);
using expander = int[];
(void) expander{0, (void(out << ' ' << std::forward<Args>(args)), 0)...};
out << std::endl;
}
}
template <typename Arg, typename... Args>
void LogError(std::ostream& out, Arg&& arg, Args&&... args)
{
out << std::forward<Arg>(arg);
using expander = int[];
(void) expander{0, (void(out << ' ' << std::forward<Args>(args)), 0)...};
out << std::endl;
}
private:
Logger(){ enableLogging = true; }; // Private so that it can not be called
Logger(Logger const&){}; // copy constructor is private
Logger& operator=(Logger const&){}; // assignment operator is private
static Logger* m_pInstance;
bool enableLogging;
};
#endif //SEH_LOGGER_H
......@@ -20,7 +20,7 @@ RetStat ComplexEventAction::ActivateActions(EventData& eventData,
retStat = p_eventAction->ActivateAction(activateActionData); //action.invoke(activateActionData.object, p_eventAction.param);
if (retStat.Fail())
{
//logger.severe("ComplexEventAction::ActivateActions-\tFailed in Action");
//Logger.severe("ComplexEventAction::ActivateActions-\tFailed in Action");
SEH_LOG_ERROR("ComplexEventAction::ActivateActions-\tFailed in Action: ",retStat.GetError());
break;
}
......@@ -36,7 +36,7 @@ RetStat ComplexEventAction::ActivateActions(EventData& eventData,
activateActionData.boolWasStateChanged = true;
activateActionData.p_nextStateIndex->Set(eventData.nextState.stateIndex);
//logger.info("SEHEngine-\tChanging to State: " + eventData.nextState.stateName);
//Logger.info("SEHEngine-\tChanging to State: " + eventData.nextState.stateName);
SEH_LOG("ComplexEventAction::ActivateActions\tChanging to State: ",eventData.nextState.stateName);
} else {
activateActionData.boolWasStateChanged = false;
......
......@@ -13,42 +13,64 @@
#include <memory>
#include "constants.h"
#include "retstat.h"
#include "Logger.h"
//
//static bool s_enable_debug = true;
//
//template <typename Arg, typename... Args>
//void seh_log(std::ostream& out, Arg&& arg, Args&&... args) {
// if (s_enable_debug)
// {
// out << std::forward<Arg>(arg);
// using expander = int[];
// (void) expander{0, (void(out << ' ' << std::forward<Args>(args)), 0)...};
// out << std::endl;
// }
//}
template <typename Arg, typename... Args>
void seh_log(std::ostream& out, Arg&& arg, Args&&... args)
{
out << std::forward<Arg>(arg);
using expander = int[];
(void)expander{0, (void(out << ' ' << std::forward<Args>(args)),0)...};
out << std::endl;
}
#define SEH_LOG(...) seh_log(std::cout,__VA_ARGS__)
#define SEH_LOG_ERROR(...) seh_log(std::cerr,__VA_ARGS__) // << ... << ... << std::endl
#define SEH_LOG(...) Logger::Instance()->Log(std::cout,__VA_ARGS__)
#define SEH_LOG_ERROR(...) Logger::Instance()->LogError(std::cerr,__VA_ARGS__) // << ... << ... << std::endl
#define SEH_METHOD_ERROR(...) SEH_LOG_ERROR(__PRETTY_FUNCTION__,__VA_ARGS__)
#define SEH_METHOD_LOG(...) SEH_LOG(__PRETTY_FUNCTION__,__VA_ARGS__)
static void seh_enable_debug(bool enable){
Logger::Instance()->EnableLogging(enable);
}
template <typename _Map, typename _Key>
static void* GetFromMap(_Map& map, _Key& key) {
void * p_val = nullptr;
auto iter = map.find(key);
if (iter != map.end())
p_val = &iter->second;
return p_val;
}
using namespace std;
struct StateIndex
{
int uiStateIndex;
int uiStateFlowIndex;
string stateName;
string fsmId;
StateIndex()
{
}
StateIndex(int uiStateIndex,int uiFlowIndex)
{
this->uiStateIndex = uiStateIndex;
this->uiStateFlowIndex = uiFlowIndex;
}
// StateIndex(StateIndex& stateIndex)
// {
// SEH_METHOD_LOG("CopyConstructor");
// Set(stateIndex);
// }
void Reset()
{
uiStateIndex = nsConstants::C_NO_ENTRY;
uiStateFlowIndex = nsConstants::C_NO_ENTRY;
stateName.clear();
fsmId.clear();
}
bool isValid()
......@@ -57,13 +79,39 @@ struct StateIndex
uiStateFlowIndex != nsConstants::C_NO_ENTRY);
}
void Set(StateIndex& stateIndex)
bool operator==(const StateIndex &rhs) const {
SEH_METHOD_LOG("is equal");
return uiStateIndex == rhs.uiStateIndex &&
uiStateFlowIndex == rhs.uiStateFlowIndex &&
stateName == rhs.stateName &&
fsmId == rhs.fsmId;
}
bool operator!=(const StateIndex &rhs) const {
SEH_METHOD_LOG("not equal");
return !(rhs == *this);
}
void Set(const StateIndex& stateIndex)
{
uiStateFlowIndex = stateIndex.uiStateFlowIndex;
uiStateIndex = stateIndex.uiStateIndex;
fsmId = stateIndex.fsmId;
stateName = stateIndex.stateName;
}
void Set(int iStateFlowIndex, int iStateIndex,string& fsmId, string& stateName)
{
this->uiStateFlowIndex = iStateFlowIndex;
this->uiStateIndex = iStateIndex;
this->fsmId = fsmId;
this->stateName = stateName;
}
StateIndex& operator = (const StateIndex& stateIndex){
SEH_METHOD_LOG("copy");
Set(stateIndex);
return *this;
}
};
struct _StateIndex
......@@ -473,10 +521,14 @@ struct CallFlow
{
int flowIndex = 0;
vector<shared_ptr<State>> stateArray;
map<string,int> stateIndexMap;
int iNumOfStates;
string flowFileName;
string fsmId;
IBaseSEH* p_baseSEHObject;
CallFlow(const string &fsmId) : fsmId(fsmId) {}
virtual ~CallFlow() {
// for(State* p_state: stateArray)
// delete(p_state);
......@@ -487,32 +539,41 @@ struct CallFlow
{
flowIndex = 0;
stateArray.clear();
stateIndexMap.clear();
flowFileName.clear();
fsmId.clear();
iNumOfStates = 0;
p_baseSEHObject = nullptr;
}
string& GetFlowFileNameStr()
{
SEH_METHOD_LOG("copy");
return flowFileName;
}
string& GetFlowFileNameStr() { return flowFileName; }
void AddState(shared_ptr<State>& p_state)
{
stateArray.push_back(p_state);
stateIndexMap[p_state->stateName] = (stateArray.size() - 1);
}
const char* GetFlowFileName()
{
return flowFileName.c_str();
}
string& GetFsmId() { return fsmId; }
int GetStateIndex(string& stateName)
{
auto ptr = stateIndexMap.find(stateName);
if(ptr != stateIndexMap.end())
return ptr->second;
return nsConstants::C_NO_ENTRY;
}
CallFlow& operator = (const CallFlow& callFlow){
SEH_METHOD_LOG("copy");
flowIndex = callFlow.flowIndex;
stateArray = move(callFlow.stateArray);
stateIndexMap = move(callFlow.stateIndexMap);
flowFileName = callFlow.flowFileName;
fsmId = callFlow.fsmId;
iNumOfStates = callFlow.iNumOfStates;
p_baseSEHObject = callFlow.p_baseSEHObject;
}
......
......@@ -8,15 +8,6 @@
#include "JsonCallFlowBuilder.h"
#include "XMLCallFlowBuilder.h"
template <typename _Map, typename _Key>
void* GetFromMap(_Map& map, _Key& key) {
void * p_val = nullptr;
auto iter = map.find(key);
if (iter != map.end())
p_val = &iter->second;
return p_val;
}
void SehEngine::Reset() {
flowsFileName_.clear();
......@@ -116,7 +107,8 @@ RetStat SehEngine::ReadAndCreateFlowsFromFile() {
{
if(!flowPrefix.empty() && !flowFileName.empty())
{
CallFlow* p_cf = new CallFlow();
CallFlow* p_cf = new CallFlow(flowPrefix);
p_cf->fsmId = flowPrefix;
callFlowMap_[flowPrefix] = p_cf;
flowFilesMap_[flowPrefix] = flowFileName;
}
......@@ -153,8 +145,9 @@ RetStat SehEngine::ResolveNextStateIndex(NextState& nextState) {
{
if (p_state->stateName.compare(nextState.stateName) == 0)
{
nextState.stateIndex.uiStateFlowIndex = iFlowIndex;
nextState.stateIndex.uiStateIndex = iStateIndex;
nextState.stateIndex.Set(iFlowIndex,iStateIndex,p_callFlow->fsmId,p_state->stateName);
// nextState.stateIndex.uiStateFlowIndex = iFlowIndex;
// nextState.stateIndex.uiStateIndex = iStateIndex;
return retStat;
}
......@@ -453,7 +446,6 @@ RetStat SehEngine::InitMultiFlows(string &flowsFileName, map<string, IBaseSEH *>
for (auto entry : this->callFlowMap_)
{
CallFlow& cf = *entry.second;
cf.Reset();
cf.flowIndex = index;
auto baseSEHObjectMapIterator = baseSEHObjectMap_.find(entry.first);
if (baseSEHObjectMapIterator != baseSEHObjectMap_.end())
......@@ -485,8 +477,7 @@ RetStat SehEngine::InitMultiFlows(map<string, string> &flowFilesMap, map<string,
//Set<Entry<String, String>> entrySet = flowFilesMap_.entrySet();
for (auto entry : flowFilesMap)
{
CallFlow* p_cf = new CallFlow();
p_cf->Reset();
CallFlow* p_cf = new CallFlow(entry.first);
callFlowMap_[entry.first] = p_cf;
p_cf->flowIndex = index;
auto baseSEHObjectMapIterator = baseSEHObjectMap_.find(entry.first);
......@@ -529,45 +520,49 @@ RetStat SehEngine::HandleEvent(StateIndex& stateIndex, string& eventStr) {
* and setting the BaseSEH object
***********************************************/
this->p_state_ = p_callFlow->stateArray[this->p_stateIndex_->uiStateIndex].get();
p_eventData_ = (EventData*)GetFromMap(this->p_state_->eventsMap,eventStr);
this->p_baseSEHObject_ = p_callFlow->p_baseSEHObject;
//this->activateActionData_.object = p_callFlow->baseSEHObject;;
string& eventName = eventStr; //this.baseSEHObject.resolveEventName(iEvent);
if (!eventName.empty())
SEH_METHOD_LOG("-\tState/Event: ",this->p_state_->stateName,'/',eventName);
/**********************************************
* if no implementation for this State/Event then looking if
* there is a BaseState
*********************************************/
if ((this->p_eventData_ == nullptr || this->p_eventData_->getNumOfActions() == 0)
&& (this->p_state_->baseState.IsValid()))
{
this->p_stateIndex_ = &this->p_state_->baseState.stateIndex;
this->p_state_ = p_callFlow->stateArray[this->p_stateIndex_->uiStateIndex].get();
this->p_eventData_ = (EventData *) GetFromMap(this->p_state_->eventsMap, eventStr); // eventCellsArray[iEvent];
}
if(p_stateIndex_->fsmId == p_callFlow->fsmId && p_stateIndex_->stateName == p_state_->stateName) {
p_eventData_ = (EventData *) GetFromMap(this->p_state_->eventsMap, eventStr);
this->p_baseSEHObject_ = p_callFlow->p_baseSEHObject;
//this->activateActionData_.object = p_callFlow->baseSEHObject;;
string &eventName = eventStr; //this.baseSEHObject.resolveEventName(iEvent);
if (!eventName.empty())
SEH_METHOD_LOG("-\tState/Event: ", this->p_state_->stateName, '/', eventName);
/**********************************************
* if no implementation for this State/Event then looking if
* there is a BaseState
*********************************************/
if ((this->p_eventData_ == nullptr || this->p_eventData_->getNumOfActions() == 0)
&& (this->p_state_->baseState.IsValid())) {
this->p_stateIndex_ = &this->p_state_->baseState.stateIndex;
this->p_state_ = p_callFlow->stateArray[this->p_stateIndex_->uiStateIndex].get();
this->p_eventData_ = (EventData *) GetFromMap(this->p_state_->eventsMap,
eventStr); // eventCellsArray[iEvent];
}
if (this->p_eventData_ != nullptr)
{
// logger.severe("SEHEngine::HandleEvent-\tEvent: "
// + eventName + " Not Implemented for State: "
// + this.statePtr.stateName);
// retStatus.setFail();
// return retStatus;
// }
/*************************
* Get & Activate Actions
************************/
retStatus = ActivateActions(*this->p_stateIndex_);
}
else
if (this->p_eventData_ != nullptr) {
// Logger.severe("SEHEngine::HandleEvent-\tEvent: "
// + eventName + " Not Implemented for State: "
// + this.statePtr.stateName);
// retStatus.setFail();
// return retStatus;
// }
/*************************
* Get & Activate Actions
************************/
retStatus = ActivateActions(*this->p_stateIndex_);
} else {
SEH_METHOD_ERROR("-\tEvent: ", eventName, " Not Implemented for State: ",
this->p_state_->stateName);
retStatus.SetFail();
}
} else
{
SEH_METHOD_ERROR("-\tEvent: ",eventName," Not Implemented for State: ",this->p_state_->stateName);
SEH_METHOD_ERROR("-\tState index mismatch with flow fsm and state name");
retStatus.SetFail();
}
} else
{
......@@ -676,5 +671,32 @@ RetStat SehEngine::ResolveNextState(NextState &nextState) {
return retStat;
}
}
return RetStat();
return retStat;
}
RetStat SehEngine::GetStateIndex(string &fsmId, string &stateName, StateIndex &stateIndex) {
RetStat retStat;
if(!fsmId.empty() && !stateName.empty())
{
CallFlow** pp_cf = (CallFlow**)GetFromMap(callFlowMap_,fsmId);
if(pp_cf)
{
int iStateIndex = (*pp_cf)->GetStateIndex(stateName);
if(iStateIndex != nsConstants::C_NO_ENTRY)
{
stateIndex.Set((*pp_cf)->flowIndex,iStateIndex,fsmId,stateName);
} else
retStat.SetFail(string("invalid State: ").append(stateName));
} else
retStat.SetFail(string("invalid fsmId: ").append(fsmId));
} else
retStat.SetFail("missing params");
return retStat;
}
RetStat SehEngine::GetStateIndex(const char *p_fsmId, const char *p_stateName, StateIndex &stateIndex) {
string fsmId = p_fsmId;
string stateName = p_stateName;
return GetStateIndex(fsmId,stateName,stateIndex);
}
......@@ -138,9 +138,19 @@ public:
*/
const string& GetStateName(StateIndex& stateIndex);
/**
* Getting the stateIndex from the State Name and flow prefix
* @param fsmId
* @param stateName
* @param stateIndex
* @return
*/
RetStat GetStateIndex(string &fsmId, string &stateName, StateIndex &stateIndex);
RetStat GetStateIndex(const char * p_fsmId, const char * p_stateName, StateIndex &stateIndex);
int GetCurrentNumOfCallFlows() { return maxNumberOfCallFlows_; }
/**
* Getting the stateIndex from the State Name and flow file
* Getting the stateIndex from the State Name
*
* @param stateIndex
* @param flowFileName
......
......@@ -8,6 +8,7 @@
#include <cstring>
#include <limits.h>
#include <mhash.h>
#include <ctime>
#include "../src/defs/seh_types.h"
#include "../src/seh/seh_engine.h"
......@@ -151,6 +152,7 @@ std::string getexepath()
int main() {
RetStat stat;
int TEST_REP = 1000000;
SehEngine* fsmEngine = new SehEngine();
TestSEH testSEH;
StateIndex state;// = new StateIndex();
......@@ -158,7 +160,8 @@ int main() {
cout << "current dir is: " << getexepath() << endl;
SEH_LOG("Hello");
seh_enable_debug(false);
SEH_LOG("Hello");
map<string,string> flowFilesMap;
map<string,IBaseSEH*> flowsSEHMap;
......@@ -167,18 +170,25 @@ int main() {
flowsSEHMap["Test"] = &testSEH;
stat = fsmEngine->InitMultiFlows(flowFilesMap, flowsSEHMap);
if(stat.Success()) {
state.uiStateFlowIndex = 0;
state.uiStateIndex = 0; // idle
event = "Event1";
fsmEngine->HandleEvent(state, event);
event = "Event3";
fsmEngine->HandleEvent(state, event);
event = "Event2";
fsmEngine->HandleEvent(state, event);
event = "Event2";
fsmEngine->HandleEvent(state, event);
event = "Event4";
fsmEngine->HandleEvent(state, event);
stat = fsmEngine->GetStateIndex("Test","Idle",state);
if(stat.Success()) {
std::time_t result = std::time(nullptr);
for (int i = 0; i < TEST_REP; i++) {
event = "Event1";
fsmEngine->HandleEvent(state, event);
event = "Event3";
fsmEngine->HandleEvent(state, event);
event = "Event2";
fsmEngine->HandleEvent(state, event);
event = "Event2";
fsmEngine->HandleEvent(state, event);
event = "Event1";
fsmEngine->HandleEvent(state, event);
event = "Event3";
fsmEngine->HandleEvent(state, event);
}
cout << "Test of " << TEST_REP << " times took: " << (std::time(nullptr) - result) << " seconds" << endl;
}
}
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment