1 // Copyright (C) 2006-2013 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #define private public
24 #define protected public
25 #include <omniORB4/CORBA.h>
26 #include <omniORB4/internal/typecode.h>
29 #include "RuntimeSALOME.hxx"
30 #include "SalomeContainer.hxx"
31 #include "SalomeComponent.hxx"
34 #include "SALOME_NamingService.hxx"
35 #include "SALOME_LifeCycleCORBA.hxx"
36 #include "SALOME_ContainerManager.hxx"
37 #include "Basics_Utils.hxx"
45 #define getpid _getpid
49 #include "YacsTrace.hxx"
51 using namespace YACS::ENGINE;
54 SalomeContainer::SalomeContainer():_trueCont(Engines::Container::_nil()),_type("mono"),_shutdownLevel(999)
56 /* Init ContainerParameters */
57 SALOME_LifeCycleCORBA::preSet(_params);
58 _params.mode= "start";
61 SalomeContainer::SalomeContainer(const SalomeContainer& other)
63 _trueCont(Engines::Container::_nil()),
65 _shutdownLevel(other._shutdownLevel),
66 _params(other._params)
70 SalomeContainer::~SalomeContainer()
74 void SalomeContainer::lock()
79 void SalomeContainer::unLock()
84 Container *SalomeContainer::clone() const
86 if(_isAttachedOnCloning)
89 return (Container*) (this);
92 return new SalomeContainer(*this);
95 void SalomeContainer::checkCapabilityToDealWith(const ComponentInstance *inst) const throw(YACS::Exception)
97 if(inst->getKind()!=SalomeComponent::KIND)
98 throw Exception("SalomeContainer::checkCapabilityToDealWith : SalomeContainer is not able to deal with this type of ComponentInstance.");
101 void SalomeContainer::setProperty(const std::string& name, const std::string& value)
103 DEBTRACE("SalomeContainer::setProperty : " << name << " ; " << value);
106 if (name == "container_name")
107 _params.container_name = CORBA::string_dup(value.c_str());
108 else if (name == "type")
111 _params.mode = "start";
112 else if (value == "multi")
113 _params.mode = "getorstart";
115 throw Exception("SalomeContainer::setProperty : type value is not correct (mono or multi): " + value);
118 else if (name == "workingdir")
119 _params.workingdir = CORBA::string_dup(value.c_str());
120 else if (name == "nb_parallel_procs")
122 std::istringstream iss(value);
123 if (!(iss >> _params.nb_proc))
124 throw Exception("salomecontainer::setproperty : params.nb_proc value not correct : " + value);
126 else if (name == "isMPI")
129 _params.isMPI = true;
130 else if (value == "false")
131 _params.isMPI = false;
133 throw Exception("SalomeContainer::setProperty : params.isMPI value not correct : " + value);
135 else if (name == "parallelLib")
136 _params.parallelLib = CORBA::string_dup(value.c_str());
139 else if (name == "name")
140 _params.resource_params.name = CORBA::string_dup(value.c_str());
141 else if (name == "hostname")
142 _params.resource_params.hostname = CORBA::string_dup(value.c_str());
143 else if (name == "OS")
144 _params.resource_params.OS = CORBA::string_dup(value.c_str());
145 else if (name == "nb_resource_procs")
147 std::istringstream iss(value);
148 if (!(iss >> _params.resource_params.nb_proc))
149 throw Exception("salomecontainer::setproperty : params.resource_params.nb_proc value not correct : " + value);
151 else if (name == "mem_mb")
153 std::istringstream iss(value);
154 if (!(iss >> _params.resource_params.mem_mb))
155 throw Exception("salomecontainer::setproperty : params.resource_params.mem_mb value not correct : " + value);
157 else if (name == "cpu_clock")
159 std::istringstream iss(value);
160 if (!(iss >> _params.resource_params.cpu_clock))
161 throw Exception("salomecontainer::setproperty : params.resource_params.cpu_clock value not correct : " + value);
163 else if (name == "nb_node")
165 std::istringstream iss(value);
166 if (!(iss >> _params.resource_params.nb_node))
167 throw Exception("salomecontainer::setproperty : params.nb_node value not correct : " + value);
169 else if (name == "nb_proc_per_node")
171 std::istringstream iss(value);
172 if (!(iss >> _params.resource_params.nb_proc_per_node))
173 throw Exception("salomecontainer::setproperty : params.nb_proc_per_node value not correct : " + value);
175 else if (name == "policy")
176 _params.resource_params.policy = CORBA::string_dup(value.c_str());
177 else if (name == "component_list")
179 std::string clean_value(value);
181 // Step 1: remove blanks
182 while(clean_value.find(" ") != std::string::npos)
183 clean_value = clean_value.erase(clean_value.find(" "), 1);
185 // Step 2: get values
186 while(!clean_value.empty())
188 std::string result("");
189 std::string::size_type loc = clean_value.find(",", 0);
190 if (loc != std::string::npos)
192 result = clean_value.substr(0, loc);
193 clean_value = clean_value.erase(0, loc+1);
197 result = clean_value;
200 if (result != "," && result != "")
202 addToComponentList(result);
207 else if (name == "resource_list")
209 std::string clean_value(value);
211 // Step 1: remove blanks
212 while(clean_value.find(" ") != std::string::npos)
213 clean_value = clean_value.erase(clean_value.find(" "), 1);
215 // Step 2: get values
216 while(!clean_value.empty())
218 std::string result("");
219 std::string::size_type loc = clean_value.find(",", 0);
220 if (loc != std::string::npos)
222 result = clean_value.substr(0, loc);
223 clean_value = clean_value.erase(0, loc+1);
227 result = clean_value;
230 if (result != "," && result != "")
232 addToResourceList(result);
238 Container::setProperty(name, value);
241 void SalomeContainer::addComponentName(std::string name)
243 _componentNames.push_back(name);
246 //! Load a component instance in this container
248 * \param inst the component instance to load
250 CORBA::Object_ptr SalomeContainer::loadComponent(ComponentInstance *inst)
252 DEBTRACE("SalomeContainer::loadComponent ");
254 if(!isAlreadyStarted(inst))
268 CORBA::Object_ptr objComponent=CORBA::Object::_nil();
269 std::string compoName=inst->getCompoName();
270 const char* componentName=compoName.c_str();
271 Engines::Container_var container;
273 container=_trueContainers[inst];
279 bool isLoadable = container->load_component_Library(componentName, reason);
282 CORBA::string_free(reason);
287 std::string value=p->getProperty("DefaultStudyID");
289 studyid= atoi(value.c_str());
291 // prepare component instance properties
292 Engines::FieldsDict_var env = new Engines::FieldsDict;
293 std::map<std::string, std::string> properties = inst->getProperties();
296 std::map<std::string,std::string> procMap=p->getProperties();
297 properties.insert(procMap.begin(),procMap.end());
300 std::map<std::string, std::string>::const_iterator itm;
301 env->length(properties.size());
303 for(itm = properties.begin(); itm != properties.end(); ++itm, item++)
305 DEBTRACE("envname="<<itm->first<<" envvalue="<< itm->second);
306 env[item].key= CORBA::string_dup(itm->first.c_str());
307 env[item].value <<= itm->second.c_str();
310 objComponent=container->create_component_instance_env(componentName, studyid, env, reason);
313 if(CORBA::is_nil(objComponent))
316 std::string text="Error while trying to create a new component: component '"+ compoName;
317 text=text+"' is not installed or it's a wrong name";
320 CORBA::string_free(reason);
321 throw Exception(text);
327 //! Get the container placement id for a component instance
329 * \param inst the component instance
330 * \return the placement id
332 std::string SalomeContainer::getPlacementId(const ComponentInstance *inst) const
335 if(isAlreadyStarted(inst))
337 Engines::Container_var container=_trueCont;
340 std::map<const ComponentInstance *, Engines::Container_var>::const_iterator found = _trueContainers.find(inst);
341 container=found->second;
343 const char *what="/";
344 CORBA::String_var corbaStr=container->name();
345 string ret(corbaStr);
348 std::string::size_type i=ret.find_first_of(what,0);
349 i=ret.find_first_of(what, i==std::string::npos ? i:i+1);
350 if(i!=std::string::npos)
351 return ret.substr(i+1);
355 return "Not placed yet !!!";
358 //! Get the container full path for a component instance
360 * \param inst the component instance
361 * \return the full placement id
363 std::string SalomeContainer::getFullPlacementId(const ComponentInstance *inst) const
366 if(isAlreadyStarted(inst))
368 Engines::Container_var container=_trueCont;
371 std::map<const ComponentInstance *, Engines::Container_var>::const_iterator found = _trueContainers.find(inst);
372 container=found->second;
376 CORBA::String_var corbaStr=container->name();
377 string ret(corbaStr);
382 return "Unknown_placement";
386 return "Not_placed_yet";
389 //! Check if the component instance container is already started
391 * \param inst the component instance
392 * \return true, if the container is already started, else false
394 bool SalomeContainer::isAlreadyStarted(const ComponentInstance *inst) const
398 if(CORBA::is_nil(_trueCont))
405 if(_trueContainers.count(inst)==0)
412 Engines::Container_ptr SalomeContainer::getContainerPtr(const ComponentInstance *inst) const
416 if(CORBA::is_nil(_trueCont))
417 return Engines::Container::_nil();
419 return Engines::Container::_duplicate(_trueCont);
423 if(_trueContainers.count(inst)==0)
424 return Engines::Container::_nil();
427 std::map<const ComponentInstance *,Engines::Container_var>::const_iterator iter=_trueContainers.find(inst);
428 return Engines::Container::_duplicate(iter->second);
433 //! Start a salome container (true salome container not yacs one) with given ContainerParameters (_params)
435 * \param inst the component instance
437 void SalomeContainer::start(const ComponentInstance *inst) throw(YACS::Exception)
439 CORBA::ORB_ptr orb=getSALOMERuntime()->getOrb();
440 SALOME_NamingService ns;
445 catch(SALOME_Exception& e)
447 throw Exception("SalomeContainer::start : Unable to contact the SALOME Naming Service");
449 CORBA::Object_var obj=ns.Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS);
450 Engines::ContainerManager_var contManager=Engines::ContainerManager::_narrow(obj);
452 std::string str(_params.container_name);
453 DEBTRACE("SalomeContainer::start " << str <<";"<<_params.resource_params.hostname <<";"<<_type);
455 // Finalize parameters with components found in the container
456 std::vector<std::string>::iterator iter;
457 for(CORBA::ULong i=0; i < _componentNames.size();i++)
458 addToComponentList(_componentNames[i]);
459 Engines::ContainerParameters myparams = _params;
461 bool namedContainer=false;
465 //If a container_name is given try to find an already existing container in naming service
466 //If not found start a new container with the given parameters
467 if (_type=="mono" && str != "")
469 myparams.mode="getorstart";
474 //give a almost unique name to the container : Pid_Name_Addr
475 std::ostringstream stream;
480 stream << (void *)(this);
481 DEBTRACE("container_name="<<stream.str());
482 myparams.container_name=CORBA::string_dup(stream.str().c_str());
486 _trueCont=Engines::Container::_nil();
487 if(namedContainer && _shutdownLevel==999)
489 //Make this only the first time start is called (_shutdownLevel==999)
490 //If the container is named, first try to get an existing container
491 //If there is an existing container use it and set the shutdown level to 3
492 //If there is no existing container, try to launch a new one and set the shutdown level to 2
496 _trueCont=contManager->GiveContainer(myparams);
498 catch( const SALOME::SALOME_Exception& ex )
500 std::string msg="SalomeContainer::start : no existing container : ";
502 msg += ex.details.text.in();
509 if(!CORBA::is_nil(_trueCont))
512 DEBTRACE( "container found: " << str << " " << _shutdownLevel );
517 myparams.mode="start";
518 DEBTRACE( "container not found: " << str << " " << _shutdownLevel);
522 if(CORBA::is_nil(_trueCont))
525 // --- GiveContainer is used in batch mode to retreive launched containers,
526 // and is equivalent to StartContainer when not in batch.
527 _trueCont=contManager->GiveContainer(myparams);
529 catch( const SALOME::SALOME_Exception& ex )
531 std::string msg="SalomeContainer::start : Unable to launch container in Salome : ";
533 msg += ex.details.text.in();
534 throw Exception(msg);
536 catch(CORBA::COMM_FAILURE&)
538 throw Exception("SalomeContainer::start : Unable to launch container in Salome : CORBA Comm failure detected");
540 catch(CORBA::Exception&)
542 throw Exception("SalomeContainer::start : Unable to launch container in Salome : Unexpected CORBA failure detected");
545 if(CORBA::is_nil(_trueCont))
546 throw Exception("SalomeContainer::start : Unable to launch container in Salome. Check your CatalogResources.xml file");
548 _trueContainers[inst]=_trueCont;
550 CORBA::String_var containerName=_trueCont->name();
551 CORBA::String_var hostName=_trueCont->getHostName();
552 std::cerr << "SalomeContainer launched : " << containerName << " " << hostName << " " << _trueCont->getPID() << std::endl;
555 DEBTRACE(_trueCont->_PR_getobj()->pd_refCount );
556 std::map<const ComponentInstance *, Engines::Container_var >::const_iterator it;
557 for(it = _trueContainers.begin(); it != _trueContainers.end(); ++it)
559 DEBTRACE(it->second->_PR_getobj()->pd_refCount );
564 void SalomeContainer::shutdown(int level)
566 DEBTRACE("SalomeContainer::shutdown: " << _name << "," << level << "," << _shutdownLevel);
567 if(level < _shutdownLevel)
571 //shutdown the SALOME containers
574 std::map<const ComponentInstance *, Engines::Container_var >::const_iterator it;
575 for(it = _trueContainers.begin(); it != _trueContainers.end(); ++it)
579 DEBTRACE("shutdown SALOME container: " );
580 CORBA::String_var containerName=it->second->name();
581 DEBTRACE(containerName);
582 it->second->Shutdown();
583 std::cerr << "shutdown SALOME container: " << containerName << std::endl;
585 catch(CORBA::Exception&)
587 DEBTRACE("Unexpected CORBA failure detected." );
591 DEBTRACE("Unknown exception ignored." );
594 _trueContainers.clear();
600 DEBTRACE("shutdown SALOME container: " );
601 CORBA::String_var containerName=_trueCont->name();
602 DEBTRACE(containerName);
603 _trueCont->Shutdown();
604 std::cerr << "shutdown SALOME container: " << containerName << std::endl;
608 DEBTRACE("Unknown exception ignored." );
610 _trueCont=Engines::Container::_nil();
615 SalomeContainer::addToComponentList(const std::string & name)
617 // Search if name is already in the list
618 for (CORBA::ULong i = 0; i < _params.resource_params.componentList.length(); i++)
620 std::string component_name = _params.resource_params.componentList[i].in();
621 if (component_name == name)
626 CORBA::ULong lgth = _params.resource_params.componentList.length();
627 _params.resource_params.componentList.length(lgth + 1);
628 _params.resource_params.componentList[lgth] = CORBA::string_dup(name.c_str());
632 SalomeContainer::addToResourceList(const std::string & name)
634 // Search if name is already in the list
635 for (CORBA::ULong i = 0; i < _params.resource_params.resList.length(); i++)
637 std::string component_name = _params.resource_params.resList[i].in();
638 if (component_name == name)
643 CORBA::ULong lgth = _params.resource_params.resList.length();
644 _params.resource_params.resList.length(lgth + 1);
645 _params.resource_params.resList[lgth] = CORBA::string_dup(name.c_str());
648 std::map<std::string,std::string> SalomeContainer::getResourceProperties(const std::string& name)
650 std::map<std::string,std::string> properties;
652 YACS::ENGINE::RuntimeSALOME* runTime = YACS::ENGINE::getSALOMERuntime();
653 CORBA::ORB_ptr orb = runTime->getOrb();
654 if (!orb) return properties;
655 SALOME_NamingService namingService(orb);
656 SALOME_LifeCycleCORBA lcc(&namingService);
657 CORBA::Object_var obj = namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS);
658 if (CORBA::is_nil(obj)) return properties;
659 Engines::ResourcesManager_var resManager = Engines::ResourcesManager::_narrow(obj);
660 if (CORBA::is_nil(resManager)) return properties;
662 std::ostringstream value;
663 Engines::ResourceDefinition_var resource_definition = resManager->GetResourceDefinition(name.c_str());
664 properties["hostname"]=resource_definition->hostname.in();
665 properties["OS"]=resource_definition->OS.in();
666 value.str(""); value << resource_definition->mem_mb;
667 properties["mem_mb"]=value.str();
668 value.str(""); value << resource_definition->cpu_clock;
669 properties["cpu_clock"]=value.str();
670 value.str(""); value << resource_definition->nb_node;
671 properties["nb_node"]=value.str();
672 value.str(""); value << resource_definition->nb_proc_per_node;
673 properties["nb_proc_per_node"]=value.str();
675 properties["component_list"]="";
676 for(CORBA::ULong i=0; i < resource_definition->componentList.length(); i++)
679 properties["component_list"]=properties["component_list"]+",";
680 properties["component_list"]=properties["component_list"]+resource_definition->componentList[i].in();