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