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