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);
98 obj = _NS->Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS);
99 ASSERT( !CORBA::is_nil(obj));
100 _ResManager=Engines::ResourcesManager::_narrow(obj);
103 //=============================================================================
107 //=============================================================================
109 SALOME_LifeCycleCORBA::~SALOME_LifeCycleCORBA()
113 //=============================================================================
115 * Find and aready existing and registered component instance.
116 * \param params machine parameters like type or name...
117 * \param componentName the name of component class
118 * \param studyId default = 0 : multistudy instance
119 * \return a CORBA reference of the component instance, or _nil if not found
121 //=============================================================================
123 Engines::Component_ptr
124 SALOME_LifeCycleCORBA::FindComponent(const Engines::MachineParameters& params,
125 const char *componentName,
128 if (! isKnownComponentClass(componentName))
129 return Engines::Component::_nil();
131 Engines::CompoList clist;
133 clist[0] = componentName;
134 Engines::MachineList_var listOfMachines =
135 _ResManager->GetFittingResources(params, clist);
137 Engines::Component_var compo = _FindComponent(params,
142 return compo._retn();
145 //=============================================================================
147 * Load a component instance on a container defined by machine parameters
148 * \param params machine parameters like type or name...
149 * \param componentName the name of component class
150 * \param studyId default = 0 : multistudy instance
151 * \return a CORBA reference of the component instance, or _nil if problem
153 //=============================================================================
155 Engines::Component_ptr
156 SALOME_LifeCycleCORBA::LoadComponent(const Engines::MachineParameters& params,
157 const char *componentName,
160 // --- Check if Component Name is known in ModuleCatalog
162 if (! isKnownComponentClass(componentName))
163 return Engines::Component::_nil();
165 Engines::CompoList clist;
167 clist[0] = componentName;
168 Engines::MachineList_var listOfMachines =
169 _ResManager->GetFittingResources(params, clist);
171 Engines::Component_var compo = _LoadComponent(params,
176 return compo._retn();
179 //=============================================================================
181 * Find and aready existing and registered component instance or load a new
182 * component instance on a container defined by machine parameters.
183 * \param params machine parameters like type or name...
184 * \param componentName the name of component class
185 * \param studyId default = 0 : multistudy instance
186 * \return a CORBA reference of the component instance, or _nil if problem
188 //=============================================================================
190 Engines::Component_ptr
191 SALOME_LifeCycleCORBA::
192 FindOrLoad_Component(const Engines::MachineParameters& params,
193 const char *componentName,
196 // --- Check if Component Name is known in ModuleCatalog
198 if (! isKnownComponentClass(componentName))
199 return Engines::Component::_nil();
201 Engines::CompoList clist;
203 clist[0] = componentName;
204 Engines::MachineList_var listOfMachines =
205 _ResManager->GetFittingResources(params,clist);
207 Engines::Component_var compo = _FindComponent(params,
212 if(CORBA::is_nil(compo))
213 compo = _LoadComponent(params,
218 return compo._retn();
221 //=============================================================================
223 * Find and aready existing and registered component instance or load a new
224 * component instance on a container defined by name
225 * \param containerName the name of container, under one of the forms
226 * - 1 aContainer (local container)
227 * - 2 machine/aContainer (container on hostname = machine)
228 * \param componentName the name of component class
229 * \return a CORBA reference of the component instance, or _nil if problem
231 //=============================================================================
233 Engines::Component_ptr
234 SALOME_LifeCycleCORBA::FindOrLoad_Component(const char *containerName,
235 const char *componentName)
237 char *valenv=getenv("SALOME_BATCH");
239 if (strcmp(valenv,"1")==0)
241 MESSAGE("SALOME_LifeCycleCORBA::FindOrLoad_Component BATCH " << containerName << " " << componentName ) ;
242 _NS->Change_Directory("/Containers");
243 CORBA::Object_ptr obj=_NS->Resolve(containerName);
244 Engines::Container_var cont=Engines::Container::_narrow(obj);
245 bool isLoadable = cont->load_component_Library(componentName);
246 if (!isLoadable) return Engines::Component::_nil();
248 Engines::Component_ptr myInstance =
249 cont->create_component_instance(componentName, 0);
252 MESSAGE("SALOME_LifeCycleCORBA::FindOrLoad_Component INTERACTIF " << containerName << " " << componentName ) ;
254 // --- Check if Component Name is known in ModuleCatalog
256 if (! isKnownComponentClass(componentName))
257 return Engines::Component::_nil();
259 // --- Check if containerName contains machine name (if yes: rg>0)
261 char *stContainer=strdup(containerName);
262 string st2Container(stContainer);
263 int rg=st2Container.find("/");
265 Engines::MachineParameters_var params=new Engines::MachineParameters;
269 // containerName doesn't contain "/" => Local container
270 params->container_name=CORBA::string_dup(stContainer);
271 params->hostname=CORBA::string_dup(GetHostname().c_str());
275 stContainer[rg]='\0';
276 params->container_name=CORBA::string_dup(stContainer+rg+1);
277 params->hostname=CORBA::string_dup(stContainer);
279 params->isMPI = false;
280 SCRUTE(params->container_name);
281 // SCRUTE(params->hostname);
282 // SCRUTE(params->OS);
283 // SCRUTE(params->mem_mb);
284 // SCRUTE(params->cpu_clock);
285 // SCRUTE(params->nb_proc_per_node);
286 // SCRUTE(params->nb_node);
287 // SCRUTE(params->isMPI);
289 return FindOrLoad_Component(params,componentName);
293 //=============================================================================
295 * Check if the component class is known in module catalog
296 * \param componentName the name of component class
297 * \return true if found, false otherwise
299 //=============================================================================
301 bool SALOME_LifeCycleCORBA::isKnownComponentClass(const char *componentName)
306 CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog");
307 SALOME_ModuleCatalog::ModuleCatalog_var Catalog =
308 SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
309 ASSERT(! CORBA::is_nil(Catalog));
310 SALOME_ModuleCatalog::Acomponent_var compoInfo =
311 Catalog->GetComponent(componentName);
312 if (CORBA::is_nil (compoInfo))
314 INFOS("Catalog Error: Component not found in the catalog" );
315 INFOS( componentName );
320 catch (ServiceUnreachable&)
322 INFOS("Caught exception: Naming Service Unreachable");
326 INFOS("Caught unknown exception.");
331 //=============================================================================
333 * Not so complex... useful ?
335 //=============================================================================
338 SALOME_LifeCycleCORBA::isMpiContainer(const Engines::MachineParameters& params)
339 throw(IncompatibleComponent)
348 //=============================================================================
350 * Pre initialisation of a given Engines::MachineParameters with default
352 * - container_name = "" : not relevant
353 * - hostname = "" : not relevant
354 * - OS = "" : not relevant
355 * - mem_mb = 0 : not relevant
356 * - cpu_clock = 0 : not relevant
357 * - nb_proc_per_node = 0 : not relevant
358 * - nb_node = 0 : not relevant
359 * - isMPI = false : standard components
361 //=============================================================================
363 void SALOME_LifeCycleCORBA::preSet( Engines::MachineParameters& params)
365 params.container_name = "";
366 params.hostname = "";
369 params.cpu_clock = 0;
370 params.nb_proc_per_node = 0;
372 params.isMPI = false;
374 params.parallelLib = "";
375 params.nb_component_nodes = 0;
378 //=============================================================================
380 * \return a number of processors not 0, only for MPI containers
382 //=============================================================================
384 int SALOME_LifeCycleCORBA::NbProc(const Engines::MachineParameters& params)
386 if( !isMpiContainer(params) )
388 else if( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
390 else if( params.nb_node == 0 )
391 return params.nb_proc_per_node;
392 else if( params.nb_proc_per_node == 0 )
393 return params.nb_node;
395 return params.nb_node * params.nb_proc_per_node;
398 //=============================================================================
400 * \return the container Manager
402 //=============================================================================
404 Engines::ContainerManager_ptr SALOME_LifeCycleCORBA::getContainerManager()
406 Engines::ContainerManager_var contManager =
407 Engines::ContainerManager::_duplicate(_ContManager);
408 return contManager._retn();
411 //=============================================================================
413 * \return the container Manager
415 //=============================================================================
417 Engines::ResourcesManager_ptr SALOME_LifeCycleCORBA::getResourcesManager()
419 Engines::ResourcesManager_var resManager =
420 Engines::ResourcesManager::_duplicate(_ResManager);
421 return resManager._retn();
425 //=============================================================================
427 * Find and aready existing and registered component instance.
428 * \param params machine parameters like type or name...
429 * \param componentName the name of component class
430 * \param studyId default = 0 : multistudy instance
431 * \param listOfMachines list of machine address
432 * \return a CORBA reference of the component instance, or _nil if not found
433 * - build a list of machines on which an instance of the component is running,
434 * - find the best machine among the list
436 //=============================================================================
438 Engines::Component_ptr
439 SALOME_LifeCycleCORBA::
440 _FindComponent(const Engines::MachineParameters& params,
441 const char *componentName,
443 const Engines::MachineList& listOfMachines)
445 // --- build the list of machines on which the component is already running
447 const char *containerName = params.container_name;
448 int nbproc = NbProc(params);
449 // MESSAGE("_FindComponent, required " << containerName <<
450 // " " << componentName << " " << nbproc);
452 Engines::MachineList_var machinesOK = new Engines::MachineList;
454 unsigned int lghtOfmachinesOK = 0;
455 machinesOK->length(listOfMachines.length());
457 for(unsigned int i=0; i<listOfMachines.length(); i++)
459 const char *currentMachine=listOfMachines[i];
460 // MESSAGE("_FindComponent, look at " << currentMachine);
461 CORBA::Object_var obj = _NS->ResolveComponent(currentMachine,
465 if (!CORBA::is_nil(obj))
466 machinesOK[lghtOfmachinesOK++] = CORBA::string_dup(currentMachine);
469 // --- find the best machine among the list
471 if(lghtOfmachinesOK != 0)
473 machinesOK->length(lghtOfmachinesOK);
474 CORBA::String_var bestMachine = _ResManager->FindFirst(machinesOK);
475 CORBA::Object_var obj = _NS->ResolveComponent(bestMachine,
479 return Engines::Component::_narrow(obj);
482 return Engines::Component::_nil();
485 //=============================================================================
487 * Load a component instance.
488 * \param params machine parameters like type or name...
489 * \param componentName the name of component class
490 * \param studyId default = 0 : multistudy instance
491 * \param listOfMachines list of machine address
492 * \return a CORBA reference of the component instance, or _nil if problem
493 * - Finds a container in the list of machine or start one.
494 * - Try to load the component library in the container,
495 * - then create an instance of the component.
497 //=============================================================================
499 Engines::Component_ptr
500 SALOME_LifeCycleCORBA::
501 _LoadComponent(const Engines::MachineParameters& params,
502 const char *componentName,
504 const Engines::MachineList& listOfMachines)
506 MESSAGE("_LoadComponent, required " << params.container_name <<
507 " " << componentName << " " << NbProc(params));
509 Engines::Container_var cont =
510 _ContManager->FindOrStartContainer(params,
512 if (CORBA::is_nil(cont)) return Engines::Component::_nil();
514 bool isLoadable = cont->load_component_Library(componentName);
515 if (!isLoadable) return Engines::Component::_nil();
517 Engines::Component_var myInstance =
518 cont->create_component_instance(componentName, studyId);
519 return myInstance._retn();
522 Engines::Component_ptr
523 SALOME_LifeCycleCORBA::Load_ParallelComponent(const Engines::MachineParameters& params,
524 const char *componentName,
527 MESSAGE("Entering LoadParallelComponent");
529 /*MESSAGE("Parameters : ");
530 MESSAGE("Container name : " << params.container_name);
531 MESSAGE("Number of component nodes : " << params.nb_component_nodes);
532 MESSAGE("Component Name : " << componentName);*/
534 Engines::CompoList clist;
536 clist[0] = componentName;
537 MESSAGE("Building a list of machines");
538 Engines::MachineList_var listOfMachines = _ResManager->GetFittingResources(params, clist);
539 if (listOfMachines->length() == 0)
541 INFOS("No matching machines founded !");
542 return Engines::Component::_nil();
545 MESSAGE("Starting Parallel Container");
546 Engines::Container_var cont = _ContManager->FindOrStartParallelContainer(params, listOfMachines);
547 if (CORBA::is_nil(cont)) {
548 INFOS("FindOrStartParallelContainer() returns a NULL container !");
549 return Engines::Component::_nil();
552 MESSAGE("Loading component library");
553 bool isLoadable = cont->load_component_Library(componentName);
555 INFOS(componentName <<" library is not loadable !");
556 return Engines::Component::_nil();
559 MESSAGE("Creating component instance");
560 // @PARALLEL@ permits to identify that the component requested
561 // is a parallel component.
562 string name = string(componentName) + string("@PARALLEL@");
563 Engines::Component_var myInstance = cont->create_component_instance(name.c_str(), studyId);
564 if (CORBA::is_nil(myInstance))
565 INFOS("create_component_instance returns a NULL component !");
566 return myInstance._retn();