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