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