Salome HOME
Merge from V6_main 13/12/2012
[modules/yacs.git] / src / LifeCycleCORBA / SALOME_LifeCycleCORBA.cxx
1 // Copyright (C) 2007-2012  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
23 //  SALOME LifeCycleCORBA : implementation of containers and engines life cycle both in Python and C++
24 //  File   : SALOME_LifeCycleCORBA.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SALOME
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   #include <unistd.h>
37 #endif
38
39 #include "Basics_Utils.hxx"
40 #include "utilities.h"
41
42 #include <ServiceUnreachable.hxx>
43
44 #include "SALOME_LifeCycleCORBA.hxx"
45 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
46 #include CORBA_CLIENT_HEADER(SALOME_Session)
47 #include CORBA_CLIENT_HEADER(DSC_Engines)
48 #include CORBA_CLIENT_HEADER(SALOME_Registry)
49 #include CORBA_CLIENT_HEADER(SALOMEDS)
50 #include CORBA_CLIENT_HEADER(Logger)
51
52 #include "SALOME_ContainerManager.hxx"
53 #include "SALOME_Component_i.hxx"
54 #include "SALOME_NamingService.hxx"
55 #include "SALOME_FileTransferCORBA.hxx"
56
57 IncompatibleComponent::IncompatibleComponent( void ):
58   SALOME_Exception( "IncompatibleComponent" )
59 {
60 }
61
62 IncompatibleComponent::IncompatibleComponent(const IncompatibleComponent &ex):
63   SALOME_Exception( ex ) 
64 {
65 }
66
67 /*! \class SALOME_LifeCycleCORBA
68     \brief A class to manage life cycle of SALOME components.
69
70 */
71
72 //=============================================================================
73 /*! 
74  *  Constructor
75  */
76 //=============================================================================
77
78 SALOME_LifeCycleCORBA::SALOME_LifeCycleCORBA(SALOME_NamingService *ns)
79 {
80   // be sure to have an instance of traceCollector, when used via SWIG
81   // in a Python module
82   int argc = 0;
83   char *xargv = (char*)"";
84   char **argv = &xargv;
85   CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
86   //  LocalTraceCollector *myThreadTrace = SALOMETraceCollector::instance(orb);
87   _NSnew=0;
88   if (!ns)
89     {
90       _NS = new SALOME_NamingService(orb);
91       _NSnew=_NS;
92     }
93   else _NS = ns;
94   //add try catch
95   _NS->Change_Directory("/"); // mpv 250105: current directory may be not root 
96                               // (in SALOMEDS for an example)
97   // not enough: set a current directory in naming service is not thread safe
98   // if naming service instance is shared among several threads...
99   // ==> allways use absolute path and dot rely on current directory!
100
101   CORBA::Object_var obj =
102     _NS->Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS);
103   ASSERT( !CORBA::is_nil(obj));
104   _ContManager=Engines::ContainerManager::_narrow(obj);
105
106   obj = _NS->Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS);
107   ASSERT( !CORBA::is_nil(obj));
108   _ResManager=Engines::ResourcesManager::_narrow(obj);
109 }
110
111 //=============================================================================
112 /*! 
113  *  Destructor
114  */
115 //=============================================================================
116
117 SALOME_LifeCycleCORBA::~SALOME_LifeCycleCORBA()
118 {
119   if(_NSnew)delete _NSnew;
120 }
121
122 //=============================================================================
123 /*! \brief Find an already existing and registered component instance.
124  *
125  *  \param params         machine parameters like type or name...
126  *  \param componentName  the name of component class
127  *  \param studyId        default = 0  : multistudy instance
128  *  \return a CORBA reference of the component instance, or _nil if not found
129  */
130 //=============================================================================
131 Engines::EngineComponent_ptr
132 SALOME_LifeCycleCORBA::FindComponent(const Engines::MachineParameters& params,
133                                      const char *componentName,
134                                      int studyId)
135 {
136   if (! isKnownComponentClass(componentName))
137     return Engines::EngineComponent::_nil();
138
139   Engines::ContainerParameters new_params;
140   convert(params, new_params);
141   new_params.resource_params.componentList.length(1);
142   new_params.resource_params.componentList[0] = componentName;
143   Engines::ResourceList_var listOfResources;
144   try
145     {
146       listOfResources = _ResManager->GetFittingResources(new_params.resource_params);
147     }
148   catch( const SALOME::SALOME_Exception& ex )
149     {
150       return Engines::EngineComponent::_nil();
151     }
152
153   Engines::EngineComponent_var compo = _FindComponent(new_params,
154                                                 componentName,
155                                                 studyId,
156                                                 listOfResources);
157
158   return compo._retn();
159 }
160
161 //=============================================================================
162 /*! \brief Load a component instance on a container defined by machine parameters
163  *
164  *  \param params         machine parameters like type or name...
165  *  \param componentName  the name of component class
166  *  \param studyId        default = 0  : multistudy instance
167  *  \return a CORBA reference of the component instance, or _nil if problem
168  */
169 //=============================================================================
170
171 Engines::EngineComponent_ptr
172 SALOME_LifeCycleCORBA::LoadComponent(const Engines::MachineParameters& params,
173                                      const char *componentName,
174                                      int studyId)
175 {
176   // --- Check if Component Name is known in ModuleCatalog
177
178   if (! isKnownComponentClass(componentName))
179     return Engines::EngineComponent::_nil();
180
181   Engines::ContainerParameters new_params;
182   convert(params, new_params);
183   new_params.resource_params.componentList.length(1);
184   new_params.resource_params.componentList[0] = componentName;
185
186   Engines::ResourceList_var listOfResources;
187   try
188     {
189       listOfResources = _ResManager->GetFittingResources(new_params.resource_params);
190     }
191   catch( const SALOME::SALOME_Exception& ex )
192     {
193       return Engines::EngineComponent::_nil();
194     }
195   new_params.resource_params.resList = listOfResources;
196
197   Engines::EngineComponent_var compo = _LoadComponent(new_params,
198                                                 componentName,
199                                                 studyId);
200
201   return compo._retn();
202 }
203
204 //=============================================================================
205 /*! \brief Find an already existing and registered component instance or load a new
206  *         component instance on a container defined by machine parameters.
207  *
208  *  \param params         machine parameters like type or name...
209  *  \param componentName  the name of component class
210  *  \param studyId        default = 0  : multistudy instance
211  *  \return a CORBA reference of the component instance, or _nil if problem
212  */
213 //=============================================================================
214
215 Engines::EngineComponent_ptr
216 SALOME_LifeCycleCORBA::
217 FindOrLoad_Component(const Engines::MachineParameters& params,
218                      const char *componentName,
219                      int studyId)
220 {
221   // --- Check if Component Name is known in ModuleCatalog
222
223   if (! isKnownComponentClass(componentName))
224     return Engines::EngineComponent::_nil();
225
226   Engines::ContainerParameters new_params;
227   convert(params, new_params);
228   new_params.resource_params.componentList.length(1);
229   new_params.resource_params.componentList[0] = componentName;
230
231   // For Compatibility -> if hostname == localhost put name == hostname
232   if (std::string(new_params.resource_params.hostname.in()) == "localhost")
233   {
234     new_params.resource_params.hostname = CORBA::string_dup(Kernel_Utils::GetHostname().c_str());
235     new_params.resource_params.name = CORBA::string_dup(Kernel_Utils::GetHostname().c_str());
236   }
237
238   Engines::ResourceList_var listOfResources;
239   try
240     {
241       listOfResources = _ResManager->GetFittingResources(new_params.resource_params);
242     }
243   catch( const SALOME::SALOME_Exception& ex )
244     {
245       return Engines::EngineComponent::_nil();
246     }
247
248   Engines::EngineComponent_var compo = _FindComponent(new_params,
249                                                 componentName,
250                                                 studyId,
251                                                 listOfResources);
252
253   if(CORBA::is_nil(compo))
254   {
255     new_params.resource_params.resList = listOfResources;
256     compo = _LoadComponent(new_params,
257                            componentName,
258                            studyId);
259   }
260
261   return compo._retn();
262 }
263
264 Engines::EngineComponent_ptr
265 SALOME_LifeCycleCORBA::
266 FindOrLoad_Component(const Engines::ContainerParameters& params,
267                      const char *componentName,
268                      int studyId)
269 {
270   // --- Check if Component Name is known in ModuleCatalog
271
272   if (! isKnownComponentClass(componentName))
273     return Engines::EngineComponent::_nil();
274
275   Engines::ContainerParameters new_params(params);
276   new_params.resource_params.componentList.length(1);
277   new_params.resource_params.componentList[0] = componentName;
278
279   Engines::ResourceList_var listOfResources;
280   try
281     {
282       listOfResources = _ResManager->GetFittingResources(new_params.resource_params);
283     }
284   catch( const SALOME::SALOME_Exception& ex )
285     {
286       return Engines::EngineComponent::_nil();
287     }
288
289   Engines::EngineComponent_var compo = _FindComponent(new_params,
290                                                 componentName,
291                                                 studyId,
292                                                 listOfResources);
293
294   if(CORBA::is_nil(compo))
295   {
296     new_params.resource_params.resList = listOfResources;
297     compo = _LoadComponent(new_params,
298                            componentName,
299                            studyId);
300   }
301
302   return compo._retn();
303 }
304
305 //=============================================================================
306 /*! \brief Find an already existing and registered component instance or load a new
307  *         component instance on a container defined by name
308  *
309  *  \param containerName  the name of container, under one of the forms
310  *           - 1 aContainer (local container)
311  *           - 2 machine/aContainer (container on hostname = machine)
312  *  \param componentName  the name of component class
313  *  \return a CORBA reference of the component instance, or _nil if problem
314  */
315 //=============================================================================
316
317 Engines::EngineComponent_ptr
318 SALOME_LifeCycleCORBA::FindOrLoad_Component(const char *containerName,
319                                             const char *componentName)
320 {
321   MESSAGE("SALOME_LifeCycleCORBA::FindOrLoad_Component INTERACTIF " << containerName << " " << componentName ) ;
322
323   // --- Check if Component Name is known in ModuleCatalog
324   if (! isKnownComponentClass(componentName))
325     return Engines::EngineComponent::_nil();
326
327   // --- Check if containerName contains machine name (if yes: rg>0)
328   char *stContainer=strdup(containerName);
329   std::string st2Container(stContainer);
330   int rg=st2Container.find("/");
331
332   Engines::MachineParameters_var params=new Engines::MachineParameters;
333   preSet(params);
334   if (rg<0)
335   {
336     // containerName doesn't contain "/" => Local container
337     params->container_name=CORBA::string_dup(stContainer);
338     params->hostname="";
339   }
340   else 
341   {
342     stContainer[rg]='\0';
343     params->container_name=CORBA::string_dup(stContainer+rg+1);
344     params->hostname=CORBA::string_dup(stContainer);
345   }
346   params->isMPI = false;
347   SCRUTE(params->container_name);
348   free(stContainer);
349   return FindOrLoad_Component(params, componentName);
350 }
351
352 //=============================================================================
353 /*! \brief Check if the component class is known in module catalog
354  *
355  *  \param componentName  the name of component class
356  *  \return true if found, false otherwise
357  */
358 //=============================================================================
359
360 bool SALOME_LifeCycleCORBA::isKnownComponentClass(const char *componentName)
361 {
362   try
363   {
364     CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog");
365     SALOME_ModuleCatalog::ModuleCatalog_var Catalog = 
366       SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
367     ASSERT(! CORBA::is_nil(Catalog));
368     SALOME_ModuleCatalog::Acomponent_var compoInfo = 
369       Catalog->GetComponent(componentName);
370     if (CORBA::is_nil (compoInfo)) 
371     {
372       MESSAGE("Catalog Error: Component not found in the catalog " << componentName);
373       return false;
374     }
375     else return true;
376   }
377   catch (ServiceUnreachable&)
378   {
379     INFOS("Caught exception: Naming Service Unreachable");
380   }
381   catch (...)
382   {
383     INFOS("Caught unknown exception.");
384   }
385   return false;
386 }
387
388 //=============================================================================
389 /*! 
390  *  Not so complex... useful ?
391  */
392 //=============================================================================
393
394 bool 
395 SALOME_LifeCycleCORBA::isMpiContainer(const Engines::ContainerParameters& params)
396   throw(IncompatibleComponent)
397 {
398   if( params.isMPI )
399     return true;
400   else
401     return false;
402 }
403
404
405 //=============================================================================
406 /*! \brief Initialisation of a given Engines::MachineParameters with default values.
407  *
408  *  - container_name = ""  : not relevant
409  *  - hostname = ""        : not relevant
410  *  - OS = ""              : not relevant
411  *  - nb_proc = 0          : not relevant
412  *  - mem_mb = 0           : not relevant
413  *  - cpu_clock = 0        : not relevant
414  *  - nb_proc_per_node = 0 : not relevant
415  *  - nb_node = 0          : not relevant
416  *  - isMPI = false        : standard components
417  */
418 //=============================================================================
419
420 void SALOME_LifeCycleCORBA::preSet(Engines::MachineParameters& params)
421 {
422   params.container_name = "";
423   params.hostname = "";
424   params.OS = "";
425   params.mem_mb = 0;
426   params.cpu_clock = 0;
427   params.nb_proc_per_node = 0;
428   params.nb_node = 0;
429   params.isMPI = false;
430   params.workingdir = "";
431   params.mode = "";
432   params.policy = "";
433   params.parallelLib = "";
434   params.nb_component_nodes = 0;
435 }
436
437 void 
438 SALOME_LifeCycleCORBA::preSet(Engines::ResourceParameters& params)
439 {
440   params.name = "";
441   params.hostname = "";
442   params.OS = "";
443   params.nb_proc = 0;
444   params.mem_mb = 0;
445   params.cpu_clock = 0;
446   params.nb_node = 0;
447   params.nb_proc_per_node = 0;
448   params.policy = "";
449 }
450
451 void SALOME_LifeCycleCORBA::preSet( Engines::ContainerParameters& params)
452 {
453   params.container_name = "";
454   params.mode = "";
455   params.workingdir = "";
456   params.nb_proc = 0;
457   params.isMPI = false;
458   params.parallelLib = "";
459   SALOME_LifeCycleCORBA::preSet(params.resource_params);
460 }
461
462 void 
463 SALOME_LifeCycleCORBA::convert(const Engines::MachineParameters& params_in, 
464                                Engines::ContainerParameters& params_out)
465 {
466   SALOME_LifeCycleCORBA::preSet(params_out);
467
468   // Container part
469   params_out.container_name = params_in.container_name;
470   params_out.mode = params_in.mode;
471   params_out.workingdir = params_in.workingdir;
472   params_out.isMPI = params_in.isMPI;
473   params_out.parallelLib = params_in.parallelLib;
474
475   // Resource part
476   params_out.resource_params.hostname = params_in.hostname;
477   params_out.resource_params.OS = params_in.OS;
478   params_out.resource_params.mem_mb = params_in.mem_mb;
479   params_out.resource_params.cpu_clock = params_in.cpu_clock;
480   params_out.resource_params.nb_node = params_in.nb_node;
481   params_out.resource_params.nb_proc_per_node = params_in.nb_proc_per_node;
482   params_out.resource_params.policy = params_in.policy;
483   params_out.resource_params.componentList = params_in.componentList;
484
485   params_out.resource_params.resList.length(params_in.computerList.length());
486   for (CORBA::ULong i = 0; i < params_in.computerList.length(); i++)
487     params_out.resource_params.resList[i] = params_in.computerList[i];
488 }
489
490 //=============================================================================
491 /*! 
492  *  \return a number of processors not 0, only for MPI containers
493  */
494 //=============================================================================
495
496 int SALOME_LifeCycleCORBA::NbProc(const Engines::ContainerParameters& params)
497 {
498   if( !isMpiContainer(params) )
499     return 0;
500   else if( params.nb_proc <= 0 )
501     return 1;
502   else
503     return params.nb_proc;
504 }
505
506 //=============================================================================
507 /*! \brief Get the container manager
508  *
509  *  \return the container Manager
510  */
511 //=============================================================================
512
513 Engines::ContainerManager_ptr SALOME_LifeCycleCORBA::getContainerManager()
514 {
515  Engines::ContainerManager_var contManager =
516    Engines::ContainerManager::_duplicate(_ContManager);
517  return contManager._retn();
518 }
519
520 //=============================================================================
521 /*! \brief Get the resources manager
522  *
523  *  \return the container Manager
524  */
525 //=============================================================================
526
527 Engines::ResourcesManager_ptr SALOME_LifeCycleCORBA::getResourcesManager()
528 {
529  Engines::ResourcesManager_var resManager =
530    Engines::ResourcesManager::_duplicate(_ResManager);
531  return resManager._retn();
532 }
533
534 //=============================================================================
535 /*! \brief shutdown all the SALOME servers except SALOME_Session_Server, omniNames and notifd
536  */
537 //=============================================================================
538
539 void SALOME_LifeCycleCORBA::shutdownServers()
540 {
541   // get each Container from NamingService => shutdown it
542   // (the order is inverse to the order of servers initialization)
543   
544   SALOME::Session_var session = SALOME::Session::_nil();
545   CORBA::Long pid = 0;
546   CORBA::Object_var objS = _NS->Resolve("/Kernel/Session");
547   if (!CORBA::is_nil(objS))
548   {
549     session = SALOME::Session::_narrow(objS);
550     if (!CORBA::is_nil(session))
551     {
552       pid = session->getPID();
553       session->Shutdown();
554     }
555   }
556
557   std::string hostname = Kernel_Utils::GetHostname();
558   
559   // 1) ConnectionManager
560   try
561     {
562       CORBA::Object_var objCnM=_NS->Resolve("/ConnectionManager");
563       Engines::ConnectionManager_var connMan=Engines::ConnectionManager::_narrow(objCnM);
564       if ( !CORBA::is_nil(connMan) && ( pid != connMan->getPID() ) )
565         connMan->ShutdownWithExit();
566     }
567   catch(const CORBA::Exception& e)
568     {
569        // ignore and continue
570     }
571
572   timespec ts_req;
573   ts_req.tv_nsec=100000000;
574   ts_req.tv_sec=0;
575
576 //Wait some time so that ConnectionManager be completely shutdown
577 #ifndef WIN32
578   nanosleep(&ts_req,0);
579 #endif
580
581   // 2) SALOMEDS
582   try
583     {
584       CORBA::Object_var objSDS = _NS->Resolve("/myStudyManager");
585       SALOMEDS::StudyManager_var studyManager = SALOMEDS::StudyManager::_narrow(objSDS) ;
586       if ( !CORBA::is_nil(studyManager) && ( pid != studyManager->getPID() ) )
587         studyManager->Shutdown();
588     }
589   catch(const CORBA::Exception& e)
590     {
591        // ignore and continue
592     }
593
594 //Wait some time so that study be completely shutdown
595 #ifndef WIN32
596   nanosleep(&ts_req,0);
597 #endif
598
599   // 3) ModuleCatalog
600   try
601     {
602       CORBA::Object_var objMC=_NS->Resolve("/Kernel/ModulCatalog");
603       SALOME_ModuleCatalog::ModuleCatalog_var catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(objMC);
604       if ( !CORBA::is_nil(catalog) && ( pid != catalog->getPID() ) )
605         catalog->shutdown();
606     }
607   catch(const CORBA::Exception& e)
608     {
609        // ignore and continue
610     }
611
612 //Wait some time so that ModulCatalog be completely shutdown
613 #ifndef WIN32
614   nanosleep(&ts_req,0);
615 #endif
616
617   // 4) SalomeLauncher
618   try
619     {
620       CORBA::Object_var objSL = _NS->Resolve("/SalomeLauncher");
621       Engines::SalomeLauncher_var launcher = Engines::SalomeLauncher::_narrow(objSL);
622       if (!CORBA::is_nil(launcher) && (pid != launcher->getPID()))
623         launcher->Shutdown();
624     }
625   catch(const CORBA::Exception& e)
626     {
627        // ignore and continue
628     }
629   
630 //Wait some time so that launcher be completely shutdown
631 #ifndef WIN32
632   nanosleep(&ts_req,0);
633 #endif
634
635   // 5) Registry
636   try
637     {
638       CORBA::Object_var objR = _NS->Resolve("/Registry");
639       Registry::Components_var registry = Registry::Components::_narrow(objR);
640       if ( !CORBA::is_nil(registry) && ( pid != registry->getPID() ) )
641           registry->Shutdown();
642     }
643   catch(const CORBA::Exception& e)
644     {
645        // ignore and continue
646     }
647
648   /*
649   // 6) Session
650   if ( !CORBA::is_nil( session ) ) {
651     try
652     {
653       session->Shutdown();
654     }
655     catch(const CORBA::Exception& e)
656     {
657       // ignore and continue
658     }
659   }
660   */
661
662   // 7) Logger
663   int argc = 0;
664   char *xargv = (char*)"";
665   char **argv = &xargv;
666   CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
667
668   CORBA::Object_var objLog = CORBA::Object::_nil();
669   CosNaming::NamingContext_var inc;
670   CORBA::Object_var theObj = CORBA::Object::_nil();
671   std::string stdname = "Logger";
672   CosNaming::Name name;
673   name.length(1);
674   name[0].id = CORBA::string_dup(stdname.c_str());
675   try
676   { 
677     if(!CORBA::is_nil(orb)) 
678       theObj = orb->resolve_initial_references("NameService");
679     if (!CORBA::is_nil(theObj))
680       inc = CosNaming::NamingContext::_narrow(theObj);
681   }
682   catch(...)
683   {
684   }
685   if(!CORBA::is_nil(inc)) 
686   {
687     try
688     {
689       objLog = inc->resolve(name);
690       SALOME_Logger::Logger_var logger = SALOME_Logger::Logger::_narrow(objLog);
691       if ( !CORBA::is_nil(logger) )
692         logger->shutdown();
693     }
694     catch(...)
695     {
696     }
697   }
698 }
699
700 //=============================================================================
701 /*! \brief shutdown  omniNames and notifd
702  */
703 //=============================================================================
704
705 void SALOME_LifeCycleCORBA::killOmniNames()
706 {
707   std::string portNumber (::getenv ("NSPORT") );
708   if ( !portNumber.empty() ) 
709   {
710 #ifdef WNT
711 #else
712     std::string cmd ;
713     cmd = std::string( "ps -eo pid,command | grep -v grep | grep -E \"omniNames.*")
714       + portNumber
715       + std::string("\" | awk '{cmd=sprintf(\"kill -9 %s\",$1); system(cmd)}'" );
716     MESSAGE(cmd);
717     try {
718       system ( cmd.c_str() );
719     }
720     catch ( ... ) {
721     }
722 #endif
723   }
724   
725   // NPAL 18309  (Kill Notifd)
726   if ( !portNumber.empty() ) 
727   {
728     std::string cmd = ("from killSalomeWithPort import killNotifdAndClean; ");
729     cmd += std::string("killNotifdAndClean(") + portNumber + "); ";
730     cmd  = std::string("python -c \"") + cmd +"\" > /dev/null 2> /dev/null";
731     MESSAGE(cmd);
732     system( cmd.c_str() );
733   }
734 }
735
736 //=============================================================================
737 /*! \brief Find an already existing and registered component instance.
738  *
739  * - build a list of machines on which an instance of the component is running,
740  * - find the best machine among the list
741  *
742  *  \param params         machine parameters like type or name...
743  *  \param componentName  the name of component class
744  *  \param studyId        default = 0  : multistudy instance
745  *  \param listOfMachines list of machine address
746  *  \return a CORBA reference of the component instance, or _nil if not found
747  */
748 //=============================================================================
749
750 Engines::EngineComponent_ptr
751 SALOME_LifeCycleCORBA::
752 _FindComponent(const Engines::ContainerParameters& params,
753                const char *componentName,
754                int studyId,
755                const Engines::ResourceList& listOfResources)
756 {
757   // --- build the list of machines on which the component is already running
758   const char *containerName = params.container_name;
759   int nbproc = NbProc(params);
760
761   Engines::ResourceList_var resourcesOK = new Engines::ResourceList;
762
763   unsigned int lghtOfresourcesOK = 0;
764   resourcesOK->length(listOfResources.length());
765
766   for(unsigned int i=0; i < listOfResources.length(); i++)
767   {
768     const char * currentResource = listOfResources[i];
769     CORBA::Object_var obj = _NS->ResolveComponent(currentResource,
770                                                   containerName,
771                                                   componentName,
772                                                   nbproc);
773     if (!CORBA::is_nil(obj))
774       resourcesOK[lghtOfresourcesOK++] = CORBA::string_dup(currentResource);
775   }
776
777   // --- find the best machine among the list
778   if(lghtOfresourcesOK != 0)
779   {
780     resourcesOK->length(lghtOfresourcesOK);
781     CORBA::String_var bestResource = _ResManager->FindFirst(resourcesOK);
782     CORBA::Object_var obj = _NS->ResolveComponent(bestResource,
783                                                   containerName,
784                                                   componentName,
785                                                   nbproc);
786     return Engines::EngineComponent::_narrow(obj);
787   }
788   else
789     return Engines::EngineComponent::_nil();
790 }
791
792 //=============================================================================
793 /*! \brief  Load a component instance.
794  *
795  *  - Finds a container in the list of machine or start one.
796  *  - Try to load the component library in the container,
797  *  - then create an instance of the component.
798  *
799  *  \param params         machine parameters like type or name...
800  *  \param componentName  the name of component class
801  *  \param studyId        default = 0  : multistudy instance
802  *  \return a CORBA reference of the component instance, or _nil if problem
803  */
804 //=============================================================================
805
806 Engines::EngineComponent_ptr 
807 SALOME_LifeCycleCORBA::
808 _LoadComponent(const Engines::ContainerParameters& params, 
809               const char *componentName,
810               int studyId)
811 {
812   MESSAGE("_LoadComponent, required " << params.container_name <<
813           " " << componentName << " " << NbProc(params));
814
815   Engines::ContainerParameters local_params(params);
816   local_params.mode = CORBA::string_dup("findorstart");
817   Engines::Container_var cont = _ContManager->GiveContainer(local_params);
818   if (CORBA::is_nil(cont)) return Engines::EngineComponent::_nil();
819
820   char* reason;
821   bool isLoadable = cont->load_component_Library(componentName,reason);
822   if (!isLoadable) 
823     {
824       //std::cerr << reason << std::endl;
825       CORBA::string_free(reason);
826       return Engines::EngineComponent::_nil();
827     }
828   CORBA::string_free(reason);
829
830   Engines::EngineComponent_var myInstance =
831     cont->create_component_instance(componentName, studyId);
832   return myInstance._retn();
833 }
834
835 //=============================================================================
836 /*! \brief  Load a parallel component instance.
837  *
838  *  \param params         machine parameters like type or name...
839  *  \param componentName  the name of component class
840  *  \param studyId        default = 0  : multistudy instance
841  *  \return a CORBA reference of the parallel component instance, or _nil if problem
842  */
843 //=============================================================================
844 Engines::EngineComponent_ptr
845 SALOME_LifeCycleCORBA::Load_ParallelComponent(const Engines::ContainerParameters& params,
846                                               const char *componentName,
847                                               int studyId)
848 {
849   MESSAGE("Entering LoadParallelComponent");
850
851 /*MESSAGE("Parameters : ");
852   MESSAGE("Container name : " << params.container_name);
853   MESSAGE("Number of component nodes : " << params.nb_component_nodes);
854   MESSAGE("Component Name : " << componentName);*/
855
856   Engines::ContainerParameters parms(params);
857   parms.resource_params.componentList.length(1);
858   parms.resource_params.componentList[0] = componentName;
859   parms.mode = CORBA::string_dup("findorstart");
860
861   MESSAGE("Starting Parallel Container");
862   Engines::Container_var cont = _ContManager->GiveContainer(parms);
863   if (CORBA::is_nil(cont)) {
864     INFOS("FindOrStartParallelContainer() returns a NULL container !");
865     return Engines::EngineComponent::_nil();
866   }
867
868   MESSAGE("Loading component library");
869   char* reason;
870   bool isLoadable = cont->load_component_Library(componentName,reason);
871   if (!isLoadable) {
872     INFOS(componentName <<" library is not loadable !");
873     //std::cerr << reason << std::endl;
874     CORBA::string_free(reason);
875     return Engines::EngineComponent::_nil();
876   }
877   CORBA::string_free(reason);
878
879   MESSAGE("Creating component instance");
880   // @PARALLEL@ permits to identify that the component requested
881   // is a parallel component.
882   std::string name = std::string(componentName);
883   Engines::EngineComponent_var myInstance = cont->create_component_instance(name.c_str(), studyId);
884   if (CORBA::is_nil(myInstance))
885     INFOS("create_component_instance returns a NULL component !");
886   return myInstance._retn();
887 }
888
889 /*! \brief copy a file from a source host to a destination host
890  * \param hostSrc the source host
891  * \param fileSrc the file to copy from the source host to the destination host
892  * \param hostDest the destination host
893  * \param fileDest the destination file
894  */
895 void SALOME_LifeCycleCORBA::copyFile(const char* hostSrc, const char* fileSrc, const char* hostDest, const char* fileDest)
896 {
897   if(strcmp(hostDest,"localhost") == 0)
898     {
899       //if localhost use a shortcut
900       SALOME_FileTransferCORBA transfer(hostSrc,fileSrc);
901       transfer.getLocalFile(fileDest);
902       return;
903     }
904
905   Engines::ContainerManager_var contManager = getContainerManager();
906
907   Engines::ContainerParameters params;
908   preSet(params);
909
910   params.resource_params.hostname = hostDest;
911   params.mode = CORBA::string_dup("findorstart");
912   Engines::Container_var containerDest = contManager->GiveContainer(params);
913
914   params.resource_params.hostname = hostSrc;
915   Engines::Container_var containerSrc = contManager->GiveContainer(params);
916
917   containerDest->copyFile(containerSrc,fileSrc,fileDest);
918 }
919
920 /*! \brief get the naming service used by the life cycle
921  *
922  *  \return the naming service
923  */
924 SALOME_NamingService * SALOME_LifeCycleCORBA::namingService()
925 {
926   return _NS;
927 }
928
929 /*! \brief get the orb used by the life cycle
930  *
931  *  \return the orb
932  */
933 CORBA::ORB_ptr SALOME_LifeCycleCORBA::orb()
934 {
935   return _NS->orb();
936 }