]> SALOME platform Git repositories - modules/kernel.git/blob - src/ResourcesManager/ResourcesManager.cxx
Salome HOME
CCAR: several changes in Container Manager and Resources Manager
[modules/kernel.git] / src / ResourcesManager / ResourcesManager.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 #include "ResourcesManager.hxx" 
23 #include <Basics_Utils.hxx>
24 #include <fstream>
25 #include <iostream>
26 #include <sstream>
27 #include <string.h>
28 #include <map>
29 #include <list>
30
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34 #include <libxml/parser.h>
35
36 #include <algorithm>
37
38 #define MAX_SIZE_FOR_HOSTNAME 256;
39
40 using namespace std;
41
42 static LoadRateManagerFirst first;
43 static LoadRateManagerCycl cycl;
44 static LoadRateManagerAltCycl altcycl;
45 //=============================================================================
46 /*!
47  * just for test
48  */ 
49 //=============================================================================
50
51 ResourcesManager_cpp::
52 ResourcesManager_cpp(const char *xmlFilePath) :
53     _path_resources(xmlFilePath)
54 {
55 #if defined(_DEBUG_) || defined(_DEBUG)
56   cerr << "ResourcesManager_cpp constructor" << endl;
57 #endif
58   _resourceManagerMap["first"]=&first;
59   _resourceManagerMap["cycl"]=&cycl;
60   _resourceManagerMap["altcycl"]=&altcycl;
61   _resourceManagerMap["best"]=&altcycl;
62   _resourceManagerMap[""]=&altcycl;
63 }
64
65 //=============================================================================
66 /*!
67  *  Standard constructor, parse resource file.
68  *  - if ${APPLI} exists in environment,
69  *    look for ${HOME}/${APPLI}/CatalogResources.xml
70  *  - else look for default:
71  *    ${KERNEL_ROOT_DIR}/share/salome/resources/kernel/CatalogResources.xml
72  *  - parse XML resource file.
73  */ 
74 //=============================================================================
75
76 ResourcesManager_cpp::ResourcesManager_cpp() throw(ResourcesException)
77 {
78 #if defined(_DEBUG_) || defined(_DEBUG)
79   cerr << "ResourcesManager_cpp constructor" << endl;
80 #endif
81   _resourceManagerMap["first"]=&first;
82   _resourceManagerMap["cycl"]=&cycl;
83   _resourceManagerMap["altcycl"]=&altcycl;
84   _resourceManagerMap["best"]=&altcycl;
85   _resourceManagerMap[""]=&altcycl;
86
87   _isAppliSalomeDefined = (getenv("APPLI") != 0);
88   if(!getenv("KERNEL_ROOT_DIR"))
89     throw ResourcesException("you must define KERNEL_ROOT_DIR environment variable!!");
90
91   if (_isAppliSalomeDefined)
92     {
93       _path_resources = getenv("HOME");
94       _path_resources += "/";
95       _path_resources += getenv("APPLI");
96       _path_resources += "/CatalogResources.xml";
97     }
98
99   else
100     {
101       _path_resources = getenv("KERNEL_ROOT_DIR");
102       _path_resources += "/share/salome/resources/kernel/CatalogResources.xml";
103     }
104
105   ParseXmlFile();
106 #if defined(_DEBUG_) || defined(_DEBUG)
107   cerr << "ResourcesManager_cpp constructor end";
108 #endif
109 }
110
111 //=============================================================================
112 /*!
113  *  Standard Destructor
114  */ 
115 //=============================================================================
116
117 ResourcesManager_cpp::~ResourcesManager_cpp()
118 {
119 #if defined(_DEBUG_) || defined(_DEBUG)
120   cerr << "ResourcesManager_cpp destructor" << endl;
121 #endif
122 }
123
124 //=============================================================================
125 //! get the list of resource names fitting constraints given by params
126 /*!
127  *  If hostname is specified, check if it is local or known in resources catalog.
128  *
129  *  Else
130  *  - select first machines with corresponding OS (all machines if
131  *    parameter OS empty),
132  *  - then select the sublist of machines on which the component is known
133  *    (if the result is empty, that probably means that the inventory of
134  *    components is probably not done, so give complete list from previous step)
135  */ 
136 //=============================================================================
137
138 std::vector<std::string> 
139 ResourcesManager_cpp::GetFittingResources(const machineParams& params) throw(ResourcesException)
140 {
141   vector <std::string> vec;
142
143   ParseXmlFile();
144
145   const char *hostname = params.hostname.c_str();
146 #if defined(_DEBUG_) || defined(_DEBUG)
147   cerr << "GetFittingResources " << hostname << " " << Kernel_Utils::GetHostname().c_str() << endl;
148 #endif
149
150   if (hostname[0] != '\0'){
151
152     if ( strcmp(hostname, "localhost") == 0 ||
153          strcmp(hostname, Kernel_Utils::GetHostname().c_str()) == 0 )
154       {
155 //#if defined(_DEBUG_) || defined(_DEBUG)
156 //      cerr << "ResourcesManager_cpp::GetFittingResources : localhost" << endl;
157 //#endif
158         vec.push_back(Kernel_Utils::GetHostname().c_str());
159 //#if defined(_DEBUG_) || defined(_DEBUG)
160 //      cerr << "ResourcesManager_cpp::GetFittingResources : " << vec.size() << endl;
161 //#endif
162       }
163         
164     else if (_resourcesList.find(hostname) != _resourcesList.end())
165       {
166         // --- params.hostname is in the list of resources so return it.
167         vec.push_back(hostname);
168       }
169         
170     else if (_resourcesBatchList.find(hostname) != _resourcesBatchList.end())
171     {
172       // --- params.hostname is in the list of resources so return it.
173       vec.push_back(hostname);
174     }
175
176     else
177       {
178         // Cas d'un cluster: nombre de noeuds > 1
179         int cpt=0;
180         for (map<string, ParserResourcesType>::const_iterator iter = _resourcesList.begin(); iter != _resourcesList.end(); iter++){
181           if( (*iter).second.DataForSort._nbOfNodes > 1 ){
182             if( strncmp(hostname,(*iter).first.c_str(),strlen(hostname)) == 0 ){
183               vec.push_back((*iter).first.c_str());
184               cpt++;
185             }
186           }
187         }
188         if(cpt==0){
189           // --- user specified an unknown hostame so notify him.
190 #if defined(_DEBUG_) || defined(_DEBUG)
191           cerr << "ResourcesManager_cpp::GetFittingResources : SALOME_Exception" << endl;
192 #endif
193           throw ResourcesException("unknown host");
194         }
195       }
196   }
197     
198   else{
199     // --- Search for available resources sorted by priority
200     vec=params.computerList;
201
202     SelectOnlyResourcesWithOS(vec, params.OS.c_str());
203       
204     KeepOnlyResourcesWithComponent(vec, params.componentList);
205
206     //if hosts list (vec) is empty, ignore componentList constraint and use only OS constraint
207     if (vec.size() == 0)
208       SelectOnlyResourcesWithOS(vec, params.OS.c_str());
209     
210     // --- set wanted parameters
211     ResourceDataToSort::_nbOfNodesWanted = params.nb_node;
212       
213     ResourceDataToSort::_nbOfProcPerNodeWanted = params.nb_proc_per_node;
214         
215     ResourceDataToSort::_CPUFreqMHzWanted = params.cpu_clock;
216         
217     ResourceDataToSort::_memInMBWanted = params.mem_mb;
218         
219     // --- end of set
220         
221     list<ResourceDataToSort> li;
222         
223     for (vector<string>::iterator iter = vec.begin();
224          iter != vec.end();
225          iter++)
226       li.push_back(_resourcesList[(*iter)].DataForSort);
227         
228     li.sort();
229         
230     unsigned int i = 0;
231         
232     for (list<ResourceDataToSort>::iterator iter2 = li.begin();
233          iter2 != li.end();
234          iter2++)
235       vec[i++] = (*iter2)._hostName;
236   }
237     
238   return vec;
239
240 }
241
242 //=============================================================================
243 /*!
244  *  add an entry in the ressources catalog  xml file.
245  *  Return 0 if OK (KERNEL found in new resources components) else throw exception
246  */ 
247 //=============================================================================
248
249 int
250 ResourcesManager_cpp::
251 AddResourceInCatalog(const machineParams& paramsOfNewResources,
252                      const vector<string>& componentsOnNewResources,
253                      const char *alias,
254                      const char *userName,
255                      AccessModeType mode,
256                      AccessProtocolType prot)
257 throw(ResourcesException)
258 {
259   vector<string>::const_iterator iter = find(componentsOnNewResources.begin(),
260                                              componentsOnNewResources.end(),
261                                              "KERNEL");
262
263   if (iter != componentsOnNewResources.end())
264     {
265       ParserResourcesType newElt;
266       newElt.DataForSort._hostName = paramsOfNewResources.hostname;
267       newElt.Alias = alias;
268       newElt.Protocol = prot;
269       newElt.Mode = mode;
270       newElt.UserName = userName;
271       newElt.ComponentsList = componentsOnNewResources;
272       newElt.OS = paramsOfNewResources.OS;
273       newElt.DataForSort._memInMB = paramsOfNewResources.mem_mb;
274       newElt.DataForSort._CPUFreqMHz = paramsOfNewResources.cpu_clock;
275       newElt.DataForSort._nbOfNodes = paramsOfNewResources.nb_node;
276       newElt.DataForSort._nbOfProcPerNode =
277         paramsOfNewResources.nb_proc_per_node;
278       _resourcesList[newElt.DataForSort._hostName] = newElt;
279       return 0;
280     }
281
282   else
283     throw ResourcesException("KERNEL is not present in this resource");
284 }
285
286 //=============================================================================
287 /*!
288  *  Deletes a resource from the catalog
289  */ 
290 //=============================================================================
291
292 void ResourcesManager_cpp::DeleteResourceInCatalog(const char *hostname)
293 {
294   _resourcesList.erase(hostname);
295 }
296
297 //=============================================================================
298 /*!
299  *  write the current data in memory in file.
300  */ 
301 //=============================================================================
302
303 void ResourcesManager_cpp::WriteInXmlFile()
304 {
305   const char* aFilePath = _path_resources.c_str();
306   
307   FILE* aFile = fopen(aFilePath, "w");
308
309   if (aFile == NULL)
310     {
311 #if defined(_DEBUG_) || defined(_DEBUG)
312       cerr << "Error opening file !"  << endl;
313 #endif
314       return;
315     }
316   
317   xmlDocPtr aDoc = xmlNewDoc(BAD_CAST "1.0");
318   xmlNewDocComment(aDoc, BAD_CAST "ResourcesCatalog");
319
320   SALOME_ResourcesCatalog_Handler* handler =
321     new SALOME_ResourcesCatalog_Handler(_resourcesList, _resourcesBatchList);
322   handler->PrepareDocToXmlFile(aDoc);
323   delete handler;
324
325 #if defined(_DEBUG_) || defined(_DEBUG)
326   int isOk = xmlSaveFile(aFilePath, aDoc);
327   if (!isOk) cerr << "Error while XML file saving." << endl;
328 #else
329   xmlSaveFile(aFilePath, aDoc);
330 #endif
331   
332   // Free the document
333   xmlFreeDoc(aDoc);
334
335   fclose(aFile);
336   
337 #if defined(_DEBUG_) || defined(_DEBUG)
338   cerr << "WRITING DONE!" << endl;
339 #endif
340 }
341
342 //=============================================================================
343 /*!
344  *  parse the data type catalog
345  */ 
346 //=============================================================================
347
348 const MapOfParserResourcesType& ResourcesManager_cpp::ParseXmlFile()
349 {
350   //Parse file only if its modification time is greater than lasttime (last registered modification time) 
351   static time_t lasttime=0;
352   struct stat statinfo;
353   int result = stat(_path_resources.c_str(), &statinfo);
354   if (result < 0) return _resourcesList;
355   if(statinfo.st_mtime <= lasttime)
356     return _resourcesList;
357   lasttime=statinfo.st_mtime;
358
359   SALOME_ResourcesCatalog_Handler* handler =
360     new SALOME_ResourcesCatalog_Handler(_resourcesList, _resourcesBatchList);
361
362   const char* aFilePath = _path_resources.c_str();
363   FILE* aFile = fopen(aFilePath, "r");
364   
365   if (aFile != NULL)
366     {
367       xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, 0);
368       
369       if (aDoc != NULL)
370         handler->ProcessXmlDocument(aDoc);
371 #if defined(_DEBUG_) || defined(_DEBUG)
372       else
373         cerr << "ResourcesManager_cpp: could not parse file "<< aFilePath << endl;
374 #endif
375       
376       // Free the document
377       xmlFreeDoc(aDoc);
378
379       fclose(aFile);
380     }
381 #if defined(_DEBUG_) || defined(_DEBUG)
382   else
383     cerr << "ResourcesManager_cpp: file "<<aFilePath<<" is not readable." << endl;
384 #endif
385   
386   delete handler;
387
388   return _resourcesList;
389 }
390
391 //=============================================================================
392 /*!
393  *   consult the content of the list
394  */ 
395 //=============================================================================
396
397 const MapOfParserResourcesType& ResourcesManager_cpp::GetList() const
398 {
399   return _resourcesList;
400 }
401
402 string ResourcesManager_cpp::Find(const std::string& policy, const std::vector<std::string>& listOfMachines)
403 {
404   if(_resourceManagerMap.count(policy)==0)
405     return _resourceManagerMap[""]->Find(listOfMachines,_resourcesList);
406   return _resourceManagerMap[policy]->Find(listOfMachines,_resourcesList);
407 }
408
409 //=============================================================================
410 /*!
411  *  Gives a sublist of machines with matching OS.
412  *  If parameter OS is empty, gives the complete list of machines
413  */ 
414 //=============================================================================
415
416 // Warning need an updated parsed list : _resourcesList
417 void ResourcesManager_cpp::SelectOnlyResourcesWithOS( vector<string>& hosts,  const char *OS) const
418 throw(ResourcesException)
419 {
420   string base(OS);
421
422   if(hosts.size()==0)
423     {
424       //No constraint on computer list : take all known resources with OS
425       map<string, ParserResourcesType>::const_iterator iter;
426       for (iter = _resourcesList.begin(); iter != _resourcesList.end(); iter++)
427         {
428           if ( (*iter).second.OS == base || base.size() == 0)
429             hosts.push_back((*iter).first);
430         }
431     }
432   else
433     {
434       //a computer list is given : take only resources with OS on those computers
435       vector<string> vec=hosts;
436       hosts.clear();
437       vector<string>::iterator iter;
438       for (iter = vec.begin(); iter != vec.end(); iter++)
439         {
440           MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
441           if(it != _resourcesList.end())
442             if ( (*it).second.OS == base || base.size() == 0 )
443               hosts.push_back(*iter);
444         }
445     }
446 }
447
448
449 //=============================================================================
450 /*!
451  *  Gives a sublist of machines on which the component is known.
452  */ 
453 //=============================================================================
454
455 //Warning need an updated parsed list : _resourcesList
456 void ResourcesManager_cpp::KeepOnlyResourcesWithComponent( vector<string>& hosts, const vector<string>& componentList) const
457 throw(ResourcesException)
458 {
459   for (vector<string>::iterator iter = hosts.begin(); iter != hosts.end();)
460     {
461       MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
462       const vector<string>& mapOfComponentsOfCurrentHost = (((*it).second).ComponentsList);
463
464       bool erasedHost = false;
465       if( mapOfComponentsOfCurrentHost.size() > 0 ){
466         for(unsigned int i=0;i<componentList.size();i++){
467           const char* compoi = componentList[i].c_str();
468           vector<string>::const_iterator itt = find(mapOfComponentsOfCurrentHost.begin(),
469                                               mapOfComponentsOfCurrentHost.end(),
470                                               compoi);
471           if (itt == mapOfComponentsOfCurrentHost.end()){
472             erasedHost = true;
473             break;
474           }
475         }
476       }
477       if(erasedHost)
478         hosts.erase(iter);
479       else
480         iter++;
481     }
482 }
483
484
485 ParserResourcesType ResourcesManager_cpp::GetResourcesList(const std::string& machine)
486 {
487   if (_resourcesList.find(machine) != _resourcesList.end())
488     return _resourcesList[machine];
489   else
490     return _resourcesBatchList[machine];
491 }