Salome HOME
7afb739d05cb70ed440fefd3d742e2bef8f200c5
[modules/yacs.git] / src / evalyfx / YACSEvalYFXPattern.cxx
1 // Copyright (C) 2012-2015  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 // 
19 // Author : Anthony Geay (EDF R&D)
20
21 #include "YACSEvalYFXPattern.hxx"
22 #include "YACSEvalResource.hxx"
23 #include "YACSEvalSeqAny.hxx"
24 #include "YACSEvalObserver.hxx"
25 #include "YACSEvalAutoPtr.hxx"
26
27 #include "ElementaryNode.hxx"
28 #include "RuntimeSALOME.hxx"
29 #include "Dispatcher.hxx"
30 #include "Executor.hxx"
31 #include "InputPort.hxx"
32 #include "LinkInfo.hxx"
33 #include "TypeCode.hxx"
34 #include "Proc.hxx"
35
36 #include "PythonPorts.hxx"
37 #include "ForEachLoop.hxx"
38 #include "PythonNode.hxx"
39 #include "InlineNode.hxx"
40 #include "ServiceNode.hxx"
41
42 #include "ResourcesManager.hxx"
43
44 #include <map>
45 #include <limits>
46 #include <numeric>
47 #include <sstream>
48 #include <iterator>
49
50 const char YACSEvalYFXPattern::DFT_PROC_NAME[]="YFX";
51
52 const char YACSEvalYFXPattern::ST_OK[]="ALL_OK";
53
54 const char YACSEvalYFXPattern::ST_FAILED[]="SOME_SAMPLES_FAILED_AND_ALL_OF_THEM_FAILED_DETERMINISTICALLY";
55
56 const char YACSEvalYFXPattern::ST_ERROR[]="SOME_SAMPLES_FAILED_BUT_IMPOSSIBLE_TO_CONCLUDE_ON_THEM";
57
58 const char YACSEvalYFXRunOnlyPattern::FIRST_FE_SUBNODE_NAME[]="Bloc";
59
60 const char YACSEvalYFXRunOnlyPattern::GATHER_NODE_NAME[]="__gather__";
61
62 std::vector< YACSEvalInputPort *> YACSEvalYFXPattern::getFreeInputPorts() const
63 {
64   std::size_t sz(_inputs.size());
65   std::vector< YACSEvalInputPort *> ret;
66   std::vector< YACSEvalInputPort >::const_iterator it(_inputs.begin());
67   for(std::size_t i=0;i<sz;i++,it++)
68     ret.push_back(const_cast<YACSEvalInputPort *>(&(*it)));
69   return ret;
70 }
71
72 std::vector< YACSEvalOutputPort *> YACSEvalYFXPattern::getFreeOutputPorts() const
73 {
74   std::size_t sz(_outputs.size());
75   std::vector< YACSEvalOutputPort *> ret;
76   std::vector< YACSEvalOutputPort >::const_iterator it(_outputs.begin());
77   for(std::size_t i=0;i<sz;i++,it++)
78     ret.push_back(const_cast<YACSEvalOutputPort *>(&(*it)));
79   return ret;
80 }
81
82 YACSEvalYFXPattern *YACSEvalYFXPattern::FindPatternFrom(YACSEvalYFX *boss, YACS::ENGINE::Proc *scheme, bool ownScheme)
83 {
84   if(!scheme)
85     throw YACS::Exception("YACSEvalYFXPattern::FindPatternFrom : input scheme must be not null !");
86   {
87       YACS::ENGINE::ComposedNode *zeRunNode(0);
88       bool isMatchingRunOnlyPattern(YACSEvalYFXRunOnlyPattern::IsMatching(scheme,zeRunNode));
89       if(isMatchingRunOnlyPattern)
90         return new YACSEvalYFXRunOnlyPattern(boss,scheme,ownScheme,zeRunNode);
91   }
92   throw YACS::Exception("YACSEvalYFXPattern::FindPatternFrom : no pattern found for the input scheme !");
93 }
94
95 bool YACSEvalYFXPattern::isAlreadyComputedResources() const
96 {
97   return _res!=0;
98 }
99
100 void YACSEvalYFXPattern::checkNonAlreadyComputedResources() const
101 {
102   if(isAlreadyComputedResources())
103     throw YACS::Exception("checkNonAlreadyComputedResources : instance of computed resources already computed !");
104 }
105
106 void YACSEvalYFXPattern::checkAlreadyComputedResources() const
107 {
108   if(!isAlreadyComputedResources())
109     throw YACS::Exception("checkAlreadyComputedResources : instance of computed resources not already computed !");
110 }
111
112 void YACSEvalYFXPattern::checkLocked() const
113 {
114   if(!isLocked())
115     throw YACS::Exception("YACSEvalYFXPattern::checkLocked : Pattern is not locked !");
116 }
117
118 void YACSEvalYFXPattern::checkNonLocked() const
119 {
120   if(isLocked())
121     throw YACS::Exception("YACSEvalYFXPattern::checkNonLocked : Pattern is locked !");
122 }
123
124 void YACSEvalYFXPattern::CheckNodeIsOK(YACS::ENGINE::ComposedNode *node)
125 {
126   /*YACS::ENGINE::LinkInfo info(YACS::ENGINE::LinkInfo::WARN_ONLY_DONT_STOP);
127   try
128   {
129       node->checkConsistency(info);
130   }
131   catch(YACS::Exception& e)
132   {
133   }
134   if(info.getNumberOfErrLinks(YACS::ENGINE::E_ALL)!=0)
135     throw YACS::Exception("YACSEvalYFXPattern::CheckNodeIsOK : found node is not OK !");
136   std::list<YACS::ENGINE::ElementaryNode *> allNodes(node->getRecursiveConstituents());
137   for(std::list<YACS::ENGINE::ElementaryNode *>::const_iterator it=allNodes.begin();it!=allNodes.end();it++)
138     {
139       YACS::ENGINE::ServiceNode *node0(dynamic_cast<YACS::ENGINE::ServiceNode *>(*it));
140       YACS::ENGINE::InlineNode *node1(dynamic_cast<YACS::ENGINE::InlineNode *>(*it));
141       if(node0)
142         {
143           YACS::ENGINE::Container *cont(node0->getContainer());
144           YACS::ENGINE::ComponentInstance *comp(node0->getComponent());
145           if(!cont || !comp)
146             {
147               std::ostringstream oss; oss << "YACSEvalYFXPattern::CheckNodeIsOK : ServiceNode called \"" << node0->getName() << "\" is not correctly defined !";
148               throw YACS::Exception(oss.str());
149             }
150         }
151       if(node1)
152         {
153           YACS::ENGINE::Container *cont(node1->getContainer());
154           if(!cont && node1->getExecutionMode()==YACS::ENGINE::InlineNode::REMOTE_STR)
155             {
156               std::ostringstream oss; oss << "YACSEvalYFXPattern::CheckNodeIsOK : InlineNode called \"" << node1->getName() << "\" is not correctly defined !";
157               throw YACS::Exception(oss.str());
158             }
159         }
160     }*/
161 }
162
163 void YACSEvalYFXPattern::registerObserver(YACSEvalObserver *observer)
164 {
165   if(_observer==observer)
166     return ;
167   if(_observer)
168     _observer->decrRef();
169   _observer=observer;
170   if(_observer)
171     _observer->incrRef();
172 }
173
174 YACSEvalYFXPattern::YACSEvalYFXPattern(YACSEvalYFX *boss, YACS::ENGINE::Proc *scheme, bool ownScheme):_boss(boss),_scheme(scheme),_ownScheme(ownScheme),_parallelizeStatus(true),_rm(new ResourcesManager_cpp),_res(0),_observer(0)
175 {
176 }
177
178 YACS::ENGINE::TypeCode *YACSEvalYFXPattern::createSeqTypeCodeFrom(YACS::ENGINE::Proc *scheme, const std::string& zeType)
179 {
180   std::ostringstream oss; oss << "list[" << zeType << "]";
181   YACS::ENGINE::TypeCode *tc(scheme->getTypeCode(zeType));
182   return scheme->createSequenceTc(oss.str(),oss.str(),tc);
183 }
184
185 void YACSEvalYFXPattern::setResources(YACSEvalListOfResources *res)
186 {
187   checkNonAlreadyComputedResources();
188   if(res!=_res)
189     delete _res;
190   _res=res;
191 }
192
193 void YACSEvalYFXPattern::resetResources()
194 {
195   delete _res;
196   _res=0;
197 }
198
199 YACSEvalSeqAny *YACSEvalYFXPattern::BuildValueInPort(YACS::ENGINE::InputPyPort *port)
200 {
201   if(!port)
202     throw YACS::Exception("YACSEvalYFXPattern::GetValueInPort : null input port !");
203   PyObject *obj(port->getPyObj());
204   YACS::ENGINE::TypeCode *tc(port->edGetType());
205   YACS::ENGINE::TypeCodeSeq *tcc(dynamic_cast<YACS::ENGINE::TypeCodeSeq *>(tc));
206   if(!tcc)
207     {
208       std::ostringstream oss; oss << "YACSEvalYFXPattern::GetValueInPort : internal error for tc of input \"" << port->getName() << "\"";
209       throw YACS::Exception(oss.str());
210     }
211   const YACS::ENGINE::TypeCode *tcct(tcc->contentType());
212   if(!PyList_Check(obj))
213     throw YACS::Exception("YACSEvalYFXPattern::GetValueInPort : internal error 2 !");
214   std::size_t sz(PyList_Size(obj));
215   if(tcct->kind()==YACS::ENGINE::Double)
216     {
217       std::vector<double> eltCpp(sz);
218       for(std::size_t i=0;i<sz;i++)
219         {
220           PyObject *elt(PyList_GetItem(obj,i));
221           eltCpp[i]=PyFloat_AsDouble(elt);
222         }
223       YACS::AutoCppPtr<YACSEvalSeqAnyDouble> elt(new YACSEvalSeqAnyDouble(eltCpp));
224       return elt.dettach();
225     }
226   else if(tcct->kind()==YACS::ENGINE::Int)
227     {
228       std::vector<int> eltCpp(sz);
229       for(std::size_t i=0;i<sz;i++)
230         {
231           PyObject *elt(PyList_GetItem(obj,i));
232           eltCpp[i]=PyInt_AsLong(elt);
233         }
234       YACS::AutoCppPtr<YACSEvalSeqAnyInt> elt(new YACSEvalSeqAnyInt(eltCpp));
235       return elt.dettach();
236     }
237   else
238     throw YACS::Exception("YACSEvalYFXPattern::GetValueInPort : not implemented yet for other than Double and Int !");
239 }
240
241 YACSEvalSeqAny *YACSEvalYFXPattern::BuildValueFromEngineFrmt(YACS::ENGINE::SequenceAny *data)
242 {
243   unsigned int sz(data->size());
244   std::vector<double> eltCpp(sz);
245   for(unsigned int ii=0;ii<sz;ii++)
246     {
247       YACS::ENGINE::AnyPtr elt((*data)[ii]);
248       YACS::ENGINE::Any *eltPtr((YACS::ENGINE::Any *)elt);
249       YACS::ENGINE::AtomAny *eltPtr2(dynamic_cast<YACS::ENGINE::AtomAny *>(eltPtr));
250       if(!eltPtr2)
251         {
252           std::ostringstream oss; oss << "YACSEvalYFXPattern::BuildValueFromEngineFrmt : error at pos #" << ii << " ! It is not an AtomAny !";
253           throw YACS::Exception(oss.str());
254         }
255       eltCpp[ii]=eltPtr2->getDoubleValue();
256     }
257   return new YACSEvalSeqAnyDouble(eltCpp);
258 }
259
260 void YACSEvalYFXPattern::cleanScheme()
261 {
262   if(_ownScheme)
263     delete _scheme;
264   _scheme=0;
265 }
266
267 YACSEvalYFXPattern::~YACSEvalYFXPattern()
268 {
269   if(_observer)
270     _observer->decrRef();
271   delete _rm;
272   delete _res;
273 }
274
275 /////////////////////
276
277 class YACSEvalYFXRunOnlyPatternInternalObserver : public YACS::ENGINE::Observer
278 {
279 public:
280   YACSEvalYFXRunOnlyPatternInternalObserver(YACSEvalYFXRunOnlyPattern *boss):_boss(boss) { if(!_boss) throw YACS::Exception("YACSEvalYFXRunOnlyPatternInternalObserver constructor : null boss not supported :)"); }
281   void notifyObserver(YACS::ENGINE::Node *object, const std::string& event);
282 private:
283   YACSEvalYFXRunOnlyPattern *_boss;
284 };
285
286 void YACSEvalYFXRunOnlyPatternInternalObserver::notifyObserver(YACS::ENGINE::Node *object, const std::string& event)
287 {
288   YACS::ENGINE::ForEachLoop *object2(dynamic_cast<YACS::ENGINE::ForEachLoop *>(object));
289   if(!object2)
290     return ;
291   YACSEvalObserver *obs(_boss->getObserver());
292   if(!obs)
293     return ;
294   if(event=="progress")
295     obs->notifyNewNumberOfPassedItems(_boss->getBoss(),object2->getCurrentIndex());
296 }
297
298 /////////////////////
299
300 YACSEvalYFXRunOnlyPattern::YACSEvalYFXRunOnlyPattern(YACSEvalYFX *boss, YACS::ENGINE::Proc *scheme, bool ownScheme, YACS::ENGINE::ComposedNode *runNode):YACSEvalYFXPattern(boss,scheme,ownScheme),_runNode(runNode),_generatedGraph(0),_FEInGeneratedGraph(0),_obs(new YACSEvalYFXRunOnlyPatternInternalObserver(this))
301 {
302   if(!_runNode)
303     throw YACS::Exception("YACSEvalYFXRunOnlyPattern : internal run node must be not null !");
304   buildInputPorts();
305   buildOutputPorts();
306 }
307
308 YACSEvalYFXRunOnlyPattern::~YACSEvalYFXRunOnlyPattern()
309 {
310   delete _obs;
311 }
312
313 void YACSEvalYFXRunOnlyPattern::setOutPortsOfInterestForEvaluation(const std::vector<YACSEvalOutputPort *>& outputsOfInterest)
314 {
315   checkNonLocked();
316   _outputsOfInterest=outputsOfInterest;
317 }
318
319 void YACSEvalYFXRunOnlyPattern::resetOutputsOfInterest()
320 {
321   checkLocked();
322   _outputsOfInterest.clear();
323 }
324
325 void YACSEvalYFXRunOnlyPattern::generateGraph()
326 {
327   static const char LISTPYOBJ_STR[]="list[pyobj]";
328   if(_outputsOfInterest.empty())
329     return ;
330   YACS::ENGINE::RuntimeSALOME::setRuntime();
331   YACS::ENGINE::RuntimeSALOME *r(YACS::ENGINE::getSALOMERuntime());
332   _generatedGraph=r->createProc(DFT_PROC_NAME);
333   YACS::ENGINE::TypeCode *pyobjTC(_generatedGraph->createInterfaceTc("python:obj:1.0","pyobj",std::list<YACS::ENGINE::TypeCodeObjref *>()));
334   std::ostringstream oss; oss << "Loop_" << _runNode->getName();
335   _generatedGraph->createType(YACSEvalAnyDouble::TYPE_REPR,"double");
336   _generatedGraph->createType(YACSEvalAnyInt::TYPE_REPR,"int");
337   //
338   YACS::ENGINE::InlineNode *n0(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,"__initializer__"));
339   _generatedGraph->edAddChild(n0);
340   YACS::ENGINE::TypeCode *listPyobjTC(_generatedGraph->createSequenceTc(LISTPYOBJ_STR,LISTPYOBJ_STR,pyobjTC));
341   YACS::ENGINE::OutputPort *sender(n0->edAddOutputPort("sender",listPyobjTC));
342   std::ostringstream var0;
343   for(std::vector< YACSEvalInputPort >::const_iterator it=_inputs.begin();it!=_inputs.end();it++)
344     {
345       if((*it).isRandomVar())
346         {
347           var0 << (*it).getName() << ",";
348           YACS::ENGINE::TypeCode *tc(createSeqTypeCodeFrom(_generatedGraph,(*it).getTypeOfData()));
349           YACS::ENGINE::InputPort *inp(n0->edAddInputPort((*it).getName(),tc));
350           YACS::ENGINE::InputPyPort *inpc(dynamic_cast<YACS::ENGINE::InputPyPort *>(inp));
351           if(!inpc)
352             throw YACS::Exception("YACSEvalYFXRunOnlyPattern::generateGraph : internal error 1 !");
353           (*it).setUndergroundPortToBeSet(inpc);
354         }
355     }
356   std::ostringstream n0Script; n0Script << "sender=zip(" << var0.str() << ")\n";
357   n0->setScript(n0Script.str());
358   //
359   YACS::ENGINE::ForEachLoop *n1(r->createForEachLoop(oss.str(),pyobjTC));
360   _FEInGeneratedGraph=n1;
361   _generatedGraph->edAddChild(n1);
362   _generatedGraph->edAddCFLink(n0,n1);
363   _generatedGraph->edAddDFLink(sender,n1->edGetSeqOfSamplesPort());
364   YACS::ENGINE::InlineNode *n2(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,GATHER_NODE_NAME));
365   _generatedGraph->edAddChild(n2);
366   _generatedGraph->edAddCFLink(n1,n2);
367   //
368   YACS::ENGINE::Bloc *n10(r->createBloc(FIRST_FE_SUBNODE_NAME));
369   n1->edAddChild(n10);
370   YACS::ENGINE::InlineNode *n100(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,"__dispatch__"));
371   YACS::ENGINE::Node *n101(_runNode->cloneWithoutCompAndContDeepCpy(0,true));
372   n10->edAddChild(n100);
373   n10->edAddChild(n101);
374   YACS::ENGINE::InputPort *dispatchIn(n100->edAddInputPort("i0",pyobjTC));
375   n10->edAddCFLink(n100,n101);
376   n1->edAddDFLink(n1->edGetSamplePort(),dispatchIn);
377   std::ostringstream var1;
378   for(std::vector< YACSEvalInputPort >::const_iterator it=_inputs.begin();it!=_inputs.end();it++)
379     {
380       if((*it).isRandomVar())
381         {
382           var1 << (*it).getName() << ",";
383           YACS::ENGINE::OutputPort *myOut(n100->edAddOutputPort((*it).getName(),_generatedGraph->getTypeCode((*it).getTypeOfData())));
384           std::string tmpPortName(_runNode->getInPortName((*it).getUndergroundPtr()));
385           YACS::ENGINE::InputPort *myIn(n101->getInputPort(tmpPortName));
386           n10->edAddDFLink(myOut,myIn);
387         }
388     }
389   std::ostringstream n100Script;  n100Script << var1.str() << "=i0\n";
390   n100->setScript(n100Script.str());
391   for(std::vector< YACSEvalOutputPort * >::const_iterator it=_outputsOfInterest.begin();it!=_outputsOfInterest.end();it++)
392     {
393       YACS::ENGINE::TypeCode *tc(createSeqTypeCodeFrom(_generatedGraph,(*it)->getTypeOfData()));
394       YACS::ENGINE::InputPort *myIn(n2->edAddInputPort((*it)->getName(),tc));
395       std::string tmpPortName(_runNode->getOutPortName((*it)->getUndergroundPtr()));
396       YACS::ENGINE::OutputPort *myOut(n101->getOutputPort(tmpPortName));
397       _generatedGraph->edAddDFLink(myOut,myIn);
398     }
399   _generatedGraph->updateContainersAndComponents();
400 }
401
402 void YACSEvalYFXRunOnlyPattern::resetGeneratedGraph()
403 {
404   delete _generatedGraph;
405   _generatedGraph=0;
406   resetResources();
407 }
408
409 int YACSEvalYFXRunOnlyPattern::assignNbOfBranches()
410 {
411   checkAlreadyComputedResources();
412   if(!_generatedGraph)
413     throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignNbOfBranches : the generated graph has not been created !");
414   std::list<YACS::ENGINE::Node *> nodes(_generatedGraph->getChildren());
415   YACS::ENGINE::ForEachLoop *zeMainNode(0);
416   for(std::list<YACS::ENGINE::Node *>::const_iterator it=nodes.begin();it!=nodes.end();it++)
417     {
418       YACS::ENGINE::ForEachLoop *isZeMainNode(dynamic_cast<YACS::ENGINE::ForEachLoop *>(*it));
419       if(isZeMainNode)
420         {
421           if(!zeMainNode)
422             zeMainNode=isZeMainNode;
423           else
424             throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignNbOfBranches : internal error 1 !");
425         }
426     }
427   if(!zeMainNode)
428     throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignNbOfBranches : internal error 2 !");
429   unsigned int nbProcsDeclared(getResourcesInternal()->getNumberOfProcsDeclared());
430   nbProcsDeclared=std::max(nbProcsDeclared,4u);
431   int nbOfBranch=1;
432   if(getParallelizeStatus())
433     {
434       nbOfBranch=(nbProcsDeclared/getResourcesInternal()->getMaxLevelOfParallelism());
435       nbOfBranch=std::max(nbOfBranch,1);
436     }
437   YACS::ENGINE::InputPort *zeInputToSet(zeMainNode->edGetNbOfBranchesPort());
438   YACS::ENGINE::AnyInputPort *zeInputToSetC(dynamic_cast<YACS::ENGINE::AnyInputPort *>(zeInputToSet));
439   if(!zeInputToSetC)
440     throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignNbOfBranches : internal error 3 !");
441   YACS::ENGINE::Any *a(YACS::ENGINE::AtomAny::New(nbOfBranch));
442   zeInputToSetC->put(a);
443   zeInputToSetC->exSaveInit();
444   a->decrRef();
445   return nbOfBranch;
446 }
447
448 void YACSEvalYFXRunOnlyPattern::assignRandomVarsInputs()
449 {
450   std::size_t sz(std::numeric_limits<std::size_t>::max());
451   for(std::vector< YACSEvalInputPort >::const_iterator it=_inputs.begin();it!=_inputs.end();it++)
452     if((*it).isRandomVar())
453       {
454         std::size_t locSize((*it).initializeUndergroundWithSeq());
455         if(sz==std::numeric_limits<std::size_t>::max())
456           sz=locSize;
457         else
458           if(sz!=locSize)
459             throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignRandomVarsInputs : length of sequences in random vars must be the same !");
460       }
461 }
462
463 bool YACSEvalYFXRunOnlyPattern::isLocked() const
464 {
465   return _generatedGraph!=0;
466 }
467
468 YACSEvalListOfResources *YACSEvalYFXRunOnlyPattern::giveResources()
469 {
470   checkLocked();
471   if(!isAlreadyComputedResources())
472     {
473       YACS::ENGINE::DeploymentTree dt(_runNode->getDeploymentTree());
474       _runNode->removeRecursivelyRedundantCL();
475       YACSEvalListOfResources *res(new YACSEvalListOfResources(_runNode->getMaxLevelOfParallelism(),getCatalogInAppli(),dt));
476       setResources(res);
477     }
478   return getResourcesInternal();
479 }
480
481 YACS::ENGINE::Proc *YACSEvalYFXRunOnlyPattern::getUndergroundGeneratedGraph() const
482 {
483   return _generatedGraph;
484 }
485
486 std::string YACSEvalYFXRunOnlyPattern::getStatusOfRunStr() const
487 {
488   YACS::StatesForNode st(_generatedGraph->getState());
489   switch(st)
490     {
491     case YACS::READY:
492     case YACS::TOLOAD:
493     case YACS::LOADED:
494     case YACS::TOACTIVATE:
495     case YACS::ACTIVATED:
496     case YACS::SUSPENDED:
497     case YACS::PAUSE:
498     case YACS::DISABLED:
499     case YACS::DESACTIVATED:
500       {
501         std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::getStatusOfRunStr : Unexpected state \"" << YACS::ENGINE::Node::getStateName(st) << "\" ! Did you invoke run ?";
502         throw YACS::Exception(oss.str());
503       }
504     case YACS::LOADFAILED:
505     case YACS::EXECFAILED:
506     case YACS::ERROR:
507     case YACS::INTERNALERR:
508       return std::string(ST_ERROR);
509     case YACS::FAILED:
510       return std::string(ST_FAILED);
511     case YACS::DONE:
512       return std::string(ST_OK);
513     default:
514       {
515         std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::getStatusOfRunStr : unrecognized and managed state \"" << YACS::ENGINE::Node::getStateName(st) << "\" !";
516         throw YACS::Exception(oss.str());
517       }
518     }
519 }
520
521 std::vector<YACSEvalSeqAny *> YACSEvalYFXRunOnlyPattern::getResults() const
522 {
523   if(_generatedGraph->getState()!=YACS::DONE)
524     throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getResults : the execution did not finished correctly ! getResults should not be called !");
525   std::vector<YACSEvalSeqAny *> ret(_outputsOfInterest.size());
526   YACS::ENGINE::Node *node(_generatedGraph->getChildByName(GATHER_NODE_NAME));
527   YACS::ENGINE::PythonNode *nodeC(dynamic_cast<YACS::ENGINE::PythonNode *>(node));
528   if(!nodeC)
529     throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getResults : internal error !");
530   std::size_t ii(0);
531   for(std::vector< YACSEvalOutputPort * >::const_iterator it=_outputsOfInterest.begin();it!=_outputsOfInterest.end();it++,ii++)
532     {
533       YACS::ENGINE::InPort *input(nodeC->getInPort((*it)->getName()));
534       YACS::ENGINE::InputPyPort *inputC(dynamic_cast<YACS::ENGINE::InputPyPort *>(input));
535       if(!inputC)
536         {
537           std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::getResults : internal error for input \"" << (*it)->getName() << "\"";
538           throw YACS::Exception(oss.str());
539         }
540       ret[ii]=BuildValueInPort(inputC);
541     }
542   return ret;
543 }
544
545 /*!
546  * 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)
547  * 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 
548  */
549 std::vector<YACSEvalSeqAny *> YACSEvalYFXRunOnlyPattern::getResultsInCaseOfFailure(std::vector<unsigned int>& passedIds) const
550 {
551   YACS::StatesForNode st(_generatedGraph->getState());
552   if(st==YACS::DONE)
553     {
554       passedIds.clear();
555       std::vector<YACSEvalSeqAny *> ret(getResults());
556       if(!ret.empty())
557         {
558           if(!ret[0])
559             throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getResultsInCaseOfFailure : internal error ! The returned vector has a null pointer at pos #0 !");
560           std::size_t sz(ret[0]->size());
561           passedIds.resize(sz);
562           for(std::size_t i=0;i<sz;i++)
563             passedIds[i]=i;
564         }
565       return ret;
566     }
567   getStatusOfRunStr();// To check that the status is recognized.
568   std::list<YACS::ENGINE::Node *> lns(_generatedGraph->edGetDirectDescendants());
569   YACS::ENGINE::ForEachLoop *fe(0);
570   for(std::list<YACS::ENGINE::Node *>::const_iterator it=lns.begin();it!=lns.end();it++)
571     {
572       fe=dynamic_cast<YACS::ENGINE::ForEachLoop *>(*it);
573       if(fe)
574         break;
575     }
576   if(!fe)
577     throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getResultsInCaseOfFailure : internal error 2 ! ForEach is not accessible !");
578   //
579   YACS::ENGINE::Executor exe;
580   std::vector<YACS::ENGINE::SequenceAny *> outputs;
581   std::vector<std::string> nameOfOutputs;
582   passedIds=fe->getPassedResults(&exe,outputs,nameOfOutputs);//<- the key invokation is here.
583   std::size_t sz(passedIds.size()),ii(0);
584   std::vector<YACSEvalSeqAny *> ret(_outputsOfInterest.size());
585   for(std::vector<YACSEvalOutputPort *>::const_iterator it=_outputsOfInterest.begin();it!=_outputsOfInterest.end();it++,ii++)
586     {
587       YACS::ENGINE::OutputPort *p((*it)->getUndergroundPtr());
588       std::string st(_runNode->getOutPortName(p));
589       std::ostringstream oss; oss << FIRST_FE_SUBNODE_NAME << '.' << _runNode->getName() << '.' << st;
590       st=oss.str();
591       YACS::ENGINE::ForEachLoop::InterceptorizeNameOfPort(st);
592       std::vector<std::string>::iterator it(std::find(nameOfOutputs.begin(),nameOfOutputs.end(),st));
593       if(it==nameOfOutputs.end())
594         {
595           std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::getResultsInCaseOfFailure : internal error 3 ! Unable to locate interceptor with name " << st << " ! Possibilities are : ";
596           std::copy(nameOfOutputs.begin(),nameOfOutputs.end(),std::ostream_iterator<std::string>(oss," "));
597           oss << " !";
598           throw YACS::Exception(oss.str());
599         }
600       std::size_t pos(std::distance(nameOfOutputs.begin(),it));
601       ret[ii]=BuildValueFromEngineFrmt(outputs[pos]);
602     }
603   return ret;
604 }
605
606 void YACSEvalYFXRunOnlyPattern::emitStart() const
607 {
608   YACSEvalObserver *obs(getObserver());
609   if(!obs)
610     return ;
611   obs->notifyNumberOfSamplesToEval(getBoss(),_FEInGeneratedGraph->getNbOfElementsToBeProcessed());
612 }
613
614 bool YACSEvalYFXRunOnlyPattern::IsMatching(YACS::ENGINE::Proc *scheme, YACS::ENGINE::ComposedNode *& runNode)
615 {
616   std::list<YACS::ENGINE::Node *> nodes(scheme->getChildren());
617   if(nodes.empty())
618     return false;
619   bool areAllElementary(true);
620   for(std::list<YACS::ENGINE::Node *>::const_iterator it=nodes.begin();it!=nodes.end() && areAllElementary;it++)
621     if(!dynamic_cast<YACS::ENGINE::ElementaryNode *>(*it))
622       areAllElementary=false;
623   if(areAllElementary)
624     {
625       if(scheme)
626         CheckNodeIsOK(scheme);
627       runNode=scheme;
628       return true;
629     }
630   if(nodes.size()!=1)
631     return false;
632   YACS::ENGINE::ComposedNode *candidate(dynamic_cast<YACS::ENGINE::ComposedNode *>(nodes.front()));
633   runNode=candidate;
634   if(candidate)
635     CheckNodeIsOK(candidate);
636   return candidate!=0;
637 }
638
639 void YACSEvalYFXRunOnlyPattern::buildInputPorts()
640 {
641   _inputs.clear();
642   std::list< YACS::ENGINE::InputPort *> allInputPorts(_runNode->getSetOfInputPort());
643   std::vector<std::string> allNames;
644   for(std::list< YACS::ENGINE::InputPort *>::const_iterator it=allInputPorts.begin();it!=allInputPorts.end();it++)
645     {
646       YACS::ENGINE::InputPort *elt(*it);
647       if(!elt)
648         throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildInputPorts : presence of null input !");
649       std::set<YACS::ENGINE::OutPort *> bls(elt->edSetOutPort());
650       if(bls.empty())
651         {
652           if(YACSEvalPort::IsInputPortPublishable(elt))
653             {
654               std::string inpName(elt->getName());
655               if(inpName.empty())
656                 throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildInputPorts : an input has empty name ! Should not !");
657               _inputs.push_back(YACSEvalInputPort(elt));
658               if(std::find(allNames.begin(),allNames.end(),inpName)!=allNames.end())
659                 {
660                   std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::buildInputPorts : input name \"" << inpName << "\" appears more than once !";
661                   throw YACS::Exception(oss.str());
662                 }
663               allNames.push_back(inpName);
664             }
665         }
666     }
667 }
668
669 void YACSEvalYFXRunOnlyPattern::buildOutputPorts()
670 {
671   _outputs.clear();
672   std::list< YACS::ENGINE::OutputPort *> allOutputPorts(_runNode->getSetOfOutputPort());
673   std::vector<std::string> allNames;
674   for(std::list< YACS::ENGINE::OutputPort *>::const_iterator it=allOutputPorts.begin();it!=allOutputPorts.end();it++)
675     {
676       YACS::ENGINE::OutputPort *elt(*it);
677       if(YACSEvalPort::IsOutputPortPublishable(elt))
678         {
679           if(!elt)
680             throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildOutputPorts : presence of null output !");
681           std::string outpName(elt->getName());
682           if(outpName.empty())
683             throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildOutputPorts : an output has empty name ! Should not !");
684           if(std::find(allNames.begin(),allNames.end(),outpName)!=allNames.end())
685             {
686               std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::buildOutputPorts : output name \"" << outpName << "\" appears more than once !";
687               throw YACS::Exception(oss.str());
688             }
689           _outputs.push_back(YACSEvalOutputPort(*it));
690         }
691     }
692 }
693