1 // SALOME LifeCycleCORBA : implementation of containers and engines life cycle both in Python and C++
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : SALOME_LifeCycleCORBA.cxx
25 // Author : Paul RASCLE, EDF
38 #include "utilities.h"
40 #include <ServiceUnreachable.hxx>
42 #include "SALOME_LifeCycleCORBA.hxx"
44 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
46 #include "SALOME_ModuleCatalog.hh"
48 #include "SALOME_ContainerManager.hxx"
49 #include "SALOME_Component_i.hxx"
50 #include "SALOME_NamingService.hxx"
51 #include "Launchers.hxx"
55 IncompatibleComponent::IncompatibleComponent( void ):
56 SALOME_Exception( "IncompatibleComponent" )
60 IncompatibleComponent::IncompatibleComponent(const IncompatibleComponent &ex):
61 SALOME_Exception( ex )
65 //=============================================================================
69 //=============================================================================
71 SALOME_LifeCycleCORBA::SALOME_LifeCycleCORBA(SALOME_NamingService *ns)
73 // be sure to have an instance of traceCollector, when used via SWIG
78 CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
79 // LocalTraceCollector *myThreadTrace = SALOMETraceCollector::instance(orb);
82 _NS = new SALOME_NamingService(orb);
86 _NS->Change_Directory("/"); // mpv 250105: current directory may be not root
87 // (in SALOMEDS for an example)
88 // not enough: set a current directory in naming service is not thread safe
89 // if naming service instance is shared among several threads...
90 // ==> allways use absolute path and dot rely on current directory!
92 CORBA::Object_var obj =
93 _NS->Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS);
94 ASSERT( !CORBA::is_nil(obj));
95 _ContManager=Engines::ContainerManager::_narrow(obj);
98 //=============================================================================
102 //=============================================================================
104 SALOME_LifeCycleCORBA::~SALOME_LifeCycleCORBA()
108 //=============================================================================
110 * Find and aready existing and registered component instance.
111 * \param params machine parameters like type or name...
112 * \param componentName the name of component class
113 * \param studyId default = 0 : multistudy instance
114 * \return a CORBA reference of the component instance, or _nil if not found
116 //=============================================================================
118 Engines::Component_ptr
119 SALOME_LifeCycleCORBA::FindComponent(const Engines::MachineParameters& params,
120 const char *componentName,
123 if (! isKnownComponentClass(componentName))
124 return Engines::Component::_nil();
126 Engines::MachineList_var listOfMachines =
127 _ContManager->GetFittingResources(params, componentName);
129 Engines::Component_var compo = _FindComponent(params,
134 return compo._retn();
137 //=============================================================================
139 * Load a component instance on a container defined by machine parameters
140 * \param params machine parameters like type or name...
141 * \param componentName the name of component class
142 * \param studyId default = 0 : multistudy instance
143 * \return a CORBA reference of the component instance, or _nil if problem
145 //=============================================================================
147 Engines::Component_ptr
148 SALOME_LifeCycleCORBA::LoadComponent(const Engines::MachineParameters& params,
149 const char *componentName,
152 // --- Check if Component Name is known in ModuleCatalog
154 if (! isKnownComponentClass(componentName))
155 return Engines::Component::_nil();
157 Engines::MachineList_var listOfMachines =
158 _ContManager->GetFittingResources(params, componentName);
160 Engines::Component_var compo = _LoadComponent(params,
165 return compo._retn();
168 //=============================================================================
170 * Find and aready existing and registered component instance or load a new
171 * component instance on a container defined by machine parameters.
172 * \param params machine parameters like type or name...
173 * \param componentName the name of component class
174 * \param studyId default = 0 : multistudy instance
175 * \return a CORBA reference of the component instance, or _nil if problem
177 //=============================================================================
179 Engines::Component_ptr
180 SALOME_LifeCycleCORBA::
181 FindOrLoad_Component(const Engines::MachineParameters& params,
182 const char *componentName,
185 // --- Check if Component Name is known in ModuleCatalog
187 if (! isKnownComponentClass(componentName))
188 return Engines::Component::_nil();
190 Engines::MachineList_var listOfMachines =
191 _ContManager->GetFittingResources(params,componentName);
193 Engines::Component_var compo = _FindComponent(params,
198 if(CORBA::is_nil(compo))
199 compo = _LoadComponent(params,
204 return compo._retn();
207 //=============================================================================
209 * Find and aready existing and registered component instance or load a new
210 * component instance on a container defined by name
211 * \param containerName the name of container, under one of the forms
212 * - 1 aContainer (local container)
213 * - 2 machine/aContainer (container on hostname = machine)
214 * \param componentName the name of component class
215 * \return a CORBA reference of the component instance, or _nil if problem
217 //=============================================================================
219 Engines::Component_ptr
220 SALOME_LifeCycleCORBA::FindOrLoad_Component(const char *containerName,
221 const char *componentName)
223 // --- Check if Component Name is known in ModuleCatalog
225 if (! isKnownComponentClass(componentName))
226 return Engines::Component::_nil();
228 // --- Check if containerName contains machine name (if yes: rg>0)
230 char *stContainer=strdup(containerName);
231 string st2Container(stContainer);
232 int rg=st2Container.find("/");
234 Engines::MachineParameters_var params=new Engines::MachineParameters;
238 // containerName doesn't contain "/" => Local container
239 params->container_name=CORBA::string_dup(stContainer);
240 params->hostname=CORBA::string_dup(GetHostname().c_str());
244 stContainer[rg]='\0';
245 params->container_name=CORBA::string_dup(stContainer+rg+1);
246 params->hostname=CORBA::string_dup(stContainer);
248 params->isMPI = false;
249 SCRUTE(params->container_name);
250 // SCRUTE(params->hostname);
251 // SCRUTE(params->OS);
252 // SCRUTE(params->mem_mb);
253 // SCRUTE(params->cpu_clock);
254 // SCRUTE(params->nb_proc_per_node);
255 // SCRUTE(params->nb_node);
256 // SCRUTE(params->isMPI);
258 return FindOrLoad_Component(params,componentName);
262 //=============================================================================
264 * Check if the component class is known in module catalog
265 * \param componentName the name of component class
266 * \return true if found, false otherwise
268 //=============================================================================
270 bool SALOME_LifeCycleCORBA::isKnownComponentClass(const char *componentName)
275 CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog");
276 SALOME_ModuleCatalog::ModuleCatalog_var Catalog =
277 SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
278 ASSERT(! CORBA::is_nil(Catalog));
279 SALOME_ModuleCatalog::Acomponent_ptr compoInfo =
280 Catalog->GetComponent(componentName);
281 if (CORBA::is_nil (compoInfo))
283 INFOS("Catalog Error : Component not found in the catalog");
288 catch (ServiceUnreachable&)
290 INFOS("Caught exception: Naming Service Unreachable");
294 INFOS("Caught unknown exception.");
299 //=============================================================================
301 * Not so complex... useful ?
303 //=============================================================================
306 SALOME_LifeCycleCORBA::isMpiContainer(const Engines::MachineParameters& params)
307 throw(IncompatibleComponent)
316 //=============================================================================
318 * Pre initialisation of a given Engines::MachineParameters with default
320 * - container_name = "" : not relevant
321 * - hostname = "" : not relevant
322 * - OS = "" : not relevant
323 * - mem_mb = 0 : not relevant
324 * - cpu_clock = 0 : not relevant
325 * - nb_proc_per_node = 0 : not relevant
326 * - nb_node = 0 : not relevant
327 * - isMPI = false : standard components
329 //=============================================================================
331 void SALOME_LifeCycleCORBA::preSet( Engines::MachineParameters& params)
333 params.container_name = "";
334 params.hostname = "";
337 params.cpu_clock = 0;
338 params.nb_proc_per_node = 0;
340 params.isMPI = false;
343 //=============================================================================
345 * \return a number of processors not 0, only for MPI containers
347 //=============================================================================
349 int SALOME_LifeCycleCORBA::NbProc(const Engines::MachineParameters& params)
351 if( !isMpiContainer(params) )
353 else if( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
355 else if( params.nb_node == 0 )
356 return params.nb_proc_per_node;
357 else if( params.nb_proc_per_node == 0 )
358 return params.nb_node;
360 return params.nb_node * params.nb_proc_per_node;
363 //=============================================================================
365 * Find and aready existing and registered component instance.
366 * \param params machine parameters like type or name...
367 * \param componentName the name of component class
368 * \param studyId default = 0 : multistudy instance
369 * \param listOfMachines list of machine address
370 * \return a CORBA reference of the component instance, or _nil if not found
371 * - build a list of machines on which an instance of the component is running,
372 * - find the best machine among the list
374 //=============================================================================
376 Engines::Component_ptr
377 SALOME_LifeCycleCORBA::
378 _FindComponent(const Engines::MachineParameters& params,
379 const char *componentName,
381 const Engines::MachineList& listOfMachines)
383 // --- build the list of machines on which the component is already running
385 const char *containerName = params.container_name;
386 int nbproc = NbProc(params);
387 // MESSAGE("_FindComponent, required " << containerName <<
388 // " " << componentName << " " << nbproc);
390 Engines::MachineList_var machinesOK = new Engines::MachineList;
392 unsigned int lghtOfmachinesOK = 0;
393 machinesOK->length(listOfMachines.length());
395 for(unsigned int i=0; i<listOfMachines.length(); i++)
397 const char *currentMachine=listOfMachines[i];
398 // MESSAGE("_FindComponent, look at " << currentMachine);
399 CORBA::Object_var obj = _NS->ResolveComponent(currentMachine,
403 if (!CORBA::is_nil(obj))
404 machinesOK[lghtOfmachinesOK++] = CORBA::string_dup(currentMachine);
407 // --- find the best machine among the list
409 if(lghtOfmachinesOK != 0)
411 machinesOK->length(lghtOfmachinesOK);
412 CORBA::String_var bestMachine = _ContManager->FindBest(machinesOK);
413 CORBA::Object_var obj = _NS->ResolveComponent(bestMachine,
417 return Engines::Component::_narrow(obj);
420 return Engines::Component::_nil();
423 //=============================================================================
425 * Load a component instance.
426 * \param params machine parameters like type or name...
427 * \param componentName the name of component class
428 * \param studyId default = 0 : multistudy instance
429 * \param listOfMachines list of machine address
430 * \return a CORBA reference of the component instance, or _nil if problem
431 * - Finds a container in the list of machine or start one.
432 * - Try to load the component library in the container,
433 * - then create an instance of the component.
435 //=============================================================================
437 Engines::Component_ptr
438 SALOME_LifeCycleCORBA::
439 _LoadComponent(const Engines::MachineParameters& params,
440 const char *componentName,
442 const Engines::MachineList& listOfMachines)
444 const char *containerName = params.container_name;
445 int nbproc = NbProc(params);
447 MESSAGE("_LoadComponent, required " << containerName <<
448 " " << componentName << " " << nbproc);
450 Engines::Container_var cont =
451 _ContManager->FindOrStartContainer(params,
453 if (CORBA::is_nil(cont)) return Engines::Component::_nil();
455 bool isLoadable = cont->load_component_Library(componentName);
456 if (!isLoadable) return Engines::Component::_nil();
458 Engines::Component_var myInstance =
459 cont->create_component_instance(componentName, studyId);
460 return myInstance._retn();