From b6c880346ddd778d5a0624eef5a08208f9521e53 Mon Sep 17 00:00:00 2001 From: Ruud Overeem <overeem@astron.nl> Date: Mon, 5 Mar 2007 15:38:26 +0000 Subject: [PATCH] BugID: 1000 Major(!) simplifications to get the control chain working for at least the sunshine scenario. --- MAC/APL/CEPCU/src/OnlineControl/CEPApplMgr.cc | 117 ++-- MAC/APL/CEPCU/src/OnlineControl/CEPApplMgr.h | 111 ++-- .../CEPCU/src/OnlineControl/OnlineControl.cc | 616 +++++++++--------- .../CEPCU/src/OnlineControl/OnlineControl.h | 60 +- 4 files changed, 483 insertions(+), 421 deletions(-) diff --git a/MAC/APL/CEPCU/src/OnlineControl/CEPApplMgr.cc b/MAC/APL/CEPCU/src/OnlineControl/CEPApplMgr.cc index e939710af46..4c228d38741 100644 --- a/MAC/APL/CEPCU/src/OnlineControl/CEPApplMgr.cc +++ b/MAC/APL/CEPCU/src/OnlineControl/CEPApplMgr.cc @@ -21,10 +21,12 @@ //# $Id$ #include <lofar_config.h> +#include <APL/APLCommon/Controller_Protocol.ph> #include "CEPApplMgr.h" namespace LOFAR { using namespace ACC::ALC; + using namespace APLCommon; namespace CEPCU { @@ -32,12 +34,13 @@ namespace LOFAR { // CEPApplMgr(interface, appl) // CEPApplMgr::CEPApplMgr(CEPApplMgrInterface& interface, - const string& appName) : + const string& appName) : + itsProcName (appName), itsCAMInterface(interface), itsACclient (this, appName, 10, 100, 1, 0), - itsContinuePoll(false), - itsLastOkCmd (ACC::ALC::ACCmdNone), - itsProcName (appName) + itsReqState (CTState::NOSTATE), + itsCurState (CTState::NOSTATE), + itsContinuePoll(true) { use(); // to avoid that this object will be deleted in GCFTask::stop; } @@ -63,75 +66,103 @@ void CEPApplMgr::workProc() // // handleAckMsg(cmd, result, info) // +// Translate ACC ack into MAC state. +// void CEPApplMgr::handleAckMsg(ACCmd cmd, - uint16 result, - const string& info) + uint16 ACCresult, + const string& info) { - LOG_INFO(formatString("command: %d, result: %d, info: %s", cmd, result, info.c_str())); + LOG_INFO(formatString("command: %d, result: %d, info: %s", cmd, ACCresult, info.c_str())); + + uint16 MACresult = (ACCresult & AcCmdMaskOk) ? + CT_RESULT_NO_ERROR : CT_RESULT_UNSPECIFIED; switch (cmd) { case ACCmdBoot: - if (result == AcCmdMaskOk) { - itsLastOkCmd = cmd; + if (ACCresult == AcCmdMaskOk) { + itsCurState = CTState::CONNECTED; } - itsCAMInterface.appBooted(itsProcName, result); - break; - - case ACCmdQuit: - if (result == AcCmdMaskOk && result == 0) { - itsContinuePoll = false; - } - itsCAMInterface.appQuitDone(itsProcName, result); + itsCAMInterface.appSetStateResult(itsProcName, CTState::CONNECT, MACresult); break; case ACCmdDefine: - if (result == AcCmdMaskOk) { - itsLastOkCmd = cmd; + if (ACCresult == AcCmdMaskOk) { + itsCurState = CTState::CLAIMED; } - itsCAMInterface.appDefined(itsProcName, result); + itsCAMInterface.appSetStateResult(itsProcName, CTState::CLAIM, MACresult); break; case ACCmdInit: - if (result == AcCmdMaskOk) { - itsLastOkCmd = cmd; + if (ACCresult == AcCmdMaskOk) { + itsCurState = CTState::PREPARED; } - itsCAMInterface.appInitialized(itsProcName, result); - break; - - case ACCmdPause: - itsCAMInterface.appPaused(itsProcName, result); + itsCAMInterface.appSetStateResult(itsProcName, CTState::PREPARE, MACresult); break; case ACCmdRun: - if (result == AcCmdMaskOk) { - itsLastOkCmd = cmd; + if (ACCresult == AcCmdMaskOk) { + itsCurState = CTState::RESUMED; } - itsCAMInterface.appRunDone(itsProcName, result); - break; - - case ACCmdSnapshot: - itsCAMInterface.appSnapshotDone(itsProcName, result); - break; - - case ACCmdRecover: - itsCAMInterface.appRecovered(itsProcName, result); + itsCAMInterface.appSetStateResult(itsProcName, CTState::RESUME, MACresult); break; - case ACCmdReinit: - itsCAMInterface.appReinitialized(itsProcName, result); + case ACCmdPause: + if (ACCresult == AcCmdMaskOk) { + itsCurState = CTState::SUSPENDED; + } + itsCAMInterface.appSetStateResult(itsProcName, CTState::SUSPEND, MACresult); break; - case ACCmdReplace: - itsCAMInterface.appReplaced(itsProcName, result); + case ACCmdQuit: + if (ACCresult == AcCmdMaskOk) { + itsContinuePoll = false; + itsCurState = CTState::QUITED; + } + itsCAMInterface.appSetStateResult(itsProcName, CTState::QUIT, MACresult); break; default: - LOG_WARN_STR("Received command = " << cmd << ", result = " << result + LOG_WARN_STR("Received command = " << cmd << ", result = " << ACCresult << ", info = " << info << " not handled!"); break; } } +// +// sendCommand (newState, options) +// +// Translate MAC commands into ACC commands. +// +void CEPApplMgr::sendCommand (CTState::CTstateNr newState, const string& options) +{ + switch (newState) { + case CTState::CONNECT: + itsACclient.boot(0, options); + break; + case CTState::CLAIM: + itsACclient.define(0); + break; + case CTState::PREPARE: + itsACclient.init(0); + break; + case CTState::RESUME: + itsACclient.run(0); + break; + case CTState::SUSPEND: + itsACclient.pause(0, 0, options); + break; + case CTState::RELEASE: // no ACC equivalent. + ASSERTSTR(false, "RELEASE has no ACC equivalent, programming error"); + break; + case CTState::QUIT: + itsACclient.quit(0); + break; + default: + break; + } +} + + // // handleAnswerMsg(answer) // diff --git a/MAC/APL/CEPCU/src/OnlineControl/CEPApplMgr.h b/MAC/APL/CEPCU/src/OnlineControl/CEPApplMgr.h index d3212dbd26f..e0748feac1a 100644 --- a/MAC/APL/CEPCU/src/OnlineControl/CEPApplMgr.h +++ b/MAC/APL/CEPCU/src/OnlineControl/CEPApplMgr.h @@ -26,6 +26,7 @@ //# Includes #include <ALC/ACAsyncClient.h> #include <GCF/TM/GCF_Handler.h> +#include <APL/APLCommon/CTState.h> //# local includes //# Common Includes @@ -33,26 +34,23 @@ // forward declaration namespace LOFAR { + using APLCommon::CTState; namespace CEPCU { +// The CEPApplMgrInterface is an abstract baseclass to define the interface +// the CEPApplMgr will call for passing the results of ACC back to the controller. class CEPApplMgrInterface { public: virtual ~CEPApplMgrInterface() {} - virtual void appBooted (const string& procName, uint16 result) = 0; - virtual void appDefined (const string& procName, uint16 result) = 0; - virtual void appInitialized (const string& procName, uint16 result) = 0; - virtual void appRunDone (const string& procName, uint16 result) = 0; - virtual void appPaused (const string& procName, uint16 result) = 0; - virtual void appQuitDone (const string& procName, uint16 result) = 0; - virtual void appSnapshotDone (const string& procName, uint16 result) = 0; - virtual void appRecovered (const string& procName, uint16 result) = 0; - virtual void appReinitialized (const string& procName, uint16 result) = 0; - virtual void appReplaced (const string& procName, uint16 result) = 0; - virtual string appSupplyInfo (const string& procName, const string& keyList) = 0; - virtual void appSupplyInfoAnswer (const string& procName, const string& answer) = 0; - + virtual void appSetStateResult (const string& procName, + CTState::CTstateNr newState, + uint16 result) = 0; + virtual string appSupplyInfo (const string& procName, + const string& keyList) = 0; + virtual void appSupplyInfoAnswer(const string& procName, + const string& answer) = 0; protected: CEPApplMgrInterface() {} @@ -65,13 +63,19 @@ private: +// The CEPApplMgr class acts as an ACClient for the OnlineController but it +// also an active component because is is also inherited from GCFHandler. +// The GCFHandler-workproc will poll the ACC connection for incomming msgs. class CEPApplMgr : public ACC::ALC::ACClientFunctions, - GCF::TM::GCFHandler + GCF::TM::GCFHandler { public: CEPApplMgr(CEPApplMgrInterface& interface, const string& appName); virtual ~CEPApplMgr(); + // method used by the OnlineController to initiate a new command + void sendCommand (CTState::CTstateNr newState, const string& options); + // methods may be called from specialized CEPApplMgrInterface bool boot (const time_t scheduleTime, const string& configID); @@ -94,8 +98,10 @@ public: const string& nodeList, const string& configID) const; string askInfo (const string& keylist) const; + bool cancelCmdQueue () const; - ACC::ALC::ACCmd getLastOkCmd() const; + + const string& getName() const; protected: // protected copy constructor @@ -117,76 +123,84 @@ private: void handleAnswerMsg (const string& answer); string supplyInfoFunc (const string& keyList); - CEPApplMgrInterface& itsCAMInterface; - ACC::ALC::ACAsyncClient itsACclient; - bool itsContinuePoll; - ACC::ALC::ACCmd itsLastOkCmd; - string itsProcName; + // --- datamembers --- + string itsProcName; // my name + CEPApplMgrInterface& itsCAMInterface; // link to OnlineController + ACC::ALC::ACAsyncClient itsACclient; // link to ACC controller + uint16 itsReqState; // requested state + uint16 itsCurState; // reached state + bool itsContinuePoll; // for workProc +// ACC::ALC::ACCmd itsLastOkCmd; }; -inline bool CEPApplMgr::boot (const time_t scheduleTime, - const string& configID) +inline const string& CEPApplMgr::getName() const +{ + return (itsProcName); +} + +inline bool CEPApplMgr::boot(const time_t scheduleTime, + const string& configID) { itsContinuePoll = true; - return itsACclient.boot(scheduleTime, configID); + return (itsACclient.boot(scheduleTime, configID)); } -inline bool CEPApplMgr::define (const time_t scheduleTime) const +inline bool CEPApplMgr::define(const time_t scheduleTime) const { - return itsACclient.define(scheduleTime); + return (itsACclient.define(scheduleTime)); } -inline bool CEPApplMgr::init (const time_t scheduleTime) const +inline bool CEPApplMgr::init(const time_t scheduleTime) const { - return itsACclient.init(scheduleTime); + return (itsACclient.init(scheduleTime)); } -inline bool CEPApplMgr::run (const time_t scheduleTime) const +inline bool CEPApplMgr::run(const time_t scheduleTime) const { - return itsACclient.run(scheduleTime); + return (itsACclient.run(scheduleTime)); } -inline bool CEPApplMgr::pause (const time_t scheduleTime, - const time_t maxWaitTime, - const string& condition) const +inline bool CEPApplMgr::pause (const time_t scheduleTime, + const time_t maxWaitTime, + const string& condition) const { - return itsACclient.pause(scheduleTime, maxWaitTime, condition); + return (itsACclient.pause(scheduleTime, maxWaitTime, condition)); } -inline bool CEPApplMgr::quit (const time_t scheduleTime) const +inline bool CEPApplMgr::quit (const time_t scheduleTime) const { - return itsACclient.quit(scheduleTime); + return (itsACclient.quit(scheduleTime)); } inline bool CEPApplMgr::shutdown (const time_t scheduleTime) const { - return itsACclient.shutdown(scheduleTime); + return (itsACclient.shutdown(scheduleTime)); } inline bool CEPApplMgr::snapshot (const time_t scheduleTime, - const string& destination) const + const string& destination) const { - return itsACclient.snapshot(scheduleTime, destination); + return (itsACclient.snapshot(scheduleTime, destination)); } inline bool CEPApplMgr::recover (const time_t scheduleTime, - const string& source) const + const string& source) const { - return itsACclient.recover(scheduleTime, source); + return (itsACclient.recover(scheduleTime, source)); } inline bool CEPApplMgr::reinit (const time_t scheduleTime, - const string& configID) const + const string& configID) const { - return itsACclient.reinit(scheduleTime, configID); + return (itsACclient.reinit(scheduleTime, configID)); } inline bool CEPApplMgr::replace (const time_t scheduleTime, - const string& processList, - const string& nodeList, - const string& configID) const + const string& processList, + const string& nodeList, + const string& configID) const { - return itsACclient.replace(scheduleTime, processList, nodeList, configID); + return (itsACclient.replace(scheduleTime, processList, nodeList, configID)); } inline bool CEPApplMgr::cancelCmdQueue () const @@ -194,11 +208,6 @@ inline bool CEPApplMgr::cancelCmdQueue () const return itsACclient.cancelCmdQueue(); } -inline ACC::ALC::ACCmd CEPApplMgr::getLastOkCmd() const -{ - return itsLastOkCmd; -} - inline void CEPApplMgr::stop() { } diff --git a/MAC/APL/CEPCU/src/OnlineControl/OnlineControl.cc b/MAC/APL/CEPCU/src/OnlineControl/OnlineControl.cc index 06b22377986..87ecf3e902a 100644 --- a/MAC/APL/CEPCU/src/OnlineControl/OnlineControl.cc +++ b/MAC/APL/CEPCU/src/OnlineControl/OnlineControl.cc @@ -24,6 +24,9 @@ #include <signal.h> #include <boost/shared_array.hpp> +#include <Common/StreamUtil.h> +//#include <Common/lofar_vector.h> +//#include <Common/lofar_string.h> #include <APS/ParameterSet.h> #include <APS/Exceptions.h> #include <GCF/GCF_PVTypes.h> @@ -38,6 +41,7 @@ #include <APL/APLCommon/Controller_Protocol.ph> #include <APL/APLCommon/StationInfo.h> #include <APL/APLCommon/APLUtilities.h> +#include <APL/APLCommon/CTState.h> #include "OnlineControl.h" #include "OnlineControlDefines.h" @@ -68,10 +72,15 @@ OnlineControl::OnlineControl(const string& cntlrName) : itsParentControl (0), itsParentPort (0), itsTimerPort (0), - itsCepApplications (), - itsCepAppParams (), + itsCEPapplications (), itsResultParams (), itsState (CTState::NOSTATE), + itsUseApplOrder (false), + itsApplOrder (), + itsCurrentAppl (), + itsApplState (CTState::NOSTATE), + itsOverallResult (0), + itsNrOfAcks2Recv (0), itsTreePrefix (""), itsInstanceNr (0), itsStartTime (), @@ -106,9 +115,9 @@ OnlineControl::OnlineControl(const string& cntlrName) : // for debugging purposes GCF::TM::registerProtocol (CONTROLLER_PROTOCOL, CONTROLLER_PROTOCOL_STRINGS); - GCF::TM::registerProtocol (PA_PROTOCOL, PA_PROTOCOL_STRINGS); + GCF::TM::registerProtocol (PA_PROTOCOL, PA_PROTOCOL_STRINGS); - setState(CTState::CREATED); + _setState(CTState::CREATED); } @@ -121,11 +130,11 @@ OnlineControl::~OnlineControl() } // -// sigintHandler(signum) +// signalHandler(signum) // -void OnlineControl::sigintHandler(int signum) +void OnlineControl::signalHandler(int signum) { - LOG_DEBUG (formatString("SIGINT signal detected(%d)", signum)); + LOG_DEBUG (formatString("SIGNAL %d detected", signum)); if (thisOnlineControl) { thisOnlineControl->finish(); @@ -140,13 +149,18 @@ void OnlineControl::finish() TRAN(OnlineControl::finishing_state); } + // -// setState(CTstateNr) +// _setState(CTstateNr) // -void OnlineControl::setState(CTState::CTstateNr newState) +void OnlineControl::_setState(CTState::CTstateNr newState) { + CTState cts; + LOG_DEBUG_STR ("Going from state " << cts.name(itsState) << " to " + << cts.name(newState)); itsState = newState; + // Update PVSS to inform operator. if (itsPropertySet) { CTState cts; itsPropertySet->setValue(PVSSNAME_FSM_STATE, GCFPVString(cts.name(newState))); @@ -154,6 +168,110 @@ void OnlineControl::setState(CTState::CTstateNr newState) } +// +// startNewState(newState) +// +void OnlineControl::startNewState(CTState::CTstateNr newState, + const string& options) +{ + // TODO: check if previous state has ended? + + _setState (newState); + + if (!itsUseApplOrder) { // no depencies between applications? + for (CAMiter iter = itsCEPapplications.begin(); + iter != itsCEPapplications.end(); ++iter) { + iter->second->sendCommand(newState, options); + } + itsOverallResult = 0; + itsNrOfAcks2Recv = itsCEPapplications.size(); + } + else { + // The applications depend on each other send command to first application. + CAMiter iter = firstApplication(newState); + iter->second->sendCommand(newState, options); + itsOverallResult = 0; + itsNrOfAcks2Recv = 1; + } + + // TODO: start timer??? +} + + +// +// appSetStateResult(procName, newState, result) +// +// A result of a new state was received. Update our admin with this result and +// inform parentController is all Applications have reached the newState now. +// When the applications are dependant of each order send the same command to +// the next application. +// +// note: function is called by CEPApplMgr +// +void OnlineControl::appSetStateResult(const string& procName, + CTState::CTstateNr aState, + uint16 result) +{ + CTState cts; + LOG_DEBUG_STR("setStateResult(" << procName <<","<< cts.name(aState) + <<","<< result <<")"); + + // is the result in sync? + if (aState != itsState) { + LOG_ERROR_STR("Application " << procName << " reports result " << result + << " for state " << cts.name(aState) << " while the current state is " + << cts.name(itsState) << ". Ignoring result!"); + return; + } + + if (itsNrOfAcks2Recv <= 0) { + LOG_INFO_STR("Application " << procName << " reports result " << result + << " for state " << cts.name(aState) + << " after parentController was informed. Result will be unknown to Parent."); + return; + } + + // result useOrder action + // OK J if nextAppl sendCmd else inform parent. [A] + // ERROR J send Error to Parent, reset sequence. [B] + // OK N decr nrOfAcks2Recv if 0 inform parent. [C] + // ERROR N decr nrOfAcks2Recv if 0 inform parent. [D] + + if (!itsUseApplOrder) { // [C],[D] + itsOverallResult |= result; + if (--itsNrOfAcks2Recv <= 0) { + LOG_DEBUG("All results received, informing parent"); + sendControlResult(*itsParentPort, cts.signal(itsState), + getName(), itsOverallResult); + } + if (aState == CTState::QUIT) { + finish(); + } + return; + } + + if (result == CT_RESULT_NO_ERROR) { // [B] + if (hasNextApplication()) { // [A] + CAMiter nextApp = nextApplication(); + LOG_DEBUG_STR("Sending " << cts.name(itsState) << " to next application: " + << nextApp->second->getName()); + nextApp->second->sendCommand(itsState, "" /*options*/); + return; + } + } + + // [A],[B] + itsOverallResult = result; + sendControlResult(*itsParentPort, cts.signal(itsState), getName(), itsOverallResult); + itsNrOfAcks2Recv = 0; + noApplication(); // reset order-sequence + + if (aState == CTState::QUIT) { + finish(); + } +} + + // // handlePropertySetAnswer(answer) // @@ -249,8 +367,8 @@ GCFEvent::TResult OnlineControl::initial_state(GCFEvent& event, // First redirect signalHandler to our finishing state to leave PVSS // in the right state when we are going down thisOnlineControl = this; - signal (SIGINT, OnlineControl::sigintHandler); // ctrl-c - signal (SIGTERM, OnlineControl::sigintHandler); // kill + signal (SIGINT, OnlineControl::signalHandler); // ctrl-c + signal (SIGTERM, OnlineControl::signalHandler); // kill // update PVSS. LOG_TRACE_FLOW ("Updateing state to PVSS"); @@ -327,10 +445,8 @@ GCFEvent::TResult OnlineControl::active_state(GCFEvent& event, GCFPortInterface& case CONTROL_CONNECT: { CONTROLConnectEvent msg(event); LOG_DEBUG_STR("Received CONNECT(" << msg.cntlrName << ")"); - setState(CTState::CONNECTED); - CONTROLConnectedEvent answer; - answer.cntlrName = msg.cntlrName; - port.send(answer); + _setState(CTState::CONNECT); + _doBoot(); // start ACC's and boot them break; } @@ -344,63 +460,44 @@ GCFEvent::TResult OnlineControl::active_state(GCFEvent& event, GCFPortInterface& case CONTROL_CLAIM: { CONTROLClaimEvent msg(event); LOG_DEBUG_STR("Received CLAIM(" << msg.cntlrName << ")"); - setState(CTState::CLAIM); - CONTROLClaimedEvent answer; - answer.cntlrName = getName(); - answer.result = doClaim(msg.cntlrName); - if (answer.result == CT_RESULT_NO_ERROR) { - setState(CTState::CLAIMED); - } - port.send(answer); - + startNewState(CTState::CLAIM, ""/*options*/); break; } case CONTROL_PREPARE: { CONTROLPrepareEvent msg(event); LOG_DEBUG_STR("Received PREPARE(" << msg.cntlrName << ")"); - setState(CTState::PREPARE); - CONTROLPreparedEvent answer; - answer.cntlrName = getName(); - answer.result = doPrepare(msg.cntlrName); - if (answer.result == CT_RESULT_NO_ERROR) { - setState(CTState::PREPARED); - } - port.send(answer); + startNewState(CTState::PREPARE, ""/*options*/); break; } case CONTROL_RESUME: { CONTROLResumeEvent msg(event); LOG_DEBUG_STR("Received RESUME(" << msg.cntlrName << ")"); - setState(CTState::RESUME); - // TODO: implement something useful - CONTROLResumedEvent answer; - answer.cntlrName = msg.cntlrName; - port.send(answer); + startNewState(CTState::RESUME, ""/*options*/); break; } case CONTROL_SUSPEND: { CONTROLSuspendEvent msg(event); LOG_DEBUG_STR("Received SUSPEND(" << msg.cntlrName << ")"); - setState(CTState::SUSPENDED); - // TODO: implement something useful - CONTROLSuspendedEvent answer; - answer.cntlrName = msg.cntlrName; - port.send(answer); + startNewState(CTState::SUSPEND, ""/*options*/); break; } case CONTROL_RELEASE: { CONTROLReleaseEvent msg(event); LOG_DEBUG_STR("Received RELEASE(" << msg.cntlrName << ")"); - setState(CTState::RELEASE); - doRelease(); - setState(CTState::RELEASED); - CONTROLReleasedEvent answer; - answer.cntlrName = msg.cntlrName; - port.send(answer); + _setState(CTState::RELEASE); + sendControlResult(*itsParentPort, event.signal, getName(), 0); + _setState(CTState::RELEASED); + break; + } + + case CONTROL_QUIT: { + CONTROLQuitEvent msg(event); + LOG_DEBUG_STR("Received QUIT(" << msg.cntlrName << ")"); + startNewState(CTState::QUIT, ""/*options*/); break; } @@ -448,49 +545,49 @@ GCFEvent::TResult OnlineControl::finishing_state(GCFEvent& event, GCFPortInterfa // -// doClaim(cntlrName) +// _doBoot() // -// Create ParameterSets for all Applications the controller has to manage. +// Create ParameterSets for all Applications the we have to manage, start all +// ACC's and give them the boot command. // -uint16_t OnlineControl::doClaim(const string& cntlrName) +void OnlineControl::_doBoot() { - uint16_t result = CT_RESULT_NO_ERROR; - ParameterSet* thePS = globalParameterSet(); - try { - // get prefix of my stuff. - // string myPrefix(thePS->locateModule("OnlineCtrl") + "OnlineCtrl."); - string myPrefix; - - // Get list of all application that should be managed - // Note: each application = 1 ACC - vector<string> applList = thePS->getStringVector(myPrefix+"applications"); - - for (size_t a = 0; a < applList.size(); a++) { - // Allocate an CEPApplManager for each application - string applName(applList[a]); - string applPrefix(myPrefix+applName+"."); - CEPApplMgrPtr accClient(new CEPApplMgr(*this, applName)); - itsCepApplications[applName] = accClient; - + ParameterSet* thePS = globalParameterSet(); // shortcut to global PS. + // Get list of all application that should be managed + // Note: each application = 1 ACC + vector<string> applList = thePS->getStringVector("applications"); + string paramFileName; + + for (size_t a = 0; a < applList.size(); a++) { + // Start an CEPApplManager for this application + uint16 result (CT_RESULT_NO_ERROR); + string applName (applList[a]); + string applPrefix(applName+"."); + LOG_INFO_STR("Starting controller for " << applName); + CEPApplMgrPtr accClient (new CEPApplMgr(*this, applName)); + itsCEPapplications[applName] = accClient; + + try { // Create a parameterSet for this AC. ParameterSet params; params.clear(); // import and extend the ApplCtrl section - params.adoptCollection(thePS->makeSubset(myPrefix+"ApplCtrl","ApplCtrl")); + params.adoptCollection(thePS->makeSubset("ApplCtrl","ApplCtrl")); params.replace("ApplCtrl.application", applName); params.replace("ApplCtrl.processes", thePS->getString(applPrefix+"processes")); params.replace("ApplCtrl.resultfile", formatString( - "./ACC-%s_result.param", applName.c_str())); + "%s/ACC_%s_%s_result.param", LOFAR_SHARE_LOCATION, + getName().c_str(), applName.c_str())); // add application info params.adoptCollection(thePS->makeSubset(applPrefix,applName+".")); - // import extra tree part if necc. + // import extra tree-parts if necc. vector<string> extraParts=thePS->getStringVector(applPrefix+"extraInfo"); for (size_t e = 0; e < extraParts.size(); e++) { if (extraParts[e][0] == '.') { // relative part? string partName = extraParts[e].substr(1); - params.adoptCollection(thePS->makeSubset(myPrefix+partName, + params.adoptCollection(thePS->makeSubset(partName, partName)); } else { @@ -502,102 +599,35 @@ uint16_t OnlineControl::doClaim(const string& cntlrName) // always add Observation string obsPrefix(thePS->locateModule("Observation")); params.adoptCollection(thePS->makeSubset(obsPrefix+"Observation", "Observation")); -// params.substractSubset(myPrefix); - - // create nodelist -// int nodeIndex(1); -// for (vector<string>::iterator it = nodes.begin();it != nodes.end(); ++it) { -// params.replace(formatString("ApplCtrl.%s[%d].node",procName.c_str(),nodeIndex++),*it); -// } + // write parset to file. + paramFileName = formatString("%s/ACC_%s_%s.param", LOFAR_SHARE_LOCATION, + getName().c_str(), applName.c_str()); + params.writeFile(paramFileName); + // TODO: waar komt de hostname vandaan??? +// string hostname(thePS->getString(xxx+"_hostname")); +// APLCommon::APLUtilities::remoteCopy(paramFileName,hostName,LOFAR_SHARE_LOCATION); + } + catch (APSException &e) { + // key not found. skip + LOG_FATAL(e.text()); + result = CT_RESULT_UNSPECIFIED; + appSetStateResult(applList[a], CTState::CONNECT, result); + } + } // for - itsCepAppParams.push_back(params); + // Finally send the boot command. + startNewState(CTState::CONNECT, paramFileName); - } // for applications - } - catch(APSException &e) { - // key not found. skip - LOG_FATAL(e.text()); - result = CT_RESULT_UNSPECIFIED; - } - return result; } -// -// doPrepare(cntlrName) -// -uint16_t OnlineControl::doPrepare(const string& cntlrName) -{ - uint16_t result = CT_RESULT_NO_ERROR; - - try { - // TODO use parameterset of 'cntlrname' when being shared controller - for (size_t i = 0; i < itsCepAppParams.size(); i++) { - string applName = itsCepAppParams[i].getString("ApplCtrl.application"); - string paramFileName(formatString("ACC-%s.param", applName.c_str())); - itsCepAppParams[i].writeFile(paramFileName); - - // REO where do we need all these times for???? - // schedule all ACC commands - time_t startTime = to_time_t(itsStartTime); - time_t initTime = startTime - itsCepAppParams[i].getTime("ApplCtrl.timeout_init"); - time_t defineTime = initTime - itsCepAppParams[i].getTime("ApplCtrl.timeout_define") - - itsCepAppParams[i].getTime("ApplCtrl.timeout_startup"); - time_t bootTime = defineTime - itsCepAppParams[i].getTime("ApplCtrl.timeout_createsubsets"); - time_t now = time(0); - time_t stopTime = to_time_t(itsStopTime); - LOG_DEBUG(formatString("%d now %s time %d", now, ctime(&now), time(0))); - LOG_DEBUG(formatString("%d boot %s", bootTime, ctime(&bootTime))); - LOG_DEBUG(formatString("%d define %s", defineTime, ctime(&defineTime))); - LOG_DEBUG(formatString("%d init %s", initTime, ctime(&initTime))); - LOG_DEBUG(formatString("%d start %s", startTime, ctime(&startTime))); - LOG_DEBUG(formatString("%d stop %s", stopTime, ctime(&stopTime))); - - if (now > bootTime) { -// APLCommon::APLUtilities::remoteCopy(paramFileName,hostName,LOFAR_SHARE_LOCATION); - LOG_WARN("Cannot guarantee all CEP processes are started in time."); - } - else { - CEPApplMgrPtr cepAppPtr = itsCepApplications[applName]; - if(cepAppPtr) { - switch (cepAppPtr->getLastOkCmd()) { - case ACCmdNone: - cepAppPtr->boot(bootTime, paramFileName); - break; - - case ACCmdBoot: - cepAppPtr->define(defineTime); - break; - - case ACCmdDefine: - case ACCmdInit: - case ACCmdRun: - cepAppPtr->recover(0, "snapshot-DB"); - break; - - default: - assert(0); - break; - } - } -// APLCommon::APLUtilities::remoteCopy(paramFileName,hostName,LOFAR_SHARE_LOCATION); - } - } - } - catch(APSException &e) { - // key not found. skip - LOG_FATAL(e.text()); - result = CT_RESULT_UNSPECIFIED; - } - - return (result); -} // -// doRelease() +// _doQuit() // -void OnlineControl::doRelease(void) +void OnlineControl::_doQuit(void) { try { +#if 0 for(size_t i = 0;i < itsCepAppParams.size();i++) { string remoteFile, resultFile, applName; applName = itsCepAppParams[i].getString("ApplCtrl.application"); @@ -611,211 +641,183 @@ void OnlineControl::doRelease(void) } itsResultParams.writeFile(formatString("%s_result.param", getName().c_str())); } +#endif } catch(...) { } map<string, CEPApplMgrPtr>::iterator it; - for(it = itsCepApplications.begin();it != itsCepApplications.end();++it) { + for(it = itsCEPapplications.begin();it != itsCEPapplications.end();++it) { it->second->quit(0); } } -// -// finishController -// -void OnlineControl::finishController(uint16_t /*result*/) -{ - setState(CTState::RELEASE); - doRelease(); - setState(CTState::RELEASED); - - LOG_DEBUG ("Going to finishing state"); - TRAN(OnlineControl::finishing_state); // go to next state. -} +// -------------------- Application-order administration -------------------- // -// _connectedHandler(port) +// setApplOrder(appl-vector) // -void OnlineControl::_connectedHandler(GCFPortInterface& /*port*/) +void OnlineControl::setApplOrder(vector<string>& anApplOrder) { -} - -// -// _disconnectedHandler(port) -// -void OnlineControl::_disconnectedHandler(GCFPortInterface& port) -{ - port.close(); -} - -// -// appBooted(procName, result) -// -void OnlineControl::appBooted(const string& procName, uint16 result) -{ - LOG_INFO_STR("appBooted from " << procName); - if (result == (AcCmdMaskOk | AcCmdMaskScheduled)) { - time_t startTime = to_time_t(itsStartTime); - time_t initTime = startTime - itsCepAppParams[0].getTime("ApplCtrl.timeout_init"); - time_t defineTime = initTime - itsCepAppParams[0].getTime("ApplCtrl.timeout_define") - - itsCepAppParams[0].getTime("ApplCtrl.timeout_startup"); - map<string,CEPApplMgrPtr>::iterator it = itsCepApplications.find(procName); - if(it != itsCepApplications.end()) { - it->second->define(defineTime); + itsUseApplOrder = true; // assume everything is right. + itsApplOrder = anApplOrder; + + // every application must be in the order list. + ASSERTSTR(itsApplOrder.size() == itsCEPapplications.size(), + "Application orderlist conflicts with length of applicationlist"); + + // check that all application exist + CAMiter applEnd = itsCEPapplications.end(); + vector<string>::iterator orderIter = itsApplOrder.begin(); + while (orderIter != itsApplOrder.end()) { + CAMiter applIter = itsCEPapplications.begin(); + while (applIter != applEnd) { + if (applIter->second->getName() == *orderIter) { + break; + } + applIter++; } + ASSERTSTR(applIter != applEnd, *orderIter << + " is not a registered application, orderlist is illegal"); + orderIter++; } - else if (result == 0) { // Error - LOG_ERROR("Error in ACC. Stops CEP application and releases Online Control."); - finishController(CT_RESULT_UNSPECIFIED); - } + LOG_INFO_STR ("Using application order: " << itsApplOrder); } -// -// appDefined(procName, result) -// -void OnlineControl::appDefined(const string& procName, uint16 result) -{ - LOG_INFO_STR("appDefined from " << procName); - if (result == (AcCmdMaskOk | AcCmdMaskScheduled)) { - time_t startTime = to_time_t(itsStartTime); - time_t initTime = startTime - itsCepAppParams[0].getTime("ApplCtrl.timeout_init"); - - map<string,CEPApplMgrPtr>::iterator it = itsCepApplications.find(procName); - if(it != itsCepApplications.end()) { - it->second->init(initTime); - } - } - else if (result == 0) { // Error - LOG_ERROR("Error in ACC. Stops CEP application and releases VB."); - finishController(CT_RESULT_UNSPECIFIED); - } -} // -// appInitialized(procName, result) +// firstApplication(newState) // -void OnlineControl::appInitialized(const string& procName, uint16 result) +OnlineControl::CAMiter OnlineControl::firstApplication(CTState::CTstateNr newState) { - LOG_INFO_STR("appInitialized from " << procName); - if (result == AcCmdMaskOk) { - // _doStateTransition(LOGICALDEVICE_STATE_SUSPENDED); - } - else if (result == (AcCmdMaskOk | AcCmdMaskScheduled)) { - map<string,CEPApplMgrPtr>::iterator it = itsCepApplications.find(procName); - if(it != itsCepApplications.end()) { - it->second->run(to_time_t(itsStartTime)); - } - } - else if (result == 0) { // Error - LOG_ERROR("Error in ACC. Stops CEP application and releases VB."); - finishController(CT_RESULT_UNSPECIFIED); + if (itsCurrentAppl != "") { + LOG_ERROR_STR("Starting new command-chain while previous command-chain was still at appplication " + << itsCurrentAppl << ". Results are unpredictable!"); + } + + itsApplState = newState; + switch (newState) { + case CTState::CONNECT: + case CTState::CLAIM: + case CTState::PREPARE: + case CTState::RESUME: + itsCurrentAppl = itsCEPapplications.begin()->second->getName(); + break; + + case CTState::SUSPEND: + case CTState::RELEASE: + case CTState::QUIT: + itsCurrentAppl = itsCEPapplications.end()->second->getName(); + break; + + default: // satisfy compiler + break; } + CTState cts; + ASSERTSTR(false, "Illegal new state in firstApplication(): " + << cts.name(newState)); } + // -// appRunDone(procName, result) +// nextApplication() // -void OnlineControl::appRunDone(const string& procName, uint16 result) +OnlineControl::CAMiter OnlineControl::nextApplication() { - LOG_INFO_STR("appRunDone from " << procName); - if (result == (AcCmdMaskOk | AcCmdMaskScheduled)) { - map<string,CEPApplMgrPtr>::iterator it = itsCepApplications.find(procName); - if(it != itsCepApplications.end()) { - it->second->quit(to_time_t(itsStopTime)); + ASSERTSTR (hasNextApplication(), "Programming error, must have next application"); + + // search current application in the list. + CAMiter iter = itsCEPapplications.begin(); + while (iter != itsCEPapplications.end()) { + if (iter->second->getName() == itsCurrentAppl) { + break; } + iter++; } - else if (result == 0) { // Error - LOG_ERROR("Error in ACC. Stops CEP application and releases VB."); - finishController(CT_RESULT_UNSPECIFIED); - } -} + ASSERTSTR (iter != itsCEPapplications.end(), "Application " << itsCurrentAppl + << "not found in applicationList"); -// -// appPaused(procname, result) -// -void OnlineControl::appPaused(const string& procName, uint16 /*result*/) -{ - LOG_INFO_STR("appPaused from " << procName); -} + switch (itsApplState) { + case CTState::CLAIM: + case CTState::PREPARE: + case CTState::RESUME: + iter++; + break; -// -// appQuitDone(procName, result) -// -void OnlineControl::appQuitDone(const string& procName, uint16 result) -{ - LOG_INFO_STR("appQuitDone from " << procName); - if (result == (AcCmdMaskOk | AcCmdMaskScheduled)) { - //_qualityGuard.stopMonitoring(); // not in this increment - } - else { - finishController(CT_RESULT_NO_ERROR); + case CTState::SUSPEND: + case CTState::RELEASE: + case CTState::QUIT: + iter--; + break; + + default: + ASSERT("Satisfy compiler"); } + + itsCurrentAppl = iter->second->getName(); + return (iter); } + // -// appSnapshotDone(procName, result) +// noApplication() // -void OnlineControl::appSnapshotDone(const string& procName, uint16 /*result*/) +void OnlineControl::noApplication() { - LOG_INFO_STR("appSnapshotDone from " << procName); - time_t rsto(0); - try { - rsto = globalParameterSet()->getTime("rescheduleTimeOut"); - } - catch (...) {} - - map<string,CEPApplMgrPtr>::iterator it = itsCepApplications.find(procName); - if(it != itsCepApplications.end()) { - it->second->pause(0, rsto, "condition"); - } + itsCurrentAppl = ""; } + // -// appRecovered(procName, result) +// hasNextApplication() // -void OnlineControl::appRecovered(const string& procName, uint16 /*result*/) +bool OnlineControl::hasNextApplication() { - LOG_INFO_STR("appRecovered from " << procName); + if (!itsUseApplOrder) { + return (false); + } - time_t startTime = to_time_t(itsStartTime); - time_t reinitTime = startTime - itsCepAppParams[0].getTime("ApplCtrl.timeout_reinit"); + switch (itsApplState) { + case CTState::CLAIM: + case CTState::PREPARE: + case CTState::RESUME: + return (itsCurrentAppl != itsCEPapplications.rbegin()->second->getName()); + break; - string paramFileName(formatString("ACC-%s.param", getName().c_str())); + case CTState::SUSPEND: + case CTState::RELEASE: + case CTState::QUIT: + return (itsCurrentAppl != itsCEPapplications.begin()->second->getName()); + break; - map<string,CEPApplMgrPtr>::iterator it = itsCepApplications.find(procName); - if(it != itsCepApplications.end()) { - it->second->reinit(reinitTime, paramFileName); + default: { + CTState cts; + ASSERTSTR(false, "Illegal state in hasNextApplication(): " + << cts.name(itsApplState)); + } } + } // -// appReinitialized(procName, result) +// _connectedHandler(port) // -void OnlineControl::appReinitialized(const string& procName, uint16 result) -{ - LOG_INFO_STR("appReinitialized from " << procName); - if (result == AcCmdMaskOk) { - // _doStateTransition(LOGICALDEVICE_STATE_SUSPENDED); - } - else if (result == (AcCmdMaskOk | AcCmdMaskScheduled)) { - map<string,CEPApplMgrPtr>::iterator it = itsCepApplications.find(procName); - if(it != itsCepApplications.end()) { - it->second->run(to_time_t(itsStartTime)); - } - } +void OnlineControl::_connectedHandler(GCFPortInterface& /*port*/) +{ } // -// appReplaced(procNAme, result) +// _disconnectedHandler(port) // -void OnlineControl::appReplaced(const string& procName, uint16 /*result*/) +void OnlineControl::_disconnectedHandler(GCFPortInterface& port) { - LOG_INFO_STR("appReplaced from " << procName); + port.close(); } // // appSupplyInfo(procName, keyList) // +// note: function is called by CEPApplMgr +// string OnlineControl::appSupplyInfo(const string& procName, const string& keyList) { LOG_INFO_STR("appSupplyInfo from " << procName); @@ -826,6 +828,8 @@ string OnlineControl::appSupplyInfo(const string& procName, const string& keyLis // // appSupplyInfoAnswer(procName, answer) // +// note: function is called by CEPApplMgr +// void OnlineControl::appSupplyInfoAnswer(const string& procName, const string& answer) { LOG_INFO_STR("Answer from " << procName << ": " << answer); diff --git a/MAC/APL/CEPCU/src/OnlineControl/OnlineControl.h b/MAC/APL/CEPCU/src/OnlineControl/OnlineControl.h index ff747c7cd62..c82acab3967 100644 --- a/MAC/APL/CEPCU/src/OnlineControl/OnlineControl.h +++ b/MAC/APL/CEPCU/src/OnlineControl/OnlineControl.h @@ -89,22 +89,18 @@ public: GCFPortInterface& port); // Interrupthandler for switching to finisingstate when exiting the program - static void sigintHandler (int signum); + static void signalHandler (int signum); void finish(); protected: // implemenation of abstract CEPApplMgrInterface methods - void appBooted (const string& procName, uint16 result); - void appDefined (const string& procName, uint16 result); - void appInitialized (const string& procName, uint16 result); - void appRunDone (const string& procName, uint16 result); - void appPaused (const string& procName, uint16 result); - void appQuitDone (const string& procName, uint16 result); - void appSnapshotDone (const string& procName, uint16 result); - void appRecovered (const string& procName, uint16 result); - void appReinitialized (const string& procName, uint16 result); - void appReplaced (const string& procName, uint16 result); string appSupplyInfo (const string& procName, const string& keyList); void appSupplyInfoAnswer (const string& procName, const string& answer); + // A result of one of the applications was received, update the administration + // off the controller and send the result to the parentcontroller if appropriate. + void appSetStateResult (const string& procName, + CTState::CTstateNr newState, + uint16 result); + private: // avoid defaultconstruction and copying @@ -112,17 +108,32 @@ private: OnlineControl(const OnlineControl&); OnlineControl& operator=(const OnlineControl&); - uint16_t doClaim(const string& cntlrName); - uint16_t doPrepare(const string& cntlrName); - void doRelease(); - void finishController(uint16_t result); - void _connectedHandler(GCFPortInterface& port); - void _disconnectedHandler(GCFPortInterface& port); - void setState(CTState::CTstateNr newState); + void _doBoot(); + void _doQuit(); + void _finishController (uint16_t result); + void _connectedHandler (GCFPortInterface& port); + void _disconnectedHandler(GCFPortInterface& port); + void _setState (CTState::CTstateNr newState); - typedef boost::shared_ptr<GCF::PAL::GCFMyPropertySet> GCFMyPropertySetPtr; + // Send a command to all (or the first) applications. + void startNewState (CTState::CTstateNr newState, + const string& options); + + // typedefs for the internal adminsitration of all the Applications we control typedef boost::shared_ptr<CEPApplMgr> CEPApplMgrPtr; + typedef map<string, CEPApplMgrPtr> CAMmap; + typedef map<string, CEPApplMgrPtr>::iterator CAMiter; + + // Internal bookkeeping-finctions for the dependancy-order of the applications. + void setApplOrder (vector<string>& anApplOrder); + CAMiter firstApplication(CTState::CTstateNr aState); + CAMiter nextApplication(); + bool hasNextApplication(); + void noApplication(); + typedef boost::shared_ptr<GCF::PAL::GCFMyPropertySet> GCFMyPropertySetPtr; + + // ----- datamembers ----- APLCommon::PropertySetAnswer itsPropertySetAnswer; GCFMyPropertySetPtr itsPropertySet; bool itsPropertySetInitialized; @@ -133,12 +144,19 @@ private: GCFTimerPort* itsTimerPort; - map<string, CEPApplMgrPtr> itsCepApplications; - vector<ACC::APS::ParameterSet> itsCepAppParams; + CAMmap itsCEPapplications; ACC::APS::ParameterSet itsResultParams; CTState::CTstateNr itsState; + bool itsUseApplOrder; // Applications depend? + vector<string> itsApplOrder; // startOrder of the applications. + string itsCurrentAppl; // current application we are handling. + CTState::CTstateNr itsApplState; // state currently handled by apps. + + uint16 itsOverallResult; + int16 itsNrOfAcks2Recv; + // ParameterSet variables string itsTreePrefix; uint32 itsInstanceNr; -- GitLab