]> SALOME platform Git repositories - modules/yacs.git/blob - src/evalyfx/YACSEvalYFXPattern.cxx
Salome HOME
Add a generic widget for choosing resource parameters.
[modules/yacs.git] / src / evalyfx / YACSEvalYFXPattern.cxx
1 // Copyright (C) 2012-2016  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 "YACSEvalSession.hxx"
25 #include "YACSEvalObserver.hxx"
26 #include "YACSEvalSessionInternal.hxx"
27 #include "YACSEvalAutoPtr.hxx"
28 #include "YACSEvalExecParams.hxx"
29
30 #include "ElementaryNode.hxx"
31 #include "RuntimeSALOME.hxx"
32 #include "Dispatcher.hxx"
33 #include "Executor.hxx"
34 #include "InputPort.hxx"
35 #include "LinkInfo.hxx"
36 #include "TypeCode.hxx"
37 #include "Proc.hxx"
38 #include "Dispatcher.hxx"
39
40 #include "PythonPorts.hxx"
41 #include "ForEachLoop.hxx"
42 #include "PythonNode.hxx"
43 #include "InlineNode.hxx"
44 #include "ServiceNode.hxx"
45 #include "PyStdout.hxx"
46 #include "AutoGIL.hxx"
47
48 #include "ResourcesManager.hxx"
49
50 #include <map>
51 #include <limits>
52 #include <numeric>
53 #include <sstream>
54 #include <iterator>
55
56 ////
57 #include <stdlib.h>
58
59 const char YACSEvalYFXPattern::ST_OK[]="ALL_OK";
60
61 const char YACSEvalYFXPattern::ST_FAILED[]="SOME_SAMPLES_FAILED_AND_ALL_OF_THEM_FAILED_DETERMINISTICALLY";
62
63 const char YACSEvalYFXPattern::ST_ERROR[]="SOME_SAMPLES_FAILED_BUT_IMPOSSIBLE_TO_CONCLUDE_ON_THEM";
64
65 const std::size_t YACSEvalYFXPattern::MAX_LGTH_OF_INP_DUMP=10000;
66
67 const char YACSEvalYFXGraphGen::DFT_PROC_NAME[]="YFX";
68
69 const char YACSEvalYFXGraphGen::FIRST_FE_SUBNODE_NAME[]="Bloc";
70
71 const char YACSEvalYFXGraphGen::GATHER_NODE_NAME[]="__gather__";
72
73 class MyAutoThreadSaver
74 {
75 public:
76   MyAutoThreadSaver(bool isToSave):_isToSave(isToSave),_save(0)
77   {
78     if(_isToSave)
79       {
80         PyThreadState *save(PyThreadState_Swap(NULL));// safe call of PyEval_SaveThread()
81         if(save)
82           {
83             _save=save;
84             PyEval_ReleaseLock();
85           }
86       }
87   }
88   ~MyAutoThreadSaver() { if(_isToSave) if(_save) { PyEval_AcquireLock(); PyThreadState_Swap(_save); /*safe call of PyEval_RestoreThread*/ } }
89 private:
90   bool _isToSave;
91   PyThreadState *_save;
92 };
93
94 std::vector< YACSEvalInputPort *> YACSEvalYFXPattern::getFreeInputPorts() const
95 {
96   std::size_t sz(_inputs.size());
97   std::vector< YACSEvalInputPort *> ret;
98   std::vector< YACSEvalInputPort >::const_iterator it(_inputs.begin());
99   for(std::size_t i=0;i<sz;i++,it++)
100     ret.push_back(const_cast<YACSEvalInputPort *>(&(*it)));
101   return ret;
102 }
103
104 std::vector< YACSEvalOutputPort *> YACSEvalYFXPattern::getFreeOutputPorts() const
105 {
106   std::size_t sz(_outputs.size());
107   std::vector< YACSEvalOutputPort *> ret;
108   std::vector< YACSEvalOutputPort >::const_iterator it(_outputs.begin());
109   for(std::size_t i=0;i<sz;i++,it++)
110     ret.push_back(const_cast<YACSEvalOutputPort *>(&(*it)));
111   return ret;
112 }
113
114 YACSEvalYFXPattern *YACSEvalYFXPattern::FindPatternFrom(YACSEvalYFX *boss, YACS::ENGINE::Proc *scheme, bool ownScheme)
115 {
116   if(!scheme)
117     throw YACS::Exception("YACSEvalYFXPattern::FindPatternFrom : input scheme must be not null !");
118   {
119       YACS::ENGINE::ComposedNode *zeRunNode(0);
120       bool isMatchingRunOnlyPattern(YACSEvalYFXRunOnlyPattern::IsMatching(scheme,zeRunNode));
121       if(isMatchingRunOnlyPattern)
122         return new YACSEvalYFXRunOnlyPattern(boss,scheme,ownScheme,zeRunNode);
123   }
124   throw YACS::Exception("YACSEvalYFXPattern::FindPatternFrom : no pattern found for the input scheme !");
125 }
126
127 bool YACSEvalYFXPattern::isAlreadyComputedResources() const
128 {
129   return _res!=0;
130 }
131
132 void YACSEvalYFXPattern::checkNonAlreadyComputedResources() const
133 {
134   if(isAlreadyComputedResources())
135     throw YACS::Exception("checkNonAlreadyComputedResources : instance of computed resources already computed !");
136 }
137
138 void YACSEvalYFXPattern::checkAlreadyComputedResources() const
139 {
140   if(!isAlreadyComputedResources())
141     throw YACS::Exception("checkAlreadyComputedResources : instance of computed resources not already computed !");
142 }
143
144 void YACSEvalYFXPattern::checkLocked() const
145 {
146   if(!isLocked())
147     throw YACS::Exception("YACSEvalYFXPattern::checkLocked : Pattern is not locked !");
148 }
149
150 void YACSEvalYFXPattern::checkNonLocked() const
151 {
152   if(isLocked())
153     throw YACS::Exception("YACSEvalYFXPattern::checkNonLocked : Pattern is locked !");
154 }
155
156 void YACSEvalYFXPattern::CheckNodeIsOK(YACS::ENGINE::ComposedNode *node)
157 {
158   /*YACS::ENGINE::LinkInfo info(YACS::ENGINE::LinkInfo::WARN_ONLY_DONT_STOP);
159   try
160   {
161       node->checkConsistency(info);
162   }
163   catch(YACS::Exception& e)
164   {
165   }
166   if(info.getNumberOfErrLinks(YACS::ENGINE::E_ALL)!=0)
167     throw YACS::Exception("YACSEvalYFXPattern::CheckNodeIsOK : found node is not OK !");
168   std::list<YACS::ENGINE::ElementaryNode *> allNodes(node->getRecursiveConstituents());
169   for(std::list<YACS::ENGINE::ElementaryNode *>::const_iterator it=allNodes.begin();it!=allNodes.end();it++)
170     {
171       YACS::ENGINE::ServiceNode *node0(dynamic_cast<YACS::ENGINE::ServiceNode *>(*it));
172       YACS::ENGINE::InlineNode *node1(dynamic_cast<YACS::ENGINE::InlineNode *>(*it));
173       if(node0)
174         {
175           YACS::ENGINE::Container *cont(node0->getContainer());
176           YACS::ENGINE::ComponentInstance *comp(node0->getComponent());
177           if(!cont || !comp)
178             {
179               std::ostringstream oss; oss << "YACSEvalYFXPattern::CheckNodeIsOK : ServiceNode called \"" << node0->getName() << "\" is not correctly defined !";
180               throw YACS::Exception(oss.str());
181             }
182         }
183       if(node1)
184         {
185           YACS::ENGINE::Container *cont(node1->getContainer());
186           if(!cont && node1->getExecutionMode()==YACS::ENGINE::InlineNode::REMOTE_STR)
187             {
188               std::ostringstream oss; oss << "YACSEvalYFXPattern::CheckNodeIsOK : InlineNode called \"" << node1->getName() << "\" is not correctly defined !";
189               throw YACS::Exception(oss.str());
190             }
191         }
192     }*/
193 }
194
195 void YACSEvalYFXPattern::registerObserver(YACSEvalObserver *observer)
196 {
197   if(_observer==observer)
198     return ;
199   if(_observer)
200     _observer->decrRef();
201   _observer=observer;
202   if(_observer)
203     _observer->incrRef();
204 }
205
206 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)
207 {
208 }
209
210 YACS::ENGINE::TypeCode *YACSEvalYFXPattern::CreateSeqTypeCodeFrom(YACS::ENGINE::Proc *scheme, const std::string& zeType)
211 {
212   std::ostringstream oss; oss << "list[" << zeType << "]";
213   YACS::ENGINE::TypeCode *tc(scheme->getTypeCode(zeType));
214   return scheme->createSequenceTc(oss.str(),oss.str(),tc);
215 }
216
217 void YACSEvalYFXPattern::setResources(YACSEvalListOfResources *res)
218 {
219   checkNonAlreadyComputedResources();
220   if(res!=_res)
221     delete _res;
222   _res=res;
223 }
224
225 void YACSEvalYFXPattern::resetResources()
226 {
227   delete _res;
228   _res=0;
229 }
230
231 YACSEvalSeqAny *YACSEvalYFXPattern::BuildValueInPort(YACS::ENGINE::InputPyPort *port)
232 {
233   if(!port)
234     throw YACS::Exception("YACSEvalYFXPattern::GetValueInPort : null input port !");
235   PyObject *obj(port->getPyObj());
236   YACS::ENGINE::TypeCode *tc(port->edGetType());
237   YACS::ENGINE::TypeCodeSeq *tcc(dynamic_cast<YACS::ENGINE::TypeCodeSeq *>(tc));
238   if(!tcc)
239     {
240       std::ostringstream oss; oss << "YACSEvalYFXPattern::GetValueInPort : internal error for tc of input \"" << port->getName() << "\"";
241       throw YACS::Exception(oss.str());
242     }
243   const YACS::ENGINE::TypeCode *tcct(tcc->contentType());
244   if(!PyList_Check(obj))
245     throw YACS::Exception("YACSEvalYFXPattern::GetValueInPort : internal error 2 !");
246   std::size_t sz(PyList_Size(obj));
247   if(tcct->kind()==YACS::ENGINE::Double)
248     {
249       std::vector<double> eltCpp(sz);
250       for(std::size_t i=0;i<sz;i++)
251         {
252           PyObject *elt(PyList_GetItem(obj,i));
253           eltCpp[i]=PyFloat_AsDouble(elt);
254         }
255       YACS::AutoCppPtr<YACSEvalSeqAnyDouble> elt(new YACSEvalSeqAnyDouble(eltCpp));
256       return elt.dettach();
257     }
258   else if(tcct->kind()==YACS::ENGINE::Int)
259     {
260       std::vector<int> eltCpp(sz);
261       for(std::size_t i=0;i<sz;i++)
262         {
263           PyObject *elt(PyList_GetItem(obj,i));
264           eltCpp[i]=PyInt_AsLong(elt);
265         }
266       YACS::AutoCppPtr<YACSEvalSeqAnyInt> elt(new YACSEvalSeqAnyInt(eltCpp));
267       return elt.dettach();
268     }
269   else
270     throw YACS::Exception("YACSEvalYFXPattern::GetValueInPort : not implemented yet for other than Double and Int !");
271 }
272
273 YACSEvalSeqAny *YACSEvalYFXPattern::BuildValueFromEngineFrmt(YACS::ENGINE::SequenceAny *data)
274 {
275   unsigned int sz(data->size());
276   std::vector<double> eltCpp(sz);
277   for(unsigned int ii=0;ii<sz;ii++)
278     {
279       YACS::ENGINE::AnyPtr elt((*data)[ii]);
280       YACS::ENGINE::Any *eltPtr((YACS::ENGINE::Any *)elt);
281       YACS::ENGINE::AtomAny *eltPtr2(dynamic_cast<YACS::ENGINE::AtomAny *>(eltPtr));
282       if(!eltPtr2)
283         {
284           std::ostringstream oss; oss << "YACSEvalYFXPattern::BuildValueFromEngineFrmt : error at pos #" << ii << " ! It is not an AtomAny !";
285           throw YACS::Exception(oss.str());
286         }
287       eltCpp[ii]=eltPtr2->getDoubleValue();
288     }
289   return new YACSEvalSeqAnyDouble(eltCpp);
290 }
291
292 void YACSEvalYFXPattern::cleanScheme()
293 {
294   if(_ownScheme)
295     delete _scheme;
296   _scheme=0;
297 }
298
299 YACSEvalYFXPattern::~YACSEvalYFXPattern()
300 {
301   if(_observer)
302     _observer->decrRef();
303   delete _rm;
304   delete _res;
305 }
306
307 /////////////////////
308
309 class YACSEvalYFXRunOnlyPatternInternalObserver : public YACS::ENGINE::Observer
310 {
311 public:
312   YACSEvalYFXRunOnlyPatternInternalObserver(YACSEvalYFXRunOnlyPattern *boss):_boss(boss) { if(!_boss) throw YACS::Exception("YACSEvalYFXRunOnlyPatternInternalObserver constructor : null boss not supported :)"); }
313   void notifyObserver2(YACS::ENGINE::Node *object, const std::string& event, void *something);
314 private:
315   YACSEvalYFXRunOnlyPattern *_boss;
316 };
317
318 void YACSEvalYFXRunOnlyPatternInternalObserver::notifyObserver2(YACS::ENGINE::Node *object, const std::string& event, void *something)
319 {
320   YACS::ENGINE::ForEachLoop *object2(_boss->getUndergroundForEach());
321   YACSEvalObserver *obs(_boss->getObserver());
322   if(!obs)
323     return ;
324   if(event=="progress_ok" && object2==object)
325     {
326       int *casted(reinterpret_cast<int *>(something));
327       obs->notifySampleOK(_boss->getBoss(),*casted);
328       return ;
329     }
330   if(event=="progress_ko" && object2==object)
331     {
332       int *casted(reinterpret_cast<int *>(something));
333       obs->notifySampleKO(_boss->getBoss(),*casted);
334       return ;
335     }
336 }
337
338 /////////////////////
339
340 YACSEvalYFXRunOnlyPattern::YACSEvalYFXRunOnlyPattern(YACSEvalYFX *boss, YACS::ENGINE::Proc *scheme, bool ownScheme, YACS::ENGINE::ComposedNode *runNode):YACSEvalYFXPattern(boss,scheme,ownScheme),_lockedStatus(false),_runNode(runNode),_gen(0),_obs(new YACSEvalYFXRunOnlyPatternInternalObserver(this))
341 {
342   if(!_runNode)
343     throw YACS::Exception("YACSEvalYFXRunOnlyPattern : internal run node must be not null !");
344   buildInputPorts();
345   buildOutputPorts();
346 }
347
348 YACSEvalYFXRunOnlyPattern::~YACSEvalYFXRunOnlyPattern()
349 {
350   delete _obs;
351   delete _gen;
352 }
353
354 void YACSEvalYFXRunOnlyPattern::setOutPortsOfInterestForEvaluation(const std::vector<YACSEvalOutputPort *>& outputsOfInterest)
355 {
356   checkNonLocked();
357   _outputsOfInterest=outputsOfInterest;
358   _lockedStatus=true;
359 }
360
361 void YACSEvalYFXRunOnlyPattern::resetOutputsOfInterest()
362 {
363   checkLocked();
364   _outputsOfInterest.clear();
365   _lockedStatus=false;
366 }
367
368 void YACSEvalYFXRunOnlyPattern::generateGraph()
369 {
370   delete _gen;
371   if(getResourcesInternal()->isInteractive())
372     _gen=new YACSEvalYFXGraphGenInteractive(this);
373   else
374     _gen=new YACSEvalYFXGraphGenCluster(this);
375   _gen->generateGraph();
376 }
377
378 void YACSEvalYFXRunOnlyPattern::resetGeneratedGraph()
379 {
380   if(_gen)
381     _gen->resetGeneratedGraph();
382 }
383
384 int YACSEvalYFXRunOnlyPattern::assignNbOfBranches()
385 {
386   checkAlreadyComputedResources();
387   if(!_gen)
388     throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignNbOfBranches : generator is NULL ! Please invoke generateGraph before !");
389   return _gen->assignNbOfBranches();
390 }
391
392 void YACSEvalYFXRunOnlyPattern::assignRandomVarsInputs()
393 {
394   std::size_t sz(std::numeric_limits<std::size_t>::max());
395   for(std::vector< YACSEvalInputPort >::const_iterator it=_inputs.begin();it!=_inputs.end();it++)
396     if((*it).isRandomVar())
397       {
398         std::size_t locSize((*it).initializeUndergroundWithSeq());
399         if(sz==std::numeric_limits<std::size_t>::max())
400           sz=locSize;
401         else
402           if(sz!=locSize)
403             throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignRandomVarsInputs : length of sequences in random vars must be the same !");
404       }
405 }
406
407 bool YACSEvalYFXRunOnlyPattern::isLocked() const
408 {
409   return _lockedStatus;
410 }
411
412 YACSEvalListOfResources *YACSEvalYFXRunOnlyPattern::giveResources()
413 {
414   checkLocked();
415   if(!isAlreadyComputedResources())
416     {
417       YACS::ENGINE::DeploymentTree dt(_runNode->getDeploymentTree());
418       _runNode->removeRecursivelyRedundantCL();
419       YACSEvalListOfResources *res(new YACSEvalListOfResources(_runNode->getMaxLevelOfParallelism(),getCatalogInAppli(),dt));
420       setResources(res);
421     }
422   return getResourcesInternal();
423 }
424
425 YACS::ENGINE::Proc *YACSEvalYFXRunOnlyPattern::getUndergroundGeneratedGraph() const
426 {
427   return getGenerator()->getUndergroundGeneratedGraph();
428 }
429
430 std::string YACSEvalYFXRunOnlyPattern::getErrorDetailsInCaseOfFailure() const
431 {
432   std::string generatorErrors = getGenerator()->getErrors();
433   if(generatorErrors.size() > 0)
434   {
435     return generatorErrors;
436   }
437   std::string st(getStatusOfRunStr());//test if a run has occurred.
438   if(st==ST_OK)
439     throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getErrorDetailsInCaseOfFailure : The execution of scheme has been carried out to the end without any problem !");
440   // All the problem can only comes from foreach -> scan it
441   YACS::ENGINE::ForEachLoop *fe(getUndergroundForEach());
442   YACS::ENGINE::NodeStateNameMap nsm;
443   unsigned nbB(fe->getNumberOfBranchesCreatedDyn());
444   std::ostringstream oss;
445   for(unsigned j=0;j<nbB;j++)
446     {
447       YACS::ENGINE::Node *nn(fe->getChildByNameExec(YACSEvalYFXGraphGen::FIRST_FE_SUBNODE_NAME,j));
448       YACS::ENGINE::Bloc *nnc(dynamic_cast<YACS::ENGINE::Bloc *>(nn));
449       if(!nnc)
450         throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getErrorDetailsInCaseOfFailure : internal error 1 ! The direct son of main foreach is expected to be a Bloc !");
451       if(nnc->getState()==YACS::DONE)
452         continue;
453       std::list< YACS::ENGINE::ElementaryNode *> fec(nnc->getRecursiveConstituents());
454       for(std::list< YACS::ENGINE::ElementaryNode *>::reverse_iterator it1=fec.rbegin();it1!=fec.rend();it1++)
455         {
456           YACS::StatesForNode st0((*it1)->getState());
457           if(st0!=YACS::DONE)
458             {
459               oss << "NODE = " << nnc->getChildName(*it1) << std::endl;
460               oss << "STATUS = " << nsm[st0] << std::endl;
461               oss << "BRANCH ID = " << j << std::endl;
462               std::list<YACS::ENGINE::InputPort *> inps((*it1)->getSetOfInputPort());
463               for(std::list<YACS::ENGINE::InputPort *>::const_iterator it2=inps.begin();it2!=inps.end();it2++)
464                 {
465                   std::string d((*it2)->getHumanRepr());
466                   if(d.size()>10000)
467                     d=d.substr(0,MAX_LGTH_OF_INP_DUMP);
468                   oss << "INPUT \"" << (*it2)->getName() << "\" = " << d << std::endl;
469                 }
470               oss << "DETAILS = " << std::endl;
471               oss << (*it1)->getErrorDetails();
472             }
473         }
474     }
475   return oss.str();
476 }
477
478 std::string YACSEvalYFXRunOnlyPattern::getStatusOfRunStr() const
479 {
480   YACS::StatesForNode st(getUndergroundGeneratedGraph()->getState());
481   switch(st)
482     {
483     case YACS::READY:
484     case YACS::TOLOAD:
485     case YACS::LOADED:
486     case YACS::TOACTIVATE:
487     case YACS::ACTIVATED:
488     case YACS::SUSPENDED:
489     case YACS::PAUSE:
490     case YACS::DISABLED:
491     case YACS::DESACTIVATED:
492       {
493         std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::getStatusOfRunStr : Unexpected state \"" << YACS::ENGINE::Node::getStateName(st) << "\" ! Did you invoke run ?";
494         throw YACS::Exception(oss.str());
495       }
496     case YACS::LOADFAILED:
497     case YACS::EXECFAILED:
498     case YACS::ERROR:
499     case YACS::INTERNALERR:
500       return std::string(ST_ERROR);
501     case YACS::FAILED:
502       return std::string(ST_FAILED);
503     case YACS::DONE:
504       return std::string(ST_OK);
505     default:
506       {
507         std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::getStatusOfRunStr : unrecognized and managed state \"" << YACS::ENGINE::Node::getStateName(st) << "\" !";
508         throw YACS::Exception(oss.str());
509       }
510     }
511 }
512
513 std::vector<YACSEvalSeqAny *> YACSEvalYFXRunOnlyPattern::getResults() const
514 {
515   return _gen->getResults();
516 }
517
518 /*!
519  * 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)
520  * 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 
521  */
522 std::vector<YACSEvalSeqAny *> YACSEvalYFXRunOnlyPattern::getResultsInCaseOfFailure(std::vector<unsigned int>& passedIds) const
523 {
524   YACS::StatesForNode st(getUndergroundGeneratedGraph()->getState());
525   if(st==YACS::DONE)
526     {
527       passedIds.clear();
528       std::vector<YACSEvalSeqAny *> ret(getResults());
529       if(!ret.empty())
530         {
531           if(!ret[0])
532             throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getResultsInCaseOfFailure : internal error ! The returned vector has a null pointer at pos #0 !");
533           std::size_t sz(ret[0]->size());
534           passedIds.resize(sz);
535           for(std::size_t i=0;i<sz;i++)
536             passedIds[i]=i;
537         }
538       return ret;
539     }
540   getStatusOfRunStr();// To check that the status is recognized.
541   std::list<YACS::ENGINE::Node *> lns(getUndergroundGeneratedGraph()->edGetDirectDescendants());
542   YACS::ENGINE::ForEachLoop *fe(getUndergroundForEach());
543   //
544   YACS::ENGINE::Executor exe;
545   std::vector<YACS::ENGINE::SequenceAny *> outputs;
546   std::vector<std::string> nameOfOutputs;
547   passedIds=fe->getPassedResults(&exe,outputs,nameOfOutputs);//<- the key invokation is here.
548   std::size_t sz(passedIds.size()),ii(0);
549   std::vector<YACSEvalSeqAny *> ret(_outputsOfInterest.size());
550   for(std::vector<YACSEvalOutputPort *>::const_iterator it1=_outputsOfInterest.begin();it1!=_outputsOfInterest.end();it1++,ii++)
551     {
552       YACS::ENGINE::OutputPort *p((*it1)->getUndergroundPtr());
553       std::string st(_runNode->getOutPortName(p));
554       std::ostringstream oss; oss << YACSEvalYFXGraphGen::FIRST_FE_SUBNODE_NAME << '.' << _runNode->getName() << '.' << st;
555       st=oss.str();
556       YACS::ENGINE::ForEachLoop::InterceptorizeNameOfPort(st);
557       std::vector<std::string>::iterator it2(std::find(nameOfOutputs.begin(),nameOfOutputs.end(),st));
558       if(it2==nameOfOutputs.end())
559         {
560           std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::getResultsInCaseOfFailure : internal error 3 ! Unable to locate interceptor with name " << st << " ! Possibilities are : ";
561           std::copy(nameOfOutputs.begin(),nameOfOutputs.end(),std::ostream_iterator<std::string>(oss," "));
562           oss << " !";
563           throw YACS::Exception(oss.str());
564         }
565       std::size_t pos(std::distance(nameOfOutputs.begin(),it2));
566       ret[ii]=BuildValueFromEngineFrmt(outputs[pos]);
567     }
568   return ret;
569 }
570
571 void YACSEvalYFXRunOnlyPattern::emitStart() const
572 {
573   YACSEvalObserver *obs(getObserver());
574   if(!obs)
575     return ;
576   obs->startComputation(getBoss());
577 }
578
579 bool YACSEvalYFXRunOnlyPattern::go(const YACSEvalExecParams& params, YACSEvalSession *session) const
580 {
581   emitStart();
582   YACS::ENGINE::Dispatcher *disp(YACS::ENGINE::Dispatcher::getDispatcher());
583   disp->addObserver(_obs,getUndergroundForEach(),"progress_ok");
584   disp->addObserver(_obs,getUndergroundForEach(),"progress_ko");
585   bool ret(getGenerator()->go(params,session));
586   disp->removeObserver(_obs,getUndergroundForEach(),"progress_ok");
587   disp->removeObserver(_obs,getUndergroundForEach(),"progress_ko");
588   return ret;
589 }
590
591 YACS::ENGINE::ForEachLoop *YACSEvalYFXRunOnlyPattern::getUndergroundForEach() const
592 {
593   return getGenerator()->getUndergroundForEach();
594 }
595
596 bool YACSEvalYFXRunOnlyPattern::IsMatching(YACS::ENGINE::Proc *scheme, YACS::ENGINE::ComposedNode *& runNode)
597 {
598   std::list<YACS::ENGINE::Node *> nodes(scheme->getChildren());
599   if(nodes.empty())
600     return false;
601   bool areAllElementary(true);
602   for(std::list<YACS::ENGINE::Node *>::const_iterator it=nodes.begin();it!=nodes.end() && areAllElementary;it++)
603     if(!dynamic_cast<YACS::ENGINE::ElementaryNode *>(*it))
604       areAllElementary=false;
605   if(areAllElementary)
606     {
607       if(scheme)
608         CheckNodeIsOK(scheme);
609       runNode=scheme;
610       return true;
611     }
612   if(nodes.size()!=1)
613     return false;
614   YACS::ENGINE::ComposedNode *candidate(dynamic_cast<YACS::ENGINE::ComposedNode *>(nodes.front()));
615   runNode=candidate;
616   if(candidate)
617     CheckNodeIsOK(candidate);
618   return candidate!=0;
619 }
620
621 void YACSEvalYFXRunOnlyPattern::buildInputPorts()
622 {
623   _inputs.clear();
624   std::list< YACS::ENGINE::InputPort *> allInputPorts(_runNode->getSetOfInputPort());
625   std::vector<std::string> allNames;
626   for(std::list< YACS::ENGINE::InputPort *>::const_iterator it=allInputPorts.begin();it!=allInputPorts.end();it++)
627     {
628       YACS::ENGINE::InputPort *elt(*it);
629       if(!elt)
630         throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildInputPorts : presence of null input !");
631       std::set<YACS::ENGINE::OutPort *> bls(elt->edSetOutPort());
632       if(bls.empty())
633         {
634           if(YACSEvalPort::IsInputPortPublishable(elt))
635             {
636               std::string inpName(elt->getName());
637               if(inpName.empty())
638                 throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildInputPorts : an input has empty name ! Should not !");
639               _inputs.push_back(YACSEvalInputPort(elt));
640               if(std::find(allNames.begin(),allNames.end(),inpName)!=allNames.end())
641                 {
642                   std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::buildInputPorts : input name \"" << inpName << "\" appears more than once !";
643                   throw YACS::Exception(oss.str());
644                 }
645               allNames.push_back(inpName);
646             }
647         }
648     }
649 }
650
651 void YACSEvalYFXRunOnlyPattern::buildOutputPorts()
652 {
653   _outputs.clear();
654   std::list< YACS::ENGINE::OutputPort *> allOutputPorts(_runNode->getSetOfOutputPort());
655   std::vector<std::string> allNames;
656   for(std::list< YACS::ENGINE::OutputPort *>::const_iterator it=allOutputPorts.begin();it!=allOutputPorts.end();it++)
657     {
658       YACS::ENGINE::OutputPort *elt(*it);
659       if(YACSEvalPort::IsOutputPortPublishable(elt))
660         {
661           if(!elt)
662             throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildOutputPorts : presence of null output !");
663           std::string outpName(elt->getName());
664           if(outpName.empty())
665             throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildOutputPorts : an output has empty name ! Should not !");
666           if(std::find(allNames.begin(),allNames.end(),outpName)!=allNames.end())
667             {
668               std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::buildOutputPorts : output name \"" << outpName << "\" appears more than once !";
669               throw YACS::Exception(oss.str());
670             }
671           _outputs.push_back(YACSEvalOutputPort(*it));
672         }
673     }
674 }
675
676 YACSEvalYFXGraphGen *YACSEvalYFXRunOnlyPattern::getGenerator() const
677 {
678   if(!_gen)
679     throw YACS::Exception("getGenerator : generator is NULL !");
680   return _gen;
681 }
682
683 /////////////////////
684
685 YACSEvalYFXGraphGen::YACSEvalYFXGraphGen(YACSEvalYFXRunOnlyPattern *boss):_boss(boss),_generatedGraph(0),_FEInGeneratedGraph(0)
686 {
687   if(!_boss)
688     throw YACS::Exception("YACSEvalYFXGraphGen constructor : boss is NULL !");
689 }
690
691 YACSEvalYFXGraphGen::~YACSEvalYFXGraphGen()
692 {
693   //delete _generatedGraph;// -> TODO : AGY why ?
694 }
695
696 void YACSEvalYFXGraphGen::resetGeneratedGraph()
697 {
698   delete _generatedGraph;
699   _generatedGraph=0; _FEInGeneratedGraph=0;
700 }
701
702 bool YACSEvalYFXGraphGen::isLocked() const
703 {
704   return _generatedGraph!=0;
705 }
706
707 int YACSEvalYFXGraphGen::assignNbOfBranches()
708 {
709   if(!_generatedGraph)
710     throw YACS::Exception("YACSEvalYFXGraphGen::assignNbOfBranches : the generated graph has not been created !");
711   std::list<YACS::ENGINE::Node *> nodes(_generatedGraph->getChildren());
712   YACS::ENGINE::ForEachLoop *zeMainNode(0);
713   for(std::list<YACS::ENGINE::Node *>::const_iterator it=nodes.begin();it!=nodes.end();it++)
714     {
715       YACS::ENGINE::ForEachLoop *isZeMainNode(dynamic_cast<YACS::ENGINE::ForEachLoop *>(*it));
716       if(isZeMainNode)
717         {
718           if(!zeMainNode)
719             zeMainNode=isZeMainNode;
720           else
721             throw YACS::Exception("YACSEvalYFXGraphGen::assignNbOfBranches : internal error 1 !");
722         }
723     }
724   if(!zeMainNode)
725     throw YACS::Exception("YACSEvalYFXGraphGen::assignNbOfBranches : internal error 2 !");
726   unsigned int nbProcsDeclared(getBoss()->getResourcesInternal()->getNumberOfProcsDeclared());
727   nbProcsDeclared=std::max(nbProcsDeclared,4u);
728   int nbOfBranch=1;
729   if(getBoss()->getParallelizeStatus())
730     {
731       nbOfBranch=(nbProcsDeclared/getBoss()->getResourcesInternal()->getMaxLevelOfParallelism());
732       nbOfBranch=std::max(nbOfBranch,1);
733     }
734   YACS::ENGINE::InputPort *zeInputToSet(zeMainNode->edGetNbOfBranchesPort());
735   YACS::ENGINE::AnyInputPort *zeInputToSetC(dynamic_cast<YACS::ENGINE::AnyInputPort *>(zeInputToSet));
736   if(!zeInputToSetC)
737     throw YACS::Exception("YACSEvalYFXGraphGen::assignNbOfBranches : internal error 3 !");
738   YACS::ENGINE::Any *a(YACS::ENGINE::AtomAny::New(nbOfBranch));
739   zeInputToSetC->put(a);
740   zeInputToSetC->exSaveInit();
741   a->decrRef();
742   return nbOfBranch;
743 }
744
745 void YACSEvalYFXGraphGenInteractive::generateGraph()
746 {
747   if(_generatedGraph)
748     { delete _generatedGraph; _generatedGraph=0; _FEInGeneratedGraph=0; }
749   static const char LISTPYOBJ_STR[]="list[pyobj]";
750   if(getBoss()->getOutputsOfInterest().empty())
751     return ;
752   YACS::ENGINE::RuntimeSALOME::setRuntime();
753   YACS::ENGINE::RuntimeSALOME *r(YACS::ENGINE::getSALOMERuntime());
754   _generatedGraph=r->createProc(DFT_PROC_NAME);
755   YACS::ENGINE::TypeCode *pyobjTC(_generatedGraph->createInterfaceTc("python:obj:1.0","pyobj",std::list<YACS::ENGINE::TypeCodeObjref *>()));
756   std::ostringstream oss; oss << "Loop_" << getBoss()->getRunNode()->getName();
757   _generatedGraph->createType(YACSEvalAnyDouble::TYPE_REPR,"double");
758   _generatedGraph->createType(YACSEvalAnyInt::TYPE_REPR,"int");
759   //
760   YACS::ENGINE::InlineNode *n0(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,"__initializer__"));
761   _generatedGraph->edAddChild(n0);
762   YACS::ENGINE::TypeCode *listPyobjTC(_generatedGraph->createSequenceTc(LISTPYOBJ_STR,LISTPYOBJ_STR,pyobjTC));
763   YACS::ENGINE::OutputPort *sender(n0->edAddOutputPort("sender",listPyobjTC));
764   std::ostringstream var0;
765   const std::vector< YACSEvalInputPort >& inputs(getBoss()->getInputs());
766   for(std::vector< YACSEvalInputPort >::const_iterator it=inputs.begin();it!=inputs.end();it++)
767     {
768       if((*it).isRandomVar())
769         {
770           var0 << (*it).getName() << ",";
771           YACS::ENGINE::TypeCode *tc(YACSEvalYFXPattern::CreateSeqTypeCodeFrom(_generatedGraph,(*it).getTypeOfData()));
772           YACS::ENGINE::InputPort *inp(n0->edAddInputPort((*it).getName(),tc));
773           YACS::ENGINE::InputPyPort *inpc(dynamic_cast<YACS::ENGINE::InputPyPort *>(inp));
774           if(!inpc)
775             throw YACS::Exception("YACSEvalYFXRunOnlyPattern::generateGraph : internal error 1 !");
776           (*it).setUndergroundPortToBeSet(inpc);
777         }
778     }
779   std::ostringstream n0Script; n0Script << "sender=zip(" << var0.str() << ")\n";
780   n0->setScript(n0Script.str());
781   //
782   YACS::ENGINE::ForEachLoop *n1(r->createForEachLoop(oss.str(),pyobjTC));
783   _FEInGeneratedGraph=n1;
784   _generatedGraph->edAddChild(n1);
785   _generatedGraph->edAddCFLink(n0,n1);
786   _generatedGraph->edAddDFLink(sender,n1->edGetSeqOfSamplesPort());
787   YACS::ENGINE::InlineNode *n2(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,GATHER_NODE_NAME));
788   _generatedGraph->edAddChild(n2);
789   _generatedGraph->edAddCFLink(n1,n2);
790   //
791   YACS::ENGINE::Bloc *n10(r->createBloc(FIRST_FE_SUBNODE_NAME));
792   n1->edAddChild(n10);
793   YACS::ENGINE::InlineNode *n100(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,"__dispatch__"));
794   YACS::ENGINE::ComposedNode *runNode(getBoss()->getRunNode());
795   YACS::ENGINE::Node *n101(runNode->cloneWithoutCompAndContDeepCpy(0,true));
796   n10->edAddChild(n100);
797   n10->edAddChild(n101);
798   YACS::ENGINE::InputPort *dispatchIn(n100->edAddInputPort("i0",pyobjTC));
799   n10->edAddCFLink(n100,n101);
800   n1->edAddDFLink(n1->edGetSamplePort(),dispatchIn);
801   std::ostringstream var1;
802   for(std::vector< YACSEvalInputPort >::const_iterator it=inputs.begin();it!=inputs.end();it++)
803     {
804       if((*it).isRandomVar())
805         {
806           var1 << (*it).getName() << ",";
807           YACS::ENGINE::OutputPort *myOut(n100->edAddOutputPort((*it).getName(),_generatedGraph->getTypeCode((*it).getTypeOfData())));
808           std::string tmpPortName(runNode->getInPortName((*it).getUndergroundPtr()));
809           YACS::ENGINE::InputPort *myIn(n101->getInputPort(tmpPortName));
810           n10->edAddDFLink(myOut,myIn);
811         }
812     }
813   std::ostringstream n100Script;  n100Script << var1.str() << "=i0\n";
814   n100->setScript(n100Script.str());
815   const std::vector<YACSEvalOutputPort *>& outputsOfInt(getBoss()->getOutputsOfInterest());
816   for(std::vector< YACSEvalOutputPort * >::const_iterator it=outputsOfInt.begin();it!=outputsOfInt.end();it++)
817     {
818       YACS::ENGINE::TypeCode *tc(YACSEvalYFXPattern::CreateSeqTypeCodeFrom(_generatedGraph,(*it)->getTypeOfData()));
819       YACS::ENGINE::InputPort *myIn(n2->edAddInputPort((*it)->getName(),tc));
820       std::string tmpPortName(runNode->getOutPortName((*it)->getUndergroundPtr()));
821       YACS::ENGINE::OutputPort *myOut(n101->getOutputPort(tmpPortName));
822       _generatedGraph->edAddDFLink(myOut,myIn);
823     }
824   _generatedGraph->updateContainersAndComponents();
825 }
826
827 bool YACSEvalYFXGraphGenInteractive::go(const YACSEvalExecParams& params, YACSEvalSession *session) const
828 {
829   YACS::ENGINE::Executor exe;
830   exe.setKeepGoingProperty(!params.getStopASAPAfterErrorStatus());
831   {
832     MyAutoThreadSaver locker(!session->isAlreadyPyThreadSaved());
833     exe.RunW(getUndergroundGeneratedGraph());
834   }
835   return getUndergroundGeneratedGraph()->getState()==YACS::DONE;
836 }
837
838 std::string YACSEvalYFXGraphGenInteractive::getErrors()const
839 {
840   return "";
841 }
842
843 std::vector<YACSEvalSeqAny *> YACSEvalYFXGraphGenInteractive::getResults() const
844 {
845   if(getUndergroundGeneratedGraph()->getState()!=YACS::DONE)
846     throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getResults : the execution did not finished correctly ! getResults should not be called !");
847   const std::vector<YACSEvalOutputPort *>& outputsOfInt(getBoss()->getOutputsOfInterest()); 
848   std::vector<YACSEvalSeqAny *> ret(outputsOfInt.size());
849   YACS::ENGINE::Node *node(getUndergroundGeneratedGraph()->getChildByName(YACSEvalYFXGraphGen::GATHER_NODE_NAME));
850   YACS::ENGINE::PythonNode *nodeC(dynamic_cast<YACS::ENGINE::PythonNode *>(node));
851   if(!nodeC)
852     throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getResults : internal error !");
853   std::size_t ii(0);
854   for(std::vector< YACSEvalOutputPort * >::const_iterator it=outputsOfInt.begin();it!=outputsOfInt.end();it++,ii++)
855     {
856       YACS::ENGINE::InPort *input(nodeC->getInPort((*it)->getName()));
857       YACS::ENGINE::InputPyPort *inputC(dynamic_cast<YACS::ENGINE::InputPyPort *>(input));
858       if(!inputC)
859         {
860           std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::getResults : internal error for input \"" << (*it)->getName() << "\"";
861           throw YACS::Exception(oss.str());
862         }
863       ret[ii]=YACSEvalYFXPattern::BuildValueInPort(inputC);
864     }
865   return ret;
866 }
867
868 ////////////////////
869
870 void YACSEvalYFXGraphGenCluster::generateGraph()
871 {
872   YACS::ENGINE::AutoGIL agil;
873   if(_generatedGraph)
874     { delete _generatedGraph; _generatedGraph=0; _FEInGeneratedGraph=0; }
875   //
876   const char EFXGenFileName[]="EFXGenFileName";
877   const char EFXGenContent[]="import getpass,datetime,os\nn=datetime.datetime.now()\nreturn os.path.join(os.path.sep,\"tmp\",\"EvalYFX_%s_%s_%s.xml\"%(getpass.getuser(),n.strftime(\"%d%m%y\"),n.strftime(\"%H%M%S\")))";
878   const char EFXGenContent2[]="import getpass,datetime\nn=datetime.datetime.now()\nreturn \"EvalYFX_%s_%s_%s\"%(getpass.getuser(),n.strftime(\"%d%m%y\"),n.strftime(\"%H%M%S\"))";
879   //
880   YACS::ENGINE::AutoPyRef func(YACS::ENGINE::evalPy(EFXGenFileName,EFXGenContent));
881   YACS::ENGINE::AutoPyRef val(YACS::ENGINE::evalFuncPyWithNoParams(func));
882   _locSchemaFile=PyString_AsString(val);
883   func=YACS::ENGINE::evalPy(EFXGenFileName,EFXGenContent2);
884   val=YACS::ENGINE::evalFuncPyWithNoParams(func);
885   _jobName=PyString_AsString(val);
886   //
887   static const char LISTPYOBJ_STR[]="list[pyobj]";
888   if(getBoss()->getOutputsOfInterest().empty())
889     return ;
890   YACS::ENGINE::RuntimeSALOME::setRuntime();
891   YACS::ENGINE::RuntimeSALOME *r(YACS::ENGINE::getSALOMERuntime());
892   _generatedGraph=r->createProc(DFT_PROC_NAME);
893   YACS::ENGINE::TypeCode *pyobjTC(_generatedGraph->createInterfaceTc("python:obj:1.0","pyobj",std::list<YACS::ENGINE::TypeCodeObjref *>()));
894   std::ostringstream oss; oss << "Loop_" << getBoss()->getRunNode()->getName();
895   _generatedGraph->createType(YACSEvalAnyDouble::TYPE_REPR,"double");
896   _generatedGraph->createType(YACSEvalAnyInt::TYPE_REPR,"int");
897   //
898   YACS::ENGINE::InlineNode *n0(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,"__initializer__"));
899   _generatedGraph->edAddChild(n0);
900   YACS::ENGINE::TypeCode *listPyobjTC(_generatedGraph->createSequenceTc(LISTPYOBJ_STR,LISTPYOBJ_STR,pyobjTC));
901   YACS::ENGINE::OutputPort *sender(n0->edAddOutputPort("sender",listPyobjTC));
902   std::ostringstream var0;
903   const std::vector< YACSEvalInputPort >& inputs(getBoss()->getInputs());
904   for(std::vector< YACSEvalInputPort >::const_iterator it=inputs.begin();it!=inputs.end();it++)
905     {
906       if((*it).isRandomVar())
907         {
908           var0 << (*it).getName() << ",";
909           YACS::ENGINE::TypeCode *tc(YACSEvalYFXPattern::CreateSeqTypeCodeFrom(_generatedGraph,(*it).getTypeOfData()));
910           YACS::ENGINE::InputPort *inp(n0->edAddInputPort((*it).getName(),tc));
911           YACS::ENGINE::InputPyPort *inpc(dynamic_cast<YACS::ENGINE::InputPyPort *>(inp));
912           if(!inpc)
913             throw YACS::Exception("YACSEvalYFXRunOnlyPattern::generateGraph : internal error 1 !");
914           (*it).setUndergroundPortToBeSet(inpc);
915         }
916     }
917   std::ostringstream n0Script; n0Script << "sender=zip(" << var0.str() << ")\n";
918   n0->setScript(n0Script.str());
919   //
920   YACS::ENGINE::ForEachLoop *n1(r->createForEachLoop(oss.str(),pyobjTC));
921   _FEInGeneratedGraph=n1;
922   _generatedGraph->edAddChild(n1);
923   _generatedGraph->edAddCFLink(n0,n1);
924   _generatedGraph->edAddDFLink(sender,n1->edGetSeqOfSamplesPort());
925   YACS::ENGINE::InlineNode *n2(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,GATHER_NODE_NAME));
926   _generatedGraph->edAddChild(n2);
927   _generatedGraph->edAddCFLink(n1,n2);
928   //
929   YACS::ENGINE::Bloc *n10(r->createBloc(FIRST_FE_SUBNODE_NAME));
930   n1->edAddChild(n10);
931   YACS::ENGINE::InlineNode *n100(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,"__dispatch__"));
932   YACS::ENGINE::ComposedNode *runNode(getBoss()->getRunNode());
933   YACS::ENGINE::Node *n101(runNode->cloneWithoutCompAndContDeepCpy(0,true));
934   n10->edAddChild(n100);
935   n10->edAddChild(n101);
936   YACS::ENGINE::InputPort *dispatchIn(n100->edAddInputPort("i0",pyobjTC));
937   n10->edAddCFLink(n100,n101);
938   n1->edAddDFLink(n1->edGetSamplePort(),dispatchIn);
939   std::ostringstream var1;
940   for(std::vector< YACSEvalInputPort >::const_iterator it=inputs.begin();it!=inputs.end();it++)
941     {
942       if((*it).isRandomVar())
943         {
944           var1 << (*it).getName() << ",";
945           YACS::ENGINE::OutputPort *myOut(n100->edAddOutputPort((*it).getName(),_generatedGraph->getTypeCode((*it).getTypeOfData())));
946           std::string tmpPortName(runNode->getInPortName((*it).getUndergroundPtr()));
947           YACS::ENGINE::InputPort *myIn(n101->getInputPort(tmpPortName));
948           n10->edAddDFLink(myOut,myIn);
949         }
950     }
951   std::ostringstream n100Script;  n100Script << var1.str() << "=i0\n";
952   n100->setScript(n100Script.str());
953   const std::vector<YACSEvalOutputPort *>& outputsOfInt(getBoss()->getOutputsOfInterest());
954   std::ostringstream n2Script; n2Script << "zeRes=[";
955   for(std::vector< YACSEvalOutputPort * >::const_iterator it=outputsOfInt.begin();it!=outputsOfInt.end();it++)
956     {
957       YACS::ENGINE::TypeCode *tc(YACSEvalYFXPattern::CreateSeqTypeCodeFrom(_generatedGraph,(*it)->getTypeOfData()));
958       YACS::ENGINE::InputPort *myIn(n2->edAddInputPort((*it)->getName(),tc));
959       n2Script << (*it)->getName() << ", ";
960       std::string tmpPortName(runNode->getOutPortName((*it)->getUndergroundPtr()));
961       YACS::ENGINE::OutputPort *myOut(n101->getOutputPort(tmpPortName));
962       _generatedGraph->edAddDFLink(myOut,myIn);
963     }
964   n2Script << "]\nf=file(\"" << _jobName << "\",\"w\") ; f.write(str(zeRes)) ; del f";
965   n2->setScript(n2Script.str());
966   _generatedGraph->updateContainersAndComponents();
967 }
968
969 bool YACSEvalYFXGraphGenCluster::go(const YACSEvalExecParams& params, YACSEvalSession *session) const
970 {
971   YACS::ENGINE::AutoGIL agil;
972   _errors = "";
973   getUndergroundGeneratedGraph()->saveSchema(_locSchemaFile);
974   YACSEvalListOfResources *rss(getBoss()->getResourcesInternal());
975   const YACSEvalParamsForCluster& cli(rss->getAddParamsForCluster());
976   std::vector<std::string> machines(rss->getAllChosenMachines());
977   if(machines.size()!=1)
978     throw YACS::Exception("YACSEvalYFXGraphGenCluster::go : internal error ! In batch mode and not exactly one machine !");
979   Engines::SalomeLauncher_var sl(session->getInternal()->goFetchingSalomeLauncherInNS());
980   Engines::ResourceParameters rr;
981   rr.name=CORBA::string_dup(machines[0].c_str());
982   rr.hostname=CORBA::string_dup("");
983   rr.can_launch_batch_jobs=true;
984   rr.can_run_containers=true;
985   rr.OS=CORBA::string_dup("Linux");
986   rr.componentList.length(0);
987   rr.nb_proc=rss->getNumberOfProcsDeclared();// <- important
988   rr.mem_mb=1024;
989   rr.cpu_clock=1000;
990   rr.nb_node=1;// useless only nb_proc used.
991   rr.nb_proc_per_node=1;// useless only nb_proc used.
992   rr.policy=CORBA::string_dup("cycl");
993   rr.resList.length(0);
994   Engines::JobParameters jp;
995   jp.job_name=CORBA::string_dup(_jobName.c_str());
996   jp.job_type=CORBA::string_dup("yacs_file");
997   jp.job_file=CORBA::string_dup(_locSchemaFile.c_str());
998   jp.env_file=CORBA::string_dup("");
999   jp.in_files.length(cli.getInFiles().size());
1000   std::list<std::string>::const_iterator it;
1001   int i;
1002   for (it = cli.getInFiles().begin(), i=0 ;
1003        it != cli.getInFiles().end();
1004        it++, i++)
1005   {
1006     jp.in_files[i] = CORBA::string_dup((*it).c_str());
1007   }
1008   jp.out_files.length(1);
1009   jp.out_files[0]=CORBA::string_dup(_jobName.c_str());
1010   jp.work_directory=CORBA::string_dup(cli.getRemoteWorkingDir().c_str());
1011   jp.local_directory=CORBA::string_dup(cli.getLocalWorkingDir().c_str());
1012   jp.result_directory=CORBA::string_dup(cli.getLocalWorkingDir().c_str());
1013   jp.maximum_duration=CORBA::string_dup(cli.getMaxDuration().c_str());
1014   jp.resource_required=rr;
1015   jp.queue=CORBA::string_dup("");
1016   jp.exclusive=false;
1017   jp.mem_per_cpu=rr.mem_mb;
1018   jp.wckey=CORBA::string_dup(cli.getWCKey().c_str());
1019   jp.extra_params=CORBA::string_dup("");
1020   jp.specific_parameters.length(0);
1021   jp.launcher_file=CORBA::string_dup("");
1022   jp.launcher_args=CORBA::string_dup("");
1023   _jobid=sl->createJob(jp);
1024   try
1025   {
1026     sl->launchJob(_jobid);
1027   }
1028   catch (const SALOME::SALOME_Exception & ex)
1029   {
1030     _errors = ex.details.text.in();
1031     return false;
1032   }
1033   catch (const CORBA::SystemException& ex)
1034   {
1035     _errors = "Receive CORBA SystemException.";
1036     return false;
1037   }
1038
1039   bool ret(false);
1040   while(true)
1041     {
1042       PyRun_SimpleString("import time ; time.sleep(10)");
1043       char *state(sl->getJobState(_jobid));//"CREATED", "IN_PROCESS", "QUEUED", "RUNNING", "PAUSED", "FINISHED" or "FAILED"
1044       std::string sstate(state);
1045       CORBA::string_free(state);
1046       if(sstate=="FINISHED" || sstate=="FAILED")
1047         {
1048           ret=sstate=="FINISHED";
1049           break;
1050         }
1051     }
1052   sl->getJobResults(_jobid,cli.getLocalWorkingDir().c_str());
1053   //
1054   try
1055     {
1056       std::ostringstream oss; oss << "import os" << std::endl << "p=os.path.join(\"" << cli.getLocalWorkingDir() << "\",\"" << _jobName  << "\")" << std::endl;
1057       oss << "if not os.path.exists(p):\n  return None\n";
1058       oss << "f=file(p,\"r\")" << std::endl;
1059       oss << "return eval(f.read())";
1060       std::string zeInput(oss.str());
1061       YACS::ENGINE::AutoPyRef func(YACS::ENGINE::evalPy("fetch",zeInput));
1062       YACS::ENGINE::AutoPyRef val(YACS::ENGINE::evalFuncPyWithNoParams(func));
1063       if(!PyList_Check(val))
1064         throw YACS::Exception("Fetched file does not contain a list !");
1065       Py_ssize_t sz(PyList_Size(val));
1066       _res.resize(sz);
1067       for(Py_ssize_t i=0;i<sz;i++)
1068         {
1069           std::vector<double>& res0(_res[i]);
1070           PyObject *elt0(PyList_GetItem(val,i));
1071           if(!PyList_Check(elt0))
1072             throw YACS::Exception("Fetched file does contain a list of list !");
1073           Py_ssize_t sz0(PyList_Size(elt0)); res0.resize(sz0);
1074           for(Py_ssize_t j=0;j<sz0;j++)
1075             {
1076               PyObject *elt1(PyList_GetItem(elt0,j));
1077               res0[j]=PyFloat_AsDouble(elt1);
1078             }
1079         }
1080       // cleanup
1081       std::ostringstream oss1; oss1 << "import os" << std::endl << "p=os.path.join(\"" << cli.getLocalWorkingDir() << "\",\"" << _jobName  << "\") ; os.remove(p)" << std::endl;
1082       std::string s1(oss1.str());
1083       PyRun_SimpleString(s1.c_str());
1084       if(!params.getFetchRemoteDirForClusterStatus())
1085         {
1086           std::ostringstream oss2; oss2 << "import os,shutil" << std::endl << "p=os.path.join(\"" << cli.getLocalWorkingDir() << "\",\"logs\") ; shutil.rmtree(p)" << std::endl;
1087           std::string s2(oss2.str());
1088           PyRun_SimpleString(s2.c_str());
1089         }
1090     }
1091   catch(YACS::Exception& e)
1092     {
1093       _errors=e.what();
1094       return false;
1095     }
1096   //
1097   return ret;
1098 }
1099
1100 std::string YACSEvalYFXGraphGenCluster::getErrors()const
1101 {
1102   return _errors;
1103 }
1104
1105 std::vector<YACSEvalSeqAny *> YACSEvalYFXGraphGenCluster::getResults() const
1106 {
1107   std::size_t sz(_res.size());
1108   std::vector<YACSEvalSeqAny *> ret(sz);
1109   for(std::size_t i=0;i<sz;i++)
1110     {
1111       YACS::AutoCppPtr<YACSEvalSeqAnyDouble> elt(new YACSEvalSeqAnyDouble(_res[i]));
1112       ret[i]=elt.dettach();
1113     }
1114   return ret;
1115 }