Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[modules/yacs.git] / src / LifeCycleCORBA / SALOME_LifeCycleCORBA.cxx
1 //  SALOME LifeCycleCORBA : implementation of containers and engines life cycle both in Python and C++
2 //
3 //  Copyright (C) 2003  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 //
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 #include <sys/time.h>
36
37 #include "OpUtil.hxx"
38 #include "utilities.h"
39
40 #include <ServiceUnreachable.hxx>
41
42 #include "SALOME_LifeCycleCORBA.hxx"
43 #ifndef WNT
44 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
45 #else
46 #include "SALOME_ModuleCatalog.hh"
47 #endif
48 #include "SALOME_ContainerManager.hxx"
49 #include "SALOME_Component_i.hxx"
50 #include "SALOME_NamingService.hxx"
51
52 using namespace std;
53
54 IncompatibleComponent::IncompatibleComponent( void ):
55   SALOME_Exception( "IncompatibleComponent" )
56 {
57 }
58
59 IncompatibleComponent::IncompatibleComponent(const IncompatibleComponent &ex):
60   SALOME_Exception( ex ) 
61 {
62 }
63
64 //=============================================================================
65 /*! 
66  *  Constructor
67  */
68 //=============================================================================
69
70 SALOME_LifeCycleCORBA::SALOME_LifeCycleCORBA(SALOME_NamingService *ns)
71 {
72   // be sure to have an instance of traceCollector, when used via SWIG
73   // in a Python module
74   int argc = 0;
75   char *xargv = "";
76   char **argv = &xargv;
77   CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
78   //  LocalTraceCollector *myThreadTrace = SALOMETraceCollector::instance(orb);
79   if (!ns)
80     {
81       _NS = new SALOME_NamingService(orb);
82     }
83   else _NS = ns;
84   //add try catch
85   _NS->Change_Directory("/"); // mpv 250105: current directory may be not root 
86                               // (in SALOMEDS for an example)
87   // not enough: set a current directory in naming service is not thread safe
88   // if naming service instance is shared among several threads...
89   // ==> allways use absolute path and dot rely on current directory!
90
91   CORBA::Object_var obj =
92     _NS->Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS);
93   ASSERT( !CORBA::is_nil(obj));
94   _ContManager=Engines::ContainerManager::_narrow(obj);
95 }
96
97 //=============================================================================
98 /*! 
99  *  Destructor
100  */
101 //=============================================================================
102
103 SALOME_LifeCycleCORBA::~SALOME_LifeCycleCORBA()
104 {
105 }
106
107 //=============================================================================
108 /*! Public - 
109  *  Find and aready existing and registered component instance.
110  *  \param params         machine parameters like type or name...
111  *  \param componentName  the name of component class
112  *  \param studyId        default = 0  : multistudy instance
113  *  \return a CORBA reference of the component instance, or _nil if not found
114  */
115 //=============================================================================
116
117 Engines::Component_ptr
118 SALOME_LifeCycleCORBA::FindComponent(const Engines::MachineParameters& params,
119                                      const char *componentName,
120                                      int studyId)
121 {
122   if (! isKnownComponentClass(componentName))
123     return Engines::Component::_nil();
124
125   Engines::MachineList_var listOfMachines =
126     _ContManager->GetFittingResources(params, componentName);
127
128   Engines::Component_var compo = _FindComponent(params,
129                                                 componentName,
130                                                 studyId,
131                                                 listOfMachines);
132
133   return compo._retn();
134 }
135
136 //=============================================================================
137 /*! Public - 
138  *  Load a component instance on a container defined by machine parameters
139  *  \param params         machine parameters like type or name...
140  *  \param componentName  the name of component class
141  *  \param studyId        default = 0  : multistudy instance
142  *  \return a CORBA reference of the component instance, or _nil if problem
143  */
144 //=============================================================================
145
146 Engines::Component_ptr
147 SALOME_LifeCycleCORBA::LoadComponent(const Engines::MachineParameters& params,
148                                      const char *componentName,
149                                      int studyId)
150 {
151   // --- Check if Component Name is known in ModuleCatalog
152
153   if (! isKnownComponentClass(componentName))
154     return Engines::Component::_nil();
155
156   Engines::MachineList_var listOfMachines =
157     _ContManager->GetFittingResources(params, componentName);
158
159   Engines::Component_var compo = _LoadComponent(params,
160                                                 componentName,
161                                                 studyId,
162                                                 listOfMachines);
163
164   return compo._retn();
165 }
166
167 //=============================================================================
168 /*! Public - 
169  *  Find and aready existing and registered component instance or load a new
170  *  component instance on a container defined by machine parameters.
171  *  \param params         machine parameters like type or name...
172  *  \param componentName  the name of component class
173  *  \param studyId        default = 0  : multistudy instance
174  *  \return a CORBA reference of the component instance, or _nil if problem
175  */
176 //=============================================================================
177
178 Engines::Component_ptr
179 SALOME_LifeCycleCORBA::
180 FindOrLoad_Component(const Engines::MachineParameters& params,
181                      const char *componentName,
182                      int studyId)
183 {
184   // --- Check if Component Name is known in ModuleCatalog
185
186   if (! isKnownComponentClass(componentName))
187     return Engines::Component::_nil();
188
189   Engines::MachineList_var listOfMachines =
190     _ContManager->GetFittingResources(params,componentName);
191
192   Engines::Component_var compo = _FindComponent(params,
193                                                 componentName,
194                                                 studyId,
195                                                 listOfMachines);
196
197   if(CORBA::is_nil(compo))
198     compo = _LoadComponent(params,
199                            componentName,
200                            studyId,
201                            listOfMachines);
202
203   return compo._retn();
204 }
205
206 //=============================================================================
207 /*! Public - 
208  *  Find and aready existing and registered component instance or load a new
209  *  component instance on a container defined by name
210  *  \param containerName  the name of container, under one of the forms
211  *           - 1 aContainer (local container)
212  *           - 2 machine/aContainer (container on hostname = machine)
213  *  \param componentName  the name of component class
214  *  \return a CORBA reference of the component instance, or _nil if problem
215  */
216 //=============================================================================
217
218 Engines::Component_ptr
219 SALOME_LifeCycleCORBA::FindOrLoad_Component(const char *containerName,
220                                             const char *componentName)
221 {
222   // --- Check if Component Name is known in ModuleCatalog
223
224   if (! isKnownComponentClass(componentName))
225     return Engines::Component::_nil();
226
227   // --- Check if containerName contains machine name (if yes: rg>0)
228
229   char *stContainer=strdup(containerName);
230   string st2Container(stContainer);
231   int rg=st2Container.find("/");
232
233   Engines::MachineParameters_var params=new Engines::MachineParameters;
234   preSet(params);
235   if (rg<0)
236     {
237       // containerName doesn't contain "/" => Local container
238       params->container_name=CORBA::string_dup(stContainer);
239       params->hostname=CORBA::string_dup(GetHostname().c_str());
240     }
241   else 
242     {
243       stContainer[rg]='\0';
244       params->container_name=CORBA::string_dup(stContainer+rg+1);
245       params->hostname=CORBA::string_dup(stContainer);
246     }
247   params->isMPI = false;
248   SCRUTE(params->container_name);
249 //   SCRUTE(params->hostname);
250 //   SCRUTE(params->OS);
251 //   SCRUTE(params->mem_mb);
252 //   SCRUTE(params->cpu_clock);
253 //   SCRUTE(params->nb_proc_per_node);
254 //   SCRUTE(params->nb_node);
255 //   SCRUTE(params->isMPI);
256   free(stContainer);
257   return FindOrLoad_Component(params,componentName);
258   
259 }
260
261 //=============================================================================
262 /*! Public -
263  *  Check if the component class is known in module catalog
264  *  \param componentName  the name of component class
265  *  \return true if found, false otherwise
266  */
267 //=============================================================================
268
269 bool SALOME_LifeCycleCORBA::isKnownComponentClass(const char *componentName)
270 {
271
272   try
273     {
274       CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog");
275       SALOME_ModuleCatalog::ModuleCatalog_var Catalog = 
276         SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
277       ASSERT(! CORBA::is_nil(Catalog));
278       SALOME_ModuleCatalog::Acomponent_ptr compoInfo = 
279         Catalog->GetComponent(componentName);
280       if (CORBA::is_nil (compoInfo)) 
281         {
282           INFOS("Catalog Error : Component not found in the catalog");
283           return false;
284         }
285       else return true;
286     }
287   catch (ServiceUnreachable&)
288     {
289       INFOS("Caught exception: Naming Service Unreachable");
290     }
291   catch (...)
292     {
293       INFOS("Caught unknown exception.");
294     }
295   return false;
296 }
297
298 //=============================================================================
299 /*! Public -
300  *  Not so complex... useful ?
301  */
302 //=============================================================================
303
304 bool 
305 SALOME_LifeCycleCORBA::isMpiContainer(const Engines::MachineParameters& params)
306   throw(IncompatibleComponent)
307 {
308   if( params.isMPI )
309     return true;
310   else
311     return false;
312 }
313
314
315 //=============================================================================
316 /*! Public -
317  *  Pre initialisation of a given Engines::MachineParameters with default
318  *  values.
319  *  - container_name = ""  : not relevant
320  *  - hostname = ""        : not relevant
321  *  - OS = ""              : not relevant
322  *  - mem_mb = 0           : not relevant
323  *  - cpu_clock = 0        : not relevant
324  *  - nb_proc_per_node = 0 : not relevant
325  *  - nb_node = 0          : not relevant
326  *  - isMPI = false        : standard components
327  */
328 //=============================================================================
329
330 void SALOME_LifeCycleCORBA::preSet( Engines::MachineParameters& params)
331 {
332   params.container_name = "";
333   params.hostname = "";
334   params.OS = "";
335   params.mem_mb = 0;
336   params.cpu_clock = 0;
337   params.nb_proc_per_node = 0;
338   params.nb_node = 0;
339   params.isMPI = false;
340 }
341
342 //=============================================================================
343 /*! Public -
344  *  \return a number of processors not 0, only for MPI containers
345  */
346 //=============================================================================
347
348 int SALOME_LifeCycleCORBA::NbProc(const Engines::MachineParameters& params)
349 {
350   if( !isMpiContainer(params) )
351     return 0;
352   else if( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
353     return 1;
354   else if( params.nb_node == 0 )
355     return params.nb_proc_per_node;
356   else if( params.nb_proc_per_node == 0 )
357     return params.nb_node;
358   else
359     return params.nb_node * params.nb_proc_per_node;
360 }
361
362 //=============================================================================
363 /*! Public -
364  *  \return the container Manager
365  */
366 //=============================================================================
367
368 Engines::ContainerManager_ptr SALOME_LifeCycleCORBA::getContainerManager()
369 {
370  Engines::ContainerManager_var contManager =
371    Engines::ContainerManager::_duplicate(_ContManager);
372  return contManager._retn();
373 }
374
375
376 //=============================================================================
377 /*! Protected -
378  *  Find and aready existing and registered component instance.
379  *  \param params         machine parameters like type or name...
380  *  \param componentName  the name of component class
381  *  \param studyId        default = 0  : multistudy instance
382  *  \param listOfMachines list of machine address
383  *  \return a CORBA reference of the component instance, or _nil if not found
384  * - build a list of machines on which an instance of the component is running,
385  * - find the best machine among the list
386  */
387 //=============================================================================
388
389 Engines::Component_ptr
390 SALOME_LifeCycleCORBA::
391 _FindComponent(const Engines::MachineParameters& params,
392                const char *componentName,
393                int studyId,
394                const Engines::MachineList& listOfMachines)
395 {
396   // --- build the list of machines on which the component is already running
397
398   const char *containerName = params.container_name;
399   int nbproc = NbProc(params);
400 //   MESSAGE("_FindComponent, required " << containerName <<
401 //        " " << componentName << " " << nbproc);
402
403   Engines::MachineList_var machinesOK = new Engines::MachineList;
404
405   unsigned int lghtOfmachinesOK = 0;
406   machinesOK->length(listOfMachines.length());
407
408   for(unsigned int i=0; i<listOfMachines.length(); i++)
409     {
410       const char *currentMachine=listOfMachines[i];
411 //       MESSAGE("_FindComponent, look at " << currentMachine);
412       CORBA::Object_var obj = _NS->ResolveComponent(currentMachine,
413                                                     containerName,
414                                                     componentName,
415                                                     nbproc);
416       if (!CORBA::is_nil(obj))
417         machinesOK[lghtOfmachinesOK++] = CORBA::string_dup(currentMachine);
418     }
419
420   // --- find the best machine among the list
421
422   if(lghtOfmachinesOK != 0)
423     {
424       machinesOK->length(lghtOfmachinesOK);
425       CORBA::String_var bestMachine = _ContManager->FindBest(machinesOK);
426       CORBA::Object_var obj = _NS->ResolveComponent(bestMachine,
427                                                     containerName,
428                                                     componentName,
429                                                     nbproc);
430       return Engines::Component::_narrow(obj);
431     }
432   else
433     return Engines::Component::_nil();
434 }
435
436 //=============================================================================
437 /*! Protected -
438  *  Load a component instance.
439  *  \param params         machine parameters like type or name...
440  *  \param componentName  the name of component class
441  *  \param studyId        default = 0  : multistudy instance
442  *  \param listOfMachines list of machine address
443  *  \return a CORBA reference of the component instance, or _nil if problem
444  *  - Finds a container in the list of machine or start one.
445  *  - Try to load the component library in the container,
446  *  - then create an instance of the component.
447  */
448 //=============================================================================
449
450 Engines::Component_ptr 
451 SALOME_LifeCycleCORBA::
452 _LoadComponent(const Engines::MachineParameters& params, 
453               const char *componentName,
454               int studyId,
455               const Engines::MachineList& listOfMachines)
456 {
457   const char *containerName = params.container_name;
458   int nbproc = NbProc(params);
459
460   MESSAGE("_LoadComponent, required " << containerName <<
461           " " << componentName << " " << nbproc);
462
463   Engines::Container_var cont =
464     _ContManager->FindOrStartContainer(params,
465                                        listOfMachines);
466   if (CORBA::is_nil(cont)) return Engines::Component::_nil();
467
468   bool isLoadable = cont->load_component_Library(componentName);
469   if (!isLoadable) return Engines::Component::_nil();
470
471   Engines::Component_var myInstance =
472     cont->create_component_instance(componentName, studyId);
473   return myInstance._retn();
474 }
475
476
477
478
479
480
481
482
483
484
485
486
487
488