Salome HOME
Change dot image format from jpg to png.
[modules/kernel.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     }
554   }
555
556   std::string hostname = Kernel_Utils::GetHostname();
557   
558   // 1) ConnectionManager
559   try
560     {
561       CORBA::Object_var objCnM=_NS->Resolve("/ConnectionManager");
562       Engines::ConnectionManager_var connMan=Engines::ConnectionManager::_narrow(objCnM);
563       if ( !CORBA::is_nil(connMan) && ( pid != connMan->getPID() ) )
564         connMan->ShutdownWithExit();
565     }
566   catch(const CORBA::Exception& e)
567     {
568        // ignore and continue
569     }
570
571   timespec ts_req;
572   ts_req.tv_nsec=100000000;
573   ts_req.tv_sec=0;
574
575 //Wait some time so that ConnectionManager be completely shutdown
576 #ifndef WIN32
577   nanosleep(&ts_req,0);
578 #endif
579
580   // 2) SALOMEDS
581   try
582     {
583       CORBA::Object_var objSDS = _NS->Resolve("/myStudyManager");
584       SALOMEDS::StudyManager_var studyManager = SALOMEDS::StudyManager::_narrow(objSDS) ;
585       if ( !CORBA::is_nil(studyManager) && ( pid != studyManager->getPID() ) )
586         studyManager->Shutdown();
587     }
588   catch(const CORBA::Exception& e)
589     {
590        // ignore and continue
591     }
592
593 //Wait some time so that study be completely shutdown
594 #ifndef WIN32
595   nanosleep(&ts_req,0);
596 #endif
597
598   // 3) ModuleCatalog
599   try
600     {
601       CORBA::Object_var objMC=_NS->Resolve("/Kernel/ModulCatalog");
602       SALOME_ModuleCatalog::ModuleCatalog_var catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(objMC);
603       if ( !CORBA::is_nil(catalog) && ( pid != catalog->getPID() ) )
604         catalog->shutdown();
605     }
606   catch(const CORBA::Exception& e)
607     {
608        // ignore and continue
609     }
610
611 //Wait some time so that ModulCatalog be completely shutdown
612 #ifndef WIN32
613   nanosleep(&ts_req,0);
614 #endif
615
616   // 4) SalomeLauncher
617   try
618     {
619       CORBA::Object_var objSL = _NS->Resolve("/SalomeLauncher");
620       Engines::SalomeLauncher_var launcher = Engines::SalomeLauncher::_narrow(objSL);
621       if (!CORBA::is_nil(launcher) && (pid != launcher->getPID()))
622         launcher->Shutdown();
623     }
624   catch(const CORBA::Exception& e)
625     {
626        // ignore and continue
627     }
628   
629 //Wait some time so that launcher be completely shutdown
630 #ifndef WIN32
631   nanosleep(&ts_req,0);
632 #endif
633
634   // 5) Registry
635   try
636     {
637       CORBA::Object_var objR = _NS->Resolve("/Registry");
638       Registry::Components_var registry = Registry::Components::_narrow(objR);
639       if ( !CORBA::is_nil(registry) && ( pid != registry->getPID() ) )
640           registry->Shutdown();
641     }
642   catch(const CORBA::Exception& e)
643     {
644        // ignore and continue
645     }
646
647   // 6) Session
648   if ( !CORBA::is_nil( session ) ) {
649     try
650     {
651       session->Shutdown();
652     }
653     catch(const CORBA::Exception& e)
654     {
655       // ignore and continue
656     }
657   }
658
659   // 7) Logger
660   int argc = 0;
661   char *xargv = (char*)"";
662   char **argv = &xargv;
663   CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
664
665   CORBA::Object_var objLog = CORBA::Object::_nil();
666   CosNaming::NamingContext_var inc;
667   CORBA::Object_var theObj = CORBA::Object::_nil();
668   std::string stdname = "Logger";
669   CosNaming::Name name;
670   name.length(1);
671   name[0].id = CORBA::string_dup(stdname.c_str());
672   try
673   { 
674     if(!CORBA::is_nil(orb)) 
675       theObj = orb->resolve_initial_references("NameService");
676     if (!CORBA::is_nil(theObj))
677       inc = CosNaming::NamingContext::_narrow(theObj);
678   }
679   catch(...)
680   {
681   }
682   if(!CORBA::is_nil(inc)) 
683   {
684     try
685     {
686       objLog = inc->resolve(name);
687       SALOME_Logger::Logger_var logger = SALOME_Logger::Logger::_narrow(objLog);
688       if ( !CORBA::is_nil(logger) )
689         logger->shutdown();
690     }
691     catch(...)
692     {
693     }
694   }
695 }
696
697 //=============================================================================
698 /*! \brief shutdown  omniNames and notifd
699  */
700 //=============================================================================
701
702 void SALOME_LifeCycleCORBA::killOmniNames()
703 {
704   std::string portNumber (::getenv ("NSPORT") );
705   if ( !portNumber.empty() ) 
706   {
707 #ifdef WNT
708 #else
709     std::string cmd ;
710     cmd = std::string( "ps -eo pid,command | grep -v grep | grep -E \"omniNames.*")
711       + portNumber
712       + std::string("\" | awk '{cmd=sprintf(\"kill -9 %s\",$1); system(cmd)}'" );
713     MESSAGE(cmd);
714     try {
715       system ( cmd.c_str() );
716     }
717     catch ( ... ) {
718     }
719 #endif
720   }
721   
722   // NPAL 18309  (Kill Notifd)
723   if ( !portNumber.empty() ) 
724   {
725     std::string cmd = ("from killSalomeWithPort import killNotifdAndClean; ");
726     cmd += std::string("killNotifdAndClean(") + portNumber + "); ";
727     cmd  = std::string("python -c \"") + cmd +"\" > /dev/null 2> /dev/null";
728     MESSAGE(cmd);
729     system( cmd.c_str() );
730   }
731 }
732
733 //=============================================================================
734 /*! \brief Find an already existing and registered component instance.
735  *
736  * - build a list of machines on which an instance of the component is running,
737  * - find the best machine among the list
738  *
739  *  \param params         machine parameters like type or name...
740  *  \param componentName  the name of component class
741  *  \param studyId        default = 0  : multistudy instance
742  *  \param listOfMachines list of machine address
743  *  \return a CORBA reference of the component instance, or _nil if not found
744  */
745 //=============================================================================
746
747 Engines::EngineComponent_ptr
748 SALOME_LifeCycleCORBA::
749 _FindComponent(const Engines::ContainerParameters& params,
750                const char *componentName,
751                int studyId,
752                const Engines::ResourceList& listOfResources)
753 {
754   // --- build the list of machines on which the component is already running
755   const char *containerName = params.container_name;
756   int nbproc = NbProc(params);
757
758   Engines::ResourceList_var resourcesOK = new Engines::ResourceList;
759
760   unsigned int lghtOfresourcesOK = 0;
761   resourcesOK->length(listOfResources.length());
762
763   for(unsigned int i=0; i < listOfResources.length(); i++)
764   {
765     const char * currentResource = listOfResources[i];
766     CORBA::Object_var obj = _NS->ResolveComponent(currentResource,
767                                                   containerName,
768                                                   componentName,
769                                                   nbproc);
770     if (!CORBA::is_nil(obj))
771       resourcesOK[lghtOfresourcesOK++] = CORBA::string_dup(currentResource);
772   }
773
774   // --- find the best machine among the list
775   if(lghtOfresourcesOK != 0)
776   {
777     resourcesOK->length(lghtOfresourcesOK);
778     CORBA::String_var bestResource = _ResManager->FindFirst(resourcesOK);
779     CORBA::Object_var obj = _NS->ResolveComponent(bestResource,
780                                                   containerName,
781                                                   componentName,
782                                                   nbproc);
783     return Engines::EngineComponent::_narrow(obj);
784   }
785   else
786     return Engines::EngineComponent::_nil();
787 }
788
789 //=============================================================================
790 /*! \brief  Load a component instance.
791  *
792  *  - Finds a container in the list of machine or start one.
793  *  - Try to load the component library in the container,
794  *  - then create an instance of the component.
795  *
796  *  \param params         machine parameters like type or name...
797  *  \param componentName  the name of component class
798  *  \param studyId        default = 0  : multistudy instance
799  *  \return a CORBA reference of the component instance, or _nil if problem
800  */
801 //=============================================================================
802
803 Engines::EngineComponent_ptr 
804 SALOME_LifeCycleCORBA::
805 _LoadComponent(const Engines::ContainerParameters& params, 
806               const char *componentName,
807               int studyId)
808 {
809   MESSAGE("_LoadComponent, required " << params.container_name <<
810           " " << componentName << " " << NbProc(params));
811
812   Engines::ContainerParameters local_params(params);
813   local_params.mode = CORBA::string_dup("findorstart");
814   Engines::Container_var cont = _ContManager->GiveContainer(local_params);
815   if (CORBA::is_nil(cont)) return Engines::EngineComponent::_nil();
816
817   char* reason;
818   bool isLoadable = cont->load_component_Library(componentName,reason);
819   if (!isLoadable) 
820     {
821       //std::cerr << reason << std::endl;
822       CORBA::string_free(reason);
823       return Engines::EngineComponent::_nil();
824     }
825   CORBA::string_free(reason);
826
827   Engines::EngineComponent_var myInstance =
828     cont->create_component_instance(componentName, studyId);
829   return myInstance._retn();
830 }
831
832 //=============================================================================
833 /*! \brief  Load a parallel component instance.
834  *
835  *  \param params         machine parameters like type or name...
836  *  \param componentName  the name of component class
837  *  \param studyId        default = 0  : multistudy instance
838  *  \return a CORBA reference of the parallel component instance, or _nil if problem
839  */
840 //=============================================================================
841 Engines::EngineComponent_ptr
842 SALOME_LifeCycleCORBA::Load_ParallelComponent(const Engines::ContainerParameters& params,
843                                               const char *componentName,
844                                               int studyId)
845 {
846   MESSAGE("Entering LoadParallelComponent");
847
848 /*MESSAGE("Parameters : ");
849   MESSAGE("Container name : " << params.container_name);
850   MESSAGE("Number of component nodes : " << params.nb_component_nodes);
851   MESSAGE("Component Name : " << componentName);*/
852
853   Engines::ContainerParameters parms(params);
854   parms.resource_params.componentList.length(1);
855   parms.resource_params.componentList[0] = componentName;
856   parms.mode = CORBA::string_dup("findorstart");
857
858   MESSAGE("Starting Parallel Container");
859   Engines::Container_var cont = _ContManager->GiveContainer(parms);
860   if (CORBA::is_nil(cont)) {
861     INFOS("FindOrStartParallelContainer() returns a NULL container !");
862     return Engines::EngineComponent::_nil();
863   }
864
865   MESSAGE("Loading component library");
866   char* reason;
867   bool isLoadable = cont->load_component_Library(componentName,reason);
868   if (!isLoadable) {
869     INFOS(componentName <<" library is not loadable !");
870     //std::cerr << reason << std::endl;
871     CORBA::string_free(reason);
872     return Engines::EngineComponent::_nil();
873   }
874   CORBA::string_free(reason);
875
876   MESSAGE("Creating component instance");
877   // @PARALLEL@ permits to identify that the component requested
878   // is a parallel component.
879   std::string name = std::string(componentName);
880   Engines::EngineComponent_var myInstance = cont->create_component_instance(name.c_str(), studyId);
881   if (CORBA::is_nil(myInstance))
882     INFOS("create_component_instance returns a NULL component !");
883   return myInstance._retn();
884 }
885
886 /*! \brief copy a file from a source host to a destination host
887  * \param hostSrc the source host
888  * \param fileSrc the file to copy from the source host to the destination host
889  * \param hostDest the destination host
890  * \param fileDest the destination file
891  */
892 void SALOME_LifeCycleCORBA::copyFile(const char* hostSrc, const char* fileSrc, const char* hostDest, const char* fileDest)
893 {
894   if(strcmp(hostDest,"localhost") == 0)
895     {
896       //if localhost use a shortcut
897       SALOME_FileTransferCORBA transfer(hostSrc,fileSrc);
898       transfer.getLocalFile(fileDest);
899       return;
900     }
901
902   Engines::ContainerManager_var contManager = getContainerManager();
903
904   Engines::ContainerParameters params;
905   preSet(params);
906
907   params.resource_params.hostname = hostDest;
908   params.mode = CORBA::string_dup("findorstart");
909   Engines::Container_var containerDest = contManager->GiveContainer(params);
910
911   params.resource_params.hostname = hostSrc;
912   Engines::Container_var containerSrc = contManager->GiveContainer(params);
913
914   containerDest->copyFile(containerSrc,fileSrc,fileDest);
915 }
916
917 /*! \brief get the naming service used by the life cycle
918  *
919  *  \return the naming service
920  */
921 SALOME_NamingService * SALOME_LifeCycleCORBA::namingService()
922 {
923   return _NS;
924 }
925
926 /*! \brief get the orb used by the life cycle
927  *
928  *  \return the orb
929  */
930 CORBA::ORB_ptr SALOME_LifeCycleCORBA::orb()
931 {
932   return _NS->orb();
933 }