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