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