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