1 // Copyright (C) 2006-2014 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, or (at your option) any later version.
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 Container *SalomeContainer::cloneAlways() const
97 return new SalomeContainer(*this);
100 void SalomeContainer::checkCapabilityToDealWith(const ComponentInstance *inst) const throw(YACS::Exception)
102 if(inst->getKind()!=SalomeComponent::KIND)
103 throw Exception("SalomeContainer::checkCapabilityToDealWith : SalomeContainer is not able to deal with this type of ComponentInstance.");
106 void SalomeContainer::setProperty(const std::string& name, const std::string& value)
108 DEBTRACE("SalomeContainer::setProperty : " << name << " ; " << value);
111 if (name == "container_name")
112 _params.container_name = CORBA::string_dup(value.c_str());
113 else if (name == "type")
116 _params.mode = "start";
117 else if (value == "multi")
118 _params.mode = "getorstart";
120 throw Exception("SalomeContainer::setProperty : type value is not correct (mono or multi): " + value);
123 else if (name == "workingdir")
124 _params.workingdir = CORBA::string_dup(value.c_str());
125 else if (name == "nb_parallel_procs")
127 std::istringstream iss(value);
128 if (!(iss >> _params.nb_proc))
129 throw Exception("salomecontainer::setproperty : params.nb_proc value not correct : " + value);
131 else if (name == "isMPI")
134 _params.isMPI = true;
135 else if (value == "false")
136 _params.isMPI = false;
138 throw Exception("SalomeContainer::setProperty : params.isMPI value not correct : " + value);
140 else if (name == "parallelLib")
141 _params.parallelLib = CORBA::string_dup(value.c_str());
144 else if (name == "name")
145 _params.resource_params.name = CORBA::string_dup(value.c_str());
146 else if (name == "hostname")
147 _params.resource_params.hostname = CORBA::string_dup(value.c_str());
148 else if (name == "OS")
149 _params.resource_params.OS = CORBA::string_dup(value.c_str());
150 else if (name == "nb_resource_procs")
152 std::istringstream iss(value);
153 if (!(iss >> _params.resource_params.nb_proc))
154 throw Exception("salomecontainer::setproperty : params.resource_params.nb_proc value not correct : " + value);
156 else if (name == "mem_mb")
158 std::istringstream iss(value);
159 if (!(iss >> _params.resource_params.mem_mb))
160 throw Exception("salomecontainer::setproperty : params.resource_params.mem_mb value not correct : " + value);
162 else if (name == "cpu_clock")
164 std::istringstream iss(value);
165 if (!(iss >> _params.resource_params.cpu_clock))
166 throw Exception("salomecontainer::setproperty : params.resource_params.cpu_clock value not correct : " + value);
168 else if (name == "nb_node")
170 std::istringstream iss(value);
171 if (!(iss >> _params.resource_params.nb_node))
172 throw Exception("salomecontainer::setproperty : params.nb_node value not correct : " + value);
174 else if (name == "nb_proc_per_node")
176 std::istringstream iss(value);
177 if (!(iss >> _params.resource_params.nb_proc_per_node))
178 throw Exception("salomecontainer::setproperty : params.nb_proc_per_node value not correct : " + value);
180 else if (name == "policy")
181 _params.resource_params.policy = CORBA::string_dup(value.c_str());
182 else if (name == "component_list")
184 std::string clean_value(value);
186 // Step 1: remove blanks
187 while(clean_value.find(" ") != std::string::npos)
188 clean_value = clean_value.erase(clean_value.find(" "), 1);
190 // Step 2: get values
191 while(!clean_value.empty())
193 std::string result("");
194 std::string::size_type loc = clean_value.find(",", 0);
195 if (loc != std::string::npos)
197 result = clean_value.substr(0, loc);
198 clean_value = clean_value.erase(0, loc+1);
202 result = clean_value;
205 if (result != "," && result != "")
207 addToComponentList(result);
212 else if (name == "resource_list")
214 std::string clean_value(value);
216 // Step 1: remove blanks
217 while(clean_value.find(" ") != std::string::npos)
218 clean_value = clean_value.erase(clean_value.find(" "), 1);
220 // Step 2: get values
221 while(!clean_value.empty())
223 std::string result("");
224 std::string::size_type loc = clean_value.find(",", 0);
225 if (loc != std::string::npos)
227 result = clean_value.substr(0, loc);
228 clean_value = clean_value.erase(0, loc+1);
232 result = clean_value;
235 if (result != "," && result != "")
237 addToResourceList(result);
243 Container::setProperty(name, value);
246 void SalomeContainer::addComponentName(std::string name)
248 _componentNames.push_back(name);
251 //! Load a component instance in this container
253 * \param inst the component instance to load
255 CORBA::Object_ptr SalomeContainer::loadComponent(ComponentInstance *inst)
257 DEBTRACE("SalomeContainer::loadComponent ");
259 if(!isAlreadyStarted(inst))
273 CORBA::Object_ptr objComponent=CORBA::Object::_nil();
274 std::string compoName=inst->getCompoName();
275 const char* componentName=compoName.c_str();
276 Engines::Container_var container;
278 container=_trueContainers[inst];
284 bool isLoadable = container->load_component_Library(componentName, reason);
287 CORBA::string_free(reason);
292 std::string value=p->getProperty("DefaultStudyID");
294 studyid= atoi(value.c_str());
296 // prepare component instance properties
297 Engines::FieldsDict_var env = new Engines::FieldsDict;
298 std::map<std::string, std::string> properties = inst->getProperties();
301 std::map<std::string,std::string> procMap=p->getProperties();
302 properties.insert(procMap.begin(),procMap.end());
305 std::map<std::string, std::string>::const_iterator itm;
306 env->length(properties.size());
308 for(itm = properties.begin(); itm != properties.end(); ++itm, item++)
310 DEBTRACE("envname="<<itm->first<<" envvalue="<< itm->second);
311 env[item].key= CORBA::string_dup(itm->first.c_str());
312 env[item].value <<= itm->second.c_str();
315 objComponent=container->create_component_instance_env(componentName, studyid, env, reason);
318 if(CORBA::is_nil(objComponent))
321 std::string text="Error while trying to create a new component: component '"+ compoName;
322 text=text+"' is not installed or it's a wrong name";
325 CORBA::string_free(reason);
326 throw Exception(text);
332 //! Get the container placement id for a component instance
334 * \param inst the component instance
335 * \return the placement id
337 std::string SalomeContainer::getPlacementId(const ComponentInstance *inst) const
340 if(isAlreadyStarted(inst))
342 Engines::Container_var container=_trueCont;
345 std::map<const ComponentInstance *, Engines::Container_var>::const_iterator found = _trueContainers.find(inst);
346 container=found->second;
348 const char *what="/";
349 CORBA::String_var corbaStr=container->name();
350 string ret(corbaStr);
353 std::string::size_type i=ret.find_first_of(what,0);
354 i=ret.find_first_of(what, i==std::string::npos ? i:i+1);
355 if(i!=std::string::npos)
356 return ret.substr(i+1);
360 return "Not placed yet !!!";
363 //! Get the container full path for a component instance
365 * \param inst the component instance
366 * \return the full placement id
368 std::string SalomeContainer::getFullPlacementId(const ComponentInstance *inst) const
371 if(isAlreadyStarted(inst))
373 Engines::Container_var container=_trueCont;
376 std::map<const ComponentInstance *, Engines::Container_var>::const_iterator found = _trueContainers.find(inst);
377 container=found->second;
381 CORBA::String_var corbaStr=container->name();
382 string ret(corbaStr);
387 return "Unknown_placement";
391 return "Not_placed_yet";
394 //! Check if the component instance container is already started
396 * \param inst the component instance
397 * \return true, if the container is already started, else false
399 bool SalomeContainer::isAlreadyStarted(const ComponentInstance *inst) const
403 if(CORBA::is_nil(_trueCont))
410 if(_trueContainers.count(inst)==0)
417 Engines::Container_ptr SalomeContainer::getContainerPtr(const ComponentInstance *inst) const
421 if(CORBA::is_nil(_trueCont))
422 return Engines::Container::_nil();
424 return Engines::Container::_duplicate(_trueCont);
428 if(_trueContainers.count(inst)==0)
429 return Engines::Container::_nil();
432 std::map<const ComponentInstance *,Engines::Container_var>::const_iterator iter=_trueContainers.find(inst);
433 return Engines::Container::_duplicate(iter->second);
438 //! Start a salome container (true salome container not yacs one) with given ContainerParameters (_params)
440 * \param inst the component instance
442 void SalomeContainer::start(const ComponentInstance *inst) throw(YACS::Exception)
444 CORBA::ORB_ptr orb=getSALOMERuntime()->getOrb();
445 SALOME_NamingService ns;
450 catch(SALOME_Exception& e)
452 throw Exception("SalomeContainer::start : Unable to contact the SALOME Naming Service");
454 CORBA::Object_var obj=ns.Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS);
455 Engines::ContainerManager_var contManager=Engines::ContainerManager::_narrow(obj);
457 std::string str(_params.container_name);
458 DEBTRACE("SalomeContainer::start " << str <<";"<<_params.resource_params.hostname <<";"<<_type);
460 // Finalize parameters with components found in the container
461 std::vector<std::string>::iterator iter;
462 for(CORBA::ULong i=0; i < _componentNames.size();i++)
463 addToComponentList(_componentNames[i]);
464 Engines::ContainerParameters myparams = _params;
466 bool namedContainer=false;
470 //If a container_name is given try to find an already existing container in naming service
471 //If not found start a new container with the given parameters
472 if (_type=="mono" && str != "")
474 myparams.mode="getorstart";
479 //give a almost unique name to the container : Pid_Name_Addr
480 std::ostringstream stream;
485 stream << (void *)(this);
486 DEBTRACE("container_name="<<stream.str());
487 myparams.container_name=CORBA::string_dup(stream.str().c_str());
491 _trueCont=Engines::Container::_nil();
492 if(namedContainer && _shutdownLevel==999)
494 //Make this only the first time start is called (_shutdownLevel==999)
495 //If the container is named, first try to get an existing container
496 //If there is an existing container use it and set the shutdown level to 3
497 //If there is no existing container, try to launch a new one and set the shutdown level to 2
501 _trueCont=contManager->GiveContainer(myparams);
503 catch( const SALOME::SALOME_Exception& ex )
505 std::string msg="SalomeContainer::start : no existing container : ";
507 msg += ex.details.text.in();
514 if(!CORBA::is_nil(_trueCont))
517 DEBTRACE( "container found: " << str << " " << _shutdownLevel );
522 myparams.mode="start";
523 DEBTRACE( "container not found: " << str << " " << _shutdownLevel);
527 if(CORBA::is_nil(_trueCont))
530 // --- GiveContainer is used in batch mode to retreive launched containers,
531 // and is equivalent to StartContainer when not in batch.
532 _trueCont=contManager->GiveContainer(myparams);
534 catch( const SALOME::SALOME_Exception& ex )
536 std::string msg="SalomeContainer::start : Unable to launch container in Salome : ";
538 msg += ex.details.text.in();
539 throw Exception(msg);
541 catch(CORBA::COMM_FAILURE&)
543 throw Exception("SalomeContainer::start : Unable to launch container in Salome : CORBA Comm failure detected");
545 catch(CORBA::Exception&)
547 throw Exception("SalomeContainer::start : Unable to launch container in Salome : Unexpected CORBA failure detected");
550 if(CORBA::is_nil(_trueCont))
551 throw Exception("SalomeContainer::start : Unable to launch container in Salome. Check your CatalogResources.xml file");
553 _trueContainers[inst]=_trueCont;
555 CORBA::String_var containerName=_trueCont->name();
556 CORBA::String_var hostName=_trueCont->getHostName();
557 std::cerr << "SalomeContainer launched : " << containerName << " " << hostName << " " << _trueCont->getPID() << std::endl;
560 DEBTRACE(_trueCont->_PR_getobj()->pd_refCount );
561 std::map<const ComponentInstance *, Engines::Container_var >::const_iterator it;
562 for(it = _trueContainers.begin(); it != _trueContainers.end(); ++it)
564 DEBTRACE(it->second->_PR_getobj()->pd_refCount );
569 void SalomeContainer::shutdown(int level)
571 DEBTRACE("SalomeContainer::shutdown: " << _name << "," << level << "," << _shutdownLevel);
572 if(level < _shutdownLevel)
576 //shutdown the SALOME containers
579 std::map<const ComponentInstance *, Engines::Container_var >::const_iterator it;
580 for(it = _trueContainers.begin(); it != _trueContainers.end(); ++it)
584 DEBTRACE("shutdown SALOME container: " );
585 CORBA::String_var containerName=it->second->name();
586 DEBTRACE(containerName);
587 it->second->Shutdown();
588 std::cerr << "shutdown SALOME container: " << containerName << std::endl;
590 catch(CORBA::Exception&)
592 DEBTRACE("Unexpected CORBA failure detected." );
596 DEBTRACE("Unknown exception ignored." );
599 _trueContainers.clear();
605 DEBTRACE("shutdown SALOME container: " );
606 CORBA::String_var containerName=_trueCont->name();
607 DEBTRACE(containerName);
608 _trueCont->Shutdown();
609 std::cerr << "shutdown SALOME container: " << containerName << std::endl;
613 DEBTRACE("Unknown exception ignored." );
615 _trueCont=Engines::Container::_nil();
620 SalomeContainer::addToComponentList(const std::string & name)
622 // Search if name is already in the list
623 for (CORBA::ULong i = 0; i < _params.resource_params.componentList.length(); i++)
625 std::string component_name = _params.resource_params.componentList[i].in();
626 if (component_name == name)
631 CORBA::ULong lgth = _params.resource_params.componentList.length();
632 _params.resource_params.componentList.length(lgth + 1);
633 _params.resource_params.componentList[lgth] = CORBA::string_dup(name.c_str());
637 SalomeContainer::addToResourceList(const std::string & name)
639 // Search if name is already in the list
640 for (CORBA::ULong i = 0; i < _params.resource_params.resList.length(); i++)
642 std::string component_name = _params.resource_params.resList[i].in();
643 if (component_name == name)
648 CORBA::ULong lgth = _params.resource_params.resList.length();
649 _params.resource_params.resList.length(lgth + 1);
650 _params.resource_params.resList[lgth] = CORBA::string_dup(name.c_str());
653 std::map<std::string,std::string> SalomeContainer::getResourceProperties(const std::string& name)
655 std::map<std::string,std::string> properties;
657 YACS::ENGINE::RuntimeSALOME* runTime = YACS::ENGINE::getSALOMERuntime();
658 CORBA::ORB_ptr orb = runTime->getOrb();
659 if (!orb) return properties;
660 SALOME_NamingService namingService(orb);
661 SALOME_LifeCycleCORBA lcc(&namingService);
662 CORBA::Object_var obj = namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS);
663 if (CORBA::is_nil(obj)) return properties;
664 Engines::ResourcesManager_var resManager = Engines::ResourcesManager::_narrow(obj);
665 if (CORBA::is_nil(resManager)) return properties;
667 std::ostringstream value;
668 Engines::ResourceDefinition_var resource_definition = resManager->GetResourceDefinition(name.c_str());
669 properties["hostname"]=resource_definition->hostname.in();
670 properties["OS"]=resource_definition->OS.in();
671 value.str(""); value << resource_definition->mem_mb;
672 properties["mem_mb"]=value.str();
673 value.str(""); value << resource_definition->cpu_clock;
674 properties["cpu_clock"]=value.str();
675 value.str(""); value << resource_definition->nb_node;
676 properties["nb_node"]=value.str();
677 value.str(""); value << resource_definition->nb_proc_per_node;
678 properties["nb_proc_per_node"]=value.str();
680 properties["component_list"]="";
681 for(CORBA::ULong i=0; i < resource_definition->componentList.length(); i++)
684 properties["component_list"]=properties["component_list"]+",";
685 properties["component_list"]=properties["component_list"]+resource_definition->componentList[i].in();