1 // Copyright (C) 2006-2012 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 _params.container_name = "";
58 _params.mode= "start";
59 _params.workingdir= "";
61 _params.isMPI = false;
62 _params.parallelLib = "";
64 _params.resource_params.name = "";
65 _params.resource_params.hostname = "";
66 _params.resource_params.OS = "";
67 _params.resource_params.nb_proc = 0;
68 _params.resource_params.mem_mb = 0;
69 _params.resource_params.cpu_clock = 0;
70 _params.resource_params.nb_node = 0;
71 _params.resource_params.nb_proc_per_node = 0;
72 _params.resource_params.policy = "";
73 // By default, componentList and resList length is 0
76 SalomeContainer::SalomeContainer(const SalomeContainer& other):Container(other),_trueCont(Engines::Container::_nil()),_type(other._type),
77 _shutdownLevel(other._shutdownLevel)
79 _params.container_name = CORBA::string_dup(other._params.container_name);
80 _params.mode= CORBA::string_dup(other._params.mode);
81 _params.workingdir= CORBA::string_dup(other._params.workingdir);
82 _params.nb_proc = other._params.nb_proc;
83 _params.isMPI = other._params.isMPI;
84 _params.parallelLib = CORBA::string_dup(other._params.parallelLib);
86 _params.resource_params.name = CORBA::string_dup(other._params.resource_params.name);
87 _params.resource_params.hostname = CORBA::string_dup(other._params.resource_params.hostname);
88 _params.resource_params.OS = CORBA::string_dup(other._params.resource_params.OS);
89 _params.resource_params.nb_proc = other._params.resource_params.nb_proc;
90 _params.resource_params.mem_mb = other._params.resource_params.mem_mb;
91 _params.resource_params.cpu_clock = other._params.resource_params.cpu_clock;
92 _params.resource_params.nb_node = other._params.resource_params.nb_node;
93 _params.resource_params.nb_proc_per_node = other._params.resource_params.nb_proc_per_node;
94 _params.resource_params.policy = CORBA::string_dup(other._params.resource_params.policy);
96 _params.resource_params.componentList.length(other._params.resource_params.componentList.length());
97 for(CORBA::ULong i=0; i < other._params.resource_params.componentList.length(); i++)
99 _params.resource_params.componentList[i]=CORBA::string_dup(other._params.resource_params.componentList[i]);
102 _params.resource_params.resList.length(other._params.resource_params.resList.length());
103 for(CORBA::ULong i=0; i < other._params.resource_params.resList.length(); i++)
105 _params.resource_params.resList[i]=CORBA::string_dup(other._params.resource_params.resList[i]);
109 SalomeContainer::~SalomeContainer()
113 void SalomeContainer::lock()
118 void SalomeContainer::unLock()
123 Container *SalomeContainer::clone() const
125 if(_isAttachedOnCloning)
128 return (Container*) (this);
131 return new SalomeContainer(*this);
134 void SalomeContainer::checkCapabilityToDealWith(const ComponentInstance *inst) const throw(YACS::Exception)
136 if(inst->getKind()!=SalomeComponent::KIND)
137 throw Exception("SalomeContainer::checkCapabilityToDealWith : SalomeContainer is not able to deal with this type of ComponentInstance.");
140 void SalomeContainer::setProperty(const std::string& name, const std::string& value)
142 DEBTRACE("SalomeContainer::setProperty : " << name << " ; " << value);
145 if (name == "container_name")
146 _params.container_name = CORBA::string_dup(value.c_str());
147 else if (name == "type")
150 _params.mode = "start";
151 else if (value == "multi")
152 _params.mode = "getorstart";
154 throw Exception("SalomeContainer::setProperty : type value is not correct (mono or multi): " + value);
157 else if (name == "workingdir")
158 _params.workingdir = CORBA::string_dup(value.c_str());
159 else if (name == "nb_parallel_procs")
161 std::istringstream iss(value);
162 if (!(iss >> _params.nb_proc))
163 throw Exception("salomecontainer::setproperty : params.nb_proc value not correct : " + value);
165 else if (name == "isMPI")
168 _params.isMPI = true;
169 else if (value == "false")
170 _params.isMPI = false;
172 throw Exception("SalomeContainer::setProperty : params.isMPI value not correct : " + value);
174 else if (name == "parallelLib")
175 _params.parallelLib = CORBA::string_dup(value.c_str());
178 else if (name == "name")
179 _params.resource_params.name = CORBA::string_dup(value.c_str());
180 else if (name == "hostname")
181 _params.resource_params.hostname = CORBA::string_dup(value.c_str());
182 else if (name == "OS")
183 _params.resource_params.OS = CORBA::string_dup(value.c_str());
184 else if (name == "nb_resource_procs")
186 std::istringstream iss(value);
187 if (!(iss >> _params.resource_params.nb_proc))
188 throw Exception("salomecontainer::setproperty : params.resource_params.nb_proc value not correct : " + value);
190 else if (name == "mem_mb")
192 std::istringstream iss(value);
193 if (!(iss >> _params.resource_params.mem_mb))
194 throw Exception("salomecontainer::setproperty : params.resource_params.mem_mb value not correct : " + value);
196 else if (name == "cpu_clock")
198 std::istringstream iss(value);
199 if (!(iss >> _params.resource_params.cpu_clock))
200 throw Exception("salomecontainer::setproperty : params.resource_params.cpu_clock value not correct : " + value);
202 else if (name == "nb_node")
204 std::istringstream iss(value);
205 if (!(iss >> _params.resource_params.nb_node))
206 throw Exception("salomecontainer::setproperty : params.nb_node value not correct : " + value);
208 else if (name == "nb_proc_per_node")
210 std::istringstream iss(value);
211 if (!(iss >> _params.resource_params.nb_proc_per_node))
212 throw Exception("salomecontainer::setproperty : params.nb_proc_per_node value not correct : " + value);
214 else if (name == "policy")
215 _params.resource_params.policy = CORBA::string_dup(value.c_str());
216 else if (name == "component_list")
218 std::string clean_value(value);
220 // Step 1: remove blanks
221 while(clean_value.find(" ") != std::string::npos)
222 clean_value = clean_value.erase(clean_value.find(" "), 1);
224 // Step 2: get values
225 while(!clean_value.empty())
227 std::string result("");
228 std::string::size_type loc = clean_value.find(",", 0);
229 if (loc != std::string::npos)
231 result = clean_value.substr(0, loc);
232 clean_value = clean_value.erase(0, loc+1);
236 result = clean_value;
239 if (result != "," && result != "")
241 addToComponentList(result);
246 else if (name == "resource_list")
248 std::string clean_value(value);
250 // Step 1: remove blanks
251 while(clean_value.find(" ") != std::string::npos)
252 clean_value = clean_value.erase(clean_value.find(" "), 1);
254 // Step 2: get values
255 while(!clean_value.empty())
257 std::string result("");
258 std::string::size_type loc = clean_value.find(",", 0);
259 if (loc != std::string::npos)
261 result = clean_value.substr(0, loc);
262 clean_value = clean_value.erase(0, loc+1);
266 result = clean_value;
269 if (result != "," && result != "")
271 addToResourceList(result);
277 Container::setProperty(name, value);
280 void SalomeContainer::addComponentName(std::string name)
282 _componentNames.push_back(name);
285 //! Load a component instance in this container
287 * \param inst the component instance to load
289 CORBA::Object_ptr SalomeContainer::loadComponent(ComponentInstance *inst)
291 DEBTRACE("SalomeContainer::loadComponent ");
293 if(!isAlreadyStarted(inst))
307 CORBA::Object_ptr objComponent=CORBA::Object::_nil();
308 std::string compoName=inst->getCompoName();
309 const char* componentName=compoName.c_str();
310 Engines::Container_var container;
312 container=_trueContainers[inst];
318 bool isLoadable = container->load_component_Library(componentName, reason);
321 CORBA::string_free(reason);
326 std::string value=p->getProperty("DefaultStudyID");
328 studyid= atoi(value.c_str());
330 // prepare component instance properties
331 Engines::FieldsDict_var env = new Engines::FieldsDict;
332 std::map<std::string, std::string> properties = inst->getProperties();
335 std::map<std::string,std::string> procMap=p->getProperties();
336 properties.insert(procMap.begin(),procMap.end());
339 std::map<std::string, std::string>::const_iterator itm;
340 env->length(properties.size());
342 for(itm = properties.begin(); itm != properties.end(); ++itm, item++)
344 DEBTRACE("envname="<<itm->first<<" envvalue="<< itm->second);
345 env[item].key= CORBA::string_dup(itm->first.c_str());
346 env[item].value <<= itm->second.c_str();
349 objComponent=container->create_component_instance_env(componentName, studyid, env, reason);
352 if(CORBA::is_nil(objComponent))
355 std::string text="Error while trying to create a new component: component '"+ compoName;
356 text=text+"' is not installed or it's a wrong name";
359 CORBA::string_free(reason);
360 throw Exception(text);
366 //! Get the container placement id for a component instance
368 * \param inst the component instance
369 * \return the placement id
371 std::string SalomeContainer::getPlacementId(const ComponentInstance *inst) const
374 if(isAlreadyStarted(inst))
376 Engines::Container_var container=_trueCont;
379 std::map<const ComponentInstance *, Engines::Container_var>::const_iterator found = _trueContainers.find(inst);
380 container=found->second;
382 const char *what="/";
383 CORBA::String_var corbaStr=container->name();
384 string ret(corbaStr);
387 std::string::size_type i=ret.find_first_of(what,0);
388 i=ret.find_first_of(what, i==std::string::npos ? i:i+1);
389 if(i!=std::string::npos)
390 return ret.substr(i+1);
394 return "Not placed yet !!!";
397 //! Get the container full path for a component instance
399 * \param inst the component instance
400 * \return the full placement id
402 std::string SalomeContainer::getFullPlacementId(const ComponentInstance *inst) const
405 if(isAlreadyStarted(inst))
407 Engines::Container_var container=_trueCont;
410 std::map<const ComponentInstance *, Engines::Container_var>::const_iterator found = _trueContainers.find(inst);
411 container=found->second;
415 CORBA::String_var corbaStr=container->name();
416 string ret(corbaStr);
421 return "Unknown_placement";
425 return "Not_placed_yet";
428 //! Check if the component instance container is already started
430 * \param inst the component instance
431 * \return true, if the container is already started, else false
433 bool SalomeContainer::isAlreadyStarted(const ComponentInstance *inst) const
437 if(CORBA::is_nil(_trueCont))
444 if(_trueContainers.count(inst)==0)
451 Engines::Container_ptr SalomeContainer::getContainerPtr(const ComponentInstance *inst) const
455 if(CORBA::is_nil(_trueCont))
456 return Engines::Container::_nil();
458 return Engines::Container::_duplicate(_trueCont);
462 if(_trueContainers.count(inst)==0)
463 return Engines::Container::_nil();
466 std::map<const ComponentInstance *,Engines::Container_var>::const_iterator iter=_trueContainers.find(inst);
467 return Engines::Container::_duplicate(iter->second);
472 //! Start a salome container (true salome container not yacs one) with given ContainerParameters (_params)
474 * \param inst the component instance
476 void SalomeContainer::start(const ComponentInstance *inst) throw(YACS::Exception)
478 CORBA::ORB_ptr orb=getSALOMERuntime()->getOrb();
479 SALOME_NamingService ns;
484 catch(SALOME_Exception& e)
486 throw Exception("SalomeContainer::start : Unable to contact the SALOME Naming Service");
488 CORBA::Object_var obj=ns.Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS);
489 Engines::ContainerManager_var contManager=Engines::ContainerManager::_narrow(obj);
491 std::string str(_params.container_name);
492 DEBTRACE("SalomeContainer::start " << str <<";"<<_params.resource_params.hostname <<";"<<_type);
494 // Finalize parameters with components found in the container
495 std::vector<std::string>::iterator iter;
496 for(CORBA::ULong i=0; i < _componentNames.size();i++)
497 addToComponentList(_componentNames[i]);
498 Engines::ContainerParameters myparams = _params;
500 bool namedContainer=false;
504 //If a container_name is given try to find an already existing container in naming service
505 //If not found start a new container with the given parameters
506 if (_type=="mono" && str != "")
508 myparams.mode="getorstart";
513 //give a almost unique name to the container : Pid_Name_Addr
514 std::ostringstream stream;
519 stream << (void *)(this);
520 DEBTRACE("container_name="<<stream.str());
521 myparams.container_name=CORBA::string_dup(stream.str().c_str());
525 _trueCont=Engines::Container::_nil();
526 if(namedContainer && _shutdownLevel==999)
528 //Make this only the first time start is called (_shutdownLevel==999)
529 //If the container is named, first try to get an existing container
530 //If there is an existing container use it and set the shutdown level to 3
531 //If there is no existing container, try to launch a new one and set the shutdown level to 2
535 _trueCont=contManager->GiveContainer(myparams);
537 catch( const SALOME::SALOME_Exception& ex )
539 std::string msg="SalomeContainer::start : no existing container : ";
541 msg += ex.details.text.in();
548 if(!CORBA::is_nil(_trueCont))
551 DEBTRACE( "container found: " << str << " " << _shutdownLevel );
556 myparams.mode="start";
557 DEBTRACE( "container not found: " << str << " " << _shutdownLevel);
561 if(CORBA::is_nil(_trueCont))
564 // --- GiveContainer is used in batch mode to retreive launched containers,
565 // and is equivalent to StartContainer when not in batch.
566 _trueCont=contManager->GiveContainer(myparams);
568 catch( const SALOME::SALOME_Exception& ex )
570 std::string msg="SalomeContainer::start : Unable to launch container in Salome : ";
572 msg += ex.details.text.in();
573 throw Exception(msg);
575 catch(CORBA::COMM_FAILURE&)
577 throw Exception("SalomeContainer::start : Unable to launch container in Salome : CORBA Comm failure detected");
579 catch(CORBA::Exception&)
581 throw Exception("SalomeContainer::start : Unable to launch container in Salome : Unexpected CORBA failure detected");
584 if(CORBA::is_nil(_trueCont))
585 throw Exception("SalomeContainer::start : Unable to launch container in Salome. Check your CatalogResources.xml file");
587 _trueContainers[inst]=_trueCont;
589 CORBA::String_var containerName=_trueCont->name();
590 CORBA::String_var hostName=_trueCont->getHostName();
591 std::cerr << "SalomeContainer launched : " << containerName << " " << hostName << " " << _trueCont->getPID() << std::endl;
594 DEBTRACE(_trueCont->_PR_getobj()->pd_refCount );
595 std::map<const ComponentInstance *, Engines::Container_var >::const_iterator it;
596 for(it = _trueContainers.begin(); it != _trueContainers.end(); ++it)
598 DEBTRACE(it->second->_PR_getobj()->pd_refCount );
603 void SalomeContainer::shutdown(int level)
605 DEBTRACE("SalomeContainer::shutdown: " << _name << "," << level << "," << _shutdownLevel);
606 if(level < _shutdownLevel)
610 //shutdown the SALOME containers
613 std::map<const ComponentInstance *, Engines::Container_var >::const_iterator it;
614 for(it = _trueContainers.begin(); it != _trueContainers.end(); ++it)
618 DEBTRACE("shutdown SALOME container: " );
619 CORBA::String_var containerName=it->second->name();
620 DEBTRACE(containerName);
621 it->second->Shutdown();
622 std::cerr << "shutdown SALOME container: " << containerName << std::endl;
624 catch(CORBA::Exception&)
626 DEBTRACE("Unexpected CORBA failure detected." );
630 DEBTRACE("Unknown exception ignored." );
633 _trueContainers.clear();
639 DEBTRACE("shutdown SALOME container: " );
640 CORBA::String_var containerName=_trueCont->name();
641 DEBTRACE(containerName);
642 _trueCont->Shutdown();
643 std::cerr << "shutdown SALOME container: " << containerName << std::endl;
647 DEBTRACE("Unknown exception ignored." );
649 _trueCont=Engines::Container::_nil();
654 SalomeContainer::addToComponentList(const std::string & name)
656 // Search if name is already in the list
657 for (CORBA::ULong i = 0; i < _params.resource_params.componentList.length(); i++)
659 std::string component_name = _params.resource_params.componentList[i].in();
660 if (component_name == name)
665 CORBA::ULong lgth = _params.resource_params.componentList.length();
666 _params.resource_params.componentList.length(lgth + 1);
667 _params.resource_params.componentList[lgth] = CORBA::string_dup(name.c_str());
671 SalomeContainer::addToResourceList(const std::string & name)
673 // Search if name is already in the list
674 for (CORBA::ULong i = 0; i < _params.resource_params.resList.length(); i++)
676 std::string component_name = _params.resource_params.resList[i].in();
677 if (component_name == name)
682 CORBA::ULong lgth = _params.resource_params.resList.length();
683 _params.resource_params.resList.length(lgth + 1);
684 _params.resource_params.resList[lgth] = CORBA::string_dup(name.c_str());
687 std::map<std::string,std::string> SalomeContainer::getResourceProperties(const std::string& name)
689 std::map<std::string,std::string> properties;
691 YACS::ENGINE::RuntimeSALOME* runTime = YACS::ENGINE::getSALOMERuntime();
692 CORBA::ORB_ptr orb = runTime->getOrb();
693 if (!orb) return properties;
694 SALOME_NamingService namingService(orb);
695 SALOME_LifeCycleCORBA lcc(&namingService);
696 CORBA::Object_var obj = namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS);
697 if (CORBA::is_nil(obj)) return properties;
698 Engines::ResourcesManager_var resManager = Engines::ResourcesManager::_narrow(obj);
699 if (CORBA::is_nil(resManager)) return properties;
701 std::ostringstream value;
702 Engines::ResourceDefinition_var resource_definition = resManager->GetResourceDefinition(name.c_str());
703 properties["hostname"]=resource_definition->hostname.in();
704 properties["OS"]=resource_definition->OS.in();
705 value.str(""); value << resource_definition->mem_mb;
706 properties["mem_mb"]=value.str();
707 value.str(""); value << resource_definition->cpu_clock;
708 properties["cpu_clock"]=value.str();
709 value.str(""); value << resource_definition->nb_node;
710 properties["nb_node"]=value.str();
711 value.str(""); value << resource_definition->nb_proc_per_node;
712 properties["nb_proc_per_node"]=value.str();
714 properties["component_list"]="";
715 for(CORBA::ULong i=0; i < resource_definition->componentList.length(); i++)
718 properties["component_list"]=properties["component_list"]+",";
719 properties["component_list"]=properties["component_list"]+resource_definition->componentList[i].in();