Salome HOME
A useful getName method on evalyfx virtual container.
[modules/yacs.git] / src / evalyfx / YACSEvalResource.cxx
1 // Copyright (C) 2012-2015  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 "YACSEvalResource.hxx"
22
23 #include "DeploymentTree.hxx"
24 #include "Container.hxx"
25 #include "Exception.hxx"
26
27 #include "SalomeContainer.hxx"
28 #include "SalomeHPContainer.hxx"
29 #include "ComponentInstance.hxx"
30
31 #include "ResourcesManager.hxx"
32
33 #include <set>
34 #include <queue>
35 #include <sstream>
36 #include <iterator>
37 #include <algorithm>
38
39 const char YACSEvalVirtualYACSContainer::CONTAINER_NAME_KEY[]="container_name";
40
41 const char YACSEvalVirtualYACSContainer::CPU_CLOCK_KEY[]="cpu_clock";
42
43 const char YACSEvalVirtualYACSContainer::HOSTNAME_KEY[]="hostname";
44
45 const char YACSEvalVirtualYACSContainer::MEM_KEY[]="mem_mb";
46
47 const char YACSEvalVirtualYACSContainer::NB_NODE_KEY[]="nb_node";
48
49 const char YACSEvalVirtualYACSContainer::NB_PROC_PER_NODE_KEY[]="nb_proc_per_node";
50
51 const char YACSEvalVirtualYACSContainer::NB_RESOURCE_PROCS_KEY[]="nb_resource_procs";
52
53 const char YACSEvalVirtualYACSContainer::POLICY_KEY[]="policy";
54
55 const char YACSEvalVirtualYACSContainer::OS_KEY[]="OS";
56
57 /*!
58  * This class is here only to avoid "friend class YACSEvalListOfResources".
59  */
60 class YACSEvalResourceEff : public YACSEvalResource
61 {
62 public:
63   YACSEvalResourceEff(YACSEvalListOfResources *gf, const std::vector< YACS::ENGINE::Container * >& conts);
64 };
65
66 YACSEvalResourceEff::YACSEvalResourceEff(YACSEvalListOfResources *gf, const std::vector< YACS::ENGINE::Container * >& conts):YACSEvalResource(gf,conts)
67 {
68 }
69
70 void YACSEvalNonConstLocker::checkNonLocked() const
71 {
72   if(_isLocked)
73     throw YACS::Exception("YACSEvalNonConstLocker::checkNonLocked : this is locked and trying to invoke non-const method !");
74 }
75
76 YACSEvalVirtualYACSContainer::YACSEvalVirtualYACSContainer():_gf(0),_cont(0)
77 {
78 }
79
80 void YACSEvalVirtualYACSContainer::set(YACSEvalResource *gf, YACS::ENGINE::Container *cont)
81 {
82   checkNonLocked();
83   _gf=gf;
84   if(_cont==cont)
85     return ;
86   if(_cont)
87     _cont->decrRef();
88   _cont=cont;
89   if(_cont)
90     _cont->incrRef();
91   _propertyMap=listOfPropertiesInYACSContainer();
92 }
93
94 YACSEvalVirtualYACSContainer::YACSEvalVirtualYACSContainer(YACSEvalResource *gf, YACS::ENGINE::Container *cont):_gf(gf),_cont(cont)
95 {
96   if(_cont)
97     _cont->incrRef();
98   _propertyMap=listOfPropertiesInYACSContainer();
99 }
100
101 YACSEvalVirtualYACSContainer::~YACSEvalVirtualYACSContainer()
102 {
103   if(_cont)
104     _cont->decrRef();
105 }
106
107 /*!
108  * \param [in,out] entry - Resource type instance to be updated with \a this.
109  */
110 void YACSEvalVirtualYACSContainer::aggregate(ParserResourcesType& entry) const
111 {
112   if(entry.HostName.empty())
113     entry.HostName=getHostName();
114   entry.DataForSort._memInMB=std::max(entry.DataForSort._memInMB,getMem());
115   entry.DataForSort._nbOfProcPerNode=std::max(entry.DataForSort._nbOfProcPerNode,getNbProcPerNode());
116   entry.DataForSort._nbOfNodes=std::max(entry.DataForSort._nbOfNodes,getNbNodes());
117   entry.DataForSort._CPUFreqMHz=std::max(entry.DataForSort._CPUFreqMHz,getCPUFreq());
118   std::vector<YACS::ENGINE::ComponentInstance *> comps(_gf->getGodFather()->getDeploymentTree()->getComponentsLinkedToContainer(_cont));
119   std::set<std::string> compNames;
120   for(std::vector<YACS::ENGINE::ComponentInstance *>::const_iterator it=comps.begin();it!=comps.end();it++)
121     {
122       YACS::ENGINE::ComponentInstance *elt(*it);
123       if(elt)
124         compNames.insert(elt->getCompoName());
125     }
126   compNames.insert(entry.ComponentsList.begin(),entry.ComponentsList.end());
127   compNames.erase(std::string());
128   std::vector<std::string> compNames2(compNames.begin(),compNames.end());
129   entry.ComponentsList=compNames2;
130 }
131
132 std::string YACSEvalVirtualYACSContainer::findDefault(bool isInteractive) const
133 {
134   std::vector<std::string> possibleHosts(_gf->getAllFittingMachines());
135   for(std::vector<std::string>::const_iterator it=possibleHosts.begin();it!=possibleHosts.end();it++)
136     {
137       if(_gf->getGodFather()->hasRightInteractiveStatus(*it,isInteractive))
138         return *it;
139     }
140   throw YACS::Exception("YACSEvalVirtualYACSContainer::findDefault : impossible to find a right machine with requested interactive status !");
141 }
142
143 void YACSEvalVirtualYACSContainer::setWantedMachine(const std::string& machine)
144 {
145   checkNonLocked();
146   std::vector<std::string> possibleHosts(_gf->getAllFittingMachines());
147   if(std::find(possibleHosts.begin(),possibleHosts.end(),machine)==possibleHosts.end())
148     throw YACS::Exception("YACSEvalVirtualYACSContainer::setWantedMachine : the specified machine is not in the list of available !");
149   std::string oldMachine(getChosenMachine());
150   setMachineNoCheck(machine);
151   try
152   {
153       _gf->notifyWantedMachine(this,oldMachine,machine);
154   }
155   catch(YACS::Exception& e)
156   {
157       setMachineNoCheck(oldMachine);
158       throw e;
159   }
160 }
161
162 std::vector<std::string> YACSEvalVirtualYACSContainer::listOfPropertyKeys() const
163 {
164   std::set<std::string> s;
165   std::map<std::string,std::string>::const_iterator it;
166   for(it=_overloadedPropertyMap.begin();it!=_overloadedPropertyMap.end();it++)
167     s.insert((*it).first);
168   for(it=_propertyMap.begin();it!=_propertyMap.end();it++)
169     s.insert((*it).first);
170   std::vector<std::string> ret(s.begin(),s.end());
171   return ret;
172 }
173
174 std::string YACSEvalVirtualYACSContainer::getValueOfKey(const char *key) const
175 {
176   std::map<std::string,std::string>::const_iterator it;
177   it=_overloadedPropertyMap.find(key);
178   if(it!=_overloadedPropertyMap.end())
179     return (*it).second;
180   it=_propertyMap.find(key);
181   if(it!=_propertyMap.end())
182     return (*it).second;
183   return std::string();
184 }
185
186 void YACSEvalVirtualYACSContainer::setProperty(const std::string& key, const std::string &value)
187 {
188   checkNonLocked();
189   _overloadedPropertyMap[key]=value;
190 }
191
192 void YACSEvalVirtualYACSContainer::apply()
193 {
194   YACS::ENGINE::SalomeContainer *cont0(dynamic_cast<YACS::ENGINE::SalomeContainer *>(_cont));
195   YACS::ENGINE::SalomeHPContainer *cont1(dynamic_cast<YACS::ENGINE::SalomeHPContainer *>(_cont));
196   if(cont0)
197     {
198       cont0->setProperty(HOSTNAME_KEY,getValueOfKey(HOSTNAME_KEY));
199       return ;
200     }
201   else if(cont1)
202     {
203       cont1->setProperty(HOSTNAME_KEY,getValueOfKey(HOSTNAME_KEY));
204       return ;
205     }
206   else
207     throw YACS::Exception("YACSEvalVirtualYACSContainer::apply : unrecognized container !");
208 }
209
210 std::string YACSEvalVirtualYACSContainer::getName() const
211 {
212   checkNotNullYACSContainer();
213   return _cont->getName();
214 }
215
216 unsigned int YACSEvalVirtualYACSContainer::getValueOfKeyUInt(const char *key) const
217 {
218   std::string v(getValueOfKey(key));
219   unsigned int ret(0);
220   if(v.empty())
221     return ret;
222   std::istringstream iss(v);
223   iss >> ret;
224   return ret;
225 }
226
227 std::map<std::string,std::string> YACSEvalVirtualYACSContainer::listOfPropertiesInYACSContainer() const
228 {
229   YACS::ENGINE::SalomeContainer *cont0(dynamic_cast<YACS::ENGINE::SalomeContainer *>(_cont));
230   YACS::ENGINE::SalomeHPContainer *cont1(dynamic_cast<YACS::ENGINE::SalomeHPContainer *>(_cont));
231   std::map<std::string,std::string> props;
232   if(cont0)
233     props=cont0->getProperties();
234   else if(cont1)
235     props=cont1->getProperties();
236   return props;
237 }
238
239 void YACSEvalVirtualYACSContainer::checkNotNullYACSContainer() const
240 {
241   if(!_cont)
242     throw YACS::Exception("YACSEvalVirtualYACSContainer::checkNotNullYACSContainer : internal YACS container is NULL !");
243 }
244
245 YACSEvalResource::~YACSEvalResource()
246 {
247 }
248
249 std::vector<std::string> YACSEvalResource::getAllChosenMachines() const
250 {
251   std::set<std::string> s;
252   for(std::vector< YACSEvalVirtualYACSContainer >::const_iterator it=_containers.begin();it!=_containers.end();it++)
253     s.insert((*it).getChosenMachine());
254   std::vector<std::string> ret(s.begin(),s.end());
255   return ret;
256 }
257
258 std::vector<std::string> YACSEvalResource::getAllFittingMachines() const
259 {
260   ParserResourcesType ref;
261   aggregate(ref);
262   return _gf->getFittingResources(&ref);
263 }
264
265 void YACSEvalResource::setWantedMachine(const std::string& machine)
266 {
267   checkNonLocked();
268   std::vector<std::string> possibleHosts(getAllFittingMachines());
269   if(std::find(possibleHosts.begin(),possibleHosts.end(),machine)==possibleHosts.end())
270     throw YACS::Exception("YACSEvalResource::setWantedMachine : the specified machine is not in the list of available !");
271   for(std::vector< YACSEvalVirtualYACSContainer >::iterator it=_containers.begin();it!=_containers.end();it++)
272     (*it).setMachineNoCheck(machine);
273 }
274
275 YACSEvalVirtualYACSContainer *YACSEvalResource::at(std::size_t i) const
276 {
277   if(i>=_containers.size())
278     throw YACS::Exception("YACSEvalResource::at : invalid input ! must be < size !");
279   return const_cast<YACSEvalVirtualYACSContainer *>(&_containers[i]);
280 }
281
282 void YACSEvalResource::apply()
283 {
284   for(std::vector< YACSEvalVirtualYACSContainer >::iterator it=_containers.begin();it!=_containers.end();it++)
285     (*it).apply();
286 }
287
288 void YACSEvalResource::fitWithCurrentCatalogAbs()
289 {
290   std::vector<std::string> ress(getAllFittingMachines());
291   if(ress.empty())
292     throw YACS::Exception("YACSEvalResource::fitWithCurrentCatalogAbs : no suitable host in your catalog of resource !");
293   setMachineNoCheck(ress.front());
294 }
295
296 void YACSEvalResource::aggregate(ParserResourcesType& entry) const
297 {
298   for(std::vector< YACSEvalVirtualYACSContainer >::const_iterator it=_containers.begin();it!=_containers.end();it++)
299     (*it).aggregate(entry);
300 }
301
302 void YACSEvalResource::notifyWantedMachine(YACSEvalVirtualYACSContainer *sender, const std::string& oldMachine, const std::string& newMachine)
303 {
304   _gf->notifyWantedMachine(sender,oldMachine,newMachine);
305 }
306
307 void YACSEvalResource::setMachineNoCheck(const std::string& machine)
308 {
309   for(std::vector< YACSEvalVirtualYACSContainer >::iterator it=_containers.begin();it!=_containers.end();it++)
310     (*it).setMachineNoCheck(machine);
311 }
312
313 YACSEvalResource::YACSEvalResource(YACSEvalListOfResources *gf, const std::vector< YACS::ENGINE::Container * >& conts):_gf(gf)
314 {
315   std::size_t sz(conts.size());
316   _containers.resize(sz);
317   for(std::size_t i=0;i<sz;i++)
318     _containers[i].set(this,conts[i]);
319 }
320
321 YACSEvalListOfResources::YACSEvalListOfResources(int maxLevOfPara, ResourcesManager_cpp *rm, const YACS::ENGINE::DeploymentTree& dt):_maxLevOfPara(maxLevOfPara),_rm(rm),_dt(new YACS::ENGINE::DeploymentTree(dt))
322 {
323   std::vector<YACS::ENGINE::Container *> conts(_dt->getAllContainers());
324   std::map<std::string, std::vector<YACS::ENGINE::Container *> > listOfHosts;
325   for(std::vector<YACS::ENGINE::Container *>::const_iterator it=conts.begin();it!=conts.end();it++)
326     {
327       std::vector<YACS::ENGINE::ComponentInstance *> cis(dt.getComponentsLinkedToContainer(*it));
328       YACS::ENGINE::SalomeContainer *c1(dynamic_cast<YACS::ENGINE::SalomeContainer *>(*it));
329       YACS::ENGINE::SalomeHPContainer *c2(dynamic_cast<YACS::ENGINE::SalomeHPContainer *>(*it));
330       std::string zeHost;
331       if(c1)
332         zeHost=c1->getProperty(YACSEvalVirtualYACSContainer::HOSTNAME_KEY);
333       if(c2)
334         zeHost=c2->getProperty(YACSEvalVirtualYACSContainer::HOSTNAME_KEY);
335       listOfHosts[zeHost].push_back(*it);
336     }
337   for(std::map<std::string, std::vector<YACS::ENGINE::Container *> >::const_iterator it=listOfHosts.begin();it!=listOfHosts.end();it++)
338     _resources.push_back(new YACSEvalResourceEff(this,(*it).second));
339   fitWithCurrentCatalog();
340 }
341
342 std::vector<std::string> YACSEvalListOfResources::getAllChosenMachines() const
343 {
344   std::set<std::string> s;
345   for(std::vector<YACSEvalResource *>::const_iterator it=_resources.begin();it!=_resources.end();it++)
346     {
347       std::vector<std::string> tmp((*it)->getAllChosenMachines());
348       s.insert(tmp.begin(),tmp.end());
349     }
350   std::vector<std::string> ret(s.begin(),s.end());
351   return ret;
352 }
353
354 std::vector<std::string> YACSEvalListOfResources::getAllFittingMachines() const
355 {
356   ParserResourcesType ref;
357   for(std::vector<YACSEvalResource *>::const_iterator it=_resources.begin();it!=_resources.end();it++)
358     (*it)->aggregate(ref);
359   return getFittingResources(&ref);
360 }
361
362 void YACSEvalListOfResources::setWantedMachine(const std::string& machine)
363 {
364   checkNonLocked();
365   std::vector<std::string> possibleHosts(getAllFittingMachines());
366   if(std::find(possibleHosts.begin(),possibleHosts.end(),machine)==possibleHosts.end())
367     throw YACS::Exception("YACSEvalResource::setWantedMachine : the specified machine is not in the list of available !");
368   for(std::vector<YACSEvalResource *>::iterator it=_resources.begin();it!=_resources.end();it++)
369     (*it)->setMachineNoCheck(machine);
370 }
371
372 YACSEvalResource *YACSEvalListOfResources::at(std::size_t i) const
373 {
374   if(i>=size())
375     throw YACS::Exception("YACSEvalListOfResources::at : invalid id !");
376   return _resources[i];
377 }
378
379 bool YACSEvalListOfResources::isInteractive() const
380 {
381   const MapOfParserResourcesType& zeList(_rm->GetList());
382   std::vector<std::string> allMachines(getAllChosenMachines());
383   if(allMachines.empty())
384     return true;
385   std::size_t ii(0),sz(allMachines.size());
386   std::vector<bool> status(sz);
387   for(std::vector<std::string>::const_iterator it=allMachines.begin();it!=allMachines.end();it++,ii++)
388     {
389       std::map<std::string, ParserResourcesType>::const_iterator it2(zeList.find(*it));
390       if(it2==zeList.end())
391         {
392           std::ostringstream oss; oss << "YACSEvalListOfResources::isInteractive : presence of non existing \"" << *it << "\" !";
393           throw YACS::Exception(oss.str());
394         }
395       const ParserResourcesType& elt((*it2).second);
396       status[ii]=(elt.ClusterInternalProtocol==sh || elt.ClusterInternalProtocol==rsh || elt.ClusterInternalProtocol==ssh);
397     }
398   std::size_t trueRet(std::count(status.begin(),status.end(),true)),falseRet(std::count(status.begin(),status.end(),false));
399   if(trueRet==sz && falseRet==0)
400     return true;
401   else if(trueRet==0 && falseRet==sz)
402     return false;
403   throw YACS::Exception("YACSEvalListOfResources::isInteractive : mix of interactive and non interactive ! internal error !");
404 }
405
406 unsigned int YACSEvalListOfResources::getNumberOfProcsDeclared() const
407 {
408   std::vector<std::string> chosen(getAllChosenMachines());
409   unsigned int ret(0);
410   for(std::vector<std::string>::const_iterator it=chosen.begin();it!=chosen.end();it++)
411     ret+=getNumberOfProcOfResource(*it);
412   return ret;
413 }
414
415 void YACSEvalListOfResources::apply()
416 {
417   for(std::vector<YACSEvalResource *>::iterator it=_resources.begin();it!=_resources.end();it++)
418     (*it)->apply();
419 }
420
421 YACSEvalListOfResources::~YACSEvalListOfResources()
422 {
423   delete _dt;
424   for(std::vector<YACSEvalResource *>::iterator it=_resources.begin();it!=_resources.end();it++)
425     delete *it;
426 }
427
428 class EffectiveComparator
429 {
430 public:
431   virtual ~EffectiveComparator() { }
432   virtual EffectiveComparator *copy() const = 0;
433   virtual bool compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const = 0;
434 };
435
436 // comparator for a null request in scheme
437 class BasicComparator : public EffectiveComparator
438 {
439 public:
440   EffectiveComparator *copy() const { return new BasicComparator; }
441   bool compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const;
442 };
443
444 class MemAwareComparator : public EffectiveComparator
445 {
446 public:
447   EffectiveComparator *copy() const { return new MemAwareComparator; }
448   bool compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const;
449 };
450
451 class CompromiseComparator : public EffectiveComparator
452 {
453 public:
454   CompromiseComparator(int memMB, int nbProcs):_memMB(memMB),_nbProcs(nbProcs) { }
455   EffectiveComparator *copy() const { return new CompromiseComparator(_memMB,_nbProcs); }
456   bool compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const;
457 private:
458   int _memMB;
459   int _nbProcs;
460 };
461
462 class CompareRes
463 {
464 public:
465   CompareRes(const ParserResourcesType *request, const MapOfParserResourcesType& zeCatalog);
466   CompareRes(const CompareRes& other);
467   bool operator()(const std::string& res1, const std::string& res2);
468   ~CompareRes() { delete _comp; }
469 private:
470   EffectiveComparator *_comp;
471   const ParserResourcesType *_request;
472   const MapOfParserResourcesType& _zeCatalog;
473 };
474
475 bool BasicComparator::compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const
476 {
477   int nbOfProcs1(elt1._nbOfNodes*elt1._nbOfProcPerNode),nbOfProcs2(elt2._nbOfNodes*elt2._nbOfProcPerNode);
478   return nbOfProcs1<nbOfProcs2;
479 }
480
481 bool MemAwareComparator::compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const
482 {
483   return elt1._memInMB<elt2._memInMB;
484 }
485
486 bool CompromiseComparator::compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const
487 {
488   double v1a(elt1._memInMB/_memMB),v1b(elt1._nbOfNodes*elt1._nbOfProcPerNode/_nbProcs);
489   double v2a(elt2._memInMB/_memMB),v2b(elt2._nbOfNodes*elt2._nbOfProcPerNode/_nbProcs);
490   return std::min(v1a,v1b)<std::min(v2a,v2b);
491 }
492
493 CompareRes::CompareRes(const ParserResourcesType *request, const MapOfParserResourcesType& zeCatalog):_comp(0),_request(request),_zeCatalog(zeCatalog)
494 {
495   const ResourceDataToSort& tmp(_request->DataForSort);
496   // all request items are set to default -> Basic comparison on procs
497   if(request->DataForSort._nbOfNodes==1 && request->DataForSort._nbOfProcPerNode==1 && request->DataForSort._memInMB==0)
498     _comp=new BasicComparator;
499   // all items are set to default except memory -> Memory aware only
500   else if(request->DataForSort._memInMB!=0 && request->DataForSort._nbOfNodes==1 && request->DataForSort._nbOfProcPerNode==1)
501     _comp=new MemAwareComparator;
502   // memory and procs are set by the user -> do the best possible.
503   else if(request->DataForSort._memInMB!=0 && ( request->DataForSort._nbOfNodes!=1 || request->DataForSort._nbOfProcPerNode!=1 ) )
504     _comp=new CompromiseComparator(request->DataForSort._memInMB,request->DataForSort._nbOfNodes*request->DataForSort._nbOfProcPerNode);
505   else
506     _comp=new BasicComparator;
507 }
508
509 CompareRes::CompareRes(const CompareRes& other):_comp(other._comp->copy()),_request(other._request),_zeCatalog(other._zeCatalog)
510 {
511 }
512
513 bool CompareRes::operator()(const std::string& res1, const std::string& res2)
514 {
515   std::map<std::string, ParserResourcesType>::const_iterator it1(_zeCatalog.find(res1)),it2(_zeCatalog.find(res2));
516   if(it1==_zeCatalog.end() || it2==_zeCatalog.end())
517     throw YACS::Exception("Internal error during comparison !");
518   const ParserResourcesType& elt1((*it1).second);
519   const ParserResourcesType& elt2((*it2).second);
520   return _comp->compare(elt1.DataForSort,elt2.DataForSort);
521 }
522
523 /*!
524  * Implements an another alg than those proposed by default in ResourcesManager_cpp in "ResourcesManager.hxx".
525  */
526 std::vector<std::string> YACSEvalListOfResources::getFittingResources(ParserResourcesType *request) const
527 {
528   int mlop(getMaxLevelOfParallelism());
529   request->DataForSort._memInMB*=mlop;
530   request->DataForSort._nbOfNodes*=mlop;
531   //
532   const MapOfParserResourcesType& zeListInCatalog(_rm->GetList());
533   std::vector<std::string> list0;
534   // first keep those having relevant components
535   const std::vector<std::string>& listExpected(request->ComponentsList);
536   std::set<std::string> listExpected2(listExpected.begin(),listExpected.end());
537   for(std::map<std::string, ParserResourcesType>::const_iterator it=zeListInCatalog.begin();it!=zeListInCatalog.end();it++)
538     {
539       const std::vector<std::string>& compoList((*it).second.ComponentsList);
540       std::set<std::string> s1(compoList.begin(),compoList.end());
541       std::vector<std::string> diff;
542       std::set_difference(listExpected2.begin(),listExpected2.end(),s1.begin(),s1.end(),std::inserter(diff,diff.begin()));
543       if(diff.empty())
544         list0.push_back((*it).first);
545     }
546   // sort list0 regarding request
547   std::sort(list0.begin(),list0.end(),CompareRes(request,zeListInCatalog));
548   // if HostName in request is defined and in list0 put it first.
549   std::string tmp(request->HostName);
550   if(!tmp.empty())
551     {
552       std::vector<std::string>::iterator it1(std::find(list0.begin(),list0.end(),tmp));
553       if(it1!=list0.end())
554         {// HostName in list0 so put it in first place.
555           list0.erase(it1);
556           list0.insert(list0.begin(),tmp);
557         }
558     }
559   return list0;
560 }
561
562 void YACSEvalListOfResources::notifyWantedMachine(YACSEvalVirtualYACSContainer *sender, const std::string& oldMachine, const std::string& newMachine)
563 {
564   const MapOfParserResourcesType& zeList(_rm->GetList());
565   std::map<std::string, ParserResourcesType>::const_iterator itOld(zeList.find(oldMachine)),itNew(zeList.find(newMachine));
566   if(itOld==zeList.end() || itNew==zeList.end())
567     throw YACS::Exception("YACSEvalListOfResources::notifyWantedMachine : internal error !");
568   const ParserResourcesType& oldPRT((*itOld).second);
569   const ParserResourcesType& newPRT((*itNew).second);
570   if(oldPRT.ClusterInternalProtocol==newPRT.ClusterInternalProtocol)
571     return ;
572   // the batch/interactive mode has changed -> try to change for all.
573   std::queue<std::string> sts;
574   try
575   {
576       for(std::vector<YACSEvalResource *>::const_iterator it=_resources.begin();it!=_resources.end();it++)
577         {
578           std::size_t sz((*it)->size());
579           for(std::size_t i=0;i<sz;i++)
580             {
581               YACSEvalVirtualYACSContainer *cont((*it)->at(i));
582               if(cont==sender)
583                 continue;
584               sts.push(cont->findDefault(newPRT.ClusterInternalProtocol==sh));
585             }
586         }
587   }
588   catch(YACS::Exception& e)
589   {
590       std::ostringstream oss; oss << "YACSEvalListOfResources::notifyWantedMachine : switching from interactive/batch must be global ! " << e.what();
591       throw YACS::Exception(oss.str());
592   }
593   for(std::vector<YACSEvalResource *>::const_iterator it=_resources.begin();it!=_resources.end();it++)
594     {
595       std::size_t sz((*it)->size());
596       for(std::size_t i=0;i<sz;i++)
597         {
598           YACSEvalVirtualYACSContainer *cont((*it)->at(i));
599           if(cont==sender)
600             continue;
601           cont->setMachineNoCheck(sts.front());
602           sts.pop();
603         }
604     }
605 }
606
607 bool YACSEvalListOfResources::hasRightInteractiveStatus(const std::string& machineToTest, bool isInteractive) const
608 {
609   const MapOfParserResourcesType& zeList(_rm->GetList());
610   std::map<std::string, ParserResourcesType>::const_iterator it(zeList.find(machineToTest));
611   if(it==zeList.end())
612     throw YACS::Exception("YACSEvalListOfResources::hasRightInteractiveStatus : internal error !");
613   const ParserResourcesType& elt((*it).second);
614   bool myStatus(elt.ClusterInternalProtocol==sh);
615   return myStatus==isInteractive;
616 }
617
618 void YACSEvalListOfResources::fitWithCurrentCatalog()
619 {
620   std::vector<std::string> ress(getAllFittingMachines());
621   if(ress.empty())
622     throw YACS::Exception("YACSEvalListOfResources::fitWithCurrentCatalog : no available resource in your catalog !");
623   for(std::vector<YACSEvalResource *>::iterator it=_resources.begin();it!=_resources.end();it++)
624     (*it)->setMachineNoCheck(ress.front());
625 }
626
627 unsigned int YACSEvalListOfResources::getNumberOfProcOfResource(const std::string& machine) const
628 {
629   const MapOfParserResourcesType& zeList(_rm->GetList());
630   std::map<std::string, ParserResourcesType>::const_iterator it(zeList.find(machine));
631   if(it==zeList.end())
632     throw YACS::Exception("YACSEvalListOfResources::getNumberOfProcOfResource : internal error !");
633   const ParserResourcesType& PRT((*it).second);
634   const ResourceDataToSort& RDT(PRT.DataForSort);
635   unsigned int ret(RDT._nbOfNodes*RDT._nbOfProcPerNode);
636   return ret;
637 }