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.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 // File : SALOME_LifeCycleCORBA.cxx
25 // Author : Paul RASCLE, EDF
40 #include "utilities.h"
42 #include <ServiceUnreachable.hxx>
44 #include "SALOME_LifeCycleCORBA.hxx"
46 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
48 #include "SALOME_ModuleCatalog.hh"
50 #include "SALOME_ContainerManager.hxx"
51 #include "SALOME_Component_i.hxx"
52 #include "SALOME_NamingService.hxx"
56 IncompatibleComponent::IncompatibleComponent( void ):
57 SALOME_Exception( "IncompatibleComponent" )
61 IncompatibleComponent::IncompatibleComponent(const IncompatibleComponent &ex):
62 SALOME_Exception( ex )
66 //=============================================================================
70 //=============================================================================
72 SALOME_LifeCycleCORBA::SALOME_LifeCycleCORBA(SALOME_NamingService *ns)
74 // be sure to have an instance of traceCollector, when used via SWIG
79 CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
80 // LocalTraceCollector *myThreadTrace = SALOMETraceCollector::instance(orb);
83 _NS = new SALOME_NamingService(orb);
87 _NS->Change_Directory("/"); // mpv 250105: current directory may be not root
88 // (in SALOMEDS for an example)
89 // not enough: set a current directory in naming service is not thread safe
90 // if naming service instance is shared among several threads...
91 // ==> allways use absolute path and dot rely on current directory!
93 CORBA::Object_var obj =
94 _NS->Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS);
95 ASSERT( !CORBA::is_nil(obj));
96 _ContManager=Engines::ContainerManager::_narrow(obj);
99 //=============================================================================
103 //=============================================================================
105 SALOME_LifeCycleCORBA::~SALOME_LifeCycleCORBA()
109 //=============================================================================
111 * Find and aready existing and registered component instance.
112 * \param params machine parameters like type or name...
113 * \param componentName the name of component class
114 * \param studyId default = 0 : multistudy instance
115 * \return a CORBA reference of the component instance, or _nil if not found
117 //=============================================================================
119 Engines::Component_ptr
120 SALOME_LifeCycleCORBA::FindComponent(const Engines::MachineParameters& params,
121 const char *componentName,
124 if (! isKnownComponentClass(componentName))
125 return Engines::Component::_nil();
127 Engines::MachineList_var listOfMachines =
128 _ContManager->GetFittingResources(params, componentName);
130 Engines::Component_var compo = _FindComponent(params,
135 return compo._retn();
138 //=============================================================================
140 * Load a component instance on a container defined by machine parameters
141 * \param params machine parameters like type or name...
142 * \param componentName the name of component class
143 * \param studyId default = 0 : multistudy instance
144 * \return a CORBA reference of the component instance, or _nil if problem
146 //=============================================================================
148 Engines::Component_ptr
149 SALOME_LifeCycleCORBA::LoadComponent(const Engines::MachineParameters& params,
150 const char *componentName,
153 // --- Check if Component Name is known in ModuleCatalog
155 if (! isKnownComponentClass(componentName))
156 return Engines::Component::_nil();
158 Engines::MachineList_var listOfMachines =
159 _ContManager->GetFittingResources(params, componentName);
161 Engines::Component_var compo = _LoadComponent(params,
166 return compo._retn();
169 //=============================================================================
171 * Find and aready existing and registered component instance or load a new
172 * component instance on a container defined by machine parameters.
173 * \param params machine parameters like type or name...
174 * \param componentName the name of component class
175 * \param studyId default = 0 : multistudy instance
176 * \return a CORBA reference of the component instance, or _nil if problem
178 //=============================================================================
180 Engines::Component_ptr
181 SALOME_LifeCycleCORBA::
182 FindOrLoad_Component(const Engines::MachineParameters& params,
183 const char *componentName,
186 // --- Check if Component Name is known in ModuleCatalog
188 if (! isKnownComponentClass(componentName))
189 return Engines::Component::_nil();
191 Engines::MachineList_var listOfMachines =
192 _ContManager->GetFittingResources(params,componentName);
194 Engines::Component_var compo = _FindComponent(params,
199 if(CORBA::is_nil(compo))
200 compo = _LoadComponent(params,
205 return compo._retn();
208 //=============================================================================
210 * Find and aready existing and registered component instance or load a new
211 * component instance on a container defined by name
212 * \param containerName the name of container, under one of the forms
213 * - 1 aContainer (local container)
214 * - 2 machine/aContainer (container on hostname = machine)
215 * \param componentName the name of component class
216 * \return a CORBA reference of the component instance, or _nil if problem
218 //=============================================================================
220 Engines::Component_ptr
221 SALOME_LifeCycleCORBA::FindOrLoad_Component(const char *containerName,
222 const char *componentName)
224 // --- Check if Component Name is known in ModuleCatalog
226 if (! isKnownComponentClass(componentName))
227 return Engines::Component::_nil();
229 // --- Check if containerName contains machine name (if yes: rg>0)
231 char *stContainer=strdup(containerName);
232 string st2Container(stContainer);
233 int rg=st2Container.find("/");
235 Engines::MachineParameters_var params=new Engines::MachineParameters;
239 // containerName doesn't contain "/" => Local container
240 params->container_name=CORBA::string_dup(stContainer);
241 params->hostname=CORBA::string_dup(GetHostname().c_str());
245 stContainer[rg]='\0';
246 params->container_name=CORBA::string_dup(stContainer+rg+1);
247 params->hostname=CORBA::string_dup(stContainer);
249 params->isMPI = false;
250 SCRUTE(params->container_name);
251 // SCRUTE(params->hostname);
252 // SCRUTE(params->OS);
253 // SCRUTE(params->mem_mb);
254 // SCRUTE(params->cpu_clock);
255 // SCRUTE(params->nb_proc_per_node);
256 // SCRUTE(params->nb_node);
257 // SCRUTE(params->isMPI);
259 return FindOrLoad_Component(params,componentName);
263 //=============================================================================
265 * Check if the component class is known in module catalog
266 * \param componentName the name of component class
267 * \return true if found, false otherwise
269 //=============================================================================
271 bool SALOME_LifeCycleCORBA::isKnownComponentClass(const char *componentName)
276 CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog");
277 SALOME_ModuleCatalog::ModuleCatalog_var Catalog =
278 SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
279 ASSERT(! CORBA::is_nil(Catalog));
280 SALOME_ModuleCatalog::Acomponent_var compoInfo =
281 Catalog->GetComponent(componentName);
282 if (CORBA::is_nil (compoInfo))
284 INFOS("Catalog Error: Component not found in the catalog" );
285 INFOS( componentName );
290 catch (ServiceUnreachable&)
292 INFOS("Caught exception: Naming Service Unreachable");
296 INFOS("Caught unknown exception.");
301 //=============================================================================
303 * Not so complex... useful ?
305 //=============================================================================
308 SALOME_LifeCycleCORBA::isMpiContainer(const Engines::MachineParameters& params)
309 throw(IncompatibleComponent)
318 //=============================================================================
320 * Pre initialisation of a given Engines::MachineParameters with default
322 * - container_name = "" : not relevant
323 * - hostname = "" : not relevant
324 * - OS = "" : not relevant
325 * - mem_mb = 0 : not relevant
326 * - cpu_clock = 0 : not relevant
327 * - nb_proc_per_node = 0 : not relevant
328 * - nb_node = 0 : not relevant
329 * - isMPI = false : standard components
331 //=============================================================================
333 void SALOME_LifeCycleCORBA::preSet( Engines::MachineParameters& params)
335 params.container_name = "";
336 params.hostname = "";
339 params.cpu_clock = 0;
340 params.nb_proc_per_node = 0;
342 params.isMPI = false;
344 params.parallelLib = "";
345 params.nb_component_nodes = 0;
348 //=============================================================================
350 * \return a number of processors not 0, only for MPI containers
352 //=============================================================================
354 int SALOME_LifeCycleCORBA::NbProc(const Engines::MachineParameters& params)
356 if( !isMpiContainer(params) )
358 else if( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
360 else if( params.nb_node == 0 )
361 return params.nb_proc_per_node;
362 else if( params.nb_proc_per_node == 0 )
363 return params.nb_node;
365 return params.nb_node * params.nb_proc_per_node;
368 //=============================================================================
370 * \return the container Manager
372 //=============================================================================
374 Engines::ContainerManager_ptr SALOME_LifeCycleCORBA::getContainerManager()
376 Engines::ContainerManager_var contManager =
377 Engines::ContainerManager::_duplicate(_ContManager);
378 return contManager._retn();
382 //=============================================================================
384 * Find and aready existing and registered component instance.
385 * \param params machine parameters like type or name...
386 * \param componentName the name of component class
387 * \param studyId default = 0 : multistudy instance
388 * \param listOfMachines list of machine address
389 * \return a CORBA reference of the component instance, or _nil if not found
390 * - build a list of machines on which an instance of the component is running,
391 * - find the best machine among the list
393 //=============================================================================
395 Engines::Component_ptr
396 SALOME_LifeCycleCORBA::
397 _FindComponent(const Engines::MachineParameters& params,
398 const char *componentName,
400 const Engines::MachineList& listOfMachines)
402 // --- build the list of machines on which the component is already running
404 const char *containerName = params.container_name;
405 int nbproc = NbProc(params);
406 // MESSAGE("_FindComponent, required " << containerName <<
407 // " " << componentName << " " << nbproc);
409 Engines::MachineList_var machinesOK = new Engines::MachineList;
411 unsigned int lghtOfmachinesOK = 0;
412 machinesOK->length(listOfMachines.length());
414 for(unsigned int i=0; i<listOfMachines.length(); i++)
416 const char *currentMachine=listOfMachines[i];
417 // MESSAGE("_FindComponent, look at " << currentMachine);
418 CORBA::Object_var obj = _NS->ResolveComponent(currentMachine,
422 if (!CORBA::is_nil(obj))
423 machinesOK[lghtOfmachinesOK++] = CORBA::string_dup(currentMachine);
426 // --- find the best machine among the list
428 if(lghtOfmachinesOK != 0)
430 machinesOK->length(lghtOfmachinesOK);
431 CORBA::String_var bestMachine = _ContManager->FindFirst(machinesOK);
432 CORBA::Object_var obj = _NS->ResolveComponent(bestMachine,
436 return Engines::Component::_narrow(obj);
439 return Engines::Component::_nil();
442 //=============================================================================
444 * Load a component instance.
445 * \param params machine parameters like type or name...
446 * \param componentName the name of component class
447 * \param studyId default = 0 : multistudy instance
448 * \param listOfMachines list of machine address
449 * \return a CORBA reference of the component instance, or _nil if problem
450 * - Finds a container in the list of machine or start one.
451 * - Try to load the component library in the container,
452 * - then create an instance of the component.
454 //=============================================================================
456 Engines::Component_ptr
457 SALOME_LifeCycleCORBA::
458 _LoadComponent(const Engines::MachineParameters& params,
459 const char *componentName,
461 const Engines::MachineList& listOfMachines)
463 const char *containerName = params.container_name;
464 int nbproc = NbProc(params);
466 MESSAGE("_LoadComponent, required " << containerName <<
467 " " << componentName << " " << nbproc);
469 Engines::Container_var cont =
470 _ContManager->FindOrStartContainer(params,
472 if (CORBA::is_nil(cont)) return Engines::Component::_nil();
474 bool isLoadable = cont->load_component_Library(componentName);
475 if (!isLoadable) return Engines::Component::_nil();
477 Engines::Component_var myInstance =
478 cont->create_component_instance(componentName, studyId);
479 return myInstance._retn();
482 Engines::Component_ptr
483 SALOME_LifeCycleCORBA::Load_ParallelComponent(const Engines::MachineParameters& params,
484 const char *componentName,
487 MESSAGE("Entering LoadParallelComponent");
489 /*MESSAGE("Parameters : ");
490 MESSAGE("Container name : " << params.container_name);
491 MESSAGE("Number of component nodes : " << params.nb_component_nodes);
492 MESSAGE("Component Name : " << componentName);*/
494 MESSAGE("Building a list of machines");
495 Engines::MachineList_var listOfMachines = _ContManager->GetFittingResources(params, componentName);
496 if (listOfMachines->length() == 0)
498 INFOS("No matching machines founded !");
499 return Engines::Component::_nil();
502 MESSAGE("Starting Parallel Container");
503 Engines::Container_var cont = _ContManager->FindOrStartParallelContainer(params, listOfMachines);
504 if (CORBA::is_nil(cont)) {
505 INFOS("FindOrStartParallelContainer() returns a NULL container !");
506 return Engines::Component::_nil();
509 MESSAGE("Loading component library");
510 bool isLoadable = cont->load_component_Library(componentName);
512 INFOS(componentName <<" library is not loadable !");
513 return Engines::Component::_nil();
516 MESSAGE("Creating component instance");
517 // @PARALLEL@ permits to identify that the component requested
518 // is a parallel component.
519 string name = string(componentName) + string("@PARALLEL@");
520 Engines::Component_var myInstance = cont->create_component_instance(name.c_str(), studyId);
521 if (CORBA::is_nil(myInstance))
522 INFOS("create_component_instance returns a NULL component !");
523 return myInstance._retn();