From: Anthony Geay Date: Thu, 3 Mar 2016 18:00:06 +0000 (+0100) Subject: Bug correction EDF12462 (2) X-Git-Tag: V7_8_0a2~25 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=c34425b3d64c211b01c29cc5655709f113e24024;p=modules%2Fyacs.git Bug correction EDF12462 (2) --- diff --git a/src/engine/ForEachLoop.cxx b/src/engine/ForEachLoop.cxx index 3b9dec62c..303cc1492 100644 --- a/src/engine/ForEachLoop.cxx +++ b/src/engine/ForEachLoop.cxx @@ -49,6 +49,8 @@ const char ForEachLoop::NAME_OF_SPLITTERNODE[]="splitter"; const int ForEachLoop::NOT_RUNNING_BRANCH_ID=-1; +const char ForEachLoop::INTERCEPTOR_STR[]="_interceptor"; + InterceptorInputPort::InterceptorInputPort(const std::string& name, Node *node, TypeCode* type):AnyInputPort(name,node,type), DataPort(name,node,type),Port(node), _repr(0) @@ -877,6 +879,12 @@ YACS::Event ForEachLoop::updateStateOnFailedEventFrom(Node *node, const Executor } } +void ForEachLoop::InterceptorizeNameOfPort(std::string& portName) +{ + std::replace_if(portName.begin(), portName.end(), std::bind1st(std::equal_to(), '.'), '_'); + portName += INTERCEPTOR_STR; +} + void ForEachLoop::buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) { DynParaLoop::buildDelegateOf(port,finalTarget,pointsOfView); @@ -904,12 +912,10 @@ void ForEachLoop::buildDelegateOf(std::pair& port, InPort // the delegated port belongs to a node child of the ForEachLoop. // The name of the delegated port contains dots (bloc.node.outport), // whereas the name of the out going port shouldn't do. - std::string outputPortName = getPortName(port.first); - std::replace_if (outputPortName.begin(), outputPortName.end(), - std::bind1st(std::equal_to(), '.'), '_'); - outputPortName += "_interceptor"; - AnySplitOutputPort *newPort=new AnySplitOutputPort(outputPortName,this,newTc); - InterceptorInputPort *intercptor=new InterceptorInputPort(outputPortName + "_in",this,port.first->edGetType()); + std::string outputPortName(getPortName(port.first)); + InterceptorizeNameOfPort(outputPortName); + AnySplitOutputPort *newPort(new AnySplitOutputPort(outputPortName,this,newTc)); + InterceptorInputPort *intercptor(new InterceptorInputPort(outputPortName + "_in",this,port.first->edGetType())); intercptor->setRepr(newPort); newTc->decrRef(); newPort->addRepr(port.first,intercptor); diff --git a/src/engine/ForEachLoop.hxx b/src/engine/ForEachLoop.hxx index d70259618..efb9888fb 100644 --- a/src/engine/ForEachLoop.hxx +++ b/src/engine/ForEachLoop.hxx @@ -220,6 +220,9 @@ namespace YACS void storeOutValsInSeqForOutOfScopeUse(int rank, int branchNb); private: int getFinishedId(); + public: + static void InterceptorizeNameOfPort(std::string& portName); + static const char INTERCEPTOR_STR[]; }; } } diff --git a/src/evalyfx/YACSEvalYFX.cxx b/src/evalyfx/YACSEvalYFX.cxx index b3fcb25e3..9e7ef2f3f 100644 --- a/src/evalyfx/YACSEvalYFX.cxx +++ b/src/evalyfx/YACSEvalYFX.cxx @@ -137,11 +137,21 @@ YACSEvalObserver *YACSEvalYFX::getObserver() return _pattern->getObserver(); } +std::string YACSEvalYFX::getStatusOfRunStr() const +{ + return _pattern->getStatusOfRunStr(); +} + std::vector YACSEvalYFX::getResults() const { return _pattern->getResults(); } +std::vector YACSEvalYFX::getResultsInCaseOfFailure(std::vector& passedIds) const +{ + return _pattern->getResultsInCaseOfFailure(passedIds); +} + YACS::ENGINE::Proc *YACSEvalYFX::getUndergroundGeneratedGraph() const { return _pattern->getUndergroundGeneratedGraph(); diff --git a/src/evalyfx/YACSEvalYFX.hxx b/src/evalyfx/YACSEvalYFX.hxx index 14dcc9573..7f723c4bc 100644 --- a/src/evalyfx/YACSEvalYFX.hxx +++ b/src/evalyfx/YACSEvalYFX.hxx @@ -58,7 +58,9 @@ public: YACSEVALYFX_EXPORT bool run(YACSEvalSession *session, int& nbOfBranches); YACSEVALYFX_EXPORT void registerObserver(YACSEvalObserver *observer); YACSEVALYFX_EXPORT YACSEvalObserver *getObserver(); + YACSEVALYFX_EXPORT std::string getStatusOfRunStr() const; YACSEVALYFX_EXPORT std::vector getResults() const; + YACSEVALYFX_EXPORT std::vector getResultsInCaseOfFailure(std::vector& passedIds) const; // YACSEVALYFX_EXPORT YACS::ENGINE::Proc *getUndergroundGeneratedGraph() const; YACSEVALYFX_EXPORT void setParallelizeStatus(bool newVal); diff --git a/src/evalyfx/YACSEvalYFXPattern.cxx b/src/evalyfx/YACSEvalYFXPattern.cxx index 8e351fed7..7afb739d0 100644 --- a/src/evalyfx/YACSEvalYFXPattern.cxx +++ b/src/evalyfx/YACSEvalYFXPattern.cxx @@ -27,6 +27,7 @@ #include "ElementaryNode.hxx" #include "RuntimeSALOME.hxx" #include "Dispatcher.hxx" +#include "Executor.hxx" #include "InputPort.hxx" #include "LinkInfo.hxx" #include "TypeCode.hxx" @@ -44,9 +45,18 @@ #include #include #include +#include const char YACSEvalYFXPattern::DFT_PROC_NAME[]="YFX"; +const char YACSEvalYFXPattern::ST_OK[]="ALL_OK"; + +const char YACSEvalYFXPattern::ST_FAILED[]="SOME_SAMPLES_FAILED_AND_ALL_OF_THEM_FAILED_DETERMINISTICALLY"; + +const char YACSEvalYFXPattern::ST_ERROR[]="SOME_SAMPLES_FAILED_BUT_IMPOSSIBLE_TO_CONCLUDE_ON_THEM"; + +const char YACSEvalYFXRunOnlyPattern::FIRST_FE_SUBNODE_NAME[]="Bloc"; + const char YACSEvalYFXRunOnlyPattern::GATHER_NODE_NAME[]="__gather__"; std::vector< YACSEvalInputPort *> YACSEvalYFXPattern::getFreeInputPorts() const @@ -228,6 +238,25 @@ YACSEvalSeqAny *YACSEvalYFXPattern::BuildValueInPort(YACS::ENGINE::InputPyPort * throw YACS::Exception("YACSEvalYFXPattern::GetValueInPort : not implemented yet for other than Double and Int !"); } +YACSEvalSeqAny *YACSEvalYFXPattern::BuildValueFromEngineFrmt(YACS::ENGINE::SequenceAny *data) +{ + unsigned int sz(data->size()); + std::vector eltCpp(sz); + for(unsigned int ii=0;ii(eltPtr)); + if(!eltPtr2) + { + std::ostringstream oss; oss << "YACSEvalYFXPattern::BuildValueFromEngineFrmt : error at pos #" << ii << " ! It is not an AtomAny !"; + throw YACS::Exception(oss.str()); + } + eltCpp[ii]=eltPtr2->getDoubleValue(); + } + return new YACSEvalSeqAnyDouble(eltCpp); +} + void YACSEvalYFXPattern::cleanScheme() { if(_ownScheme) @@ -336,7 +365,7 @@ void YACSEvalYFXRunOnlyPattern::generateGraph() _generatedGraph->edAddChild(n2); _generatedGraph->edAddCFLink(n1,n2); // - YACS::ENGINE::Bloc *n10(r->createBloc("Bloc")); + YACS::ENGINE::Bloc *n10(r->createBloc(FIRST_FE_SUBNODE_NAME)); n1->edAddChild(n10); YACS::ENGINE::InlineNode *n100(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,"__dispatch__")); YACS::ENGINE::Node *n101(_runNode->cloneWithoutCompAndContDeepCpy(0,true)); @@ -454,6 +483,41 @@ YACS::ENGINE::Proc *YACSEvalYFXRunOnlyPattern::getUndergroundGeneratedGraph() co return _generatedGraph; } +std::string YACSEvalYFXRunOnlyPattern::getStatusOfRunStr() const +{ + YACS::StatesForNode st(_generatedGraph->getState()); + switch(st) + { + case YACS::READY: + case YACS::TOLOAD: + case YACS::LOADED: + case YACS::TOACTIVATE: + case YACS::ACTIVATED: + case YACS::SUSPENDED: + case YACS::PAUSE: + case YACS::DISABLED: + case YACS::DESACTIVATED: + { + std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::getStatusOfRunStr : Unexpected state \"" << YACS::ENGINE::Node::getStateName(st) << "\" ! Did you invoke run ?"; + throw YACS::Exception(oss.str()); + } + case YACS::LOADFAILED: + case YACS::EXECFAILED: + case YACS::ERROR: + case YACS::INTERNALERR: + return std::string(ST_ERROR); + case YACS::FAILED: + return std::string(ST_FAILED); + case YACS::DONE: + return std::string(ST_OK); + default: + { + std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::getStatusOfRunStr : unrecognized and managed state \"" << YACS::ENGINE::Node::getStateName(st) << "\" !"; + throw YACS::Exception(oss.str()); + } + } +} + std::vector YACSEvalYFXRunOnlyPattern::getResults() const { if(_generatedGraph->getState()!=YACS::DONE) @@ -478,6 +542,67 @@ std::vector YACSEvalYFXRunOnlyPattern::getResults() const return ret; } +/*! + * This method works if run succeeded (true return) and also if graph has failed. Graph failed means soft error of evaluation due to error in evaluation (example 1/0 or a normal throw from one node) + * If a more serious error occured (SIGSEGV of a server or internal error in YACS engine, cluster error, loose of connection...) this method will throw an exception to warn the caller that the results may be + */ +std::vector YACSEvalYFXRunOnlyPattern::getResultsInCaseOfFailure(std::vector& passedIds) const +{ + YACS::StatesForNode st(_generatedGraph->getState()); + if(st==YACS::DONE) + { + passedIds.clear(); + std::vector ret(getResults()); + if(!ret.empty()) + { + if(!ret[0]) + throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getResultsInCaseOfFailure : internal error ! The returned vector has a null pointer at pos #0 !"); + std::size_t sz(ret[0]->size()); + passedIds.resize(sz); + for(std::size_t i=0;i lns(_generatedGraph->edGetDirectDescendants()); + YACS::ENGINE::ForEachLoop *fe(0); + for(std::list::const_iterator it=lns.begin();it!=lns.end();it++) + { + fe=dynamic_cast(*it); + if(fe) + break; + } + if(!fe) + throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getResultsInCaseOfFailure : internal error 2 ! ForEach is not accessible !"); + // + YACS::ENGINE::Executor exe; + std::vector outputs; + std::vector nameOfOutputs; + passedIds=fe->getPassedResults(&exe,outputs,nameOfOutputs);//<- the key invokation is here. + std::size_t sz(passedIds.size()),ii(0); + std::vector ret(_outputsOfInterest.size()); + for(std::vector::const_iterator it=_outputsOfInterest.begin();it!=_outputsOfInterest.end();it++,ii++) + { + YACS::ENGINE::OutputPort *p((*it)->getUndergroundPtr()); + std::string st(_runNode->getOutPortName(p)); + std::ostringstream oss; oss << FIRST_FE_SUBNODE_NAME << '.' << _runNode->getName() << '.' << st; + st=oss.str(); + YACS::ENGINE::ForEachLoop::InterceptorizeNameOfPort(st); + std::vector::iterator it(std::find(nameOfOutputs.begin(),nameOfOutputs.end(),st)); + if(it==nameOfOutputs.end()) + { + std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::getResultsInCaseOfFailure : internal error 3 ! Unable to locate interceptor with name " << st << " ! Possibilities are : "; + std::copy(nameOfOutputs.begin(),nameOfOutputs.end(),std::ostream_iterator(oss," ")); + oss << " !"; + throw YACS::Exception(oss.str()); + } + std::size_t pos(std::distance(nameOfOutputs.begin(),it)); + ret[ii]=BuildValueFromEngineFrmt(outputs[pos]); + } + return ret; +} + void YACSEvalYFXRunOnlyPattern::emitStart() const { YACSEvalObserver *obs(getObserver()); diff --git a/src/evalyfx/YACSEvalYFXPattern.hxx b/src/evalyfx/YACSEvalYFXPattern.hxx index ea3c4d4fa..6db957d04 100644 --- a/src/evalyfx/YACSEvalYFXPattern.hxx +++ b/src/evalyfx/YACSEvalYFXPattern.hxx @@ -38,6 +38,7 @@ namespace YACS class ForEachLoop; class ComposedNode; class InputPyPort; + class SequenceAny; } } @@ -74,7 +75,9 @@ public: virtual bool isLocked() const = 0; virtual YACSEvalListOfResources *giveResources() = 0; virtual YACS::ENGINE::Proc *getUndergroundGeneratedGraph() const = 0; + virtual std::string getStatusOfRunStr() const = 0; virtual std::vector getResults() const = 0; + virtual std::vector getResultsInCaseOfFailure(std::vector& passedIds) const = 0; virtual void emitStart() const = 0; public: static const char DFT_PROC_NAME[]; @@ -86,6 +89,7 @@ protected: YACSEvalListOfResources *getResourcesInternal() const { return _res; } ResourcesManager_cpp *getCatalogInAppli() const { return _rm; } static YACSEvalSeqAny *BuildValueInPort(YACS::ENGINE::InputPyPort *port); + static YACSEvalSeqAny *BuildValueFromEngineFrmt(YACS::ENGINE::SequenceAny *data); private: void cleanScheme(); private: @@ -99,6 +103,10 @@ private: protected: std::vector< YACSEvalInputPort > _inputs; std::vector< YACSEvalOutputPort > _outputs; +public: + static const char ST_OK[]; // execution goes to the end without any trouble -> results can be exploited without any problem with getResults and getResultsInCaseOfFailure. + static const char ST_FAILED[]; // execution has reached some failed evaluation (normal errors due to incapacity of one node to evaluate) -> results can be exploited without any problem with getResultsInCaseOfFailure + static const char ST_ERROR[]; // execution has encountered hard errors (SIGSEGV in a server, internal error in YACS) -> results can be exploited with getResultsInCaseOfFailure but you can't make hypothesis for other ids not in passedIds. }; class YACSEvalYFXRunOnlyPattern : public YACSEvalYFXPattern @@ -115,12 +123,15 @@ public: bool isLocked() const; YACSEvalListOfResources *giveResources(); YACS::ENGINE::Proc *getUndergroundGeneratedGraph() const; + std::string getStatusOfRunStr() const; std::vector getResults() const; + std::vector getResultsInCaseOfFailure(std::vector& passedIds) const; void emitStart() const; // YACS::ENGINE::ForEachLoop *getUndergroundForEach() const { return _FEInGeneratedGraph; } static bool IsMatching(YACS::ENGINE::Proc *scheme, YACS::ENGINE::ComposedNode *& runNode); public: + static const char FIRST_FE_SUBNODE_NAME[]; static const char GATHER_NODE_NAME[]; private: void buildInputPorts(); diff --git a/src/evalyfx_swig/evalyfx.i b/src/evalyfx_swig/evalyfx.i index 89668a64e..212865470 100644 --- a/src/evalyfx_swig/evalyfx.i +++ b/src/evalyfx_swig/evalyfx.i @@ -75,6 +75,15 @@ static void convertPyToIntArr(PyObject *pyLi, std::vector& arr) } } +static PyObject *convertToPyToInt(const std::vector& arr) +{ + std::size_t sz(arr.size()); + PyObject *ret(PyList_New(sz)); + for(std::size_t i=0;i& arr) { if(PyList_Check(pyLi)) @@ -114,6 +123,40 @@ static void convertPyToDblArr(PyObject *pyLi, std::vector& arr) throw YACS::Exception("convertPyToNewIntArr3 : not a list nor a tuple"); } } + +static PyObject *convertVectOfSeqAny(const std::vector& retCpp) +{ + std::size_t sz(retCpp.size()); + PyObject *ret(PyList_New(sz)); + for(std::size_t i=0;i(elt)); + YACSEvalSeqAnyInt *elt2(dynamic_cast(elt)); + if(elt1) + { + std::vector *zeArr(elt1->getInternal()); + std::size_t sz2(zeArr->size()); + PyObject *ret2(PyList_New(sz2)); + for(std::size_t i2=0;i2 *zeArr(elt2->getInternal()); + std::size_t sz2(zeArr->size()); + PyObject *ret2(PyList_New(sz2)); + for(std::size_t i2=0;i2 retCpp(self->getResults()); - std::size_t sz(retCpp.size()); - PyObject *ret(PyList_New(sz)); - for(std::size_t i=0;i(elt)); - YACSEvalSeqAnyInt *elt2(dynamic_cast(elt)); - if(elt1) - { - std::vector *zeArr(elt1->getInternal()); - std::size_t sz2(zeArr->size()); - PyObject *ret2(PyList_New(sz2)); - for(std::size_t i2=0;i2 *zeArr(elt2->getInternal()); - std::size_t sz2(zeArr->size()); - PyObject *ret2(PyList_New(sz2)); - for(std::size_t i2=0;i2 ret1Cpp; + std::vector ret0Cpp(self->getResultsInCaseOfFailure(ret1Cpp)); + PyObject *retPy(PyTuple_New(2)); + PyTuple_SetItem(retPy,0,convertVectOfSeqAny(ret0Cpp)); + PyTuple_SetItem(retPy,1,convertToPyToInt(ret1Cpp)); + return retPy; } PyObject *run(YACSEvalSession *session) diff --git a/src/evalyfx_swig/test2.py b/src/evalyfx_swig/test2.py new file mode 100644 index 000000000..706b1707d --- /dev/null +++ b/src/evalyfx_swig/test2.py @@ -0,0 +1,49 @@ +# bug revealed by otgui on 8/2/16. Several lock/unlock session. test1.xml is Cogeneration.xml. + +def buildScheme(fname): + import SALOMERuntime + import loader + SALOMERuntime.RuntimeSALOME.setRuntime() + r=SALOMERuntime.getSALOMERuntime() + p0=r.createProc("run") + # + p=r.createBloc("toto") + p0.edAddChild(p) + # + cont=p0.createContainer("MyWonderfulContainer","Salome") + td=p0.createType("double","double") + n0=r.createScriptNode("Salome","PyScript0") + p.edAddChild(n0) + q=n0.edAddInputPort("q",td) + ep=n0.edAddOutputPort("ep",td) + n0.setScript("ep=1./(4.-q)") # <- force division by 0 + n0.setExecutionMode("remote") + n0.setContainer(cont) + p0.saveSchema(fname) + pass + +fname="test2.xml" +import evalyfx +session=evalyfx.YACSEvalSession() +session.launch() +buildScheme(fname) +efx=evalyfx.YACSEvalYFX.BuildFromFile(fname) +#efx.setParallelizeStatus(False) +efx.getParams().setStopASAPAfterErrorStatus(False) +inps=efx.getFreeInputPorts() +assert(len(inps)==1) +outps=efx.getFreeOutputPorts() +inps[0].setSequenceOfValuesToEval([1.,2.,3.,4.,5.,6.]) +efx.lockPortsForEvaluation(inps,outps) +rss=efx.giveResources() +rss[0][0].setWantedMachine("localhost") +a,b=efx.run(session) +assert(efx.getStatusOfRunStr()=='SOME_SAMPLES_FAILED_AND_ALL_OF_THEM_FAILED_DETERMINISTICALLY') +c,d=efx.getResultsInCaseOfFailure() +assert(d==[0,1,2,4,5])# case 3 is not in ! +assert(len(c)==1) +c=c[0] +for f,g in zip(c,[0.3333333333333333,0.5,1.0,-1.0,-0.5]): + assert(abs(f-g)<1e-12) + pass +