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