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