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