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