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