Salome HOME
CCAR: move DSC trace function from Calcium directory to DSC_Basic directory
[modules/kernel.git] / src / LifeCycleCORBA / SALOME_LifeCycleCORBA.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SALOME LifeCycleCORBA : implementation of containers and engines life cycle both in Python and C++
23 //  File   : SALOME_LifeCycleCORBA.cxx
24 //  Author : Paul RASCLE, EDF
25 //  Module : SALOME
26 //  $Header$
27 //
28 #include <iostream>
29 #include <fstream>
30 #include <sstream>
31 #include <iomanip>
32
33 #include <time.h>
34 #ifndef WIN32
35   #include <sys/time.h>
36 #endif
37
38 #include "Basics_Utils.hxx"
39 #include "utilities.h"
40
41 #include <ServiceUnreachable.hxx>
42
43 #include "SALOME_LifeCycleCORBA.hxx"
44 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
45 #include CORBA_CLIENT_HEADER(SALOME_Session)
46 #include CORBA_CLIENT_HEADER(DSC_Engines)
47 #include CORBA_CLIENT_HEADER(SALOME_Registry)
48 #include CORBA_CLIENT_HEADER(SALOMEDS)
49 #include CORBA_CLIENT_HEADER(Logger)
50
51 #include "SALOME_ContainerManager.hxx"
52 #include "SALOME_Component_i.hxx"
53 #include "SALOME_NamingService.hxx"
54 #include "SALOME_FileTransferCORBA.hxx"
55
56 using namespace std;
57
58 IncompatibleComponent::IncompatibleComponent( void ):
59   SALOME_Exception( "IncompatibleComponent" )
60 {
61 }
62
63 IncompatibleComponent::IncompatibleComponent(const IncompatibleComponent &ex):
64   SALOME_Exception( ex ) 
65 {
66 }
67
68 /*! \class SALOME_LifeCycleCORBA
69     \brief A class to manage life cycle of SALOME components.
70
71 */
72
73 //=============================================================================
74 /*! 
75  *  Constructor
76  */
77 //=============================================================================
78
79 SALOME_LifeCycleCORBA::SALOME_LifeCycleCORBA(SALOME_NamingService *ns)
80 {
81   // be sure to have an instance of traceCollector, when used via SWIG
82   // in a Python module
83   int argc = 0;
84   char *xargv = (char*)"";
85   char **argv = &xargv;
86   CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
87   //  LocalTraceCollector *myThreadTrace = SALOMETraceCollector::instance(orb);
88   _NSnew=0;
89   if (!ns)
90     {
91       _NS = new SALOME_NamingService(orb);
92       _NSnew=_NS;
93     }
94   else _NS = ns;
95   //add try catch
96   _NS->Change_Directory("/"); // mpv 250105: current directory may be not root 
97                               // (in SALOMEDS for an example)
98   // not enough: set a current directory in naming service is not thread safe
99   // if naming service instance is shared among several threads...
100   // ==> allways use absolute path and dot rely on current directory!
101
102   CORBA::Object_var obj =
103     _NS->Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS);
104   ASSERT( !CORBA::is_nil(obj));
105   _ContManager=Engines::ContainerManager::_narrow(obj);
106
107   obj = _NS->Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS);
108   ASSERT( !CORBA::is_nil(obj));
109   _ResManager=Engines::ResourcesManager::_narrow(obj);
110 }
111
112 //=============================================================================
113 /*! 
114  *  Destructor
115  */
116 //=============================================================================
117
118 SALOME_LifeCycleCORBA::~SALOME_LifeCycleCORBA()
119 {
120   if(_NSnew)delete _NSnew;
121 }
122
123 //=============================================================================
124 /*! \brief Find an already existing and registered component instance.
125  *
126  *  \param params         machine parameters like type or name...
127  *  \param componentName  the name of component class
128  *  \param studyId        default = 0  : multistudy instance
129  *  \return a CORBA reference of the component instance, or _nil if not found
130  */
131 //=============================================================================
132 Engines::Component_ptr
133 SALOME_LifeCycleCORBA::FindComponent(const Engines::MachineParameters& params,
134                                      const char *componentName,
135                                      int studyId)
136 {
137   if (! isKnownComponentClass(componentName))
138     return Engines::Component::_nil();
139
140   Engines::MachineParameters parms(params);
141   parms.componentList.length(1);
142   parms.componentList[0] = componentName;
143   Engines::MachineList_var listOfMachines = _ResManager->GetFittingResources(parms);
144
145   Engines::Component_var compo = _FindComponent(parms,
146                                                 componentName,
147                                                 studyId,
148                                                 listOfMachines);
149
150   return compo._retn();
151 }
152
153 //=============================================================================
154 /*! \brief Load a component instance on a container defined by machine parameters
155  *
156  *  \param params         machine parameters like type or name...
157  *  \param componentName  the name of component class
158  *  \param studyId        default = 0  : multistudy instance
159  *  \return a CORBA reference of the component instance, or _nil if problem
160  */
161 //=============================================================================
162
163 Engines::Component_ptr
164 SALOME_LifeCycleCORBA::LoadComponent(const Engines::MachineParameters& params,
165                                      const char *componentName,
166                                      int studyId)
167 {
168   // --- Check if Component Name is known in ModuleCatalog
169
170   if (! isKnownComponentClass(componentName))
171     return Engines::Component::_nil();
172
173   Engines::MachineParameters parms(params);
174   parms.componentList.length(1);
175   parms.componentList[0] = componentName;
176
177   Engines::MachineList_var listOfMachines = _ResManager->GetFittingResources(parms);
178   parms.computerList=listOfMachines;
179
180   Engines::Component_var compo = _LoadComponent(parms,
181                                                 componentName,
182                                                 studyId);
183
184   return compo._retn();
185 }
186
187 //=============================================================================
188 /*! \brief Find an already existing and registered component instance or load a new
189  *         component instance on a container defined by machine parameters.
190  *
191  *  \param params         machine parameters like type or name...
192  *  \param componentName  the name of component class
193  *  \param studyId        default = 0  : multistudy instance
194  *  \return a CORBA reference of the component instance, or _nil if problem
195  */
196 //=============================================================================
197
198 Engines::Component_ptr
199 SALOME_LifeCycleCORBA::
200 FindOrLoad_Component(const Engines::MachineParameters& params,
201                      const char *componentName,
202                      int studyId)
203 {
204   // --- Check if Component Name is known in ModuleCatalog
205
206   if (! isKnownComponentClass(componentName))
207     return Engines::Component::_nil();
208
209   Engines::MachineParameters parms(params);
210   parms.componentList.length(1);
211   parms.componentList[0] = componentName;
212   Engines::MachineList_var listOfMachines = _ResManager->GetFittingResources(parms);
213
214   Engines::Component_var compo = _FindComponent(parms,
215                                                 componentName,
216                                                 studyId,
217                                                 listOfMachines);
218
219   if(CORBA::is_nil(compo))
220     {
221       parms.computerList=listOfMachines;
222       compo = _LoadComponent(parms,
223                            componentName,
224                            studyId);
225     }
226
227   return compo._retn();
228 }
229
230 //=============================================================================
231 /*! \brief Find an already existing and registered component instance or load a new
232  *         component instance on a container defined by name
233  *
234  *  \param containerName  the name of container, under one of the forms
235  *           - 1 aContainer (local container)
236  *           - 2 machine/aContainer (container on hostname = machine)
237  *  \param componentName  the name of component class
238  *  \return a CORBA reference of the component instance, or _nil if problem
239  */
240 //=============================================================================
241
242 Engines::Component_ptr
243 SALOME_LifeCycleCORBA::FindOrLoad_Component(const char *containerName,
244                                             const char *componentName)
245 {
246   char *valenv=getenv("SALOME_BATCH");
247   if(valenv)
248     if (strcmp(valenv,"1")==0)
249       {
250         MESSAGE("SALOME_LifeCycleCORBA::FindOrLoad_Component BATCH " << containerName << " " << componentName ) ;
251         _NS->Change_Directory("/Containers");
252         CORBA::Object_ptr obj=_NS->Resolve(containerName);
253         Engines::Container_var cont=Engines::Container::_narrow(obj);
254         bool isLoadable = cont->load_component_Library(componentName);
255         if (!isLoadable) return Engines::Component::_nil();
256         
257         Engines::Component_ptr myInstance =
258           cont->create_component_instance(componentName, 0);
259         return myInstance;
260       }
261   MESSAGE("SALOME_LifeCycleCORBA::FindOrLoad_Component INTERACTIF " << containerName << " " << componentName ) ;
262   //#if 0
263   // --- Check if Component Name is known in ModuleCatalog
264
265   if (! isKnownComponentClass(componentName))
266     return Engines::Component::_nil();
267
268   // --- Check if containerName contains machine name (if yes: rg>0)
269
270   char *stContainer=strdup(containerName);
271   string st2Container(stContainer);
272   int rg=st2Container.find("/");
273
274   Engines::MachineParameters_var params=new Engines::MachineParameters;
275   preSet(params);
276   if (rg<0)
277     {
278       // containerName doesn't contain "/" => Local container
279       params->container_name=CORBA::string_dup(stContainer);
280       params->hostname="";
281     }
282   else 
283     {
284       stContainer[rg]='\0';
285       params->container_name=CORBA::string_dup(stContainer+rg+1);
286       params->hostname=CORBA::string_dup(stContainer);
287     }
288   params->isMPI = false;
289   SCRUTE(params->container_name);
290 //   SCRUTE(params->hostname);
291 //   SCRUTE(params->OS);
292 //   SCRUTE(params->mem_mb);
293 //   SCRUTE(params->cpu_clock);
294 //   SCRUTE(params->nb_proc_per_node);
295 //   SCRUTE(params->nb_node);
296 //   SCRUTE(params->isMPI);
297   free(stContainer);
298   return FindOrLoad_Component(params,componentName);
299   //#endif  
300 }
301
302 //=============================================================================
303 /*! \brief Check if the component class is known in module catalog
304  *
305  *  \param componentName  the name of component class
306  *  \return true if found, false otherwise
307  */
308 //=============================================================================
309
310 bool SALOME_LifeCycleCORBA::isKnownComponentClass(const char *componentName)
311 {
312
313   try
314     {
315       CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog");
316       SALOME_ModuleCatalog::ModuleCatalog_var Catalog = 
317         SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
318       ASSERT(! CORBA::is_nil(Catalog));
319       SALOME_ModuleCatalog::Acomponent_var compoInfo = 
320         Catalog->GetComponent(componentName);
321       if (CORBA::is_nil (compoInfo)) 
322         {
323           INFOS("Catalog Error: Component not found in the catalog" );
324           INFOS( componentName );         
325           return false;
326         }
327       else return true;
328     }
329   catch (ServiceUnreachable&)
330     {
331       INFOS("Caught exception: Naming Service Unreachable");
332     }
333   catch (...)
334     {
335       INFOS("Caught unknown exception.");
336     }
337   return false;
338 }
339
340 //=============================================================================
341 /*! 
342  *  Not so complex... useful ?
343  */
344 //=============================================================================
345
346 bool 
347 SALOME_LifeCycleCORBA::isMpiContainer(const Engines::MachineParameters& params)
348   throw(IncompatibleComponent)
349 {
350   if( params.isMPI )
351     return true;
352   else
353     return false;
354 }
355
356
357 //=============================================================================
358 /*! \brief Initialisation of a given Engines::MachineParameters with default values.
359  *
360  *  - container_name = ""  : not relevant
361  *  - hostname = ""        : not relevant
362  *  - OS = ""              : not relevant
363  *  - mem_mb = 0           : not relevant
364  *  - cpu_clock = 0        : not relevant
365  *  - nb_proc_per_node = 0 : not relevant
366  *  - nb_node = 0          : not relevant
367  *  - isMPI = false        : standard components
368  */
369 //=============================================================================
370
371 void SALOME_LifeCycleCORBA::preSet( Engines::MachineParameters& params)
372 {
373   params.container_name = "";
374   params.hostname = "";
375   //param.componentList = 0;
376   //param.computerList = 0;
377   params.OS = "";
378   params.mem_mb = 0;
379   params.cpu_clock = 0;
380   params.nb_proc_per_node = 0;
381   params.nb_node = 0;
382   params.isMPI = false;
383   params.workingdir = "";
384   params.mode = "";
385   params.policy = "";
386   params.parallelLib = "";
387   params.nb_component_nodes = 0;
388 }
389
390 //=============================================================================
391 /*! 
392  *  \return a number of processors not 0, only for MPI containers
393  */
394 //=============================================================================
395
396 int SALOME_LifeCycleCORBA::NbProc(const Engines::MachineParameters& params)
397 {
398   if( !isMpiContainer(params) )
399     return 0;
400   else if( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
401     return 1;
402   else if( params.nb_node == 0 )
403     return params.nb_proc_per_node;
404   else if( params.nb_proc_per_node == 0 )
405     return params.nb_node;
406   else
407     return params.nb_node * params.nb_proc_per_node;
408 }
409
410 //=============================================================================
411 /*! \brief Get the container manager
412  *
413  *  \return the container Manager
414  */
415 //=============================================================================
416
417 Engines::ContainerManager_ptr SALOME_LifeCycleCORBA::getContainerManager()
418 {
419  Engines::ContainerManager_var contManager =
420    Engines::ContainerManager::_duplicate(_ContManager);
421  return contManager._retn();
422 }
423
424 //=============================================================================
425 /*! \brief Get the resources manager
426  *
427  *  \return the container Manager
428  */
429 //=============================================================================
430
431 Engines::ResourcesManager_ptr SALOME_LifeCycleCORBA::getResourcesManager()
432 {
433  Engines::ResourcesManager_var resManager =
434    Engines::ResourcesManager::_duplicate(_ResManager);
435  return resManager._retn();
436 }
437
438 //=============================================================================
439 /*! \brief shutdown all the SALOME servers except SALOME_Session_Server, omniNames and notifd
440  */
441 //=============================================================================
442
443 void SALOME_LifeCycleCORBA::shutdownServers()
444 {
445   // get each Container from NamingService => shutdown it
446   // (the order is inverse to the order of servers initialization)
447   
448   SALOME::Session_var session = SALOME::Session::_nil();
449   CORBA::Long pid = 0;
450   CORBA::Object_var objS = _NS->Resolve("/Kernel/Session");
451   if (!CORBA::is_nil(objS))
452     {
453       session = SALOME::Session::_narrow(objS);
454       if (!CORBA::is_nil(session))
455         {
456           pid = session->getPID();
457           session->ping();
458         }
459     }
460
461   string hostname = Kernel_Utils::GetHostname();
462   
463   // 1) SalomeLauncher
464   CORBA::Object_var objSL = _NS->Resolve("/SalomeLauncher");
465   Engines::SalomeLauncher_var launcher = Engines::SalomeLauncher::_narrow(objSL);
466   if (!CORBA::is_nil(launcher) && (pid != launcher->getPID()))
467     launcher->Shutdown();
468   
469   // 2) ConnectionManager
470   CORBA::Object_var objCnM=_NS->Resolve("/ConnectionManager");
471   Engines::ConnectionManager_var connMan=Engines::ConnectionManager::_narrow(objCnM);
472   if ( !CORBA::is_nil(connMan) && ( pid != connMan->getPID() ) )
473     connMan->ShutdownWithExit();
474   
475   // 3) SALOMEDS
476   CORBA::Object_var objSDS = _NS->Resolve("/myStudyManager");
477   SALOMEDS::StudyManager_var studyManager = SALOMEDS::StudyManager::_narrow(objSDS) ;
478   if ( !CORBA::is_nil(studyManager) && ( pid != studyManager->getPID() ) )
479     studyManager->Shutdown();
480   
481   // 4) ModuleCatalog
482   CORBA::Object_var objMC=_NS->Resolve("/Kernel/ModulCatalog");
483   SALOME_ModuleCatalog::ModuleCatalog_var catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(objMC);
484   if ( !CORBA::is_nil(catalog) && ( pid != catalog->getPID() ) )
485     catalog->shutdown();
486   
487   // 5) Registry
488   CORBA::Object_var objR = _NS->Resolve("/Registry");
489   Registry::Components_var registry = Registry::Components::_narrow(objR);
490   if ( !CORBA::is_nil(registry) && ( pid != registry->getPID() ) )
491       registry->Shutdown();
492
493   // 6) Logger
494   int argc = 0;
495   char *xargv = (char*)"";
496   char **argv = &xargv;
497   CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
498
499   CORBA::Object_var objLog = CORBA::Object::_nil();
500   CosNaming::NamingContext_var inc;
501   CORBA::Object_var theObj = CORBA::Object::_nil();
502   std::string stdname = "Logger";
503   CosNaming::Name name;
504   name.length(1);
505   name[0].id = CORBA::string_dup(stdname.c_str());
506   try
507     { 
508       if(!CORBA::is_nil(orb)) 
509         theObj = orb->resolve_initial_references("NameService");
510       if (!CORBA::is_nil(theObj))
511         inc = CosNaming::NamingContext::_narrow(theObj);
512     }
513   catch(...)
514     {
515     }
516   if(!CORBA::is_nil(inc)) {
517     try
518       {
519         objLog = inc->resolve(name);
520         SALOME_Logger::Logger_var logger = SALOME_Logger::Logger::_narrow(objLog);
521         if ( !CORBA::is_nil(logger) )
522           logger->shutdown();
523       }
524     catch(...)
525       {
526       }
527   }
528 }
529
530 //=============================================================================
531 /*! \brief shutdown  omniNames and notifd
532  */
533 //=============================================================================
534
535 void SALOME_LifeCycleCORBA::killOmniNames()
536 {
537   string portNumber (::getenv ("NSPORT") );
538   if ( !portNumber.empty() ) 
539     {
540 #ifdef WNT
541 #else
542       string cmd ;
543       cmd = string( "ps -eo pid,command | grep -v grep | grep -E \"omniNames.*")
544         + portNumber
545         + string("\" | awk '{cmd=sprintf(\"kill -9 %s\",$1); system(cmd)}'" );
546       MESSAGE(cmd);
547       try {
548         system ( cmd.c_str() );
549       }
550       catch ( ... ) {
551       }
552 #endif
553     }
554   
555   // NPAL 18309  (Kill Notifd)
556   if ( !portNumber.empty() ) 
557     {
558       string cmd = ("from killSalomeWithPort import killNotifdAndClean; ");
559       cmd += string("killNotifdAndClean(") + portNumber + "); ";
560       cmd  = string("python -c \"") + cmd +"\" >& /dev/null";
561       MESSAGE(cmd);
562       system( cmd.c_str() );
563     }
564 }
565
566 //=============================================================================
567 /*! \brief Find an already existing and registered component instance.
568  *
569  * - build a list of machines on which an instance of the component is running,
570  * - find the best machine among the list
571  *
572  *  \param params         machine parameters like type or name...
573  *  \param componentName  the name of component class
574  *  \param studyId        default = 0  : multistudy instance
575  *  \param listOfMachines list of machine address
576  *  \return a CORBA reference of the component instance, or _nil if not found
577  */
578 //=============================================================================
579
580 Engines::Component_ptr
581 SALOME_LifeCycleCORBA::
582 _FindComponent(const Engines::MachineParameters& params,
583                const char *componentName,
584                int studyId,
585                const Engines::MachineList& listOfMachines)
586 {
587   // --- build the list of machines on which the component is already running
588
589   const char *containerName = params.container_name;
590   int nbproc = NbProc(params);
591 //   MESSAGE("_FindComponent, required " << containerName <<
592 //        " " << componentName << " " << nbproc);
593
594   Engines::MachineList_var machinesOK = new Engines::MachineList;
595
596   unsigned int lghtOfmachinesOK = 0;
597   machinesOK->length(listOfMachines.length());
598
599   for(unsigned int i=0; i<listOfMachines.length(); i++)
600     {
601       const char *currentMachine=listOfMachines[i];
602 //       MESSAGE("_FindComponent, look at " << currentMachine);
603       CORBA::Object_var obj = _NS->ResolveComponent(currentMachine,
604                                                     containerName,
605                                                     componentName,
606                                                     nbproc);
607       if (!CORBA::is_nil(obj))
608         machinesOK[lghtOfmachinesOK++] = CORBA::string_dup(currentMachine);
609     }
610
611   // --- find the best machine among the list
612
613   if(lghtOfmachinesOK != 0)
614     {
615       machinesOK->length(lghtOfmachinesOK);
616       CORBA::String_var bestMachine = _ResManager->FindFirst(machinesOK);
617       CORBA::Object_var obj = _NS->ResolveComponent(bestMachine,
618                                                     containerName,
619                                                     componentName,
620                                                     nbproc);
621       return Engines::Component::_narrow(obj);
622     }
623   else
624     return Engines::Component::_nil();
625 }
626
627 //=============================================================================
628 /*! \brief  Load a component instance.
629  *
630  *  - Finds a container in the list of machine or start one.
631  *  - Try to load the component library in the container,
632  *  - then create an instance of the component.
633  *
634  *  \param params         machine parameters like type or name...
635  *  \param componentName  the name of component class
636  *  \param studyId        default = 0  : multistudy instance
637  *  \return a CORBA reference of the component instance, or _nil if problem
638  */
639 //=============================================================================
640
641 Engines::Component_ptr 
642 SALOME_LifeCycleCORBA::
643 _LoadComponent(const Engines::MachineParameters& params, 
644               const char *componentName,
645               int studyId)
646 {
647   MESSAGE("_LoadComponent, required " << params.container_name <<
648           " " << componentName << " " << NbProc(params));
649
650   Engines::Container_var cont = _ContManager->FindOrStartContainer(params);
651   if (CORBA::is_nil(cont)) return Engines::Component::_nil();
652
653   bool isLoadable = cont->load_component_Library(componentName);
654   if (!isLoadable) return Engines::Component::_nil();
655
656   Engines::Component_var myInstance =
657     cont->create_component_instance(componentName, studyId);
658   return myInstance._retn();
659 }
660
661 //=============================================================================
662 /*! \brief  Load a parallel component instance.
663  *
664  *  \param params         machine parameters like type or name...
665  *  \param componentName  the name of component class
666  *  \param studyId        default = 0  : multistudy instance
667  *  \return a CORBA reference of the parallel component instance, or _nil if problem
668  */
669 //=============================================================================
670 Engines::Component_ptr
671 SALOME_LifeCycleCORBA::Load_ParallelComponent(const Engines::MachineParameters& params,
672                                               const char *componentName,
673                                               int studyId)
674 {
675   MESSAGE("Entering LoadParallelComponent");
676
677 /*MESSAGE("Parameters : ");
678   MESSAGE("Container name : " << params.container_name);
679   MESSAGE("Number of component nodes : " << params.nb_component_nodes);
680   MESSAGE("Component Name : " << componentName);*/
681
682   Engines::MachineParameters parms(params);
683   parms.componentList.length(1);
684   parms.componentList[0] = componentName;
685
686   MESSAGE("Starting Parallel Container");
687   Engines::Container_var cont = _ContManager->StartParallelContainer(parms);
688   if (CORBA::is_nil(cont)) {
689     INFOS("FindOrStartParallelContainer() returns a NULL container !");
690     return Engines::Component::_nil();
691   }
692
693   MESSAGE("Loading component library");
694   bool isLoadable = cont->load_component_Library(componentName);
695   if (!isLoadable) {
696     INFOS(componentName <<" library is not loadable !");
697     return Engines::Component::_nil();
698   }
699
700   MESSAGE("Creating component instance");
701   // @PARALLEL@ permits to identify that the component requested
702   // is a parallel component.
703   string name = string(componentName);
704   Engines::Component_var myInstance = cont->create_component_instance(name.c_str(), studyId);
705   if (CORBA::is_nil(myInstance))
706     INFOS("create_component_instance returns a NULL component !");
707   return myInstance._retn();
708 }
709
710 /*! \brief copy a file from a source host to a destination host
711  * \param hostSrc the source host
712  * \param fileSrc the file to copy from the source host to the destination host
713  * \param hostDest the destination host
714  * \param fileDest the destination file
715  */
716 void SALOME_LifeCycleCORBA::copyFile(const char* hostSrc, const char* fileSrc, const char* hostDest, const char* fileDest)
717 {
718   if(strcmp(hostDest,"localhost") == 0)
719     {
720       //if localhost use a shortcut
721       SALOME_FileTransferCORBA transfer(hostSrc,fileSrc);
722       transfer.getLocalFile(fileDest);
723       return;
724     }
725
726   Engines::ContainerManager_var contManager = getContainerManager();
727
728   Engines::MachineParameters params;
729   preSet(params);
730
731   params.hostname = hostDest;
732   Engines::Container_var containerDest = contManager->FindOrStartContainer(params);
733
734   params.hostname = hostSrc;
735   Engines::Container_var containerSrc = contManager->FindOrStartContainer(params);
736
737   containerDest->copyFile(containerSrc,fileSrc,fileDest);
738 }
739
740 /*! \brief get the naming service used by the life cycle
741  *
742  *  \return the naming service
743  */
744 SALOME_NamingService * SALOME_LifeCycleCORBA::namingService()
745 {
746   return _NS;
747 }
748
749 /*! \brief get the orb used by the life cycle
750  *
751  *  \return the orb
752  */
753 CORBA::ORB_ptr SALOME_LifeCycleCORBA::orb()
754 {
755   return _NS->orb();
756 }
757