]> SALOME platform Git repositories - modules/kernel.git/blob - src/ResourcesManager/ResourcesManager.cxx
Salome HOME
update flags for TestLauncher
[modules/kernel.git] / src / ResourcesManager / ResourcesManager.cxx
1 //  Copyright (C) 2007-2010  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
23 #include "ResourcesManager.hxx" 
24 #include <Basics_Utils.hxx>
25 #include <fstream>
26 #include <iostream>
27 #include <sstream>
28 #include <string.h>
29 #include <map>
30 #include <list>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #ifdef WNT
34 #else
35 #include <unistd.h>
36 #endif
37 #include <libxml/parser.h>
38
39 #include <algorithm>
40
41 #define MAX_SIZE_FOR_HOSTNAME 256;
42
43 static LoadRateManagerFirst first;
44 static LoadRateManagerCycl cycl;
45 static LoadRateManagerAltCycl altcycl;
46 //=============================================================================
47 /*!
48  * just for test
49  */ 
50 //=============================================================================
51
52 ResourcesManager_cpp::
53 ResourcesManager_cpp(const char *xmlFilePath)
54 {
55   _path_resources.push_back(xmlFilePath);
56 #if defined(_DEBUG_) || defined(_DEBUG)
57   std::cerr << "ResourcesManager_cpp constructor" << std::endl;
58 #endif
59   _resourceManagerMap["first"]=&first;
60   _resourceManagerMap["cycl"]=&cycl;
61   _resourceManagerMap["altcycl"]=&altcycl;
62   _resourceManagerMap["best"]=&altcycl;
63   _resourceManagerMap[""]=&altcycl;
64 }
65
66 //=============================================================================
67 /*!
68  *  Standard constructor, parse resource file.
69  *  - if ${APPLI} exists in environment,
70  *    look for ${HOME}/${APPLI}/CatalogResources.xml
71  *  - else look for default:
72  *    ${KERNEL_ROOT_DIR}/share/salome/resources/kernel/CatalogResources.xml
73  *  - parse XML resource file.
74  */ 
75 //=============================================================================
76
77 ResourcesManager_cpp::ResourcesManager_cpp() throw(ResourcesException)
78 {
79   RES_MESSAGE("ResourcesManager_cpp constructor");
80
81   _resourceManagerMap["first"]=&first;
82   _resourceManagerMap["cycl"]=&cycl;
83   _resourceManagerMap["altcycl"]=&altcycl;
84   _resourceManagerMap["best"]=&altcycl;
85   _resourceManagerMap[""]=&altcycl;
86
87   if (getenv("USER_CATALOG_RESOURCES_FILE") != 0)
88   {
89     std::string user_file("");
90     user_file = getenv("USER_CATALOG_RESOURCES_FILE");
91     _path_resources.push_back(user_file);
92   }
93   else
94   {
95     std::string default_file("");
96     if (getenv("APPLI") != 0)
97     {
98       default_file += getenv("HOME");
99       default_file += "/";
100       default_file += getenv("APPLI");
101       default_file += "/CatalogResources.xml";
102       _path_resources.push_back(default_file);
103     }
104     else
105     {
106       if(!getenv("KERNEL_ROOT_DIR"))
107         throw ResourcesException("you must define KERNEL_ROOT_DIR environment variable!! -> cannot load a CatalogResources.xml");
108       default_file = getenv("KERNEL_ROOT_DIR");
109       default_file += "/share/salome/resources/kernel/CatalogResources.xml";
110       _path_resources.push_back(default_file);
111     }
112   }
113
114   _lasttime=0;
115
116   ParseXmlFiles();
117   RES_MESSAGE("ResourcesManager_cpp constructor end");
118 }
119
120 //=============================================================================
121 /*!
122  *  Standard Destructor
123  */ 
124 //=============================================================================
125
126 ResourcesManager_cpp::~ResourcesManager_cpp()
127 {
128   RES_MESSAGE("ResourcesManager_cpp destructor");
129 }
130
131 //=============================================================================
132 //! get the list of resource names fitting constraints given by params
133 /*!
134  * Steps:
135  * 1: Restrict list with resourceList if defined
136  * 2: If name is defined -> check resource list
137  * 3: If not 2:, if hostname is defined -> check resource list
138  * 4: If not 3:, sort resource with nb_proc, etc...
139  * 5: In all cases remove resource that does not correspond with OS
140  * 6: And remove resource with componentList - if list is empty ignored it...
141  */ 
142 //=============================================================================
143
144 std::vector<std::string> 
145 ResourcesManager_cpp::GetFittingResources(const resourceParams& params) throw(ResourcesException)
146 {
147   RES_MESSAGE("[GetFittingResources] on computer " << Kernel_Utils::GetHostname().c_str());
148   RES_MESSAGE("[GetFittingResources] with resource name: " << params.name);
149   RES_MESSAGE("[GetFittingResources] with hostname: "<< params.hostname);
150
151   // Result
152   std::vector<std::string> vec;
153
154   // Parse Again CalatogResource File
155   ParseXmlFiles();
156
157   // Steps:
158   // 1: If name is defined -> check resource list
159   // 2: Restrict list with resourceList if defined
160   // 3: If not 2:, if hostname is defined -> check resource list
161   // 4: If not 3:, sort resource with nb_proc, etc...
162   // 5: In all cases remove resource that does not correspond with OS
163   // 6: And remove resource with componentList - if list is empty ignored it...
164
165   // Step 1
166   if (params.name != "")
167   {
168     RES_MESSAGE("[GetFittingResources] name parameter found !");
169     if (_resourcesList.find(params.name) != _resourcesList.end())
170     {
171       vec.push_back(params.name);
172       return vec;
173     }
174     else
175       RES_MESSAGE("[GetFittingResources] resource name was not found on resource list ! name requested was " << params.name);
176       std::string error("[GetFittingResources] resource name was not found on resource list ! name requested was " + params.name);
177       throw ResourcesException(error);
178   }
179
180   MapOfParserResourcesType local_resourcesList = _resourcesList;
181   // Step 2
182   if (params.resourceList.size() > 0)
183   {
184     RES_MESSAGE("[GetFittingResources] Restricted resource list found !");
185     local_resourcesList.clear();
186     std::vector<std::string>::size_type sz = params.resourceList.size();
187
188     for (unsigned int i=0; i < sz; i++)
189     {
190       if (_resourcesList.find(params.resourceList[i]) != _resourcesList.end())
191         local_resourcesList[params.resourceList[i]] = _resourcesList[params.resourceList[i]];
192     }
193   }
194
195   // Step 3
196   if (params.hostname != "")
197   {
198     RES_MESSAGE("[GetFittingResources] Entering in hostname case !");
199
200     std::string hostname = params.hostname;
201     if (hostname ==  "localhost")
202       hostname = Kernel_Utils::GetHostname().c_str();
203
204     std::map<std::string, ParserResourcesType>::const_iterator iter = _resourcesList.begin();
205     for (; iter != _resourcesList.end(); iter++)
206     {
207       if ((*iter).second.HostName == hostname)
208         vec.push_back((*iter).first);
209     }
210   }
211   // Step 4
212   else
213   {
214     // --- Search for available resources sorted by priority
215     MapOfParserResourcesType_it i = local_resourcesList.begin();
216     for (; i != local_resourcesList.end(); ++i)
217       vec.push_back(i->first);
218
219     // --- set wanted parameters
220     ResourceDataToSort::_nbOfProcWanted = params.nb_proc;
221     ResourceDataToSort::_nbOfNodesWanted = params.nb_node;
222     ResourceDataToSort::_nbOfProcPerNodeWanted = params.nb_proc_per_node;
223     ResourceDataToSort::_CPUFreqMHzWanted = params.cpu_clock;
224     ResourceDataToSort::_memInMBWanted = params.mem_mb;
225     // --- end of set
226         
227     // Sort
228     std::list<ResourceDataToSort> li;
229     std::vector<std::string>::iterator iter = vec.begin();
230     for (; iter != vec.end(); iter++)
231       li.push_back(local_resourcesList[(*iter)].DataForSort);
232     li.sort();
233
234     vec.clear();
235     for (std::list<ResourceDataToSort>::iterator iter2 = li.begin(); iter2 != li.end(); iter2++)
236       vec.push_back((*iter2)._Name);
237   }
238
239   // Step 5
240   SelectOnlyResourcesWithOS(vec, params.OS.c_str());
241     
242   // Step 6
243   std::vector<std::string> vec_save(vec);
244   KeepOnlyResourcesWithComponent(vec, params.componentList);
245   if (vec.size() == 0)
246     vec = vec_save;
247
248   // End
249   // Send an exception if return list is empty...
250   if (vec.size() == 0)
251   {
252     std::string error("[GetFittingResources] ResourcesManager doesn't find any resource that fits to your parameters");
253     throw ResourcesException(error);
254   }
255
256   return vec;
257 }
258
259 //=============================================================================
260 /*!
261  *  add an entry in the ressources catalog xml file.
262  */ 
263 //=============================================================================
264
265 void
266 ResourcesManager_cpp::AddResourceInCatalog(const ParserResourcesType & new_resource) throw(ResourcesException)
267 {
268   // TODO - Add minimal check
269   _resourcesList[new_resource.Name] = new_resource;
270 }
271
272 //=============================================================================
273 /*!
274  *  Deletes a resource from the catalog
275  */ 
276 //=============================================================================
277
278 void ResourcesManager_cpp::DeleteResourceInCatalog(const char * name)
279 {
280   MapOfParserResourcesType_it it = _resourcesList.find(name);
281   if (it != _resourcesList.end())
282     _resourcesList.erase(name);
283   else
284     RES_INFOS("You try to delete a resource that does not exist... : " << name);
285 }
286
287 //=============================================================================
288 /*!
289  *  write the current data in memory in file.
290  */ 
291 //=============================================================================
292
293 void ResourcesManager_cpp::WriteInXmlFile(std::string xml_file)
294 {
295   RES_MESSAGE("WriteInXmlFile : start");
296
297   if (xml_file == "")
298   {
299     _path_resources_it = _path_resources.begin();
300     xml_file = *_path_resources_it;
301   }
302
303   const char* aFilePath = xml_file.c_str();
304   FILE* aFile = fopen(aFilePath, "w");
305
306   if (aFile == NULL)
307   {
308     std::cerr << "Error opening file in WriteInXmlFile : " << xml_file << std::endl;
309     return;
310   }
311   
312   xmlDocPtr aDoc = xmlNewDoc(BAD_CAST "1.0");
313   xmlNewDocComment(aDoc, BAD_CAST "ResourcesCatalog");
314
315   SALOME_ResourcesCatalog_Handler* handler =
316     new SALOME_ResourcesCatalog_Handler(_resourcesList);
317   handler->PrepareDocToXmlFile(aDoc);
318   delete handler;
319
320   int isOk = xmlSaveFormatFile(aFilePath, aDoc, 1);
321   if (!isOk) 
322      std::cerr << "Error while XML file saving : " << xml_file << std::endl;
323   
324   // Free the document
325   xmlFreeDoc(aDoc);
326   fclose(aFile);
327   RES_MESSAGE("WriteInXmlFile : WRITING DONE!");
328 }
329
330 //=============================================================================
331 /*!
332  *  parse the data type catalog
333  */ 
334 //=============================================================================
335
336 const MapOfParserResourcesType& ResourcesManager_cpp::ParseXmlFiles()
337 {
338   // Parse file only if its modification time is greater than lasttime (last registered modification time)
339   bool to_parse = false;
340   for(_path_resources_it = _path_resources.begin(); _path_resources_it != _path_resources.end(); ++_path_resources_it)
341   {
342     struct stat statinfo;
343     int result = stat((*_path_resources_it).c_str(), &statinfo);
344     if (result < 0)
345     {
346       std::cerr << "Error in method stat for file : " << (*_path_resources_it).c_str() << " no new xml file is parsed" << std::endl;
347       return _resourcesList;
348     }
349
350     if(statinfo.st_mtime > _lasttime)
351     {
352       to_parse = true;
353       _lasttime = statinfo.st_mtime;
354     }
355   }
356
357   if (to_parse)
358   {
359     _resourcesList.clear();
360     // On parse tous les fichiers
361     for(_path_resources_it = _path_resources.begin(); _path_resources_it != _path_resources.end(); ++_path_resources_it)
362     {
363       MapOfParserResourcesType _resourcesList_tmp;
364       MapOfParserResourcesType _resourcesBatchList_tmp;
365       SALOME_ResourcesCatalog_Handler* handler =
366         new SALOME_ResourcesCatalog_Handler(_resourcesList_tmp);
367       const char* aFilePath = (*_path_resources_it).c_str();
368       FILE* aFile = fopen(aFilePath, "r");
369
370       if (aFile != NULL)
371       {
372         xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, 0);
373         if (aDoc != NULL)
374         {
375           handler->ProcessXmlDocument(aDoc);
376
377           // adding new resources to the file
378           for (MapOfParserResourcesType_it i = _resourcesList_tmp.begin(); i != _resourcesList_tmp.end(); ++i)
379           {
380             MapOfParserResourcesType_it j = _resourcesList.find(i->first);
381             if (j == _resourcesList.end())
382             {
383               _resourcesList[i->first] = i->second;
384             }
385             else
386             {
387               std::cerr << "ParseXmlFiles Warning, two resources with the same name were found, taking the first declaration : " << i->first << std::endl;
388             }
389           }
390         }
391         else
392           std::cerr << "ResourcesManager_cpp: could not parse file " << aFilePath << std::endl;
393         // Free the document
394         xmlFreeDoc(aDoc);
395         fclose(aFile);
396       }
397       else
398         std::cerr << "ResourcesManager_cpp: file " << aFilePath << " is not readable." << std::endl;
399
400       delete handler;
401     }
402   }
403   return _resourcesList;
404 }
405
406 //=============================================================================
407 /*!
408  *   consult the content of the list
409  */ 
410 //=============================================================================
411
412 const MapOfParserResourcesType& ResourcesManager_cpp::GetList() const
413 {
414   return _resourcesList;
415 }
416
417 std::string ResourcesManager_cpp::Find(const std::string& policy, const std::vector<std::string>& listOfResources)
418 {
419   if(_resourceManagerMap.count(policy)==0)
420     return _resourceManagerMap[""]->Find(listOfResources, _resourcesList);
421   return _resourceManagerMap[policy]->Find(listOfResources, _resourcesList);
422 }
423
424 //=============================================================================
425 /*!
426  *  Gives a sublist of resources with matching OS.
427  *  If parameter OS is empty, gives the complete list of resources
428  */ 
429 //=============================================================================
430 void 
431 ResourcesManager_cpp::SelectOnlyResourcesWithOS(std::vector<std::string>& resources, std::string OS)
432 {
433   if (OS != "")
434   {
435     // a computer list is given : take only resources with OS on those computers
436     std::vector<std::string> vec_tmp = resources;
437     resources.clear();
438     std::vector<std::string>::iterator iter = vec_tmp.begin();
439     for (; iter != vec_tmp.end(); iter++)
440     {
441       MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
442       if(it != _resourcesList.end())
443         if ( (*it).second.OS == OS)
444           resources.push_back(*iter);
445     }
446   }
447 }
448
449
450 //=============================================================================
451 /*!
452  *  Gives a sublist of machines on which the component is known.
453  */ 
454 //=============================================================================
455 void 
456 ResourcesManager_cpp::KeepOnlyResourcesWithComponent(std::vector<std::string>& resources, 
457                                                      const std::vector<std::string>& componentList)
458 {
459   std::vector<std::string> kept_resources;
460
461   std::vector<std::string>::iterator iter = resources.begin();
462   for (; iter != resources.end(); iter++)
463   {
464     const std::vector<std::string>& mapOfComponentsOfCurrentHost = _resourcesList[*iter].ComponentsList;
465
466     bool erasedHost = false;
467     if( mapOfComponentsOfCurrentHost.size() > 0 )
468     {
469       for(unsigned int i=0; i<componentList.size(); i++)
470       {
471         std::vector<std::string>::const_iterator itt = find(mapOfComponentsOfCurrentHost.begin(),
472                                                             mapOfComponentsOfCurrentHost.end(),
473                                                             componentList[i]);
474         if (itt == mapOfComponentsOfCurrentHost.end())
475         {
476           erasedHost = true;
477           break;
478         }
479       }
480     }
481     if(!erasedHost)
482       kept_resources.push_back(*iter);
483   }
484   resources=kept_resources;
485 }
486
487
488 ParserResourcesType 
489 ResourcesManager_cpp::GetResourcesDescr(const std::string & name)
490 {
491   if (_resourcesList.find(name) != _resourcesList.end())
492     return _resourcesList[name];
493   else
494   {
495     std::string error("[GetResourcesDescr] Resource does not exist: ");
496     error += name;
497     throw ResourcesException(error);
498   }
499 }