Back to index

salome-kernel  6.5.0
ResourcesManager.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 #include "ResourcesManager.hxx" 
00024 #include <Basics_Utils.hxx>
00025 #include <fstream>
00026 #include <iostream>
00027 #include <sstream>
00028 #include <string.h>
00029 #include <map>
00030 #include <list>
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033 #ifdef WNT
00034 #else
00035 #include <unistd.h>
00036 #endif
00037 #include <libxml/parser.h>
00038 
00039 #include <algorithm>
00040 
00041 #define MAX_SIZE_FOR_HOSTNAME 256;
00042 
00043 static LoadRateManagerFirst first;
00044 static LoadRateManagerCycl cycl;
00045 static LoadRateManagerAltCycl altcycl;
00046 //=============================================================================
00050 //=============================================================================
00051 
00052 ResourcesManager_cpp::
00053 ResourcesManager_cpp(const char *xmlFilePath)
00054 {
00055   _path_resources.push_back(xmlFilePath);
00056 #if defined(_DEBUG_) || defined(_DEBUG)
00057   std::cerr << "ResourcesManager_cpp constructor" << std::endl;
00058 #endif
00059   _resourceManagerMap["first"]=&first;
00060   _resourceManagerMap["cycl"]=&cycl;
00061   _resourceManagerMap["altcycl"]=&altcycl;
00062   _resourceManagerMap["best"]=&altcycl;
00063   _resourceManagerMap[""]=&altcycl;
00064 }
00065 
00066 //=============================================================================
00075 //=============================================================================
00076 
00077 ResourcesManager_cpp::ResourcesManager_cpp() throw(ResourcesException)
00078 {
00079   RES_MESSAGE("ResourcesManager_cpp constructor");
00080 
00081   _resourceManagerMap["first"]=&first;
00082   _resourceManagerMap["cycl"]=&cycl;
00083   _resourceManagerMap["altcycl"]=&altcycl;
00084   _resourceManagerMap["best"]=&altcycl;
00085   _resourceManagerMap[""]=&altcycl;
00086 
00087   bool default_catalog_resource = true;
00088   if (getenv("USER_CATALOG_RESOURCES_FILE") != 0)
00089   {
00090     default_catalog_resource = false;
00091     std::string user_file("");
00092     user_file = getenv("USER_CATALOG_RESOURCES_FILE");
00093     std::ifstream ifile(user_file.c_str(), std::ifstream::in );
00094     if (ifile) {
00095       // The file exists, and is open for input
00096       _path_resources.push_back(user_file);
00097     }
00098     else {
00099       default_catalog_resource = false;
00100       RES_INFOS("Warning: USER_CATALOG_RESOURCES_FILE is set and file cannot be found.")
00101       RES_INFOS("Warning: That's why we try to create a new one.")
00102       std::ofstream user_catalog_file;
00103       user_catalog_file.open(user_file.c_str());
00104       if (user_catalog_file.fail())
00105       {
00106         RES_INFOS("Error: cannot write in the user catalog resouces files");
00107         RES_INFOS("Error: using default CatalogResources.xml file");
00108         default_catalog_resource = true;
00109       }
00110       else
00111       {
00112         user_catalog_file << "<!-- File created by SALOME -->" << std::endl;
00113         user_catalog_file << "<!DOCTYPE ResourcesCatalog>" << std::endl;
00114         user_catalog_file << "<resources>" << std::endl;
00115         user_catalog_file << "   <machine name=\"localhost\" hostname=\"localhost\" />" << std::endl;
00116         user_catalog_file << "</resources>" << std::endl;
00117         user_catalog_file.close();
00118       }
00119     }
00120   }
00121   if (default_catalog_resource)
00122   {
00123     std::string default_file("");
00124     if (getenv("APPLI") != 0)
00125     {
00126       default_file += getenv("HOME");
00127       default_file += "/";
00128       default_file += getenv("APPLI");
00129       default_file += "/CatalogResources.xml";
00130       _path_resources.push_back(default_file);
00131     }
00132     else
00133     {
00134       if(!getenv("KERNEL_ROOT_DIR"))
00135         throw ResourcesException("you must define KERNEL_ROOT_DIR environment variable!! -> cannot load a CatalogResources.xml");
00136       default_file = getenv("KERNEL_ROOT_DIR");
00137       default_file += "/share/salome/resources/kernel/CatalogResources.xml";
00138       _path_resources.push_back(default_file);
00139     }
00140   }
00141 
00142   _lasttime=0;
00143 
00144   ParseXmlFiles();
00145   RES_MESSAGE("ResourcesManager_cpp constructor end");
00146 }
00147 
00148 //=============================================================================
00152 //=============================================================================
00153 
00154 ResourcesManager_cpp::~ResourcesManager_cpp()
00155 {
00156   RES_MESSAGE("ResourcesManager_cpp destructor");
00157 }
00158 
00159 //=============================================================================
00161 
00170 //=============================================================================
00171 
00172 std::vector<std::string> 
00173 ResourcesManager_cpp::GetFittingResources(const resourceParams& params) throw(ResourcesException)
00174 {
00175   RES_MESSAGE("[GetFittingResources] on computer " << Kernel_Utils::GetHostname().c_str());
00176   RES_MESSAGE("[GetFittingResources] with resource name: " << params.name);
00177   RES_MESSAGE("[GetFittingResources] with hostname: "<< params.hostname);
00178 
00179   // Result
00180   std::vector<std::string> vec;
00181 
00182   // Parse Again CalatogResource File
00183   ParseXmlFiles();
00184 
00185   // Steps:
00186   // 1: If name is defined -> check resource list
00187   // 2: Restrict list with resourceList if defined
00188   // 3: If not 2:, if hostname is defined -> check resource list
00189   // 4: If not 3:, sort resource with nb_proc, etc...
00190   // 5: In all cases remove resource that does not correspond with OS
00191   // 6: And remove resource with componentList - if list is empty ignored it...
00192 
00193   // Step 1
00194   if (params.name != "")
00195   {
00196     RES_MESSAGE("[GetFittingResources] name parameter found !");
00197     if (_resourcesList.find(params.name) != _resourcesList.end())
00198     {
00199       vec.push_back(params.name);
00200       return vec;
00201     }
00202     else
00203       RES_MESSAGE("[GetFittingResources] resource name was not found on resource list ! name requested was " << params.name);
00204       std::string error("[GetFittingResources] resource name was not found on resource list ! name requested was " + params.name);
00205       throw ResourcesException(error);
00206   }
00207 
00208   MapOfParserResourcesType local_resourcesList = _resourcesList;
00209   // Step 2
00210   if (params.resourceList.size() > 0)
00211   {
00212     RES_MESSAGE("[GetFittingResources] Restricted resource list found !");
00213     local_resourcesList.clear();
00214     std::vector<std::string>::size_type sz = params.resourceList.size();
00215 
00216     for (unsigned int i=0; i < sz; i++)
00217     {
00218       if (_resourcesList.find(params.resourceList[i]) != _resourcesList.end())
00219         local_resourcesList[params.resourceList[i]] = _resourcesList[params.resourceList[i]];
00220     }
00221   }
00222 
00223   // Step 3
00224   if (params.hostname != "")
00225   {
00226     RES_MESSAGE("[GetFittingResources] Entering in hostname case !");
00227 
00228     std::string hostname = params.hostname;
00229     if (hostname ==  "localhost")
00230       hostname = Kernel_Utils::GetHostname().c_str();
00231 
00232     std::map<std::string, ParserResourcesType>::const_iterator iter = _resourcesList.begin();
00233     for (; iter != _resourcesList.end(); iter++)
00234     {
00235       if ((*iter).second.HostName == hostname)
00236         vec.push_back((*iter).first);
00237     }
00238   }
00239   // Step 4
00240   else
00241   {
00242     // --- Search for available resources sorted by priority
00243     MapOfParserResourcesType_it i = local_resourcesList.begin();
00244     for (; i != local_resourcesList.end(); ++i)
00245       vec.push_back(i->first);
00246 
00247     // --- set wanted parameters
00248     ResourceDataToSort::_nbOfProcWanted = params.nb_proc;
00249     ResourceDataToSort::_nbOfNodesWanted = params.nb_node;
00250     ResourceDataToSort::_nbOfProcPerNodeWanted = params.nb_proc_per_node;
00251     ResourceDataToSort::_CPUFreqMHzWanted = params.cpu_clock;
00252     ResourceDataToSort::_memInMBWanted = params.mem_mb;
00253     // --- end of set
00254         
00255     // Sort
00256     std::list<ResourceDataToSort> li;
00257     std::vector<std::string>::iterator iter = vec.begin();
00258     for (; iter != vec.end(); iter++)
00259       li.push_back(local_resourcesList[(*iter)].DataForSort);
00260     li.sort();
00261 
00262     vec.clear();
00263     for (std::list<ResourceDataToSort>::iterator iter2 = li.begin(); iter2 != li.end(); iter2++)
00264       vec.push_back((*iter2)._Name);
00265   }
00266 
00267   // Step 5
00268   SelectOnlyResourcesWithOS(vec, params.OS.c_str());
00269     
00270   // Step 6
00271   std::vector<std::string> vec_save(vec);
00272   KeepOnlyResourcesWithComponent(vec, params.componentList);
00273   if (vec.size() == 0)
00274     vec = vec_save;
00275 
00276   // End
00277   // Send an exception if return list is empty...
00278   if (vec.size() == 0)
00279   {
00280     std::string error("[GetFittingResources] ResourcesManager doesn't find any resource that fits to your parameters");
00281     throw ResourcesException(error);
00282   }
00283 
00284   return vec;
00285 }
00286 
00287 //=============================================================================
00291 //=============================================================================
00292 
00293 void
00294 ResourcesManager_cpp::AddResourceInCatalog(const ParserResourcesType & new_resource) throw(ResourcesException)
00295 {
00296   // TODO - Add minimal check
00297   _resourcesList[new_resource.Name] = new_resource;
00298 }
00299 
00300 //=============================================================================
00304 //=============================================================================
00305 
00306 void ResourcesManager_cpp::DeleteResourceInCatalog(const char * name)
00307 {
00308   MapOfParserResourcesType_it it = _resourcesList.find(name);
00309   if (it != _resourcesList.end())
00310     _resourcesList.erase(name);
00311   else
00312     RES_INFOS("You try to delete a resource that does not exist... : " << name);
00313 }
00314 
00315 //=============================================================================
00319 //=============================================================================
00320 
00321 void ResourcesManager_cpp::WriteInXmlFile(std::string xml_file)
00322 {
00323   RES_MESSAGE("WriteInXmlFile : start");
00324 
00325   if (xml_file == "")
00326   {
00327     _path_resources_it = _path_resources.begin();
00328     xml_file = *_path_resources_it;
00329   }
00330 
00331   const char* aFilePath = xml_file.c_str();
00332   FILE* aFile = fopen(aFilePath, "w");
00333 
00334   if (aFile == NULL)
00335   {
00336     std::cerr << "Error opening file in WriteInXmlFile : " << xml_file << std::endl;
00337     return;
00338   }
00339   
00340   xmlDocPtr aDoc = xmlNewDoc(BAD_CAST "1.0");
00341   xmlNewDocComment(aDoc, BAD_CAST "ResourcesCatalog");
00342 
00343   SALOME_ResourcesCatalog_Handler* handler =
00344     new SALOME_ResourcesCatalog_Handler(_resourcesList);
00345   handler->PrepareDocToXmlFile(aDoc);
00346   delete handler;
00347 
00348   int isOk = xmlSaveFormatFile(aFilePath, aDoc, 1);
00349   if (!isOk) 
00350      std::cerr << "Error while XML file saving : " << xml_file << std::endl;
00351   
00352   // Free the document
00353   xmlFreeDoc(aDoc);
00354   fclose(aFile);
00355   RES_MESSAGE("WriteInXmlFile : WRITING DONE!");
00356 }
00357 
00358 //=============================================================================
00362 //=============================================================================
00363 
00364 const MapOfParserResourcesType& ResourcesManager_cpp::ParseXmlFiles()
00365 {
00366   // Parse file only if its modification time is greater than lasttime (last registered modification time)
00367   bool to_parse = false;
00368   for(_path_resources_it = _path_resources.begin(); _path_resources_it != _path_resources.end(); ++_path_resources_it)
00369   {
00370     struct stat statinfo;
00371     int result = stat((*_path_resources_it).c_str(), &statinfo);
00372     if (result < 0)
00373     {
00374       std::cerr << "Error in method stat for file : " << (*_path_resources_it).c_str() << " no new xml file is parsed" << std::endl;
00375       return _resourcesList;
00376     }
00377 
00378     if(statinfo.st_mtime > _lasttime)
00379     {
00380       to_parse = true;
00381       _lasttime = statinfo.st_mtime;
00382     }
00383   }
00384 
00385   if (to_parse)
00386   {
00387     _resourcesList.clear();
00388     // On parse tous les fichiers
00389     for(_path_resources_it = _path_resources.begin(); _path_resources_it != _path_resources.end(); ++_path_resources_it)
00390     {
00391       MapOfParserResourcesType _resourcesList_tmp;
00392       MapOfParserResourcesType _resourcesBatchList_tmp;
00393       SALOME_ResourcesCatalog_Handler* handler =
00394         new SALOME_ResourcesCatalog_Handler(_resourcesList_tmp);
00395       const char* aFilePath = (*_path_resources_it).c_str();
00396       FILE* aFile = fopen(aFilePath, "r");
00397 
00398       if (aFile != NULL)
00399       {
00400         xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, 0);
00401         if (aDoc != NULL)
00402         {
00403           handler->ProcessXmlDocument(aDoc);
00404 
00405           // adding new resources to the file
00406           for (MapOfParserResourcesType_it i = _resourcesList_tmp.begin(); i != _resourcesList_tmp.end(); ++i)
00407           {
00408             MapOfParserResourcesType_it j = _resourcesList.find(i->first);
00409             if (j == _resourcesList.end())
00410             {
00411               _resourcesList[i->first] = i->second;
00412             }
00413             else
00414             {
00415               std::cerr << "ParseXmlFiles Warning, two resources with the same name were found, taking the first declaration : " << i->first << std::endl;
00416             }
00417           }
00418         }
00419         else
00420           std::cerr << "ResourcesManager_cpp: could not parse file " << aFilePath << std::endl;
00421         // Free the document
00422         xmlFreeDoc(aDoc);
00423         fclose(aFile);
00424       }
00425       else
00426         std::cerr << "ResourcesManager_cpp: file " << aFilePath << " is not readable." << std::endl;
00427 
00428       delete handler;
00429     }
00430   }
00431   return _resourcesList;
00432 }
00433 
00434 //=============================================================================
00438 //=============================================================================
00439 
00440 const MapOfParserResourcesType& ResourcesManager_cpp::GetList() const
00441 {
00442   return _resourcesList;
00443 }
00444 
00445 std::string ResourcesManager_cpp::Find(const std::string& policy, const std::vector<std::string>& listOfResources)
00446 {
00447   if(_resourceManagerMap.count(policy)==0)
00448     return _resourceManagerMap[""]->Find(listOfResources, _resourcesList);
00449   return _resourceManagerMap[policy]->Find(listOfResources, _resourcesList);
00450 }
00451 
00452 //=============================================================================
00457 //=============================================================================
00458 void 
00459 ResourcesManager_cpp::SelectOnlyResourcesWithOS(std::vector<std::string>& resources, std::string OS)
00460 {
00461   if (OS != "")
00462   {
00463     // a computer list is given : take only resources with OS on those computers
00464     std::vector<std::string> vec_tmp = resources;
00465     resources.clear();
00466     std::vector<std::string>::iterator iter = vec_tmp.begin();
00467     for (; iter != vec_tmp.end(); iter++)
00468     {
00469       MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
00470       if(it != _resourcesList.end())
00471         if ( (*it).second.OS == OS)
00472           resources.push_back(*iter);
00473     }
00474   }
00475 }
00476 
00477 
00478 //=============================================================================
00482 //=============================================================================
00483 void 
00484 ResourcesManager_cpp::KeepOnlyResourcesWithComponent(std::vector<std::string>& resources, 
00485                                                      const std::vector<std::string>& componentList)
00486 {
00487   std::vector<std::string> kept_resources;
00488 
00489   std::vector<std::string>::iterator iter = resources.begin();
00490   for (; iter != resources.end(); iter++)
00491   {
00492     const std::vector<std::string>& mapOfComponentsOfCurrentHost = _resourcesList[*iter].ComponentsList;
00493 
00494     bool erasedHost = false;
00495     if( mapOfComponentsOfCurrentHost.size() > 0 )
00496     {
00497       for(unsigned int i=0; i<componentList.size(); i++)
00498       {
00499         std::vector<std::string>::const_iterator itt = find(mapOfComponentsOfCurrentHost.begin(),
00500                                                             mapOfComponentsOfCurrentHost.end(),
00501                                                             componentList[i]);
00502         if (itt == mapOfComponentsOfCurrentHost.end())
00503         {
00504           erasedHost = true;
00505           break;
00506         }
00507       }
00508     }
00509     if(!erasedHost)
00510       kept_resources.push_back(*iter);
00511   }
00512   resources=kept_resources;
00513 }
00514 
00515 
00516 ParserResourcesType 
00517 ResourcesManager_cpp::GetResourcesDescr(const std::string & name)
00518 {
00519   if (_resourcesList.find(name) != _resourcesList.end())
00520     return _resourcesList[name];
00521   else
00522   {
00523     std::string error("[GetResourcesDescr] Resource does not exist: ");
00524     error += name;
00525     throw ResourcesException(error);
00526   }
00527 }