Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/kernel.git] / src / ParallelContainer / SALOME_ParallelContainer_i.cxx
1 //  SALOME_ParallelContainer : implementation of container and engine for ParallelKernel
2 //
3 //  Copyright (C) 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //  File   : SALOME_ParallelContainer_i.cxx
23 //  Author : Andr� RIBES, EDF
24 //  Author : Paul RASCLE, EDF - MARC TAJCHMAN, CEA 
25
26 #include <SALOMEconfig.h>
27 #ifndef WNT
28 #else
29 #include <SALOME_Component.hxx>
30 #endif
31 #include "SALOME_ParallelContainer_i.hxx"
32
33 #include "SALOME_Component_i.hxx"
34
35 #include "SALOME_FileRef_i.hxx"
36 #include "SALOME_FileTransfer_i.hxx"
37 #include "SALOME_NamingService.hxx"
38 #include "OpUtil.hxx"
39
40 #include "OpUtil.hxx"
41 #include <string.h>
42 #include <stdio.h>
43 #ifndef WNT
44 #include <dlfcn.h>
45 #include <unistd.h>
46 #else
47 #include "../../adm/win32/SALOME_WNT.hxx"
48 #include <signal.h>
49 #include <process.h>
50 int SIGUSR1 = 1000;
51 #endif
52
53 #include <paco_omni.h>
54 #include "utilities.h"
55 using namespace std;
56
57 bool _Sleeping = false ;
58
59 // Containers with name FactoryServer are started via rsh in LifeCycleCORBA
60 // Other Containers are started via start_impl of FactoryServer
61
62 extern "C" {void ActSigIntHandler() ; }
63 #ifndef WNT
64 extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; }
65 #else
66 extern "C" {void SigIntHandler( int ) ; }
67 #endif
68
69
70 map<std::string, int> Engines_Parallel_Container_i::_cntInstances_map;
71 map<std::string, void *> Engines_Parallel_Container_i::_library_map;
72 map<std::string, void *> Engines_Parallel_Container_i::_toRemove_map;
73 omni_mutex Engines_Parallel_Container_i::_numInstanceMutex ;
74
75 //=============================================================================
76 /*! 
77  *  Default constructor, not for use
78  */
79 //=============================================================================
80
81 Engines_Parallel_Container_i::Engines_Parallel_Container_i (CORBA::ORB_ptr orb, 
82                                                             char * ior, 
83                                                             int rank) : 
84   InterfaceParallel_impl(orb,ior,rank), 
85   Engines::Container_serv(orb,ior,rank),
86   _numInstance(0)
87 {
88 }
89
90 //=============================================================================
91 /*! 
92  *  Construtor to use
93  */
94 //=============================================================================
95
96 Engines_Parallel_Container_i::Engines_Parallel_Container_i (CORBA::ORB_ptr orb, 
97                                                             char * ior, 
98                                                             int rank,
99                                                             PortableServer::POA_ptr poa,
100                                                             char *containerName ,
101                                                             int argc , char* argv[],
102                                                             bool activAndRegist,
103                                                             bool isServantAloneInProcess
104                                                            ) :
105   InterfaceParallel_impl(orb,ior,rank), 
106   Engines::Container_serv(orb,ior,rank),
107   _numInstance(0),_isServantAloneInProcess(isServantAloneInProcess)
108 {
109   _pid = (long)getpid();
110
111   if(activAndRegist)
112     ActSigIntHandler() ;
113
114   _argc = argc ;
115   _argv = argv ;
116
117   string hostname = GetHostname();
118
119   _orb = CORBA::ORB::_duplicate(orb) ;
120   _poa = PortableServer::POA::_duplicate(poa) ;
121   _NS = new SALOME_NamingService();
122   _NS->init_orb( CORBA::ORB::_duplicate(_orb) );
123   _containerName = _NS->BuildContainerNameForNS(containerName, hostname.c_str());
124
125   fileTransfer_i* aFileTransfer = new fileTransfer_i();
126   _fileTransfer = Engines::fileTransfer::_narrow(aFileTransfer->_this());
127 }
128
129 //=============================================================================
130 /*! 
131  *  Destructor
132  */
133 //=============================================================================
134
135 Engines_Parallel_Container_i::~Engines_Parallel_Container_i()
136 {
137   MESSAGE("Container_i::~Container_i()");
138   delete _id;
139 }
140
141 //=============================================================================
142 /*! 
143  *  CORBA attribute: Container name (see constructor)
144  */
145 //=============================================================================
146
147 char* Engines_Parallel_Container_i::name()
148 {
149   return CORBA::string_dup(_containerName.c_str()) ;
150 }
151
152 //=============================================================================
153 /*! 
154  *  CORBA method: Get the hostName of the Container (without domain extensions)
155  */
156 //=============================================================================
157
158 char* Engines_Parallel_Container_i::getHostName()
159 {
160   string s = GetHostname();
161   MESSAGE("Engines_Parallel_Container_i::getHostName " << s);
162   return CORBA::string_dup(s.c_str()) ;
163 }
164
165 //=============================================================================
166 /*! 
167  *  CORBA method: Get the PID (process identification) of the Container
168  */
169 //=============================================================================
170
171 CORBA::Long Engines_Parallel_Container_i::getPID()
172 {
173   return (CORBA::Long)getpid();
174 }
175
176 //=============================================================================
177 /*! 
178  *  CORBA method: check if servant is still alive
179  */
180 //=============================================================================
181
182 void Engines_Parallel_Container_i::ping()
183 {
184   MESSAGE("Engines_Parallel_Container_i::ping() pid "<< getpid());
185 }
186
187 //=============================================================================
188 /*! 
189  *  CORBA method, oneway: Server shutdown. 
190  *  - Container name removed from naming service,
191  *  - servant deactivation,
192  *  - orb shutdown if no other servants in the process 
193  */
194 //=============================================================================
195
196 void Engines_Parallel_Container_i::Shutdown()
197 {
198   MESSAGE("Engines_Parallel_Container_i::Shutdown()");
199   _NS->Destroy_FullDirectory(_containerName.c_str());
200   //_remove_ref();
201   //_poa->deactivate_object(*_id);
202   if(_isServantAloneInProcess)
203   {
204     MESSAGE("Effective Shutdown of container Begins...");
205     LocalTraceBufferPool* bp1 = LocalTraceBufferPool::instance();
206     bp1->deleteInstance(bp1);
207     _orb->shutdown(0);
208   }
209 }
210
211
212 //=============================================================================
213 /*! 
214  *  CORBA method: load a new component class (Python or C++ implementation)
215  *  \param componentName like COMPONENT
216  *                          try to make a Python import of COMPONENT,
217  *                          then a lib open of libCOMPONENTEngine.so
218  *  \return true if dlopen successfull or already done, false otherwise
219  */
220 //=============================================================================
221
222 bool
223 Engines_Parallel_Container_i::load_component_Library(const char* componentName)
224 {
225   bool ret = false;
226   string aCompName = componentName;
227   // --- try dlopen C++ component
228
229 #ifndef WNT
230   string impl_name = string ("lib") + aCompName + string("Engine.so");
231 #else
232   string impl_name = aCompName + string("Engine.dll");
233 #endif
234
235   SCRUTE(impl_name);
236
237   _numInstanceMutex.lock(); // lock to be alone 
238   if (_toRemove_map[impl_name]) _toRemove_map.erase(impl_name);
239   if (_library_map[impl_name])
240   {
241     MESSAGE("Library " << impl_name << " already loaded");
242     _numInstanceMutex.unlock();
243     ret = true;
244   }
245
246   void* handle;
247 #ifndef WNT
248   handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ;
249 #else
250   handle = dlopen( impl_name.c_str() , 0 ) ;
251 #endif
252   if ( handle )
253   {
254     _library_map[impl_name] = handle;
255     _numInstanceMutex.unlock();
256     ret = true;
257   }
258   else
259   {
260     cerr << "Can't load shared library : " << impl_name << endl;
261     cerr << "error dlopen: " << dlerror() << endl;
262     _numInstanceMutex.unlock();
263     ret = false;
264   }
265
266   // To be sure that all the nodes of the component as loaded the library
267   _my_com->paco_barrier();
268
269   return ret;
270 }
271
272 //=============================================================================
273 /*! 
274  *  CORBA method: Creates a new servant instance of a component.
275  *  The servant registers itself to naming service and Registry.
276  *  \param genericRegisterName  Name of the component instance to register
277  *                         in Registry & Name Service (without _inst_n suffix)
278  *  \param studyId         0 for multiStudy instance, 
279  *                         study Id (>0) otherwise
280  *  \return a loaded component
281  */
282 //=============================================================================
283
284 Engines::Component_ptr
285 Engines_Parallel_Container_i::create_component_instance(const char*genericRegisterName,
286                                                         CORBA::Long studyId)
287 {
288   cerr << "----------------- create_component_instance node : " << getMyRank() << endl;
289
290   if (studyId < 0)
291   {
292     INFOS("studyId must be > 0 for mono study instance, =0 for multiStudy");
293     return Engines::Component::_nil() ;
294   }
295
296   Engines::Component_var iobject = Engines::Component::_nil() ;
297
298   // is it a parallel component ?
299   bool parallel = false;
300   string aCompName = genericRegisterName;
301   int par = aCompName.find("@PARALLEL@");
302   if (par>0) {
303     parallel = true;
304     aCompName = aCompName.substr(0,par);
305   }
306
307   //--- try C++
308 #ifndef WNT
309   string impl_name = string ("lib") + aCompName +string("Engine.so");
310 #else
311   string impl_name = aCompName +string("Engine.dll");
312 #endif
313   void* handle = _library_map[impl_name];
314
315   if ( !handle )
316   {
317     cerr << "shared library " << impl_name <<"must be loaded before instance" << endl;;
318     return Engines::Component::_nil() ;
319   }
320   else
321   {
322     if (parallel) {
323       // Sequential component case
324       // Component parallel proxy created on node 0
325       iobject = createParallelInstance(aCompName,
326                                        handle,
327                                        studyId);
328
329     }
330     else {
331       // Sequential component case
332       iobject = createInstance(aCompName,
333                                handle,
334                                studyId);
335     }
336
337     return iobject._retn();
338   }
339 }
340
341 //=============================================================================
342 /*! 
343  *  CORBA method: Finds a servant instance of a component
344  *  \param registeredName  Name of the component in Registry or Name Service,
345  *                         without instance suffix number
346  *  \param studyId         0 if instance is not associated to a study, 
347  *                         >0 otherwise (== study id)
348  *  \return the first instance found with same studyId
349  */
350 //=============================================================================
351
352 Engines::Component_ptr Engines_Parallel_Container_i::find_component_instance( const char* registeredName,
353                                                                               CORBA::Long studyId)
354 {
355   Engines::Component_var anEngine = Engines::Component::_nil();
356   map<string,Engines::Component_var>::iterator itm =_listInstances_map.begin();
357   while (itm != _listInstances_map.end())
358   {
359     string instance = (*itm).first;
360     SCRUTE(instance);
361     if (instance.find(registeredName) == 0)
362     {
363       anEngine = (*itm).second;
364       if (studyId == anEngine->getStudyId())
365       {
366         return anEngine._retn();
367       }
368     }
369     itm++;
370   }
371   return anEngine._retn();  
372 }
373
374 //=============================================================================
375 /*! 
376  *  CORBA method: find or create an instance of the component (servant),
377  *  load a new component class (dynamic library) if required,
378  *  ---- FOR COMPATIBILITY WITH 2.2 ---- 
379  *  ---- USE ONLY FOR MULTISTUDY INSTANCES ! --------
380  *  The servant registers itself to naming service and Registry.
381  *  \param genericRegisterName  Name of the component to register
382  *                              in Registry & Name Service
383  *  \param componentName       Name of the constructed library of the component
384  *  \return a loaded component
385  */
386 //=============================================================================
387
388 Engines::Component_ptr Engines_Parallel_Container_i::load_impl( const char* genericRegisterName,
389                                                                 const char* componentName )
390 {
391   string impl_name = string ("lib") + genericRegisterName +string("Engine.so");
392   Engines::Component_var iobject = Engines::Component::_nil() ;
393   if (load_component_Library(genericRegisterName))
394     iobject = find_or_create_instance(genericRegisterName, impl_name);
395   return iobject._retn();
396 }
397
398
399 //=============================================================================
400 /*! 
401  *  CORBA method: Stops the component servant, and deletes all related objects
402  *  \param component_i     Component to be removed
403  */
404 //=============================================================================
405
406 void Engines_Parallel_Container_i::remove_impl(Engines::Component_ptr component_i)
407 {
408   ASSERT(! CORBA::is_nil(component_i));
409   string instanceName = component_i->instanceName() ;
410   MESSAGE("unload component " << instanceName);
411   _listInstances_map.erase(instanceName);
412   component_i->destroy() ;
413   _NS->Destroy_Name(instanceName.c_str());
414 }
415
416 //=============================================================================
417 /*! 
418  *  CORBA method: Discharges unused libraries from the container.
419  */
420 //=============================================================================
421
422 void Engines_Parallel_Container_i::finalize_removal()
423 {
424   MESSAGE("finalize unload : dlclose");
425   _numInstanceMutex.lock(); // lock to be alone
426   // (see decInstanceCnt, load_component_Library)
427   map<string, void *>::iterator ith;
428   for (ith = _toRemove_map.begin(); ith != _toRemove_map.end(); ith++)
429   {
430     void *handle = (*ith).second;
431     string impl_name= (*ith).first;
432     if (handle)
433     {
434       SCRUTE(handle);
435       SCRUTE(impl_name);
436       //          dlclose(handle);                // SALOME unstable after ...
437       //          _library_map.erase(impl_name);
438     }
439   }
440   _toRemove_map.clear();
441   _numInstanceMutex.unlock();
442 }
443
444 //=============================================================================
445 /*! 
446  *  CORBA method: Kill the container process with exit(0).
447  *  To remove :  never returns !
448  */
449 //=============================================================================
450
451 bool Engines_Parallel_Container_i::Kill_impl()
452 {
453   MESSAGE("Engines_Parallel_Container_i::Kill() pid "<< getpid() << " containerName "
454           << _containerName.c_str() << " machineName "
455           << GetHostname().c_str());
456   INFOS("===============================================================");
457   INFOS("= REMOVE calls to Kill_impl in C++ container                  =");
458   INFOS("===============================================================");
459   //exit( 0 ) ;
460   ASSERT(0);
461   return false;
462 }
463
464 //=============================================================================
465 /*! 
466  *  C++ method: Finds an already existing servant instance of a component, or
467  *              create an instance.
468  *  ---- USE ONLY FOR MULTISTUDY INSTANCES ! --------
469  *  \param genericRegisterName    Name of the component instance to register
470  *                                in Registry & Name Service,
471  *                                (without _inst_n suffix, like "COMPONENT")
472  *  \param componentLibraryName   like "libCOMPONENTEngine.so"
473  *  \return a loaded component
474  * 
475  *  example with names:
476  *  aGenRegisterName = COMPONENT (= first argument)
477  *  impl_name = libCOMPONENTEngine.so (= second argument)
478  *  _containerName = /Containers/cli76ce/FactoryServer
479  *  factoryName = COMPONENTEngine_factory
480  *  component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
481  *
482  *  instanceName = COMPONENT_inst_1
483  *  component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
484  */
485 //=============================================================================
486
487 Engines::Component_ptr
488 Engines_Parallel_Container_i::find_or_create_instance(string genericRegisterName,
489                                                       string componentLibraryName)
490 {
491   string aGenRegisterName = genericRegisterName;
492   string impl_name = componentLibraryName;
493   void* handle = _library_map[impl_name];
494   if ( !handle )
495   {
496     INFOS("shared library " << impl_name <<"must be loaded before instance");
497     return Engines::Component::_nil() ;
498   }
499   else
500   {
501     // --- find a registered instance in naming service, or create
502
503     string component_registerBase =
504       _containerName + "/" + aGenRegisterName;
505     Engines::Component_var iobject = Engines::Component::_nil() ;
506     try
507     {
508       CORBA::Object_var obj =
509         _NS->ResolveFirst( component_registerBase.c_str());
510       if ( CORBA::is_nil( obj ) )
511       {
512         iobject = createInstance(genericRegisterName,
513                                  handle,
514                                  0); // force multiStudy instance here !
515       }
516       else
517       { 
518         iobject = Engines::Component::_narrow( obj ) ;
519         Engines_Component_i *servant =
520           dynamic_cast<Engines_Component_i*>
521           (_poa->reference_to_servant(iobject));
522         ASSERT(servant)
523           int studyId = servant->getStudyId();
524         ASSERT (studyId >= 0);
525         if (studyId == 0) // multiStudy instance, OK
526         {
527           // No ReBind !
528           MESSAGE(component_registerBase.c_str()<<" already bound");
529         }
530         else // monoStudy instance: NOK
531         {
532           iobject = Engines::Component::_nil();
533           INFOS("load_impl & find_component_instance methods "
534                 << "NOT SUITABLE for mono study components");
535         }
536       }
537     }
538     catch (...)
539     {
540       INFOS( "Container_i::load_impl catched" ) ;
541     }
542     return iobject._retn();
543   }
544 }
545
546 //=============================================================================
547 /*! 
548  *  C++ method: create a servant instance of a component.
549  *  \param genericRegisterName    Name of the component instance to register
550  *                                in Registry & Name Service,
551  *                                (without _inst_n suffix, like "COMPONENT")
552  *  \param handle                 loaded library handle
553  *  \param studyId                0 for multiStudy instance, 
554  *                                study Id (>0) otherwise
555  *  \return a loaded component
556  * 
557  *  example with names:
558  *  aGenRegisterName = COMPONENT (= first argument)
559  *  _containerName = /Containers/cli76ce/FactoryServer
560  *  factoryName = COMPONENTEngine_factory
561  *  component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
562  *  instanceName = COMPONENT_inst_1
563  *  component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
564  */
565 //=============================================================================
566
567 Engines::Component_ptr
568 Engines_Parallel_Container_i::createInstance(string genericRegisterName,
569                                              void *handle,
570                                              int studyId)
571 {
572   // --- find the factory
573
574   string aGenRegisterName = genericRegisterName;
575   string factory_name = aGenRegisterName + string("Engine_factory");
576
577   SCRUTE(factory_name) ;
578
579   typedef  PortableServer::ObjectId * (*FACTORY_FUNCTION)
580     (CORBA::ORB_ptr,
581      PortableServer::POA_ptr, 
582      PortableServer::ObjectId *, 
583      const char *, 
584      const char *) ;
585
586   FACTORY_FUNCTION Component_factory
587     = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
588
589   char *error ;
590   if ( (error = dlerror() ) != NULL)
591   {
592     INFOS("Can't resolve symbol: " + factory_name);
593     SCRUTE(error);
594     return Engines::Component::_nil() ;
595   }
596
597   // --- create instance
598   Engines::Component_var iobject = Engines::Component::_nil() ;
599   try
600   {
601     _numInstanceMutex.lock() ; // lock on the instance number
602     _numInstance++ ;
603     int numInstance = _numInstance ;
604     _numInstanceMutex.unlock() ;
605
606     char aNumI[12];
607     sprintf( aNumI , "%d" , numInstance ) ;
608     string instanceName = aGenRegisterName + "_inst_" + aNumI ;
609     string component_registerName =
610       _containerName + "/" + instanceName;
611
612     // --- Instanciate required CORBA object
613
614     PortableServer::ObjectId *id ; //not owner, do not delete (nore use var)
615     id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str(),
616                                aGenRegisterName.c_str() ) ;
617
618     // --- get reference & servant from id
619     CORBA::Object_var obj = _poa->id_to_reference(*id);
620     iobject = Engines::Component::_narrow(obj) ;
621
622     Engines_Component_i *servant = 
623       dynamic_cast<Engines_Component_i*>(_poa->reference_to_servant(iobject));
624     ASSERT(servant);
625     servant->_remove_ref(); // compensate previous id_to_reference 
626     _listInstances_map[instanceName] = iobject;
627     _cntInstances_map[aGenRegisterName] += 1;
628     bool ret_studyId = servant->setStudyId(studyId);
629     ASSERT(ret_studyId);
630
631     // --- register the engine under the name
632     //     containerName(.dir)/instanceName(.object)
633     _NS->Register(iobject , component_registerName.c_str()) ;
634     MESSAGE( component_registerName.c_str() << " bound" ) ;
635   }
636   catch (...)
637   {
638     INFOS( "Container_i::createInstance exception catched" ) ;
639   }
640   return iobject._retn();
641 }
642
643 Engines::Component_ptr
644 Engines_Parallel_Container_i::createParallelInstance(string genericRegisterName,
645                                                      void *handle,
646                                                      int studyId)
647 {
648   cerr << "----------------- createParallelInstance node : " << getMyRank() << endl;
649   // --- create instance
650   Engines::Component_var iobject = Engines::Component::_nil();
651   string aGenRegisterName = genericRegisterName;
652
653   //////////////////////////////////////////////////////////////////////////
654   // 1: Proxy Step
655   // Node 0 create the proxy
656   if (getMyRank() == 0) {
657     // --- find the factory
658     string factory_name = aGenRegisterName + string("EngineProxy_factory");
659
660     typedef  PortableServer::ObjectId * (*FACTORY_FUNCTION)
661       (CORBA::ORB_ptr,
662        paco_fabrique_thread *,
663        PortableServer::POA_ptr,
664        PortableServer::ObjectId *, 
665        const char *,
666        int) ;
667
668     FACTORY_FUNCTION Component_factory
669       = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
670
671     char *error ;
672     if ( (error = dlerror() ) != NULL) {
673       INFOS("Can't resolve symbol: " + factory_name);
674       SCRUTE(error);
675       return Engines::Component::_nil();
676     }
677     try {
678       _numInstanceMutex.lock() ; // lock on the instance number
679       _numInstance++ ;
680       int numInstance = _numInstance ;
681       _numInstanceMutex.unlock() ;
682
683       char aNumI[12];
684       sprintf( aNumI , "%d" , numInstance ) ;
685       string instanceName = aGenRegisterName + "_inst_" + aNumI ;
686       string component_registerName =
687         _containerName + "/" + instanceName;
688
689       // --- Instanciate required CORBA object
690       PortableServer::ObjectId *id ; //not owner, do not delete (nore use var)
691       id = (Component_factory) ( _orb, new paco_omni_fabrique(), _poa, _id, instanceName.c_str(), getTotalNode()) ;
692
693       // --- get reference & servant from id
694       CORBA::Object_var obj = _poa->id_to_reference(*id);
695       iobject = Engines::Component::_narrow(obj) ;
696
697       _listInstances_map[instanceName] = iobject;
698       _cntInstances_map[aGenRegisterName] += 1;
699
700       // --- register the engine under the name
701       //     containerName(.dir)/instanceName(.object)
702       _NS->Register(iobject , component_registerName.c_str()) ;
703       MESSAGE( component_registerName.c_str() << " bound" ) ;
704     }
705     catch (...)
706     {
707       INFOS( "Container_i::createParallelInstance exception catched in Proxy creation" ) ;
708     }
709   }
710   else {
711     // We have to have the same numIntance to be able to get the proxy reference 
712     // in the nameing service.
713     _numInstanceMutex.lock() ; // lock on the instance number
714     _numInstance++ ;
715     //    int numInstance = _numInstance ;
716     _numInstanceMutex.unlock() ;
717   }
718   cerr << "Node " << getMyRank() << " entering in paco_barrier()" << endl;
719   _my_com->paco_barrier();
720   cerr << "Node " << getMyRank() << " quitting paco_barrier()" << endl;
721
722   //////////////////////////////////////////////////////////////////////////
723   // 2: Nodes Step
724
725   char * proxy_ior;
726   Engines::Component_PaCO_var iobject2;
727
728   char aNumI[12];
729   sprintf( aNumI , "%d" , _numInstance ) ;
730   string instanceName = aGenRegisterName + "_inst_" + aNumI ;
731
732   string component_registerName = _containerName + "/" + instanceName;
733   string hostname = GetHostname();
734
735   CORBA::Object_var temp = _NS->Resolve(component_registerName.c_str());
736   Engines::Component_var obj_proxy = Engines::Component::_narrow(temp);
737   proxy_ior = _orb->object_to_string(obj_proxy);
738
739   // --- find the factory
740   string factory_name = aGenRegisterName + string("Engine_factory");
741
742   typedef  PortableServer::ObjectId * (*FACTORY_FUNCTION)
743     (CORBA::ORB_ptr, char *, int,
744      PortableServer::POA_ptr, 
745      PortableServer::ObjectId *, 
746      const char *, 
747      const char *) ;
748
749   FACTORY_FUNCTION Component_factory
750     = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
751
752   char *error ;
753   if ( (error = dlerror() ) != NULL)
754   {
755     INFOS("Can't resolve symbol: " + factory_name);
756     SCRUTE(error);
757     return Engines::Component::_nil() ;
758   }
759   try
760   {
761     char aNumI2[12];
762     sprintf(aNumI2 , "%d" , getMyRank()) ;
763     string instanceName = aGenRegisterName + "_inst_node_" + aNumI2;
764     string component_registerName = _containerName + aNumI2 + "/" + instanceName;
765
766     // --- Instanciate required CORBA object
767
768     PortableServer::ObjectId *id ; //not owner, do not delete (nore use var)
769     id = (Component_factory) ( _orb, proxy_ior, getMyRank(), _poa, _id, instanceName.c_str(),
770                                aGenRegisterName.c_str() ) ;
771
772     // --- get reference & servant from id
773     CORBA::Object_var obj = _poa->id_to_reference(*id);
774     iobject2 = Engines::Component_PaCO::_narrow(obj) ;
775
776     // --- register the engine under the name
777     _NS->Register(iobject2 , component_registerName.c_str()) ;
778     MESSAGE( component_registerName.c_str() << " bound" ) ;
779   }
780   catch (...)
781   {
782     INFOS( "Container_i::createParallelInstance exception catched" ) ;
783   }
784
785   //////////////////////////////////////////////////////////////////////////
786   // 3: Deployment Step
787
788   iobject2->deploy();
789   _my_com->paco_barrier();
790   cerr << "--------- createParallelInstance : End Deploy step ----------" << endl;  
791   if (getMyRank() == 0) {
792     PaCO::InterfaceManager_var proxy = PaCO::InterfaceManager::_narrow(iobject);
793     proxy->start();
794     _my_com->paco_barrier();
795   }
796   else
797     _my_com->paco_barrier();
798
799   return iobject._retn();
800 }
801
802 //=============================================================================
803 /*! 
804  *
805  */
806 //=============================================================================
807
808 void Engines_Parallel_Container_i::decInstanceCnt(string genericRegisterName)
809 {
810   string aGenRegisterName =genericRegisterName;
811   MESSAGE("Engines_Parallel_Container_i::decInstanceCnt " << aGenRegisterName);
812   ASSERT(_cntInstances_map[aGenRegisterName] > 0); 
813   _numInstanceMutex.lock(); // lock to be alone
814   // (see finalize_removal, load_component_Library)
815   _cntInstances_map[aGenRegisterName] -= 1;
816   SCRUTE(_cntInstances_map[aGenRegisterName]);
817   if (_cntInstances_map[aGenRegisterName] == 0)
818   {
819     string impl_name =
820       Engines_Component_i::GetDynLibraryName(aGenRegisterName.c_str());
821     SCRUTE(impl_name);
822     void* handle = _library_map[impl_name];
823     ASSERT(handle);
824     _toRemove_map[impl_name] = handle;
825   }
826   _numInstanceMutex.unlock();
827 }
828
829 //=============================================================================
830 /*! 
831  *  Retrieves only with container naming convention if it is a python container
832  */
833 //=============================================================================
834
835 bool Engines_Parallel_Container_i::isPythonContainer(const char* ContainerName)
836 {
837   bool ret=false;
838   int len=strlen(ContainerName);
839   if(len>=2)
840     if(strcmp(ContainerName+len-2,"Py")==0)
841       ret=true;
842   return ret;
843 }
844
845 //=============================================================================
846 /*! 
847  *  
848  */
849 //=============================================================================
850
851 void ActSigIntHandler()
852 {
853 #ifndef WNT
854   struct sigaction SigIntAct ;
855   SigIntAct.sa_sigaction = &SigIntHandler ;
856   SigIntAct.sa_flags = SA_SIGINFO ;
857 #endif
858
859   // DEBUG 03.02.2005 : the first parameter of sigaction is not a mask of signals
860   // (SIGINT | SIGUSR1) :
861   // it must be only one signal ===> one call for SIGINT 
862   // and an other one for SIGUSR1
863 #ifndef WNT
864   if ( sigaction( SIGINT , &SigIntAct, NULL ) ) {
865     perror("SALOME_Container main ") ;
866     exit(0) ;
867   }
868   if ( sigaction( SIGUSR1 , &SigIntAct, NULL ) ) {
869     perror("SALOME_Container main ") ;
870     exit(0) ;
871   }
872   //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
873   //             use of streams (and so on) should never be used because :
874   //             streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
875   //             A stream operation may be interrupted by a signal and if the Handler use stream we
876   //             may have a "Dead-Lock" ===HangUp
877   //==INFOS is commented
878   //  INFOS(pthread_self() << "SigIntHandler activated") ;
879 #else  
880   signal( SIGINT, SigIntHandler );
881   signal( SIGUSR1, SigIntHandler );
882 #endif
883
884 }
885
886 void SetCpuUsed() ;
887
888 #ifndef WNT
889 void SigIntHandler(int what , siginfo_t * siginfo ,
890                    void * toto ) {
891   //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
892   //             use of streams (and so on) should never be used because :
893   //             streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
894   //             A stream operation may be interrupted by a signal and if the Handler use stream we
895   //             may have a "Dead-Lock" ===HangUp
896   //==MESSAGE is commented
897   //  MESSAGE(pthread_self() << "SigIntHandler what     " << what << endl
898   //          << "              si_signo " << siginfo->si_signo << endl
899   //          << "              si_code  " << siginfo->si_code << endl
900   //          << "              si_pid   " << siginfo->si_pid) ;
901   if ( _Sleeping ) {
902     _Sleeping = false ;
903     //     MESSAGE("SigIntHandler END sleeping.") ;
904     return ;
905   }
906   else {
907     ActSigIntHandler() ;
908     if ( siginfo->si_signo == SIGUSR1 ) {
909       SetCpuUsed() ;
910     }
911     else {
912       _Sleeping = true ;
913       //      MESSAGE("SigIntHandler BEGIN sleeping.") ;
914       int count = 0 ;
915       while( _Sleeping ) {
916         sleep( 1 ) ;
917         count += 1 ;
918       }
919       //      MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
920     }
921     return ;
922   }
923 }
924 #else // Case WNT
925 void SigIntHandler( int what ) {
926   MESSAGE( pthread_self() << "SigIntHandler what     " << what << endl );
927   if ( _Sleeping ) {
928     _Sleeping = false ;
929     MESSAGE("SigIntHandler END sleeping.") ;
930     return ;
931   }
932   else {
933     ActSigIntHandler() ;
934     if ( what == SIGUSR1 ) {
935       SetCpuUsed() ;
936     }
937     else {
938       _Sleeping = true ;
939       MESSAGE("SigIntHandler BEGIN sleeping.") ;
940       int count = 0 ;
941       while( _Sleeping ) {
942         Sleep( 1000 ) ;
943         count += 1 ;
944       }
945       MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
946     }
947     return ;
948   }
949 }
950 #endif
951
952 //=============================================================================
953 /*! 
954  *  CORBA method: get or create a fileRef object associated to a local file
955  *  (a file on the computer on which runs the container server), which stores
956  *  a list of (machine, localFileName) corresponding to copies already done.
957  * 
958  *  \param  origFileName absolute path for a local file to copy on other
959  *          computers
960  *  \return a fileRef object associated to the file.
961  */
962 //=============================================================================
963
964 Engines::fileRef_ptr
965 Engines_Parallel_Container_i::createFileRef(const char* origFileName)
966 {
967   string origName(origFileName);
968   Engines::fileRef_var theFileRef = Engines::fileRef::_nil();
969
970   if (origName[0] != '/')
971   {
972     INFOS("path of file to copy must be an absolute path begining with '/'");
973     return Engines::fileRef::_nil();
974   }
975
976   if (CORBA::is_nil(_fileRef_map[origName]))
977   {
978     CORBA::Object_var obj=_poa->id_to_reference(*_id);
979     Engines::Container_var pCont = Engines::Container::_narrow(obj);
980     fileRef_i* aFileRef = new fileRef_i(pCont, origFileName);
981     theFileRef = Engines::fileRef::_narrow(aFileRef->_this());
982     _numInstanceMutex.lock() ; // lock to be alone (stl container write)
983     _fileRef_map[origName] = theFileRef;
984     _numInstanceMutex.unlock() ;
985   }
986
987   theFileRef =  Engines::fileRef::_duplicate(_fileRef_map[origName]);
988   ASSERT(! CORBA::is_nil(theFileRef));
989   return theFileRef._retn();
990 }
991
992 //=============================================================================
993 /*! 
994  *  CORBA method:
995  *  \return a reference to the fileTransfer object
996  */
997 //=============================================================================
998
999 Engines::fileTransfer_ptr
1000 Engines_Parallel_Container_i::getFileTransfer()
1001 {
1002   Engines::fileTransfer_var aFileTransfer
1003     = Engines::fileTransfer::_duplicate(_fileTransfer);
1004   return aFileTransfer._retn();
1005 }
1006
1007
1008 Engines::Salome_file_ptr 
1009 Engines_Parallel_Container_i::createSalome_file(const char* origFileName) 
1010 {
1011   string origName(origFileName);
1012   if (CORBA::is_nil(_Salome_file_map[origName]))
1013   {
1014     Salome_file_i* aSalome_file = new Salome_file_i();
1015     try 
1016     {
1017       aSalome_file->setLocalFile(origFileName);
1018       aSalome_file->recvFiles();
1019     }
1020     catch (const SALOME::SALOME_Exception& e)
1021     {
1022       return Engines::Salome_file::_nil();
1023     }
1024
1025     Engines::Salome_file_var theSalome_file = Engines::Salome_file::_nil();
1026     theSalome_file = Engines::Salome_file::_narrow(aSalome_file->_this());
1027     _numInstanceMutex.lock() ; // lock to be alone (stl container write)
1028     _Salome_file_map[origName] = theSalome_file;
1029     _numInstanceMutex.unlock() ;
1030   }
1031
1032   Engines::Salome_file_ptr theSalome_file =  
1033     Engines::Salome_file::_duplicate(_Salome_file_map[origName]);
1034   ASSERT(!CORBA::is_nil(theSalome_file));
1035   return theSalome_file;
1036 }
1037
1038 //=============================================================================
1039 /*! 
1040  *  CORBA attribute: Container working directory 
1041  */
1042 //=============================================================================
1043
1044 char* 
1045 Engines_Parallel_Container_i::workingdir()
1046 {
1047   char wd[256];
1048   getcwd (wd,256);
1049   return CORBA::string_dup(wd) ;
1050 }
1051
1052 //=============================================================================
1053 /*! 
1054  *  CORBA attribute: Container log file name
1055  */
1056 //=============================================================================
1057
1058 char* 
1059 Engines_Parallel_Container_i::logfilename()
1060 {
1061   return CORBA::string_dup(_logfilename.c_str()) ;
1062 }
1063
1064 void 
1065 Engines_Parallel_Container_i::logfilename(const char* name)
1066 {
1067   _logfilename=name;
1068 }