Version: 9.16.0
SalomeContainerTools.cxx
Go to the documentation of this file.
1// Copyright (C) 2006-2026 CEA, EDF
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#define _DEVDEBUG_
21#include "SALOME_LifeCycleCORBA.hxx"
23#include "SALOME_ResourcesManager.hxx"
24#include "SALOME_ContainerManager.hxx"
25
26#include "Container.hxx"
27#include "AutoLocker.hxx"
28
29#include "YacsTrace.hxx"
30#include "Proc.hxx"
31#include "ServiceNode.hxx"
32#include "ComponentInstance.hxx"
35#include "RuntimeSALOME.hxx"
36#include "Exception.hxx"
37
38#include <sstream>
39
40#ifdef WIN32
41#include <process.h>
42#define getpid _getpid
43#endif
44
45using namespace YACS::ENGINE;
46
47SalomeContainerTools::SalomeContainerTools()
48{
49 /* Init ContainerParameters */
50 SALOME_LifeCycleCORBA::preSet(_params);
51}
52
53SalomeContainerTools::SalomeContainerTools(const SalomeContainerTools& other):_params(other._params),_propertyMap(other._propertyMap)
54{
55}
56
58{
59 _propertyMap.clear();
60 _params=Engines::ContainerParameters();
61}
62
63std::string SalomeContainerTools::getProperty(const std::string& name) const
64{
65 std::map<std::string,std::string>::const_iterator it(_propertyMap.find(name));
66 if(it!=_propertyMap.end())
67 return (*it).second;
68 else
69 return std::string();
70}
71
72void SalomeContainerTools::setProperty(const std::string& name, const std::string& value)
73{
74 //DEBUG_YACSTRACE("SalomeContainer::setProperty : " << name << " ; " << value);
75 // Container Part
76 if (name == "container_name")
77 _params.container_name = CORBA::string_dup(value.c_str());
78 else if (name == "workingdir")
79 _params.workingdir = CORBA::string_dup(value.c_str());
80 else if (name == "nb_parallel_procs")
81 {
82 std::istringstream iss(value);
83 if (!(iss >> _params.nb_proc))
84 throw Exception("salomecontainer::setproperty : params.nb_proc value not correct : " + value);
85 }
86 else if (name == "isMPI")
87 {
88 if (value == "true")
89 _params.isMPI = true;
90 else if (value == "false")
91 _params.isMPI = false;
92 else
93 throw Exception("SalomeContainer::setProperty : params.isMPI value not correct : " + value);
94 }
95 else if (name == "parallelLib")
96 _params.parallelLib = CORBA::string_dup(value.c_str());
97
98 // Resource part
99 else if (name == "name")
100 _params.resource_params.name = CORBA::string_dup(value.c_str());
101 else if (name == "hostname")
102 _params.resource_params.hostname = CORBA::string_dup(value.c_str());
103 else if (name == "OS")
104 _params.resource_params.OS = CORBA::string_dup(value.c_str());
105 else if (name == "nb_resource_procs")
106 {
107 std::istringstream iss(value);
108 if (!(iss >> _params.resource_params.nb_proc))
109 throw Exception("salomecontainer::setproperty : params.resource_params.nb_proc value not correct : " + value);
110 }
111 else if (name == "mem_mb")
112 {
113 std::istringstream iss(value);
114 if (!(iss >> _params.resource_params.mem_mb))
115 throw Exception("salomecontainer::setproperty : params.resource_params.mem_mb value not correct : " + value);
116 }
117 else if (name == "cpu_clock")
118 {
119 std::istringstream iss(value);
120 if (!(iss >> _params.resource_params.cpu_clock))
121 throw Exception("salomecontainer::setproperty : params.resource_params.cpu_clock value not correct : " + value);
122 }
123 else if (name == "nb_node")
124 {
125 std::istringstream iss(value);
126 if (!(iss >> _params.resource_params.nb_node))
127 throw Exception("salomecontainer::setproperty : params.nb_node value not correct : " + value);
128 }
129 else if (name == "nb_proc_per_node")
130 {
131 std::istringstream iss(value);
132 if (!(iss >> _params.resource_params.nb_proc_per_node))
133 throw Exception("salomecontainer::setproperty : params.nb_proc_per_node value not correct : " + value);
134 }
135 else if (name == "policy")
136 _params.resource_params.policy = CORBA::string_dup(value.c_str());
137 else if (name == "component_list")
138 {
139 std::string clean_value(value);
140
141 // Step 1: remove blanks
142 while(clean_value.find(" ") != std::string::npos)
143 clean_value = clean_value.erase(clean_value.find(" "), 1);
144
145 // Step 2: get values
146 while(!clean_value.empty())
147 {
148 std::string result("");
149 std::string::size_type loc = clean_value.find(",", 0);
150 if (loc != std::string::npos)
151 {
152 result = clean_value.substr(0, loc);
153 clean_value = clean_value.erase(0, loc+1);
154 }
155 else
156 {
157 result = clean_value;
158 clean_value.erase();
159 }
160 if (result != "," && result != "")
161 {
162 addToComponentList(result);
163 }
164 }
165
166 }
167 else if (name == "resource_list")
168 {
169 std::string clean_value(value);
170
171 // Step 1: remove blanks
172 while(clean_value.find(" ") != std::string::npos)
173 clean_value = clean_value.erase(clean_value.find(" "), 1);
174
175 // Step 2: get values
176 while(!clean_value.empty())
177 {
178 std::string result("");
179 std::string::size_type loc = clean_value.find(",", 0);
180 if (loc != std::string::npos)
181 {
182 result = clean_value.substr(0, loc);
183 clean_value = clean_value.erase(0, loc+1);
184 }
185 else
186 {
187 result = clean_value;
188 clean_value.erase();
189 }
190 if (result != "," && result != "")
191 {
192 addToResourceList(result);
193 }
194 }
195
196 }
197 _propertyMap[name]=value;
198}
199
200void SalomeContainerTools::addToComponentList(const std::string& name)
201{
202 // Search if name is already in the list
203 for (CORBA::ULong i = 0; i < _params.resource_params.componentList.length(); i++)
204 {
205 std::string component_name = _params.resource_params.componentList[i].in();
206 if (component_name == name)
207 return;
208 }
209 // Add name to list
210 CORBA::ULong lgth = _params.resource_params.componentList.length();
211 _params.resource_params.componentList.length(lgth + 1);
212 _params.resource_params.componentList[lgth] = CORBA::string_dup(name.c_str());
213}
214
215void SalomeContainerTools::addToResourceList(const std::string& name)
216{
217 // Search if name is already in the list
218 for (CORBA::ULong i = 0; i < _params.resource_params.resList.length(); i++)
219 {
220 std::string component_name = _params.resource_params.resList[i].in();
221 if (component_name == name)
222 return;
223 }
224 // Add name to list
225 CORBA::ULong lgth = _params.resource_params.resList.length();
226 _params.resource_params.resList.length(lgth + 1);
227 _params.resource_params.resList[lgth] = CORBA::string_dup(name.c_str());
228}
229
231{
232 return std::string(_params.container_name);
233}
234
236{
237 return _params.resource_params.nb_proc_per_node;
238}
239
240void SalomeContainerTools::setContainerName(const std::string& name)
241{
243}
244
245std::string SalomeContainerTools::getNotNullContainerName(const Container *contPtr, const Task *askingNode, bool& isEmpty) const
246{
247 isEmpty=true;
248 std::string name(_params.container_name);
249 if(!name.empty())
250 {
251 isEmpty=false;
252 return name;
253 }
254 else
255 {
256 //give a almost unique name to the container : Pid_Name_Addr
257 std::ostringstream stream;
258 stream << getpid();
259 stream << "_";
260 stream << contPtr->getName();
261 stream << "_";
262 stream << contPtr->getDiscreminantStrOfThis(askingNode);
263 return stream.str();
264 }
265}
266
268{
269 return std::string(_params.resource_params.hostname);
270}
271
272void SalomeContainerToolsBase::SetContainerNameOf(Engines::ContainerParameters& params, const std::string& name)
273{
274 params.container_name=CORBA::string_dup(name.c_str());
275}
276
277std::map<std::string,std::string> SalomeContainerTools::getResourceProperties(const std::string& name) const
278{
279 std::map<std::string,std::string> properties;
280
282 CORBA::ORB_ptr orb = runTime->getOrb();
283 if (!orb) return properties;
284 SALOME_NamingService_Wrapper namingService(orb);
285 SALOME_LifeCycleCORBA lcc(&namingService);
286 CORBA::Object_var obj = namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS);
287 if (CORBA::is_nil(obj))
288 return properties;
289 Engines::ResourcesManager_var resManager = Engines::ResourcesManager::_narrow(obj);
290 if (CORBA::is_nil(resManager))
291 return properties;
292
293 std::ostringstream value;
294 Engines::ResourceDefinition_var resource_definition = resManager->GetResourceDefinition(name.c_str());
295 properties["hostname"]=resource_definition->hostname.in();
296 properties["OS"]=resource_definition->OS.in();
297 value.str(""); value << resource_definition->mem_mb;
298 properties["mem_mb"]=value.str();
299 value.str(""); value << resource_definition->cpu_clock;
300 properties["cpu_clock"]=value.str();
301 value.str(""); value << resource_definition->nb_node;
302 properties["nb_node"]=value.str();
303 value.str(""); value << resource_definition->nb_proc_per_node;
304 properties["nb_proc_per_node"]=value.str();
305 /*
306 properties["component_list"]="";
307 for(CORBA::ULong i=0; i < resource_definition->componentList.length(); i++)
308 {
309 if(i > 0)
310 properties["component_list"]=properties["component_list"]+",";
311 properties["component_list"]=properties["component_list"]+resource_definition->componentList[i].in();
312 }
313 */
314 return properties;
315}
316
321void SalomeContainerToolsBase::Start(const std::vector<std::string>& compoNames, SalomeContainerHelper *schelp, SalomeContainerToolsBase& sct, int& shutdownLevel, const Container *cont, const Task *askingNode)
322{
323 CORBA::ORB_ptr orb(getSALOMERuntime()->getOrb());
325 try
326 {
327 ns.init_orb(orb);
328 }
329 catch(SALOME_Exception& e)
330 {
331 throw Exception("SalomeContainer::start : Unable to contact the SALOME Naming Service");
332 }
333 CORBA::Object_var obj(ns.Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS));
334 Engines::ContainerManager_var contManager(Engines::ContainerManager::_narrow(obj));
335
336 bool isEmptyName;
337 std::string str(sct.getNotNullContainerName(cont,askingNode,isEmptyName));
338 DEBUG_YACSTRACE("SalomeContainer::start " << str <<";"<< sct.getHostName() );
339
340 // Finalize parameters with components found in the container
341
342 for(std::vector<std::string>::const_iterator iter=compoNames.begin();iter!=compoNames.end();iter++)
343 sct.addToComponentList(*iter);
344
345 Engines::ContainerParameters myparams(sct.getParameters());
346 {
347 std::string dftLauchMode(schelp->getDftLaunchMode());
348 myparams.mode=CORBA::string_dup(dftLauchMode.c_str());
349 }
350
351 //If a container_name is given try to find an already existing container in naming service
352 //If not found start a new container with the given parameters
353 if (dynamic_cast<SalomeContainerMonoHelper *>(schelp) && !isEmptyName)
354 {
355 myparams.mode=CORBA::string_dup("getorstart");
356 }
357
358 if (isEmptyName)
359 {
360 shutdownLevel=1;
361 }
362 //sct.setContainerName(str);
363 SetContainerNameOf(myparams,str);
364 Engines::Container_var trueCont(Engines::Container::_nil());
365 if(!isEmptyName && shutdownLevel==999)
366 {
367 //Make this only the first time start is called (_shutdownLevel==999)
368 //If the container is named, first try to get an existing container
369 //If there is an existing container use it and set the shutdown level to 3
370 //If there is no existing container, try to launch a new one and set the shutdown level to 2
371 myparams.mode="get";
372 try
373 {
374 DEBUG_YACSTRACE("GiveContainer " << str << " mode " << myparams.mode);
375 trueCont=contManager->GiveContainer(myparams);
376 }
377 catch( const SALOME::SALOME_Exception& ex )
378 {
379 std::string msg="SalomeContainer::start : no existing container : ";
380 msg += '\n';
381 msg += ex.details.text.in();
382 DEBUG_YACSTRACE( msg );
383 }
384 catch(...)
385 {
386 }
387
388 if(!CORBA::is_nil(trueCont))
389 {
390 shutdownLevel=3;
391 DEBUG_YACSTRACE( "container found: " << str << " " << shutdownLevel );
392 }
393 else
394 {
395 shutdownLevel=2;
396 myparams.mode="start";
397 DEBUG_YACSTRACE( "container not found: " << str << " " << shutdownLevel);
398 }
399 }
400
401 int nbTries=0;
402 while(CORBA::is_nil(trueCont))
403 {
404 try
405 {
406 // --- GiveContainer is used in batch mode to retreive launched containers,
407 // and is equivalent to StartContainer when not in batch.
408 DEBUG_YACSTRACE("GiveContainer " << str << " mode " << myparams.mode);
409 trueCont=contManager->GiveContainer(myparams);
410 }
411 catch( const SALOME::SALOME_Exception& ex )
412 {
413 std::string msg="SalomeContainer::start : Unable to launch container in Salome : ";
414 msg += '\n';
415 msg += ex.details.text.in();
416 throw Exception(msg);
417 }
418 catch(CORBA::COMM_FAILURE&)
419 {
420 //std::cerr << "SalomeContainer::start : CORBA Comm failure detected. Make another try!" << std::endl;
421 DEBUG_YACSTRACE("SalomeContainer::start :" << str << " :CORBA Comm failure detected. Make another try!");
422 nbTries++;
423 if(nbTries > 5)
424 {
425 std::ostringstream oss; oss << "SalomeContainer::start : Unable to launch container " << myparams.container_name << " in Salome : CORBA Comm failure detected";
426 throw Exception( oss.str() );
427 }
428 }
429 catch(CORBA::Exception&)
430 {
431 std::ostringstream oss; oss << "SalomeContainer::start : Unable to launch container " << myparams.container_name << " in Salome : Unexpected CORBA failure detected";
432 throw Exception( oss.str() );
433 }
434 }
435
436 if(CORBA::is_nil(trueCont))
437 {
438 std::ostringstream oss; oss << "SalomeContainer::start : Unable to launch container " << myparams.container_name << " in Salome. Check your CatalogResources.xml file";
439 throw Exception( oss.str() );
440 }
441
442 // TODO : thread safety!
443 schelp->setContainer(askingNode,trueCont);
444
445 CORBA::String_var containerName(trueCont->name()),hostName(trueCont->getHostName());
446 //std::cerr << "SalomeContainer launched : " << containerName << " " << hostName << " " << trueCont->getPID() << std::endl;
447 DEBUG_YACSTRACE("SalomeContainer launched : NS entry : " << containerName << " PID : " << trueCont->getPID() );
448}
449
450CORBA::Object_ptr SalomeContainerToolsBase::LoadComponent(SalomeContainerHelper *launchModeType, Container *cont, Task *askingNode)
451{
452 DEBUG_YACSTRACE("SalomeContainer::loadComponent ");
453 const ComponentInstance *inst(askingNode?askingNode->getComponent():0);
454 {
455 YACS::BASES::AutoLocker<Container> alck(cont);//To be sure
456 if(!cont->isAlreadyStarted(askingNode))
457 cont->start(askingNode);
458 }
459 if(!inst)
460 throw Exception("SalomeContainerToolsBase::LoadComponent : no instance of component in the task requesting for a load of its component !");
461 CORBA::Object_ptr objComponent=CORBA::Object::_nil();
462 {
463 YACS::BASES::AutoLocker<Container> alck(cont);//To be sure
464 std::string compoName(inst->getCompoName());
465 Engines::Container_var container(launchModeType->getContainer(askingNode));
466
467 char *reason;
468 bool isLoadable(container->load_component_Library(compoName.c_str(), reason));
469 if(isLoadable)
470 objComponent=CreateComponentInstance(cont,container,inst);
471 }
472 return objComponent;
473}
474
475CORBA::Object_ptr SalomeContainerToolsBase::CreateComponentInstance(Container *cont, Engines::Container_ptr contPtr, const ComponentInstance *inst)
476{
477 if(!inst)
478 throw Exception("SalomeContainerToolsBase::CreateComponentInstance : no instance of component in the task requesting for a load of its component !");
479 char *reason(0);
480 std::string compoName(inst->getCompoName());
481 CORBA::Object_ptr objComponent=CORBA::Object::_nil();
482 Proc* p(cont->getProc());
483 // prepare component instance properties
484 Engines::FieldsDict_var env(new Engines::FieldsDict);
485 std::map<std::string, std::string> properties(inst->getProperties());
486 if(p)
487 {
488 std::map<std::string,std::string> procMap=p->getProperties();
489 properties.insert(procMap.begin(),procMap.end());
490 }
491
492 std::map<std::string, std::string>::const_iterator itm;
493 env->length(properties.size());
494 int item=0;
495 for(itm = properties.begin(); itm != properties.end(); ++itm, item++)
496 {
497 DEBUG_YACSTRACE("envname="<<itm->first<<" envvalue="<< itm->second);
498 env[item].key= CORBA::string_dup(itm->first.c_str());
499 env[item].value <<= itm->second.c_str();
500 }
501
502 objComponent=contPtr->create_component_instance_env(compoName.c_str(), env, reason);
503 if(CORBA::is_nil(objComponent))
504 {
505 std::string text="Error while trying to create a new component: component '"+ compoName;
506 text=text+"' is not installed or it's a wrong name";
507 text += '\n';
508 text += reason;
509 CORBA::string_free(reason);
510 throw Exception(text);
511 }
512 return objComponent;
513}
514
515std::string SalomeContainerToolsBase::GetPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode)
516{
517 if(cont->isAlreadyStarted(askingNode))
518 {
519 Engines::Container_var container(launchModeType->getContainer(askingNode));
520 const char *what="/";
521 CORBA::String_var corbaStr(container->name());
522 std::string ret(corbaStr);
523
524 //Salome FOREVER ...
525 std::string::size_type i=ret.find_first_of(what,0);
526 i=ret.find_first_of(what, i==std::string::npos ? i:i+1);
527 if(i!=std::string::npos)
528 return ret.substr(i+1);
529 return ret;
530 }
531 else
532 return "Not placed yet !!!";
533}
534
535std::string SalomeContainerToolsBase::GetFullPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode)
536{
537 if(cont->isAlreadyStarted(askingNode))
538 {
539 Engines::Container_var container(launchModeType->getContainer(askingNode));
540 try
541 {
542 CORBA::String_var corbaStr(container->name());
543 std::string ret(corbaStr);
544 return ret;
545 }
546 catch(...)
547 {
548 return "Unknown_placement";
549 }
550 }
551 else
552 return "Not_placed_yet";
553}
554
555Engines::ContainerParameters SalomeContainerToolsDecorator::getParameters() const
556{
557 Engines::ContainerParameters ret(_decorated->getParameters());
558 std::string st(ret.resource_params.hostname);
559 if(!st.empty())
560 return ret;
561 int nbProcPerNode(this->_nb_cores_per_worker);
562 std::size_t iPos(_vh->locateTask(_node)),nPos(_vh->size());
563 if(_vh->size()!=_pg->getNumberOfWorkers(nbProcPerNode))
564 throw YACS::Exception("SalomeContainerToolsDecorator::getParameters : Internal error !");
565 std::string zeMachine(_pg->deduceMachineFrom(iPos,nbProcPerNode));
566 ret.resource_params.hostname=CORBA::string_dup(zeMachine.c_str());
567 return ret;
568}
#define DEBUG_YACSTRACE(msg)
Definition: YacsTrace.hxx:53
void init_orb(CORBA::ORB_ptr orb=0) override
CORBA::Object_ptr Resolve(const char *Path) override
Base class for all component instances.
const std::string & getCompoName() const
virtual void start(const Task *askingNode)=0
virtual std::string getDiscreminantStrOfThis(const Task *askingNode) const
Definition: Container.cxx:45
virtual bool isAlreadyStarted(const Task *askingNode) const =0
virtual std::string getName() const
Definition: Container.hxx:81
std::map< std::string, std::string > getProperties()
Definition: Node.cxx:509
int getNumberOfWorkers(int nbCoresPerWorker) const
Definition: PlayGround.cxx:579
std::string deduceMachineFrom(int workerId, int nbProcPerNode) const
Definition: PlayGround.cxx:570
Base class for all schema objects.
Definition: Proc.hxx:44
std::map< std::string, std::string > getProperties() const
CORBA::ORB_ptr getOrb() const
virtual Engines::Container_var getContainer(const Task *askingNode) const =0
virtual std::string getDftLaunchMode() const =0
virtual void setContainer(const Task *askingNode, Engines::Container_var cont)=0
static std::string GetPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode)
virtual Engines::ContainerParameters getParameters() const =0
virtual std::string getHostName() const =0
static void Start(const std::vector< std::string > &compoNames, SalomeContainerHelper *schelp, SalomeContainerToolsBase &sct, int &shutdownLevel, const Container *cont, const Task *askingNode)
static CORBA::Object_ptr CreateComponentInstance(Container *cont, Engines::Container_ptr contPtr, const ComponentInstance *inst)
static CORBA::Object_ptr LoadComponent(SalomeContainerHelper *launchModeType, Container *cont, Task *askingNode)
static std::string GetFullPlacementId(const SalomeContainerHelper *launchModeType, const Container *cont, const Task *askingNode)
virtual void addToComponentList(const std::string &name)=0
virtual std::string getNotNullContainerName(const Container *contPtr, const Task *askingNode, bool &isEmpty) const =0
static void SetContainerNameOf(Engines::ContainerParameters &params, const std::string &name)
Engines::ContainerParameters getParameters() const override
std::map< std::string, std::string > getResourceProperties(const std::string &name) const override
std::string getHostName() const override
std::map< std::string, std::string > _propertyMap
std::string getProperty(const std::string &name) const override
Engines::ContainerParameters _params
std::string getNotNullContainerName(const Container *contPtr, const Task *askingNode, bool &isEmpty) const override
std::string getContainerName() const override
void addToComponentList(const std::string &name) override
void setProperty(const std::string &name, const std::string &value) override
void addToResourceList(const std::string &name) override
void setContainerName(const std::string &name) override
std::size_t locateTask(const Task *node) const
virtual ComponentInstance * getComponent()=0
Proc * p
Definition: driver.cxx:216
YACSRUNTIMESALOME_EXPORT RuntimeSALOME * getSALOMERuntime()
CORBA::ORB_ptr orb
Definition: yacsSrv.cxx:39