1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #include "ResourcesManager.hxx"
23 #include <Basics_Utils.hxx>
30 #include <sys/types.h>
36 #include <libxml/parser.h>
40 #define MAX_SIZE_FOR_HOSTNAME 256;
44 static LoadRateManagerFirst first;
45 static LoadRateManagerCycl cycl;
46 static LoadRateManagerAltCycl altcycl;
47 //=============================================================================
51 //=============================================================================
53 ResourcesManager_cpp::
54 ResourcesManager_cpp(const char *xmlFilePath)
56 _path_resources.push_back(xmlFilePath);
57 #if defined(_DEBUG_) || defined(_DEBUG)
58 cerr << "ResourcesManager_cpp constructor" << endl;
60 _resourceManagerMap["first"]=&first;
61 _resourceManagerMap["cycl"]=&cycl;
62 _resourceManagerMap["altcycl"]=&altcycl;
63 _resourceManagerMap["best"]=&altcycl;
64 _resourceManagerMap[""]=&altcycl;
67 //=============================================================================
69 * Standard constructor, parse resource file.
70 * - if ${APPLI} exists in environment,
71 * look for ${HOME}/${APPLI}/CatalogResources.xml
72 * - else look for default:
73 * ${KERNEL_ROOT_DIR}/share/salome/resources/kernel/CatalogResources.xml
74 * - parse XML resource file.
76 //=============================================================================
78 ResourcesManager_cpp::ResourcesManager_cpp() throw(ResourcesException)
80 #if defined(_DEBUG_) || defined(_DEBUG)
81 cerr << "ResourcesManager_cpp constructor" << endl;
83 _resourceManagerMap["first"]=&first;
84 _resourceManagerMap["cycl"]=&cycl;
85 _resourceManagerMap["altcycl"]=&altcycl;
86 _resourceManagerMap["best"]=&altcycl;
87 _resourceManagerMap[""]=&altcycl;
89 std::string default_file("");
90 if (getenv("APPLI") != 0)
92 default_file += getenv("HOME");
94 default_file += getenv("APPLI");
95 default_file += "/CatalogResources.xml";
96 _path_resources.push_back(default_file);
100 if(!getenv("KERNEL_ROOT_DIR"))
101 throw ResourcesException("you must define KERNEL_ROOT_DIR environment variable!! -> cannot load a CatalogResources.xml");
102 default_file = getenv("KERNEL_ROOT_DIR");
103 default_file += "/share/salome/resources/kernel/CatalogResources.xml";
104 _path_resources.push_back(default_file);
107 if (getenv("USER_CATALOG_RESOURCES_FILE") != 0)
109 std::string user_file("");
110 user_file = getenv("USER_CATALOG_RESOURCES_FILE");
111 _path_resources.push_back(user_file);
117 #if defined(_DEBUG_) || defined(_DEBUG)
118 cerr << "ResourcesManager_cpp constructor end";
122 //=============================================================================
124 * Standard Destructor
126 //=============================================================================
128 ResourcesManager_cpp::~ResourcesManager_cpp()
130 #if defined(_DEBUG_) || defined(_DEBUG)
131 cerr << "ResourcesManager_cpp destructor" << endl;
135 //=============================================================================
136 //! get the list of resource names fitting constraints given by params
138 * If hostname is specified, check if it is local or known in resources catalog.
141 * - select first machines with corresponding OS (all machines if
142 * parameter OS empty),
143 * - then select the sublist of machines on which the component is known
144 * (if the result is empty, that probably means that the inventory of
145 * components is probably not done, so give complete list from previous step)
147 //=============================================================================
149 std::vector<std::string>
150 ResourcesManager_cpp::GetFittingResources(const machineParams& params) throw(ResourcesException)
152 vector <std::string> vec;
156 const char *hostname = params.hostname.c_str();
157 #if defined(_DEBUG_) || defined(_DEBUG)
158 cerr << "GetFittingResources " << hostname << " " << Kernel_Utils::GetHostname().c_str() << endl;
161 // PaCO++ parallel container case
162 std::string parallelLib(params.parallelLib);
163 if (params.nb_component_nodes > 0 && parallelLib != "")
165 #if defined(_DEBUG_) || defined(_DEBUG)
166 std::cerr << "[GetFittingResources] ParallelContainer case" << std::endl;
167 std::cerr << "[GetFittingResources] parallelLib is " << parallelLib << std::endl;
168 std::cerr << "[GetFittingResources] nb_component_nodes is " << params.nb_component_nodes << std::endl;
171 // Currently we only support parallel containers that define a hostname target
172 if (hostname[0] != '\0')
174 // Special case of localhost -> put containers into the real computer name
175 if (strcmp(hostname, "localhost") == 0)
176 vec.push_back(Kernel_Utils::GetHostname().c_str());
179 // Try find the resource into the map
180 if (_resourcesList.find(hostname) != _resourcesList.end())
181 vec.push_back(hostname);
183 std::cerr << "[GetFittingResources] ParallelContainer hostname does not exist into the resource list !" << std::endl;
187 std::cerr << "[GetFittingResources] ParallelContainer hostname is empty -> cannot find a possible resource" << std::endl;
191 if (hostname[0] != '\0'){
193 if ( strcmp(hostname, "localhost") == 0 ||
194 strcmp(hostname, Kernel_Utils::GetHostname().c_str()) == 0 )
196 //#if defined(_DEBUG_) || defined(_DEBUG)
197 // cerr << "ResourcesManager_cpp::GetFittingResources : localhost" << endl;
199 vec.push_back(Kernel_Utils::GetHostname().c_str());
200 //#if defined(_DEBUG_) || defined(_DEBUG)
201 // cerr << "ResourcesManager_cpp::GetFittingResources : " << vec.size() << endl;
205 else if (_resourcesList.find(hostname) != _resourcesList.end())
207 // --- params.hostname is in the list of resources so return it.
208 vec.push_back(hostname);
211 else if (_resourcesBatchList.find(hostname) != _resourcesBatchList.end())
213 // --- params.hostname is in the list of resources so return it.
214 vec.push_back(hostname);
219 // Cas d'un cluster: nombre de noeuds > 1
221 for (map<string, ParserResourcesType>::const_iterator iter = _resourcesList.begin(); iter != _resourcesList.end(); iter++){
222 if( (*iter).second.DataForSort._nbOfNodes > 1 ){
223 if( strncmp(hostname,(*iter).first.c_str(),strlen(hostname)) == 0 ){
224 vec.push_back((*iter).first.c_str());
230 // --- user specified an unknown hostame so notify him.
231 #if defined(_DEBUG_) || defined(_DEBUG)
232 cerr << "ResourcesManager_cpp::GetFittingResources : SALOME_Exception" << endl;
234 std::string error("GetFittinResouces : ResourcesManager doesn't find the host requested : ");
236 throw ResourcesException(error);
242 // --- Search for available resources sorted by priority
243 vec=params.computerList;
245 SelectOnlyResourcesWithOS(vec, params.OS.c_str());
247 KeepOnlyResourcesWithComponent(vec, params.componentList);
249 //if hosts list (vec) is empty, ignore componentList constraint and use only OS constraint
251 SelectOnlyResourcesWithOS(vec, params.OS.c_str());
253 // --- set wanted parameters
254 ResourceDataToSort::_nbOfNodesWanted = params.nb_node;
256 ResourceDataToSort::_nbOfProcPerNodeWanted = params.nb_proc_per_node;
258 ResourceDataToSort::_CPUFreqMHzWanted = params.cpu_clock;
260 ResourceDataToSort::_memInMBWanted = params.mem_mb;
264 list<ResourceDataToSort> li;
266 for (vector<string>::iterator iter = vec.begin();
269 li.push_back(_resourcesList[(*iter)].DataForSort);
275 for (list<ResourceDataToSort>::iterator iter2 = li.begin();
278 vec[i++] = (*iter2)._hostName;
285 //=============================================================================
287 * add an entry in the ressources catalog xml file.
288 * Return 0 if OK (KERNEL found in new resources components) else throw exception
290 //=============================================================================
293 ResourcesManager_cpp::
294 AddResourceInCatalog(const machineParams& paramsOfNewResources,
295 const vector<string>& componentsOnNewResources,
297 const char *userName,
299 AccessProtocolType prot)
300 throw(ResourcesException)
302 vector<string>::const_iterator iter = find(componentsOnNewResources.begin(),
303 componentsOnNewResources.end(),
306 if (iter != componentsOnNewResources.end())
308 ParserResourcesType newElt;
309 newElt.DataForSort._hostName = paramsOfNewResources.hostname;
310 newElt.Alias = alias;
311 newElt.Protocol = prot;
313 newElt.UserName = userName;
314 newElt.ComponentsList = componentsOnNewResources;
315 newElt.OS = paramsOfNewResources.OS;
316 newElt.DataForSort._memInMB = paramsOfNewResources.mem_mb;
317 newElt.DataForSort._CPUFreqMHz = paramsOfNewResources.cpu_clock;
318 newElt.DataForSort._nbOfNodes = paramsOfNewResources.nb_node;
319 newElt.DataForSort._nbOfProcPerNode =
320 paramsOfNewResources.nb_proc_per_node;
321 _resourcesList[newElt.DataForSort._hostName] = newElt;
326 throw ResourcesException("KERNEL is not present in this resource");
329 //=============================================================================
331 * Deletes a resource from the catalog
333 //=============================================================================
335 void ResourcesManager_cpp::DeleteResourceInCatalog(const char *hostname)
337 _resourcesList.erase(hostname);
340 //=============================================================================
342 * write the current data in memory in file.
344 //=============================================================================
346 void ResourcesManager_cpp::WriteInXmlFile(std::string & xml_file)
348 #if defined(_DEBUG_) || defined(_DEBUG)
349 std::cerr << "WriteInXmlFile : start" << std::endl;
351 const char* aFilePath = xml_file.c_str();
352 FILE* aFile = fopen(aFilePath, "w");
356 std::cerr << "Error opening file in WriteInXmlFile : " << xml_file << std::endl;
360 xmlDocPtr aDoc = xmlNewDoc(BAD_CAST "1.0");
361 xmlNewDocComment(aDoc, BAD_CAST "ResourcesCatalog");
363 SALOME_ResourcesCatalog_Handler* handler =
364 new SALOME_ResourcesCatalog_Handler(_resourcesList, _resourcesBatchList);
365 handler->PrepareDocToXmlFile(aDoc);
368 int isOk = xmlSaveFile(aFilePath, aDoc);
370 std::cerr << "Error while XML file saving : " << xml_file << std::endl;
375 #if defined(_DEBUG_) || defined(_DEBUG)
376 std::cerr << "WriteInXmlFile : WRITING DONE!" << std::endl;
380 //=============================================================================
382 * parse the data type catalog
384 //=============================================================================
386 const MapOfParserResourcesType& ResourcesManager_cpp::ParseXmlFiles()
388 // Parse file only if its modification time is greater than lasttime (last registered modification time)
389 bool to_parse = false;
390 for(_path_resources_it = _path_resources.begin(); _path_resources_it != _path_resources.end(); ++_path_resources_it)
392 struct stat statinfo;
393 int result = stat((*_path_resources_it).c_str(), &statinfo);
396 std::cerr << "Error in method stat for file : " << (*_path_resources_it).c_str() << " no new xml file is parsed" << std::endl;
397 return _resourcesList;
400 if(statinfo.st_mtime > _lasttime)
403 _lasttime = statinfo.st_mtime;
409 _resourcesList.clear();
410 _resourcesBatchList.clear();
411 // On parse tous les fichiers
412 for(_path_resources_it = _path_resources.begin(); _path_resources_it != _path_resources.end(); ++_path_resources_it)
414 MapOfParserResourcesType _resourcesList_tmp;
415 MapOfParserResourcesType _resourcesBatchList_tmp;
416 SALOME_ResourcesCatalog_Handler* handler =
417 new SALOME_ResourcesCatalog_Handler(_resourcesList_tmp, _resourcesBatchList_tmp);
418 const char* aFilePath = (*_path_resources_it).c_str();
419 FILE* aFile = fopen(aFilePath, "r");
423 xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, 0);
426 handler->ProcessXmlDocument(aDoc);
428 // adding new resources to the file
429 for (MapOfParserResourcesType_it i = _resourcesList_tmp.begin(); i != _resourcesList_tmp.end(); ++i)
431 MapOfParserResourcesType_it j = _resourcesList.find(i->first);
432 if (j == _resourcesList.end())
434 _resourcesList[i->first] = i->second;
438 std::cerr << "ParseXmlFiles Warning, to resource with the same name was found, taking the first declaration : " << i->first << std::endl;
441 for (MapOfParserResourcesType_it i = _resourcesBatchList_tmp.begin(); i != _resourcesBatchList_tmp.end(); ++i)
443 MapOfParserResourcesType_it j = _resourcesBatchList.find(i->first);
444 if (j == _resourcesBatchList.end())
446 _resourcesBatchList[i->first] = i->second;
450 std::cerr << "ParseXmlFiles Warning, to resource with the same name was found, taking the first declaration : " << i->first << std::endl;
455 std::cerr << "ResourcesManager_cpp: could not parse file " << aFilePath << std::endl;
461 std::cerr << "ResourcesManager_cpp: file " << aFilePath << " is not readable." << std::endl;
466 return _resourcesList;
469 //=============================================================================
471 * consult the content of the list
473 //=============================================================================
475 const MapOfParserResourcesType& ResourcesManager_cpp::GetList() const
477 return _resourcesList;
480 string ResourcesManager_cpp::Find(const std::string& policy, const std::vector<std::string>& listOfMachines)
482 if(_resourceManagerMap.count(policy)==0)
483 return _resourceManagerMap[""]->Find(listOfMachines,_resourcesList);
484 return _resourceManagerMap[policy]->Find(listOfMachines,_resourcesList);
487 //=============================================================================
489 * Gives a sublist of machines with matching OS.
490 * If parameter OS is empty, gives the complete list of machines
492 //=============================================================================
494 // Warning need an updated parsed list : _resourcesList
495 void ResourcesManager_cpp::SelectOnlyResourcesWithOS( vector<string>& hosts, const char *OS) const
496 throw(ResourcesException)
502 //No constraint on computer list : take all known resources with OS
503 map<string, ParserResourcesType>::const_iterator iter;
504 for (iter = _resourcesList.begin(); iter != _resourcesList.end(); iter++)
506 if ( (*iter).second.OS == base || base.size() == 0)
507 hosts.push_back((*iter).first);
512 //a computer list is given : take only resources with OS on those computers
513 vector<string> vec=hosts;
515 vector<string>::iterator iter;
516 for (iter = vec.begin(); iter != vec.end(); iter++)
518 MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
519 if(it != _resourcesList.end())
520 if ( (*it).second.OS == base || base.size() == 0 )
521 hosts.push_back(*iter);
527 //=============================================================================
529 * Gives a sublist of machines on which the component is known.
531 //=============================================================================
533 //Warning need an updated parsed list : _resourcesList
534 void ResourcesManager_cpp::KeepOnlyResourcesWithComponent( vector<string>& hosts, const vector<string>& componentList) const
535 throw(ResourcesException)
537 for (vector<string>::iterator iter = hosts.begin(); iter != hosts.end();)
539 MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
540 const vector<string>& mapOfComponentsOfCurrentHost = (((*it).second).ComponentsList);
542 bool erasedHost = false;
543 if( mapOfComponentsOfCurrentHost.size() > 0 ){
544 for(unsigned int i=0;i<componentList.size();i++){
545 const char* compoi = componentList[i].c_str();
546 vector<string>::const_iterator itt = find(mapOfComponentsOfCurrentHost.begin(),
547 mapOfComponentsOfCurrentHost.end(),
549 if (itt == mapOfComponentsOfCurrentHost.end()){
563 ParserResourcesType ResourcesManager_cpp::GetResourcesList(const std::string& machine)
565 if (_resourcesList.find(machine) != _resourcesList.end())
566 return _resourcesList[machine];
568 return _resourcesBatchList[machine];