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