Salome HOME
b15c6a55812f6ccd94debea9fa82855831bb2081
[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(_wcKey.empty())
341     throw YACS::Exception("YACSEvalParamsForCluster::checkConsistency : WC key is not set !");
342   if(_nbOfProcs==0)
343     throw YACS::Exception("YACSEvalParamsForCluster::checkConsistency : nb procs must be != 0 !");
344 }
345
346 YACSEvalListOfResources::YACSEvalListOfResources(int maxLevOfPara, ResourcesManager_cpp *rm, const YACS::ENGINE::DeploymentTree& dt):_maxLevOfPara(maxLevOfPara),_rm(rm),_dt(new YACS::ENGINE::DeploymentTree(dt))
347 {
348   std::vector<YACS::ENGINE::Container *> conts(_dt->getAllContainers());
349   std::map<std::string, std::vector<YACS::ENGINE::Container *> > listOfHosts;
350   for(std::vector<YACS::ENGINE::Container *>::const_iterator it=conts.begin();it!=conts.end();it++)
351     {
352       std::vector<YACS::ENGINE::ComponentInstance *> cis(dt.getComponentsLinkedToContainer(*it));
353       YACS::ENGINE::SalomeContainer *c1(dynamic_cast<YACS::ENGINE::SalomeContainer *>(*it));
354       YACS::ENGINE::SalomeHPContainer *c2(dynamic_cast<YACS::ENGINE::SalomeHPContainer *>(*it));
355       std::string zeHost;
356       if(c1)
357         zeHost=c1->getProperty(YACSEvalVirtualYACSContainer::HOSTNAME_KEY);
358       if(c2)
359         zeHost=c2->getProperty(YACSEvalVirtualYACSContainer::HOSTNAME_KEY);
360       listOfHosts[zeHost].push_back(*it);
361     }
362   for(std::map<std::string, std::vector<YACS::ENGINE::Container *> >::const_iterator it=listOfHosts.begin();it!=listOfHosts.end();it++)
363     _resources.push_back(new YACSEvalResourceEff(this,(*it).second));
364   fitWithCurrentCatalog();
365 }
366
367 std::vector<std::string> YACSEvalListOfResources::getAllChosenMachines() const
368 {
369   std::set<std::string> s;
370   for(std::vector<YACSEvalResource *>::const_iterator it=_resources.begin();it!=_resources.end();it++)
371     {
372       std::vector<std::string> tmp((*it)->getAllChosenMachines());
373       s.insert(tmp.begin(),tmp.end());
374     }
375   std::vector<std::string> ret(s.begin(),s.end());
376   return ret;
377 }
378
379 std::vector<std::string> YACSEvalListOfResources::getAllFittingMachines() const
380 {
381   ParserResourcesType ref;
382   for(std::vector<YACSEvalResource *>::const_iterator it=_resources.begin();it!=_resources.end();it++)
383     (*it)->aggregate(ref);
384   return getFittingResources(&ref);
385 }
386
387 void YACSEvalListOfResources::setWantedMachine(const std::string& machine)
388 {
389   checkNonLocked();
390   std::vector<std::string> possibleHosts(getAllFittingMachines());
391   if(std::find(possibleHosts.begin(),possibleHosts.end(),machine)==possibleHosts.end())
392     throw YACS::Exception("YACSEvalResource::setWantedMachine : the specified machine is not in the list of available !");
393   for(std::vector<YACSEvalResource *>::iterator it=_resources.begin();it!=_resources.end();it++)
394     (*it)->setMachineNoCheck(machine);
395 }
396
397 YACSEvalResource *YACSEvalListOfResources::at(std::size_t i) const
398 {
399   if(i>=size())
400     throw YACS::Exception("YACSEvalListOfResources::at : invalid id !");
401   return _resources[i];
402 }
403
404 bool YACSEvalListOfResources::isInteractive() const
405 {
406   const MapOfParserResourcesType& zeList(_rm->GetList());
407   std::vector<std::string> allMachines(getAllChosenMachines());
408   if(allMachines.empty())
409     return true;
410   std::size_t ii(0),sz(allMachines.size());
411   std::vector<bool> status(sz);
412   for(std::vector<std::string>::const_iterator it=allMachines.begin();it!=allMachines.end();it++,ii++)
413     {
414       std::map<std::string, ParserResourcesType>::const_iterator it2(zeList.find(*it));
415       if(it2==zeList.end())
416         {
417           std::ostringstream oss; oss << "YACSEvalListOfResources::isInteractive : presence of non existing \"" << *it << "\" !";
418           throw YACS::Exception(oss.str());
419         }
420       const ParserResourcesType& elt((*it2).second);
421       status[ii]=(elt.Batch==none);
422     }
423   std::size_t trueRet(std::count(status.begin(),status.end(),true)),falseRet(std::count(status.begin(),status.end(),false));
424   if(trueRet==sz && falseRet==0)
425     return true;
426   else if(trueRet==0 && falseRet==sz)
427     return false;
428   throw YACS::Exception("YACSEvalListOfResources::isInteractive : mix of interactive and non interactive ! internal error !");
429 }
430
431 unsigned int YACSEvalListOfResources::getNumberOfProcsDeclared() const
432 {
433   if(isInteractive())
434     {
435       std::vector<std::string> chosen(getAllChosenMachines());
436       unsigned int ret(0);
437       for(std::vector<std::string>::const_iterator it=chosen.begin();it!=chosen.end();it++)
438         ret+=getNumberOfProcOfResource(*it);
439       return ret;
440     }
441   else
442     return _paramsInCaseOfCluster.getNbProcs();
443 }
444
445 void YACSEvalListOfResources::checkOKForRun() const
446 {
447   if(!isInteractive())
448     _paramsInCaseOfCluster.checkConsistency();
449 }
450
451 void YACSEvalListOfResources::apply()
452 {
453   bool interactiveSt(isInteractive());
454   for(std::vector<YACSEvalResource *>::iterator it=_resources.begin();it!=_resources.end();it++)
455     (*it)->apply(interactiveSt);
456 }
457
458 YACSEvalListOfResources::~YACSEvalListOfResources()
459 {
460   delete _dt;
461   for(std::vector<YACSEvalResource *>::iterator it=_resources.begin();it!=_resources.end();it++)
462     delete *it;
463 }
464
465 class EffectiveComparator
466 {
467 public:
468   virtual ~EffectiveComparator() { }
469   virtual EffectiveComparator *copy() const = 0;
470   virtual bool compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const = 0;
471 };
472
473 // comparator for a null request in scheme
474 class BasicComparator : public EffectiveComparator
475 {
476 public:
477   EffectiveComparator *copy() const { return new BasicComparator; }
478   bool compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const;
479 };
480
481 class MemAwareComparator : public EffectiveComparator
482 {
483 public:
484   EffectiveComparator *copy() const { return new MemAwareComparator; }
485   bool compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const;
486 };
487
488 class CompromiseComparator : public EffectiveComparator
489 {
490 public:
491   CompromiseComparator(int memMB, int nbProcs):_memMB(memMB),_nbProcs(nbProcs) { }
492   EffectiveComparator *copy() const { return new CompromiseComparator(_memMB,_nbProcs); }
493   bool compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const;
494 private:
495   int _memMB;
496   int _nbProcs;
497 };
498
499 class CompareRes
500 {
501 public:
502   CompareRes(const ParserResourcesType *request, const MapOfParserResourcesType& zeCatalog);
503   CompareRes(const CompareRes& other);
504   bool operator()(const std::string& res1, const std::string& res2);
505   ~CompareRes() { delete _comp; }
506 private:
507   EffectiveComparator *_comp;
508   const ParserResourcesType *_request;
509   const MapOfParserResourcesType& _zeCatalog;
510 };
511
512 bool BasicComparator::compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const
513 {
514   int nbOfProcs1(elt1._nbOfNodes*elt1._nbOfProcPerNode),nbOfProcs2(elt2._nbOfNodes*elt2._nbOfProcPerNode);
515   return nbOfProcs1<nbOfProcs2;
516 }
517
518 bool MemAwareComparator::compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const
519 {
520   return elt1._memInMB<elt2._memInMB;
521 }
522
523 bool CompromiseComparator::compare(const ResourceDataToSort& elt1, const ResourceDataToSort& elt2) const
524 {
525   double v1a(elt1._memInMB/_memMB),v1b(elt1._nbOfNodes*elt1._nbOfProcPerNode/_nbProcs);
526   double v2a(elt2._memInMB/_memMB),v2b(elt2._nbOfNodes*elt2._nbOfProcPerNode/_nbProcs);
527   return std::min(v1a,v1b)<std::min(v2a,v2b);
528 }
529
530 CompareRes::CompareRes(const ParserResourcesType *request, const MapOfParserResourcesType& zeCatalog):_comp(0),_request(request),_zeCatalog(zeCatalog)
531 {
532   const ResourceDataToSort& tmp(_request->DataForSort);
533   // all request items are set to default -> Basic comparison on procs
534   if(request->DataForSort._nbOfNodes==1 && request->DataForSort._nbOfProcPerNode==1 && request->DataForSort._memInMB==0)
535     _comp=new BasicComparator;
536   // all items are set to default except memory -> Memory aware only
537   else if(request->DataForSort._memInMB!=0 && request->DataForSort._nbOfNodes==1 && request->DataForSort._nbOfProcPerNode==1)
538     _comp=new MemAwareComparator;
539   // memory and procs are set by the user -> do the best possible.
540   else if(request->DataForSort._memInMB!=0 && ( request->DataForSort._nbOfNodes!=1 || request->DataForSort._nbOfProcPerNode!=1 ) )
541     _comp=new CompromiseComparator(request->DataForSort._memInMB,request->DataForSort._nbOfNodes*request->DataForSort._nbOfProcPerNode);
542   else
543     _comp=new BasicComparator;
544 }
545
546 CompareRes::CompareRes(const CompareRes& other):_comp(other._comp->copy()),_request(other._request),_zeCatalog(other._zeCatalog)
547 {
548 }
549
550 bool CompareRes::operator()(const std::string& res1, const std::string& res2)
551 {
552   std::map<std::string, ParserResourcesType>::const_iterator it1(_zeCatalog.find(res1)),it2(_zeCatalog.find(res2));
553   if(it1==_zeCatalog.end() || it2==_zeCatalog.end())
554     throw YACS::Exception("Internal error during comparison !");
555   const ParserResourcesType& elt1((*it1).second);
556   const ParserResourcesType& elt2((*it2).second);
557   return _comp->compare(elt1.DataForSort,elt2.DataForSort);
558 }
559
560 /*!
561  * Implements an another alg than those proposed by default in ResourcesManager_cpp in "ResourcesManager.hxx".
562  */
563 std::vector<std::string> YACSEvalListOfResources::getFittingResources(ParserResourcesType *request) const
564 {
565   int mlop(getMaxLevelOfParallelism());
566   request->DataForSort._memInMB*=mlop;
567   request->DataForSort._nbOfNodes*=mlop;
568   //
569   const MapOfParserResourcesType& zeListInCatalog(_rm->GetList());
570   std::vector<std::string> list0;
571   // first keep those having relevant components
572   const std::vector<std::string>& listExpected(request->ComponentsList);
573   std::set<std::string> listExpected2(listExpected.begin(),listExpected.end());
574   for(std::map<std::string, ParserResourcesType>::const_iterator it=zeListInCatalog.begin();it!=zeListInCatalog.end();it++)
575     {
576       const std::vector<std::string>& compoList((*it).second.ComponentsList);
577       std::set<std::string> s1(compoList.begin(),compoList.end());
578       std::vector<std::string> diff;
579       std::set_difference(listExpected2.begin(),listExpected2.end(),s1.begin(),s1.end(),std::inserter(diff,diff.begin()));
580       if(diff.empty())
581         list0.push_back((*it).first);
582     }
583   // sort list0 regarding request
584   std::sort(list0.begin(),list0.end(),CompareRes(request,zeListInCatalog));
585   // if HostName in request is defined and in list0 put it first.
586   std::string tmp(request->HostName);
587   if(!tmp.empty())
588     {
589       std::vector<std::string>::iterator it1(std::find(list0.begin(),list0.end(),tmp));
590       if(it1!=list0.end())
591         {// HostName in list0 so put it in first place.
592           list0.erase(it1);
593           list0.insert(list0.begin(),tmp);
594         }
595     }
596   return list0;
597 }
598
599 void YACSEvalListOfResources::notifyWantedMachine(YACSEvalVirtualYACSContainer *sender, const std::string& oldMachine, const std::string& newMachine)
600 {
601   const MapOfParserResourcesType& zeList(_rm->GetList());
602   std::map<std::string, ParserResourcesType>::const_iterator itOld(zeList.find(oldMachine)),itNew(zeList.find(newMachine));
603   if(itOld==zeList.end() || itNew==zeList.end())
604     throw YACS::Exception("YACSEvalListOfResources::notifyWantedMachine : internal error !");
605   const ParserResourcesType& oldPRT((*itOld).second);
606   const ParserResourcesType& newPRT((*itNew).second);
607   bool oldISt(oldPRT.Batch==none),newISt(newPRT.Batch==none);//interactive status
608   if(oldISt==newISt)
609     return ;
610   // the batch/interactive mode has changed -> try to change for all.
611   std::queue<std::string> sts;
612   try
613   {
614     if(newISt)
615       {// switching from interactive to batch -> In batch every YACSEvalVirtualYACSContainer instances in this must lie on newMachine.
616         for(std::vector<YACSEvalResource *>::const_iterator it=_resources.begin();it!=_resources.end();it++)
617           {
618             std::vector<std::string> fms((*it)->getAllFittingMachines());
619             std::vector<std::string>::iterator it0(std::find(fms.begin(),fms.end(),newMachine));
620             if(it0==fms.end())
621               {
622                 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;
623                 std::size_t sz((*it)->size());
624                 for(std::size_t i=0;i<sz;i++)
625                   {
626                     YACSEvalVirtualYACSContainer *cont((*it)->at(i));
627                     if(cont)
628                       oss << " \"" << cont->getName() << "\", ";
629                   }
630                 throw YACS::Exception(oss.str());
631               }
632             std::size_t sz((*it)->size());
633             for(std::size_t i=0;i<sz;i++)
634               {
635                 std::size_t sz((*it)->size());
636                 for(std::size_t i=0;i<sz;i++)
637                   {
638                     YACSEvalVirtualYACSContainer *cont((*it)->at(i));
639                     if(cont==sender)
640                       continue;
641                     sts.push(newMachine);
642                   }
643               }
644           }
645       }
646     else
647       {
648         for(std::vector<YACSEvalResource *>::const_iterator it=_resources.begin();it!=_resources.end();it++)
649           {
650             std::size_t sz((*it)->size());
651             for(std::size_t i=0;i<sz;i++)
652               {
653                 YACSEvalVirtualYACSContainer *cont((*it)->at(i));
654                 if(cont==sender)
655                   continue;
656                 sts.push(cont->findDefault(false));
657               }
658           }
659       }
660   }
661   catch(YACS::Exception& e)
662   {
663       std::ostringstream oss; oss << "YACSEvalListOfResources::notifyWantedMachine : switching from interactive/batch must be global ! " << e.what();
664       throw YACS::Exception(oss.str());
665   }
666   for(std::vector<YACSEvalResource *>::const_iterator it=_resources.begin();it!=_resources.end();it++)
667     {
668       std::size_t sz((*it)->size());
669       for(std::size_t i=0;i<sz;i++)
670         {
671           YACSEvalVirtualYACSContainer *cont((*it)->at(i));
672           if(cont==sender)
673             continue;
674           cont->setMachineNoCheck(sts.front());
675           sts.pop();
676         }
677     }
678 }
679
680 bool YACSEvalListOfResources::hasRightInteractiveStatus(const std::string& machineToTest, bool isInteractive) const
681 {
682   const MapOfParserResourcesType& zeList(_rm->GetList());
683   std::map<std::string, ParserResourcesType>::const_iterator it(zeList.find(machineToTest));
684   if(it==zeList.end())
685     throw YACS::Exception("YACSEvalListOfResources::hasRightInteractiveStatus : internal error !");
686   const ParserResourcesType& elt((*it).second);
687   bool myStatus(elt.Batch==none);
688   return myStatus==isInteractive;
689 }
690
691 void YACSEvalListOfResources::fitWithCurrentCatalog()
692 {
693   std::vector<std::string> ress(getAllFittingMachines());
694   if(ress.empty())
695     throw YACS::Exception("YACSEvalListOfResources::fitWithCurrentCatalog : no available resource in your catalog !");
696   for(std::vector<YACSEvalResource *>::iterator it=_resources.begin();it!=_resources.end();it++)
697     (*it)->setMachineNoCheck(ress.front());
698 }
699
700 unsigned int YACSEvalListOfResources::getNumberOfProcOfResource(const std::string& machine) const
701 {
702   const MapOfParserResourcesType& zeList(_rm->GetList());
703   std::map<std::string, ParserResourcesType>::const_iterator it(zeList.find(machine));
704   if(it==zeList.end())
705     throw YACS::Exception("YACSEvalListOfResources::getNumberOfProcOfResource : internal error !");
706   const ParserResourcesType& PRT((*it).second);
707   const ResourceDataToSort& RDT(PRT.DataForSort);
708   unsigned int ret(RDT._nbOfNodes*RDT._nbOfProcPerNode);
709   return ret;
710 }