Salome HOME
Direct manipulation of resource map singleton
[modules/kernel.git] / src / ResourcesManager / ResourcesManager.cxx
1 // Copyright (C) 2007-2024  CEA, EDF, 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, or (at your option) any later version.
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
25 #include "SALOME_ResourcesCatalog_Handler.hxx"
26 #include <Basics_Utils.hxx>
27 #include <Basics_DirUtils.hxx>
28 #include "utilities.h"
29
30 #include <fstream>
31 #include <iostream>
32 #include <sstream>
33 #include <string.h>
34 #include <map>
35 #include <list>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #ifdef WIN32
39 #else
40 #include <unistd.h>
41 #endif
42 #include <libxml/parser.h>
43
44 #include <algorithm>
45 #include <memory>
46
47 #define MAX_SIZE_FOR_HOSTNAME 256;
48
49 using namespace std;
50
51 const string ResourcesManager_cpp::DEFAULT_RESOURCE_NAME = "localhost";
52
53 static LoadRateManagerFirst first;
54 static LoadRateManagerCycl cycl;
55 static LoadRateManagerAltCycl altcycl;
56
57 resourceParams::resourceParams()
58 : can_launch_batch_jobs(false),
59   can_run_containers(false),
60   nb_proc(-1),
61   nb_node(0),
62   nb_proc_per_node(-1),
63   cpu_clock(-1),
64   mem_mb(-1)
65 {
66 }
67
68 //=============================================================================
69 /*!
70  * just for test
71  */ 
72 //=============================================================================
73
74 ResourcesManager_cpp::
75 ResourcesManager_cpp(const char *xmlFilePath)
76 {
77   _path_resources.push_back(xmlFilePath);
78 #if defined(_DEBUG_) || defined(_DEBUG)
79   std::cerr << "ResourcesManager_cpp constructor" << std::endl;
80 #endif
81   _resourceManagerMap["first"]=&first;
82   _resourceManagerMap["cycl"]=&cycl;
83   _resourceManagerMap["altcycl"]=&altcycl;
84   _resourceManagerMap["best"]=&altcycl;
85   _resourceManagerMap[""]=&altcycl;
86
87   AddDefaultResourceInCatalog();
88   ParseXmlFiles();
89 }
90
91 //=============================================================================
92 /*!
93  *  Standard constructor, parse resource file.
94  *  - if ${APPLI} exists in environment,
95  *    look for ${HOME}/${APPLI}/CatalogResources.xml
96  *  - else look for default:
97  *    ${KERNEL_ROOT_DIR}/share/salome/resources/kernel/CatalogResources.xml
98  *  - parse XML resource file.
99  */ 
100 //=============================================================================
101
102 ResourcesManager_cpp::ResourcesManager_cpp()
103 {
104   RES_MESSAGE("ResourcesManager_cpp constructor");
105
106   _resourceManagerMap["first"]=&first;
107   _resourceManagerMap["cycl"]=&cycl;
108   _resourceManagerMap["altcycl"]=&altcycl;
109   _resourceManagerMap["best"]=&altcycl;
110   _resourceManagerMap[""]=&altcycl;
111
112   AddDefaultResourceInCatalog();
113
114   bool default_catalog_resource = true;
115   if (getenv("USER_CATALOG_RESOURCES_FILE") != 0)
116   {
117     default_catalog_resource = false;
118     std::string user_file("");
119     user_file = getenv("USER_CATALOG_RESOURCES_FILE");
120     std::ifstream ifile(user_file.c_str(), std::ifstream::in );
121     if (ifile) {
122       // The file exists, and is open for input
123       DEBUG_MESSAGE("USER_CATALOG_RESOURCES_FILE positioned -> add it into resourcefiles list");
124       _path_resources.push_back(user_file);
125     }
126     else {
127       default_catalog_resource = false;
128       WARNING_MESSAGE("Warning: USER_CATALOG_RESOURCES_FILE is set and file cannot be found.")
129       WARNING_MESSAGE("Warning: That's why we try to create a new one.")
130       std::ofstream user_catalog_file;
131       user_catalog_file.open(user_file.c_str());
132       if (user_catalog_file.fail())
133       {
134         WARNING_MESSAGE("Error: cannot write in the user catalog resources files");
135         WARNING_MESSAGE("Error: using default CatalogResources.xml file");
136         default_catalog_resource = true;
137       }
138       else
139       {
140         user_catalog_file << "<!-- File created by SALOME -->" << std::endl;
141         user_catalog_file << "<!DOCTYPE ResourcesCatalog>" << std::endl;
142         user_catalog_file << "<resources>" << std::endl;
143         user_catalog_file << "   <machine name=\"localhost\" hostname=\"localhost\" />" << std::endl;
144         user_catalog_file << "</resources>" << std::endl;
145         user_catalog_file.close();
146       }
147     }
148   }
149   if (default_catalog_resource)
150   {
151     std::string default_file("");
152     if (getenv("APPLI") != 0)
153     {
154       default_file += Kernel_Utils::HomePath();
155       default_file += "/";
156       default_file += getenv("APPLI");
157       default_file += "/CatalogResources.xml";
158       std::ifstream ifile(default_file.c_str(), std::ifstream::in );
159       if (ifile) {
160         // The file exists, and is open for input
161         DEBUG_MESSAGE("${APPLI}/CatalogResources.xml exists -> add it into resourcefiles list");
162         _path_resources.push_back(default_file);
163         default_catalog_resource=false;
164       }
165     }
166   }
167   if (default_catalog_resource)
168   {
169     std::string default_file("");
170     if(!getenv("KERNEL_ROOT_DIR"))
171       throw ResourcesException("you must define KERNEL_ROOT_DIR environment variable!! -> cannot load a CatalogResources.xml");
172     default_file = getenv("KERNEL_ROOT_DIR");
173     default_file += "/share/salome/resources/kernel/CatalogResources.xml";
174     DEBUG_MESSAGE("${KERNEL_ROOT_DIR}/share/salome/resources/kernel/CatalogResources.xml -> add it into resourcefiles list");
175     _path_resources.push_back(default_file);
176   }
177
178   ParseXmlFiles();
179   RES_MESSAGE("ResourcesManager_cpp constructor end");
180 }
181
182 //=============================================================================
183 /*!
184  *  Standard Destructor
185  */ 
186 //=============================================================================
187
188 ResourcesManager_cpp::~ResourcesManager_cpp()
189 {
190   RES_MESSAGE("ResourcesManager_cpp destructor");
191 }
192
193 //=============================================================================
194 //! get the list of resource names fitting constraints given by params
195 /*!
196  * Steps:
197  * 1: Restrict list with resourceList if defined
198  * 2: If name is defined -> check resource list
199  * 3: If not 2:, if hostname is defined -> check resource list
200  * 4: If not 3:, sort resource with nb_proc, etc...
201  * 5: In all cases remove resource that does not correspond with OS
202  * 6: And remove resource with componentList - if list is empty ignored it...
203  */ 
204 //=============================================================================
205
206 std::vector<std::string> 
207 ResourcesManager_cpp::GetFittingResources(const resourceParams& params) 
208 {
209   RES_MESSAGE("[GetFittingResources] on computer " << Kernel_Utils::GetHostname().c_str());
210   RES_MESSAGE("[GetFittingResources] with resource name: " << params.name);
211   RES_MESSAGE("[GetFittingResources] with hostname: "<< params.hostname);
212
213   // Result
214   std::vector<std::string> vec;
215
216   // Parse Again CalatogResource File
217   ParseXmlFiles();
218
219   // Steps:
220   // 1: If name is defined -> check resource list
221   // 2: Restrict list with resourceList if defined
222   // 3: If not 2:, if hostname is defined -> check resource list
223   // 4: If not 3:, sort resource with nb_proc, etc...
224   // 5: In all cases remove resource that does not correspond with OS
225   // 6: And remove resource with componentList - if list is empty ignored it...
226
227   // Step 1
228   if (params.name != "")
229   {
230     RES_MESSAGE("[GetFittingResources] name parameter found !");
231     if (_resourcesList.find(params.name) != _resourcesList.end())
232     {
233       vec.push_back(params.name);
234       return vec;
235     }
236     else
237       RES_MESSAGE("[GetFittingResources] resource name was not found on resource list ! name requested was " << params.name);
238       std::string error("[GetFittingResources] resource name was not found on resource list ! name requested was " + params.name);
239       throw ResourcesException(error);
240   }
241
242   MapOfParserResourcesType local_resourcesList = _resourcesList;
243   // Step 2
244   if (params.resourceList.size() > 0)
245   {
246     RES_MESSAGE("[GetFittingResources] Restricted resource list found !");
247     local_resourcesList.clear();
248     std::vector<std::string>::size_type sz = params.resourceList.size();
249
250     for (unsigned int i=0; i < sz; i++)
251     {
252       if (_resourcesList.find(params.resourceList[i]) != _resourcesList.end())
253         local_resourcesList[params.resourceList[i]] = _resourcesList[params.resourceList[i]];
254     }
255   }
256
257   // Step 3
258   if (params.hostname != "")
259   {
260     RES_MESSAGE("[GetFittingResources] Entering in hostname case !");
261
262     std::string hostname = params.hostname;
263     if (hostname ==  "localhost")
264       hostname = Kernel_Utils::GetHostname().c_str();
265
266     std::map<std::string, ParserResourcesType>::const_iterator iter = _resourcesList.begin();
267     for (; iter != _resourcesList.end(); iter++)
268     {
269       if ((*iter).second.HostName == hostname)
270         vec.push_back((*iter).first);
271     }
272   }
273   // Step 4
274   else
275   {
276     // --- Search for available resources sorted by priority
277     MapOfParserResourcesType_it i = local_resourcesList.begin();
278     for (; i != local_resourcesList.end(); ++i)
279       vec.push_back(i->first);
280
281     // --- set wanted parameters
282     ResourceDataToSort::_nbOfProcWanted = params.nb_proc;
283     ResourceDataToSort::_nbOfNodesWanted = params.nb_node;
284     ResourceDataToSort::_nbOfProcPerNodeWanted = params.nb_proc_per_node;
285     ResourceDataToSort::_CPUFreqMHzWanted = params.cpu_clock;
286     ResourceDataToSort::_memInMBWanted = params.mem_mb;
287     // --- end of set
288         
289     // Sort
290     std::list<ResourceDataToSort> li;
291     std::vector<std::string>::iterator iter = vec.begin();
292     for (; iter != vec.end(); iter++)
293       li.push_back(local_resourcesList[(*iter)].DataForSort);
294     li.sort();
295
296     vec.clear();
297     for (std::list<ResourceDataToSort>::iterator iter2 = li.begin(); iter2 != li.end(); iter2++)
298       vec.push_back((*iter2)._Name);
299   }
300
301   // Step 5
302   SelectOnlyResourcesWithOS(vec, params.OS.c_str());
303
304   // Step 6
305   std::vector<std::string> vec_save(vec);
306   KeepOnlyResourcesWithComponent(vec, params.componentList);
307   if (vec.size() == 0)
308     vec = vec_save;
309
310   // Step 7 : Filter on possible usage
311   vector<string> prev_list(vec);
312   vec.clear();
313   for (vector<string>::iterator iter = prev_list.begin() ; iter != prev_list.end() ; iter++)
314   {
315     MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
316     if (it != _resourcesList.end() &&
317         (!params.can_launch_batch_jobs || it->second.can_launch_batch_jobs) &&
318         (!params.can_run_containers || it->second.can_run_containers))
319       vec.push_back(*iter);
320   }
321
322   // End
323   // Send an exception if return list is empty...
324   if (vec.size() == 0)
325   {
326     std::string error("[GetFittingResources] ResourcesManager doesn't find any resource that fits to your parameters");
327     throw ResourcesException(error);
328   }
329
330   return vec;
331 }
332
333 void ResourcesManager_cpp::AddResourceInCatalogNoQuestion (const ParserResourcesType & new_resource)
334 {
335   _resourcesList[new_resource.Name] = new_resource;
336 }
337
338 //=============================================================================
339 /*!
340  *  add an entry in the resources catalog xml file.
341  */ 
342 //=============================================================================
343
344 void
345 ResourcesManager_cpp::AddResourceInCatalog(const ParserResourcesType & new_resource)
346 {
347   if (new_resource.Name == DEFAULT_RESOURCE_NAME){
348     ParserResourcesType default_resource = _resourcesList[DEFAULT_RESOURCE_NAME];
349     // some of the properties of the default resource shouldn't be modified
350     std::string check;
351     if( default_resource.HostName != new_resource.HostName)
352       check += "The Hostname property of the default resource can not be modified.\n";
353     if( default_resource.AppliPath != new_resource.AppliPath)
354       check += "The Applipath property of the default resource can not be modified.\n";
355     if( !new_resource.can_run_containers)
356       check += "The default resource should be able to run containers.\n";
357     if( !new_resource.can_launch_batch_jobs)
358       check += "The default resource should be able to launch batch jobs.\n";
359     if( default_resource.Protocol != new_resource.Protocol)
360       check += "The Protocol property of the default resource can not be modified.\n";
361     if(!check.empty())
362       throw ResourcesException(check);
363   }
364   // TODO - Add minimal check
365   this->AddResourceInCatalogNoQuestion( new_resource );
366 }
367
368 void ResourcesManager_cpp::DeleteAllResourcesInCatalog()
369 {
370   _resourcesList.clear();
371 }
372
373 //=============================================================================
374 /*!
375  *  Deletes a resource from the catalog
376  */ 
377 //=============================================================================
378
379 void ResourcesManager_cpp::DeleteResourceInCatalog(const char * name)
380 {
381   if (DEFAULT_RESOURCE_NAME == name){
382     std::string error("Cannot delete default local resource \"" + DEFAULT_RESOURCE_NAME + "\"");
383     throw ResourcesException(error);
384   }
385   MapOfParserResourcesType_it it = _resourcesList.find(name);
386   if (it != _resourcesList.end())
387     _resourcesList.erase(name);
388   else
389     RES_INFOS("You try to delete a resource that does not exist... : " << name);
390 }
391
392 //=============================================================================
393 /*!
394  *  write the current data in memory in file.
395  */ 
396 //=============================================================================
397
398 void ResourcesManager_cpp::WriteInXmlFile(std::string xml_file)
399 {
400   RES_MESSAGE("WriteInXmlFile : start");
401
402   MapOfParserResourcesType resourceListToSave(_resourcesList);
403   if (resourceListToSave.empty())
404   {
405     RES_MESSAGE("WriteInXmlFile: nothing to do, no resource to save!");
406     return;
407   }
408
409   if (xml_file == "")
410   {
411     _path_resources_it = _path_resources.begin();
412     xml_file = *_path_resources_it;
413   }
414
415   const char* aFilePath = xml_file.c_str();
416   FILE* aFile = fopen(aFilePath, "w");
417
418   if (aFile == NULL)
419   {
420     std::cerr << "Error opening file in WriteInXmlFile : " << xml_file << std::endl;
421     return;
422   }
423   
424   xmlDocPtr aDoc = xmlNewDoc(BAD_CAST "1.0");
425   xmlNewDocComment(aDoc, BAD_CAST "ResourcesCatalog");
426
427   SALOME_ResourcesCatalog_Handler* handler =
428     new SALOME_ResourcesCatalog_Handler(resourceListToSave);
429   handler->PrepareDocToXmlFile(aDoc);
430   delete handler;
431
432   int isOk = xmlSaveFormatFile(aFilePath, aDoc, 1);
433   if (!isOk) 
434      std::cerr << "Error while XML file saving : " << xml_file << std::endl;
435   
436   // Free the document
437   xmlFreeDoc(aDoc);
438   fclose(aFile);
439   RES_MESSAGE("WriteInXmlFile : WRITING DONE!");
440 }
441
442 //=============================================================================
443 /*!
444  *  parse the data type catalog
445  */ 
446 //=============================================================================
447
448 const MapOfParserResourcesType& ResourcesManager_cpp::ParseXmlFiles()
449 {
450   // Parse file only if its modification time is greater than lasttime (last registered modification time)
451   bool to_parse = false;
452   for(_path_resources_it = _path_resources.begin(); _path_resources_it != _path_resources.end(); ++_path_resources_it)
453   {
454     struct stat statinfo;
455     int result = stat((*_path_resources_it).c_str(), &statinfo);
456     if (result < 0)
457     {
458       WARNING_MESSAGE("Resource file " << *_path_resources_it << " does not exist -> no parsing");
459       return _resourcesList;
460     }
461
462     if(_lasttime == 0 || statinfo.st_mtime > _lasttime)
463     {
464       DEBUG_MESSAGE("Resource file " << *_path_resources_it << " has been detected to be present and newer than Resources in memory");
465       to_parse = true;
466       _lasttime = statinfo.st_mtime;
467     }
468   }
469
470   if (to_parse)
471   {
472     DEBUG_MESSAGE("After analyze of resoure files time meta data, a load of resources from scratch from files is necessary.");
473     _resourcesList.clear();
474     AddDefaultResourceInCatalog();
475     // On parse tous les fichiers
476     for(_path_resources_it = _path_resources.begin(); _path_resources_it != _path_resources.end(); ++_path_resources_it)
477     {
478       MapOfParserResourcesType _resourcesList_tmp;
479       MapOfParserResourcesType _resourcesBatchList_tmp;
480       std::unique_ptr<SALOME_ResourcesCatalog_Handler> handler( new SALOME_ResourcesCatalog_Handler(_resourcesList_tmp) );
481       const char *aFilePath( (*_path_resources_it).c_str() );
482       FILE* aFile = fopen(aFilePath, "r");
483       if (aFile != NULL)
484       {
485         xmlDocPtr aDoc = xmlReadFile(aFilePath, NULL, 0);
486         if (aDoc != NULL)
487         {
488           DEBUG_MESSAGE("XML parsing of Resource file \"" << aFilePath << "\"");
489           handler->ProcessXmlDocument(aDoc);
490
491           // adding new resources to the file
492           for (MapOfParserResourcesType_it i = _resourcesList_tmp.begin(); i != _resourcesList_tmp.end(); ++i)
493           {
494             MapOfParserResourcesType_it j = _resourcesList.find(i->first);
495             if (i->second.HostName == DEFAULT_RESOURCE_NAME || i->second.HostName == Kernel_Utils::GetHostname())
496             {
497               DEBUG_MESSAGE("Resource \"" << i->first << "\" in file \"" << aFilePath << "\" is detected as localhost");
498               MapOfParserResourcesType_it it0(_resourcesList.find(DEFAULT_RESOURCE_NAME));
499               if(it0!=_resourcesList.end())
500                 {
501                   DEBUG_MESSAGE("Resource \"" << i->first << "\" in file \"" << aFilePath << "\" detected as localhost is already in memory -> update resource with content in file ( for attributes : nbOfNodes, nbOfProcPerNode, CPUFreqMHz and memInMB)");
502                   ParserResourcesType& localhostElt((*it0).second);
503                   localhostElt.DataForSort._nbOfNodes=(*i).second.DataForSort._nbOfNodes;
504                   localhostElt.DataForSort._nbOfProcPerNode=(*i).second.DataForSort._nbOfProcPerNode;
505                   localhostElt.DataForSort._CPUFreqMHz=(*i).second.DataForSort._CPUFreqMHz;
506                   localhostElt.DataForSort._memInMB=(*i).second.DataForSort._memInMB;
507                 }
508               DEBUG_MESSAGE("Resource \"" << i->first << "\" is not added because it is the same machine as default local resource \"" << DEFAULT_RESOURCE_NAME << "\"");
509             }
510             else if (j != _resourcesList.end())
511             {
512               WARNING_MESSAGE("ParseXmlFiles Warning, two resources with the same name were found, taking the first declaration : " << i->first );
513             }
514             else
515             {
516               DEBUG_MESSAGE("Resource \"" << i->first << "\" added");
517               _resourcesList[i->first] = i->second;
518             }
519           }
520         }
521         else
522           ERROR_MESSAGE( "ResourcesManager_cpp: could not parse file " << aFilePath );
523         // Free the document
524         xmlFreeDoc(aDoc);
525         fclose(aFile);
526       }
527       else
528         ERROR_MESSAGE( "ResourcesManager_cpp: file " << aFilePath << " is not readable." );
529     }
530   }
531   return _resourcesList;
532 }
533
534 //=============================================================================
535 /*!
536  *   consult the content of the list
537  */ 
538 //=============================================================================
539
540 const MapOfParserResourcesType& ResourcesManager_cpp::GetList() const
541 {
542   return _resourcesList;
543 }
544
545 //! threadsafe
546 std::string ResourcesManager_cpp::Find(const std::string& policy, const std::vector<std::string>& listOfResources) const
547 {
548   std::map<std::string , LoadRateManager*>::const_iterator it(_resourceManagerMap.find(policy));
549   if(it==_resourceManagerMap.end())
550         {
551           it=_resourceManagerMap.find("");
552           return ((*it).second)->Find(listOfResources, _resourcesList);
553         }
554   return ((*it).second)->Find(listOfResources, _resourcesList);
555 }
556
557 //=============================================================================
558 /*!
559  *  Gives a sublist of resources with matching OS.
560  *  If parameter OS is empty, gives the complete list of resources
561  */ 
562 //=============================================================================
563 void 
564 ResourcesManager_cpp::SelectOnlyResourcesWithOS(std::vector<std::string>& resources, std::string OS)
565 {
566   if (OS != "")
567   {
568     // a computer list is given : take only resources with OS on those computers
569     std::vector<std::string> vec_tmp = resources;
570     resources.clear();
571     std::vector<std::string>::iterator iter = vec_tmp.begin();
572     for (; iter != vec_tmp.end(); iter++)
573     {
574       MapOfParserResourcesType::const_iterator it = _resourcesList.find(*iter);
575       if(it != _resourcesList.end())
576         if ( (*it).second.OS == OS)
577           resources.push_back(*iter);
578     }
579   }
580 }
581
582
583 //=============================================================================
584 /*!
585  *  Gives a sublist of machines on which the component is known.
586  */ 
587 //=============================================================================
588 void 
589 ResourcesManager_cpp::KeepOnlyResourcesWithComponent(std::vector<std::string>& resources, 
590                                                      const std::vector<std::string>& componentList)
591 {
592   std::vector<std::string> kept_resources;
593
594   std::vector<std::string>::iterator iter = resources.begin();
595   for (; iter != resources.end(); iter++)
596   {
597     const std::vector<std::string>& mapOfComponentsOfCurrentHost = _resourcesList[*iter].ComponentsList;
598
599     bool erasedHost = false;
600     if( mapOfComponentsOfCurrentHost.size() > 0 )
601     {
602       for(unsigned int i=0; i<componentList.size(); i++)
603       {
604         std::vector<std::string>::const_iterator itt = find(mapOfComponentsOfCurrentHost.begin(),
605                                                             mapOfComponentsOfCurrentHost.end(),
606                                                             componentList[i]);
607         if (itt == mapOfComponentsOfCurrentHost.end())
608         {
609           erasedHost = true;
610           break;
611         }
612       }
613     }
614     if(!erasedHost)
615       kept_resources.push_back(*iter);
616   }
617   resources=kept_resources;
618 }
619
620 //! thread safe
621 ParserResourcesType ResourcesManager_cpp::GetResourcesDescr(const std::string & name) const
622 {
623   MapOfParserResourcesType::const_iterator it(_resourcesList.find(name));
624   if (it != _resourcesList.end())
625     return (*it).second;
626   else
627   {
628     std::string error("[GetResourcesDescr] Resource does not exist: ");
629     error += name;
630     throw ResourcesException(error);
631   }
632 }
633
634 void ResourcesManager_cpp::AddDefaultResourceInCatalog()
635 {
636   ParserResourcesType resource;
637   resource.Name = DEFAULT_RESOURCE_NAME;
638   // We can't use "localhost" for parameter hostname because the containers are registered in the
639   // naming service with the real hostname, not "localhost"
640   resource.HostName = Kernel_Utils::GetHostname();
641   resource.DataForSort._Name = DEFAULT_RESOURCE_NAME;
642   resource.Protocol = sh;
643   resource.Batch = none;
644 #ifndef WIN32
645   struct stat statbuf;
646   std::string aHomePath = Kernel_Utils::HomePath();
647   if (aHomePath != "" && getenv("APPLI") != NULL)
648   {
649     if (stat(getenv("APPLI"), &statbuf) ==0 &&  S_ISREG(statbuf.st_mode))
650     {
651         // if $APPLI is a regular file, we asume it's a salome Launcher file
652         resource.AppliPath = string(getenv("APPLI"));
653     }
654     else
655     {
656         resource.AppliPath = aHomePath + "/" + getenv("APPLI");
657     }
658   }
659   string tmpdir = "/tmp";
660   if (getenv("TMPDIR") != NULL)
661     tmpdir = getenv("TMPDIR");
662   resource.working_directory = tmpdir + "/salome_localres_workdir";
663   if (getenv("USER") != NULL)
664     resource.working_directory += string("_") + getenv("USER");
665 #else
666   if (getenv("USERPROFILE") != NULL && getenv("APPLI") != NULL)
667   {
668     resource.AppliPath = string(getenv("USERPROFILE")) + "\\" + getenv("APPLI");
669   }
670   string tmpdir = "C:\\tmp";
671   if (getenv("TEMP") != NULL)
672     tmpdir = getenv("TEMP");
673   resource.working_directory = tmpdir + "\\salome_localres_workdir";
674   if (getenv("USERNAME") != NULL)
675     resource.working_directory += string("_") + getenv("USERNAME");
676 #endif
677   resource.can_launch_batch_jobs = true;
678   resource.can_run_containers = true;
679   _resourcesList[resource.Name] = resource;
680   DEBUG_MESSAGE("Put Ressource \"" << resource.Name << "\" in dictionary of resources. This resource will be present even if resource files define it later.");
681 }