]> SALOME platform Git repositories - modules/yacs.git/blob - src/runtime/SalomeContainerTools.cxx
Salome HOME
Revert commit bc803f251236fa3b020c (14/03/2020) due to new ForEachLoopDyn implementation
[modules/yacs.git] / src / runtime / SalomeContainerTools.cxx
1 // Copyright (C) 2006-2016  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "SalomeContainerTools.hxx"
21 #include "SALOME_LifeCycleCORBA.hxx"
22 #include "SALOME_NamingService.hxx"
23 #include "SALOME_ResourcesManager.hxx"
24 #include "SALOME_ContainerManager.hxx"
25 #include "Container.hxx"
26 #include "AutoLocker.hxx"
27
28 #include "YacsTrace.hxx"
29 #include "Proc.hxx"
30 #include "ServiceNode.hxx"
31 #include "ComponentInstance.hxx"
32 #include "SalomeContainerHelper.hxx"
33 #include "RuntimeSALOME.hxx"
34 #include "Exception.hxx"
35
36 #include <sstream>
37
38 #ifdef WIN32
39 #include <process.h>
40 #define getpid _getpid
41 #endif
42
43 using namespace YACS::ENGINE;
44
45 SalomeContainerTools::SalomeContainerTools()
46 {
47   /* Init ContainerParameters */
48   SALOME_LifeCycleCORBA::preSet(_params);
49 }
50
51 SalomeContainerTools::SalomeContainerTools(const SalomeContainerTools& other):_params(other._params),_propertyMap(other._propertyMap)
52 {
53 }
54
55 void SalomeContainerTools::clearProperties()
56 {
57   _propertyMap.clear();
58   _params=Engines::ContainerParameters();
59 }
60
61 std::string SalomeContainerTools::getProperty(const std::string& name) const
62 {
63   std::map<std::string,std::string>::const_iterator it(_propertyMap.find(name));
64   if(it!=_propertyMap.end())
65     return (*it).second;
66   else
67     return std::string();
68 }
69
70 void SalomeContainerTools::setProperty(const std::string& name, const std::string& value)
71 {
72   //DEBTRACE("SalomeContainer::setProperty : " << name << " ; " << value);
73   // Container Part
74   if (name == "container_name")
75     _params.container_name = CORBA::string_dup(value.c_str());
76   else if (name == "workingdir")
77     _params.workingdir = CORBA::string_dup(value.c_str());
78   else if (name == "nb_parallel_procs")
79   {
80     std::istringstream iss(value);
81     if (!(iss >> _params.nb_proc))
82       throw Exception("salomecontainer::setproperty : params.nb_proc value not correct : " + value);
83   }
84   else if (name == "isMPI")
85   {
86     if (value == "true")
87       _params.isMPI = true;
88     else if (value == "false")
89       _params.isMPI = false;
90     else 
91       throw Exception("SalomeContainer::setProperty : params.isMPI value not correct : " + value);
92   }
93   else if (name == "parallelLib")
94     _params.parallelLib = CORBA::string_dup(value.c_str());
95
96   // Resource part
97   else if (name == "name")
98     _params.resource_params.name = CORBA::string_dup(value.c_str());
99   else if (name == "hostname")
100     _params.resource_params.hostname = CORBA::string_dup(value.c_str());
101   else if (name == "OS")
102     _params.resource_params.OS = CORBA::string_dup(value.c_str());
103   else if (name == "nb_resource_procs")
104   {
105     std::istringstream iss(value);
106     if (!(iss >> _params.resource_params.nb_proc))
107       throw Exception("salomecontainer::setproperty : params.resource_params.nb_proc value not correct : " + value);
108   }
109   else if (name == "mem_mb")
110   {
111     std::istringstream iss(value);
112     if (!(iss >> _params.resource_params.mem_mb))
113       throw Exception("salomecontainer::setproperty : params.resource_params.mem_mb value not correct : " + value);
114   }
115   else if (name == "cpu_clock")
116   {
117     std::istringstream iss(value);
118     if (!(iss >> _params.resource_params.cpu_clock))
119       throw Exception("salomecontainer::setproperty : params.resource_params.cpu_clock value not correct : " + value);
120   }
121   else if (name == "nb_node")
122   {
123     std::istringstream iss(value);
124     if (!(iss >> _params.resource_params.nb_node))
125       throw Exception("salomecontainer::setproperty : params.nb_node value not correct : " + value);
126   }
127   else if (name == "nb_proc_per_node")
128   {
129     std::istringstream iss(value);
130     if (!(iss >> _params.resource_params.nb_proc_per_node))
131       throw Exception("salomecontainer::setproperty : params.nb_proc_per_node value not correct : " + value);
132   }
133   else if (name == "policy")
134     _params.resource_params.policy = CORBA::string_dup(value.c_str());
135   else if (name == "component_list")
136   {
137     std::string clean_value(value);
138
139     // Step 1: remove blanks
140     while(clean_value.find(" ") != std::string::npos)
141       clean_value = clean_value.erase(clean_value.find(" "), 1);
142
143     // Step 2: get values
144     while(!clean_value.empty())
145     {
146       std::string result("");
147       std::string::size_type loc = clean_value.find(",", 0);
148       if (loc != std::string::npos)
149       {
150         result = clean_value.substr(0, loc);
151         clean_value = clean_value.erase(0, loc+1);
152       }
153       else
154       {
155         result = clean_value;
156         clean_value.erase();
157       }
158       if (result != "," && result != "")
159       {
160         addToComponentList(result);
161       }
162     }
163
164   }
165   else if (name == "resource_list")
166   {
167     std::string clean_value(value);
168
169     // Step 1: remove blanks
170     while(clean_value.find(" ") != std::string::npos)
171       clean_value = clean_value.erase(clean_value.find(" "), 1);
172
173     // Step 2: get values
174     while(!clean_value.empty())
175     {
176       std::string result("");
177       std::string::size_type loc = clean_value.find(",", 0);
178       if (loc != std::string::npos)
179       {
180         result = clean_value.substr(0, loc);
181         clean_value = clean_value.erase(0, loc+1);
182       }
183       else
184       {
185         result = clean_value;
186         clean_value.erase();
187       }
188       if (result != "," && result != "")
189       {
190         addToResourceList(result);
191       }
192     }
193
194   }
195   _propertyMap[name]=value;
196 }
197
198 void SalomeContainerTools::addToComponentList(const std::string& name)
199 {
200   // Search if name is already in the list
201   for (CORBA::ULong i = 0; i < _params.resource_params.componentList.length(); i++)
202     {
203       std::string component_name = _params.resource_params.componentList[i].in();
204       if (component_name == name)
205         return;
206     }
207   // Add name to list
208   CORBA::ULong lgth = _params.resource_params.componentList.length();
209   _params.resource_params.componentList.length(lgth + 1);
210   _params.resource_params.componentList[lgth] = CORBA::string_dup(name.c_str());
211 }
212
213 void SalomeContainerTools::addToResourceList(const std::string& name)
214 {
215   // Search if name is already in the list
216   for (CORBA::ULong i = 0; i < _params.resource_params.resList.length(); i++)
217     {
218       std::string component_name = _params.resource_params.resList[i].in();
219       if (component_name == name)
220         return;
221     }
222   // Add name to list
223   CORBA::ULong lgth = _params.resource_params.resList.length();
224   _params.resource_params.resList.length(lgth + 1);
225   _params.resource_params.resList[lgth] = CORBA::string_dup(name.c_str());
226 }
227
228 std::string SalomeContainerTools::getContainerName() const
229 {
230   return std::string(_params.container_name);
231 }
232
233 void SalomeContainerTools::setContainerName(const std::string& name)
234 {
235   SetContainerNameOf(_params,name);
236 }
237
238 std::string SalomeContainerTools::getNotNullContainerName(const Container *contPtr, const Task *askingNode, bool& isEmpty) const
239 {
240   isEmpty=true;
241   std::string name(_params.container_name);
242   if(!name.empty())
243     {
244       isEmpty=false;
245       return name;
246     }
247   else
248     {
249       //give a almost unique name to the container : Pid_Name_Addr
250       std::ostringstream stream;
251       stream << getpid();
252       stream << "_";
253       stream << contPtr->getName();
254       stream << "_";
255       stream << contPtr->getDiscreminantStrOfThis(askingNode);
256       return stream.str();
257     }
258 }
259
260 std::string SalomeContainerTools::getHostName() const
261 {
262   return std::string(_params.resource_params.hostname);
263 }
264
265 void SalomeContainerTools::SetContainerNameOf(Engines::ContainerParameters& params, const std::string& name)
266 {
267   params.container_name=CORBA::string_dup(name.c_str());
268 }
269
270 std::map<std::string,std::string> SalomeContainerTools::getResourceProperties(const std::string& name) const
271 {
272   std::map<std::string,std::string> properties;
273
274   YACS::ENGINE::RuntimeSALOME* runTime = YACS::ENGINE::getSALOMERuntime();
275   CORBA::ORB_ptr orb = runTime->getOrb();
276   if (!orb) return properties;
277   SALOME_NamingService namingService(orb);
278   SALOME_LifeCycleCORBA lcc(&namingService);
279   CORBA::Object_var obj = namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS);
280   if (CORBA::is_nil(obj))
281     return properties;
282   Engines::ResourcesManager_var resManager = Engines::ResourcesManager::_narrow(obj);
283   if (CORBA::is_nil(resManager))
284     return properties;
285
286   std::ostringstream value;
287   Engines::ResourceDefinition_var resource_definition = resManager->GetResourceDefinition(name.c_str());
288   properties["hostname"]=resource_definition->hostname.in();
289   properties["OS"]=resource_definition->OS.in();
290   value.str(""); value << resource_definition->mem_mb;
291   properties["mem_mb"]=value.str();
292   value.str(""); value << resource_definition->cpu_clock;
293   properties["cpu_clock"]=value.str();
294   value.str(""); value << resource_definition->nb_node;
295   properties["nb_node"]=value.str();
296   value.str(""); value << resource_definition->nb_proc_per_node;
297   properties["nb_proc_per_node"]=value.str();
298   /*
299   properties["component_list"]="";
300   for(CORBA::ULong i=0; i < resource_definition->componentList.length(); i++)
301     {
302       if(i > 0)
303         properties["component_list"]=properties["component_list"]+",";
304       properties["component_list"]=properties["component_list"]+resource_definition->componentList[i].in();
305     }
306     */
307   return properties;
308 }
309
310 /*!
311  * \param [in] compoNames
312  * \param [in,out] shutdownLevel
313  */
314 void SalomeContainerTools::Start(const std::vector<std::string>& compoNames, SalomeContainerHelper *schelp, SalomeContainerTools& sct, int& shutdownLevel, const Container *cont, const Task *askingNode)
315 {
316   CORBA::ORB_ptr orb(getSALOMERuntime()->getOrb());
317   SALOME_NamingService ns;
318   try
319   {
320       ns.init_orb(orb);
321   }
322   catch(SALOME_Exception& e)
323   {
324       throw Exception("SalomeContainer::start : Unable to contact the SALOME Naming Service");
325   }
326   CORBA::Object_var obj(ns.Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS));
327   Engines::ContainerManager_var contManager(Engines::ContainerManager::_narrow(obj));
328
329   bool isEmptyName;
330   std::string str(sct.getNotNullContainerName(cont,askingNode,isEmptyName));
331   DEBTRACE("SalomeContainer::start " << str <<";"<< _sct.getHostName() <<";"<<_type);
332
333   // Finalize parameters with components found in the container
334
335   for(std::vector<std::string>::const_iterator iter=compoNames.begin();iter!=compoNames.end();iter++)
336     sct.addToComponentList(*iter);
337
338   Engines::ContainerParameters myparams(sct.getParameters());
339   {
340     std::string dftLauchMode(schelp->getDftLaunchMode());
341     myparams.mode=CORBA::string_dup(dftLauchMode.c_str());
342   }
343
344   //If a container_name is given try to find an already existing container in naming service
345   //If not found start a new container with the given parameters
346   if (dynamic_cast<SalomeContainerMonoHelper *>(schelp) && !isEmptyName)
347     {
348       myparams.mode=CORBA::string_dup("getorstart");
349     }
350
351   if (isEmptyName)
352     {
353       shutdownLevel=1;
354     }
355   //sct.setContainerName(str);
356   SetContainerNameOf(myparams,str);
357   Engines::Container_var trueCont(Engines::Container::_nil());
358   if(!isEmptyName && shutdownLevel==999)
359     {
360       //Make this only the first time start is called (_shutdownLevel==999)
361       //If the container is named, first try to get an existing container
362       //If there is an existing container use it and set the shutdown level to 3
363       //If there is no existing container, try to launch a new one and set the shutdown level to 2
364       myparams.mode="get";
365       try
366       {
367           trueCont=contManager->GiveContainer(myparams);
368       }
369       catch( const SALOME::SALOME_Exception& ex )
370       {
371           std::string msg="SalomeContainer::start : no existing container : ";
372           msg += '\n';
373           msg += ex.details.text.in();
374           DEBTRACE( msg );
375       }
376       catch(...)
377       {
378       }
379
380       if(!CORBA::is_nil(trueCont))
381         {
382           shutdownLevel=3;
383           DEBTRACE( "container found: " << str << " " << _shutdownLevel );
384         }
385       else
386         {
387           shutdownLevel=2;
388           myparams.mode="start";
389           DEBTRACE( "container not found: " << str << " " << _shutdownLevel);
390         }
391     }
392
393   if(CORBA::is_nil(trueCont))
394     try
395   {
396         // --- GiveContainer is used in batch mode to retreive launched containers,
397         //     and is equivalent to StartContainer when not in batch.
398         trueCont=contManager->GiveContainer(myparams);
399   }
400   catch( const SALOME::SALOME_Exception& ex )
401   {
402       std::string msg="SalomeContainer::start : Unable to launch container in Salome : ";
403       msg += '\n';
404       msg += ex.details.text.in();
405       throw Exception(msg);
406   }
407   catch(CORBA::COMM_FAILURE&)
408   {
409       throw Exception("SalomeContainer::start : Unable to launch container in Salome : CORBA Comm failure detected");
410   }
411   catch(CORBA::Exception&)
412   {
413       throw Exception("SalomeContainer::start : Unable to launch container in Salome : Unexpected CORBA failure detected");
414   }
415
416   if(CORBA::is_nil(trueCont))
417     throw Exception("SalomeContainer::start : Unable to launch container in Salome. Check your CatalogResources.xml file");
418
419   schelp->setContainer(askingNode,trueCont);
420
421   CORBA::String_var containerName(trueCont->name()),hostName(trueCont->getHostName());
422   std::cerr << "SalomeContainer launched : " << containerName << " " << hostName << " " << trueCont->getPID() << std::endl;
423 }
424
425 CORBA::Object_ptr SalomeContainerTools::LoadComponent(SalomeContainerHelper *launchModeType, Container *cont, Task *askingNode)
426 {
427   DEBTRACE("SalomeContainer::loadComponent ");
428   const ComponentInstance *inst(askingNode?askingNode->getComponent():0);
429   {
430     YACS::BASES::AutoLocker<Container> alck(cont);//To be sure
431     if(!cont->isAlreadyStarted(askingNode))
432       cont->start(askingNode);
433   }
434   if(!inst)
435     throw Exception("SalomeContainerTools::LoadComponent : no instance of component in the task requesting for a load of its component !");
436   CORBA::Object_ptr objComponent=CORBA::Object::_nil();
437   {
438     YACS::BASES::AutoLocker<Container> alck(cont);//To be sure
439     std::string compoName(inst->getCompoName());
440     Engines::Container_var container(launchModeType->getContainer(askingNode));
441
442     char *reason;
443     bool isLoadable(container->load_component_Library(compoName.c_str(), reason));
444     if(isLoadable)
445       objComponent=CreateComponentInstance(cont,container,inst);
446   }
447   return objComponent;
448 }
449
450 CORBA::Object_ptr SalomeContainerTools::CreateComponentInstance(Container *cont, Engines::Container_ptr contPtr, const ComponentInstance *inst)
451 {
452   if(!inst)
453     throw Exception("SalomeContainerTools::CreateComponentInstance : no instance of component in the task requesting for a load of its component !");
454   char *reason(0);
455   std::string compoName(inst->getCompoName());
456   CORBA::Object_ptr objComponent=CORBA::Object::_nil();
457   Proc* p(cont->getProc());
458   // prepare component instance properties
459   Engines::FieldsDict_var env(new Engines::FieldsDict);
460   std::map<std::string, std::string> properties(inst->getProperties());
461   if(p)
462     {
463       std::map<std::string,std::string> procMap=p->getProperties();
464       properties.insert(procMap.begin(),procMap.end());
465     }
466
467   std::map<std::string, std::string>::const_iterator itm;
468   env->length(properties.size());
469   int item=0;
470   for(itm = properties.begin(); itm != properties.end(); ++itm, item++)
471     {
472       DEBTRACE("envname="<<itm->first<<" envvalue="<< itm->second);
473       env[item].key= CORBA::string_dup(itm->first.c_str());
474       env[item].value <<= itm->second.c_str();
475     }
476
477   objComponent=contPtr->create_component_instance_env(compoName.c_str(), env, reason);
478   if(CORBA::is_nil(objComponent))
479     {
480       std::string text="Error while trying to create a new component: component '"+ compoName;
481       text=text+"' is not installed or it's a wrong name";
482       text += '\n';
483       text += reason;
484       CORBA::string_free(reason);
485       throw Exception(text);
486     }
487   return objComponent;
488 }
489
490 std::string SalomeContainerTools::GetPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode)
491 {
492   if(cont->isAlreadyStarted(askingNode))
493     {
494       Engines::Container_var container(launchModeType->getContainer(askingNode));
495       const char *what="/";
496       CORBA::String_var corbaStr(container->name());
497       std::string ret(corbaStr);
498
499       //Salome FOREVER ...
500       std::string::size_type i=ret.find_first_of(what,0);
501       i=ret.find_first_of(what, i==std::string::npos ? i:i+1);
502       if(i!=std::string::npos)
503         return ret.substr(i+1);
504       return ret;
505     }
506   else
507     return "Not placed yet !!!";
508 }
509
510 std::string SalomeContainerTools::GetFullPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode)
511 {
512   if(cont->isAlreadyStarted(askingNode))
513     {
514       Engines::Container_var container(launchModeType->getContainer(askingNode));
515       try
516       {
517           CORBA::String_var corbaStr(container->name());
518           std::string ret(corbaStr);
519           return ret;
520       }
521       catch(...)
522       {
523           return "Unknown_placement";
524       }
525     }
526   else
527     return "Not_placed_yet";
528 }