Salome HOME
62b58f98a438ba85468db47dba26ec300b076ca5
[modules/kernel.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       LocalTraceBufferPool* bp1 = LocalTraceBufferPool::instance();
266       bp1->deleteInstance(bp1);
267       _orb->shutdown(0);
268     }
269 }
270
271
272 //=============================================================================
273 /*! 
274  *  CORBA method: load a new component class (Python or C++ implementation)
275  *  \param componentName like COMPONENT
276  *                          try to make a Python import of COMPONENT,
277  *                          then a lib open of libCOMPONENTEngine.so
278  *  \return true if dlopen successfull or already done, false otherwise
279  */
280 //=============================================================================
281
282 bool
283 Engines_Container_i::load_component_Library(const char* componentName)
284 {
285
286   string aCompName = componentName;
287
288   // --- try dlopen C++ component
289
290 #ifndef WNT
291   string impl_name = string ("lib") + aCompName + string("Engine.so");
292 #else
293   string impl_name = aCompName + string("Engine.dll");
294 #endif
295   SCRUTE(impl_name);
296   
297   _numInstanceMutex.lock(); // lock to be alone 
298   // (see decInstanceCnt, finalize_removal))
299   if (_toRemove_map[impl_name]) _toRemove_map.erase(impl_name);
300   if (_library_map[impl_name])
301     {
302       MESSAGE("Library " << impl_name << " already loaded");
303       _numInstanceMutex.unlock();
304       return true;
305     }
306   
307   void* handle;
308 #ifndef WNT
309   handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ;
310 #else
311   handle = dlopen( impl_name.c_str() , 0 ) ;
312 #endif
313   if ( handle )
314     {
315       _library_map[impl_name] = handle;
316       _numInstanceMutex.unlock();
317       return true;
318     }
319   else
320     {
321       INFOS("Can't load shared library : " << impl_name);
322       INFOS("error dlopen: " << dlerror());
323     }
324   _numInstanceMutex.unlock();
325
326   // --- try import Python component
327
328   INFOS("try import Python component "<<componentName);
329   if (_isSupervContainer)
330     {
331       INFOS("Supervision Container does not support Python Component Engines");
332       return false;
333     }
334   if (_library_map[aCompName])
335     {
336       return true; // Python Component, already imported
337     }
338   else
339     {
340       Py_ACQUIRE_NEW_THREAD;
341       PyObject *mainmod = PyImport_AddModule("__main__");
342       PyObject *globals = PyModule_GetDict(mainmod);
343       PyObject *pyCont = PyDict_GetItemString(globals, "pyCont");
344       PyObject *result = PyObject_CallMethod(pyCont,
345                                              "import_component",
346                                              "s",componentName);
347       int ret= PyInt_AsLong(result);
348       SCRUTE(ret);
349       Py_RELEASE_NEW_THREAD;
350   
351       if (ret) // import possible: Python component
352         {
353           _library_map[aCompName] = (void *)pyCont; // any non O value OK
354           MESSAGE("import Python: "<<aCompName<<" OK");
355           return true;
356         }
357     }
358   return false;
359 }
360
361 //=============================================================================
362 /*! 
363  *  CORBA method: Creates a new servant instance of a component.
364  *  The servant registers itself to naming service and Registry.
365  *  \param genericRegisterName  Name of the component instance to register
366  *                         in Registry & Name Service (without _inst_n suffix)
367  *  \param studyId         0 for multiStudy instance, 
368  *                         study Id (>0) otherwise
369  *  \return a loaded component
370  */
371 //=============================================================================
372
373 Engines::Component_ptr
374 Engines_Container_i::create_component_instance(const char*genericRegisterName,
375                                                CORBA::Long studyId)
376 {
377   if (studyId < 0)
378     {
379       INFOS("studyId must be > 0 for mono study instance, =0 for multiStudy");
380       return Engines::Component::_nil() ;
381     }
382
383   Engines::Component_var iobject = Engines::Component::_nil() ;
384
385   string aCompName = genericRegisterName;
386   if (_library_map[aCompName]) // Python component
387     {
388       if (_isSupervContainer)
389         {
390           INFOS("Supervision Container does not support Python Component Engines");
391           return Engines::Component::_nil();
392         }
393       _numInstanceMutex.lock() ; // lock on the instance number
394       _numInstance++ ;
395       int numInstance = _numInstance ;
396       _numInstanceMutex.unlock() ;
397
398       char aNumI[12];
399       sprintf( aNumI , "%d" , numInstance ) ;
400       string instanceName = aCompName + "_inst_" + aNumI ;
401       string component_registerName =
402         _containerName + "/" + instanceName;
403
404       Py_ACQUIRE_NEW_THREAD;
405       PyObject *mainmod = PyImport_AddModule("__main__");
406       PyObject *globals = PyModule_GetDict(mainmod);
407       PyObject *pyCont = PyDict_GetItemString(globals, "pyCont");
408       PyObject *result = PyObject_CallMethod(pyCont,
409                                              "create_component_instance",
410                                              "ssl",
411                                              aCompName.c_str(),
412                                              instanceName.c_str(),
413                                              studyId);
414       string iors = PyString_AsString(result);
415       SCRUTE(iors);
416       Py_RELEASE_NEW_THREAD;
417   
418       CORBA::Object_var obj = _orb->string_to_object(iors.c_str());
419       iobject = Engines::Component::_narrow( obj ) ;
420       return iobject._retn();
421     }
422   
423   //--- try C++
424
425 #ifndef WNT
426   string impl_name = string ("lib") + genericRegisterName +string("Engine.so");
427 #else
428   string impl_name = genericRegisterName +string("Engine.dll");
429 #endif
430   void* handle = _library_map[impl_name];
431   if ( !handle )
432     {
433       INFOS("shared library " << impl_name <<"must be loaded before instance");
434       return Engines::Component::_nil() ;
435     }
436   else
437     {
438       iobject = createInstance(genericRegisterName,
439                                handle,
440                                studyId);
441       return iobject._retn();
442     }
443 }
444
445 //=============================================================================
446 /*! 
447  *  CORBA method: Finds a servant instance of a component
448  *  \param registeredName  Name of the component in Registry or Name Service,
449  *                         without instance suffix number
450  *  \param studyId         0 if instance is not associated to a study, 
451  *                         >0 otherwise (== study id)
452  *  \return the first instance found with same studyId
453  */
454 //=============================================================================
455
456 Engines::Component_ptr
457 Engines_Container_i::find_component_instance( const char* registeredName,
458                                               CORBA::Long studyId)
459 {
460   Engines::Component_var anEngine = Engines::Component::_nil();
461   map<string,Engines::Component_var>::iterator itm =_listInstances_map.begin();
462   while (itm != _listInstances_map.end())
463     {
464       string instance = (*itm).first;
465       SCRUTE(instance);
466       if (instance.find(registeredName) == 0)
467         {
468           anEngine = (*itm).second;
469           if (studyId == anEngine->getStudyId())
470             {
471               return anEngine._retn();
472             }
473         }
474       itm++;
475     }
476   return anEngine._retn();  
477 }
478
479 //=============================================================================
480 /*! 
481  *  CORBA method: find or create an instance of the component (servant),
482  *  load a new component class (dynamic library) if required,
483  *  ---- FOR COMPATIBILITY WITH 2.2 ---- 
484  *  ---- USE ONLY FOR MULTISTUDY INSTANCES ! --------
485  *  The servant registers itself to naming service and Registry.
486  *  \param genericRegisterName  Name of the component to register
487  *                              in Registry & Name Service
488  *  \param componentName       Name of the constructed library of the component
489  *  \return a loaded component
490  */
491 //=============================================================================
492
493 Engines::Component_ptr
494 Engines_Container_i::load_impl( const char* genericRegisterName,
495                                 const char* componentName )
496 {
497   string impl_name = string ("lib") + genericRegisterName +string("Engine.so");
498   Engines::Component_var iobject = Engines::Component::_nil() ;
499   if (load_component_Library(genericRegisterName))
500     iobject = find_or_create_instance(genericRegisterName, impl_name);
501   return iobject._retn();
502 }
503     
504
505 //=============================================================================
506 /*! 
507  *  CORBA method: Stops the component servant, and deletes all related objects
508  *  \param component_i     Component to be removed
509  */
510 //=============================================================================
511
512 void Engines_Container_i::remove_impl(Engines::Component_ptr component_i)
513 {
514   ASSERT(! CORBA::is_nil(component_i));
515   string instanceName = component_i->instanceName() ;
516   MESSAGE("unload component " << instanceName);
517   _listInstances_map.erase(instanceName);
518   component_i->destroy() ;
519   _NS->Destroy_Name(instanceName.c_str());
520 }
521
522 //=============================================================================
523 /*! 
524  *  CORBA method: Discharges unused libraries from the container.
525  */
526 //=============================================================================
527
528 void Engines_Container_i::finalize_removal()
529 {
530   MESSAGE("finalize unload : dlclose");
531   _numInstanceMutex.lock(); // lock to be alone
532                             // (see decInstanceCnt, load_component_Library)
533   map<string, void *>::iterator ith;
534   for (ith = _toRemove_map.begin(); ith != _toRemove_map.end(); ith++)
535     {
536       void *handle = (*ith).second;
537       string impl_name= (*ith).first;
538       if (handle)
539         {
540           SCRUTE(handle);
541           SCRUTE(impl_name);
542 //        dlclose(handle);                // SALOME unstable after ...
543 //        _library_map.erase(impl_name);
544         }
545     }
546   _toRemove_map.clear();
547   _numInstanceMutex.unlock();
548 }
549
550 //=============================================================================
551 /*! 
552  *  CORBA method: Kill the container process with exit(0).
553  *  To remove :  never returns !
554  */
555 //=============================================================================
556
557 bool Engines_Container_i::Kill_impl()
558 {
559   MESSAGE("Engines_Container_i::Kill() pid "<< getpid() << " containerName "
560           << _containerName.c_str() << " machineName "
561           << GetHostname().c_str());
562   INFOS("===============================================================");
563   INFOS("= REMOVE calls to Kill_impl in C++ container                  =");
564   INFOS("===============================================================");
565   //exit( 0 ) ;
566   ASSERT(0);
567   return false;
568 }
569
570 //=============================================================================
571 /*! 
572  *  C++ method: Finds an already existing servant instance of a component, or
573  *              create an instance.
574  *  ---- USE ONLY FOR MULTISTUDY INSTANCES ! --------
575  *  \param genericRegisterName    Name of the component instance to register
576  *                                in Registry & Name Service,
577  *                                (without _inst_n suffix, like "COMPONENT")
578  *  \param componentLibraryName   like "libCOMPONENTEngine.so"
579  *  \return a loaded component
580  * 
581  *  example with names:
582  *  aGenRegisterName = COMPONENT (= first argument)
583  *  impl_name = libCOMPONENTEngine.so (= second argument)
584  *  _containerName = /Containers/cli76ce/FactoryServer
585  *  factoryName = COMPONENTEngine_factory
586  *  component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
587  *
588  *  instanceName = COMPONENT_inst_1
589  *  component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
590  */
591 //=============================================================================
592
593 Engines::Component_ptr
594 Engines_Container_i::find_or_create_instance(string genericRegisterName,
595                                              string componentLibraryName)
596 {
597   string aGenRegisterName = genericRegisterName;
598   string impl_name = componentLibraryName;
599   void* handle = _library_map[impl_name];
600   if ( !handle )
601     {
602       INFOS("shared library " << impl_name <<"must be loaded before instance");
603       return Engines::Component::_nil() ;
604     }
605   else
606     {
607       // --- find a registered instance in naming service, or create
608
609       string component_registerBase =
610         _containerName + "/" + aGenRegisterName;
611       Engines::Component_var iobject = Engines::Component::_nil() ;
612       try
613         {
614           CORBA::Object_var obj =
615             _NS->ResolveFirst( component_registerBase.c_str());
616           if ( CORBA::is_nil( obj ) )
617             {
618               iobject = createInstance(genericRegisterName,
619                                        handle,
620                                        0); // force multiStudy instance here !
621             }
622           else
623             { 
624               iobject = Engines::Component::_narrow( obj ) ;
625               Engines_Component_i *servant =
626                 dynamic_cast<Engines_Component_i*>
627                 (_poa->reference_to_servant(iobject));
628               ASSERT(servant)
629               int studyId = servant->getStudyId();
630               ASSERT (studyId >= 0);
631               if (studyId == 0) // multiStudy instance, OK
632                 {
633                   // No ReBind !
634                   MESSAGE(component_registerBase.c_str()<<" already bound");
635                 }
636               else // monoStudy instance: NOK
637                 {
638                   iobject = Engines::Component::_nil();
639                   INFOS("load_impl & find_component_instance methods "
640                         << "NOT SUITABLE for mono study components");
641                 }
642             }
643         }
644       catch (...)
645         {
646           INFOS( "Container_i::load_impl catched" ) ;
647         }
648       return iobject._retn();
649     }
650 }
651
652 //=============================================================================
653 /*! 
654  *  C++ method: create a servant instance of a component.
655  *  \param genericRegisterName    Name of the component instance to register
656  *                                in Registry & Name Service,
657  *                                (without _inst_n suffix, like "COMPONENT")
658  *  \param handle                 loaded library handle
659  *  \param studyId                0 for multiStudy instance, 
660  *                                study Id (>0) otherwise
661  *  \return a loaded component
662  * 
663  *  example with names:
664  *  aGenRegisterName = COMPONENT (= first argument)
665  *  _containerName = /Containers/cli76ce/FactoryServer
666  *  factoryName = COMPONENTEngine_factory
667  *  component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
668  *  instanceName = COMPONENT_inst_1
669  *  component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
670  */
671 //=============================================================================
672
673 Engines::Component_ptr
674 Engines_Container_i::createInstance(string genericRegisterName,
675                                     void *handle,
676                                     int studyId)
677 {
678   // --- find the factory
679
680   string aGenRegisterName = genericRegisterName;
681   string factory_name = aGenRegisterName + string("Engine_factory");
682   SCRUTE(factory_name) ;
683
684   typedef  PortableServer::ObjectId * (*FACTORY_FUNCTION)
685     (CORBA::ORB_ptr,
686      PortableServer::POA_ptr, 
687      PortableServer::ObjectId *, 
688      const char *, 
689      const char *) ;
690
691   FACTORY_FUNCTION Component_factory
692     = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
693
694   char *error ;
695   if ( (error = dlerror() ) != NULL)
696     {
697       INFOS("Can't resolve symbol: " + factory_name);
698       SCRUTE(error);
699       return Engines::Component::_nil() ;
700     }
701
702   // --- create instance
703
704   Engines::Component_var iobject = Engines::Component::_nil() ;
705
706   try
707     {
708       _numInstanceMutex.lock() ; // lock on the instance number
709       _numInstance++ ;
710       int numInstance = _numInstance ;
711       _numInstanceMutex.unlock() ;
712
713       char aNumI[12];
714       sprintf( aNumI , "%d" , numInstance ) ;
715       string instanceName = aGenRegisterName + "_inst_" + aNumI ;
716       string component_registerName =
717         _containerName + "/" + instanceName;
718
719       // --- Instanciate required CORBA object
720
721       PortableServer::ObjectId *id ; //not owner, do not delete (nore use var)
722       id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str(),
723                                  aGenRegisterName.c_str() ) ;
724
725       // --- get reference & servant from id
726
727       CORBA::Object_var obj = _poa->id_to_reference(*id);
728       iobject = Engines::Component::_narrow( obj ) ;
729
730       Engines_Component_i *servant =
731         dynamic_cast<Engines_Component_i*>(_poa->reference_to_servant(iobject));
732       ASSERT(servant);
733       //SCRUTE(servant->pd_refCount);
734       servant->_remove_ref(); // compensate previous id_to_reference 
735       //SCRUTE(servant->pd_refCount);
736       _listInstances_map[instanceName] = iobject;
737       _cntInstances_map[aGenRegisterName] += 1;
738       SCRUTE(aGenRegisterName);
739       SCRUTE(_cntInstances_map[aGenRegisterName]);
740       //SCRUTE(servant->pd_refCount);
741       bool ret_studyId = servant->setStudyId(studyId);
742       ASSERT(ret_studyId);
743
744       // --- register the engine under the name
745       //     containerName(.dir)/instanceName(.object)
746
747       _NS->Register( iobject , component_registerName.c_str() ) ;
748       MESSAGE( component_registerName.c_str() << " bound" ) ;
749     }
750   catch (...)
751     {
752       INFOS( "Container_i::createInstance exception catched" ) ;
753     }
754   return iobject._retn();
755 }
756
757 //=============================================================================
758 /*! 
759  *
760  */
761 //=============================================================================
762
763 void Engines_Container_i::decInstanceCnt(string genericRegisterName)
764 {
765   string aGenRegisterName =genericRegisterName;
766   MESSAGE("Engines_Container_i::decInstanceCnt " << aGenRegisterName);
767   ASSERT(_cntInstances_map[aGenRegisterName] > 0); 
768   _numInstanceMutex.lock(); // lock to be alone
769                             // (see finalize_removal, load_component_Library)
770   _cntInstances_map[aGenRegisterName] -= 1;
771   SCRUTE(_cntInstances_map[aGenRegisterName]);
772   if (_cntInstances_map[aGenRegisterName] == 0)
773     {
774       string impl_name =
775         Engines_Component_i::GetDynLibraryName(aGenRegisterName.c_str());
776       SCRUTE(impl_name);
777       void* handle = _library_map[impl_name];
778       ASSERT(handle);
779       _toRemove_map[impl_name] = handle;
780     }
781   _numInstanceMutex.unlock();
782 }
783
784 //=============================================================================
785 /*! 
786  *  Retrieves only with container naming convention if it is a python container
787  */
788 //=============================================================================
789
790 bool Engines_Container_i::isPythonContainer(const char* ContainerName)
791 {
792   bool ret=false;
793   int len=strlen(ContainerName);
794   if(len>=2)
795     if(strcmp(ContainerName+len-2,"Py")==0)
796       ret=true;
797   return ret;
798 }
799
800 //=============================================================================
801 /*! 
802  *  
803  */
804 //=============================================================================
805
806 void ActSigIntHandler()
807 {
808 #ifndef WNT
809   struct sigaction SigIntAct ;
810   SigIntAct.sa_sigaction = &SigIntHandler ;
811   SigIntAct.sa_flags = SA_SIGINFO ;
812 #endif
813
814 // DEBUG 03.02.2005 : the first parameter of sigaction is not a mask of signals
815 // (SIGINT | SIGUSR1) :
816 // it must be only one signal ===> one call for SIGINT 
817 // and an other one for SIGUSR1
818 #ifndef WNT
819   if ( sigaction( SIGINT , &SigIntAct, NULL ) ) {
820     perror("SALOME_Container main ") ;
821     exit(0) ;
822   }
823   if ( sigaction( SIGUSR1 , &SigIntAct, NULL ) ) {
824     perror("SALOME_Container main ") ;
825     exit(0) ;
826   }
827   //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
828   //             use of streams (and so on) should never be used because :
829   //             streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
830   //             A stream operation may be interrupted by a signal and if the Handler use stream we
831   //             may have a "Dead-Lock" ===HangUp
832   //==INFOS is commented
833   //  INFOS(pthread_self() << "SigIntHandler activated") ;
834 #else  
835   signal( SIGINT, SigIntHandler );
836   signal( SIGUSR1, SigIntHandler );
837 #endif
838
839 }
840
841 void SetCpuUsed() ;
842
843 #ifndef WNT
844 void SigIntHandler(int what , siginfo_t * siginfo ,
845                                         void * toto ) {
846   //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
847   //             use of streams (and so on) should never be used because :
848   //             streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
849   //             A stream operation may be interrupted by a signal and if the Handler use stream we
850   //             may have a "Dead-Lock" ===HangUp
851   //==MESSAGE is commented
852   //  MESSAGE(pthread_self() << "SigIntHandler what     " << what << endl
853   //          << "              si_signo " << siginfo->si_signo << endl
854   //          << "              si_code  " << siginfo->si_code << endl
855   //          << "              si_pid   " << siginfo->si_pid) ;
856   if ( _Sleeping ) {
857     _Sleeping = false ;
858     //     MESSAGE("SigIntHandler END sleeping.") ;
859     return ;
860   }
861   else {
862     ActSigIntHandler() ;
863     if ( siginfo->si_signo == SIGUSR1 ) {
864       SetCpuUsed() ;
865     }
866     else {
867       _Sleeping = true ;
868       //      MESSAGE("SigIntHandler BEGIN sleeping.") ;
869       int count = 0 ;
870       while( _Sleeping ) {
871         sleep( 1 ) ;
872         count += 1 ;
873       }
874       //      MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
875     }
876     return ;
877   }
878 }
879 #else // Case WNT
880 void SigIntHandler( int what ) {
881   MESSAGE( pthread_self() << "SigIntHandler what     " << what << endl );
882   if ( _Sleeping ) {
883     _Sleeping = false ;
884     MESSAGE("SigIntHandler END sleeping.") ;
885     return ;
886   }
887   else {
888     ActSigIntHandler() ;
889     if ( what == SIGUSR1 ) {
890       SetCpuUsed() ;
891     }
892     else {
893       _Sleeping = true ;
894       MESSAGE("SigIntHandler BEGIN sleeping.") ;
895       int count = 0 ;
896       while( _Sleeping ) {
897         Sleep( 1000 ) ;
898         count += 1 ;
899       }
900       MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
901     }
902     return ;
903   }
904 }
905 #endif
906
907 //=============================================================================
908 /*! 
909  *  CORBA method: Create one instance of componentName component 
910  *  and register it as genericRegisterName in naming service
911  */
912 //=============================================================================
913
914 // Engines::Component_ptr Engines_Container_i::instance( const char* genericRegisterName,
915 //                                                    const char* componentName )
916 // {
917 //   _numInstanceMutex.lock() ; // lock on the instance number
918 //   BEGIN_OF( "Container_i::instance " << componentName ) ;
919
920 //   string _genericRegisterName = genericRegisterName;
921 //   string component_registerName = _containerName + "/" + _genericRegisterName;
922   
923 //   Engines::Component_var iobject = Engines::Component::_nil() ;
924   
925 //   try 
926 //     {
927 //       CORBA::Object_var obj = _NS->Resolve( component_registerName.c_str() ) ;
928 //       if (! CORBA::is_nil( obj ) )
929 //      {
930 //        MESSAGE( "Container_i::instance " << component_registerName.c_str() << " already registered" ) ;
931 //        iobject = Engines::Component::_narrow( obj ) ;
932 //      }
933 //       else
934 //      {
935 //        string _compo_name = componentName;
936 //        string _impl_name = "lib" + _compo_name + "Engine.so";
937 //        SCRUTE(_impl_name);
938       
939 //        void* handle;
940 //        handle = dlopen( _impl_name.c_str() , RTLD_LAZY ) ;
941           
942 //        if ( handle )
943 //          {
944 //            string factory_name = _compo_name + "Engine_factory";
945 //            SCRUTE(factory_name) ;
946               
947 //            typedef  PortableServer::ObjectId * (*FACTORY_FUNCTION)
948 //              (CORBA::ORB_ptr,
949 //               PortableServer::POA_ptr, 
950 //               PortableServer::ObjectId *, 
951 //               const char *, 
952 //               const char *) ; 
953 //            FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
954
955 //            char *error ;
956 //            if ( (error = dlerror() ) == NULL)
957 //              {
958 //                // Instanciate required CORBA object
959 //                _numInstance++ ;
960 //                char _aNumI[12];
961 //                sprintf( _aNumI , "%d" , _numInstance ) ;
962 //                string instanceName = _compo_name + "_inst_" + _aNumI ;
963 //                SCRUTE(instanceName);
964                   
965 //                PortableServer::ObjectId * id ;
966 //                id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str() ,
967 //                                           _genericRegisterName.c_str() ) ;
968 //                // get reference from id
969 //                obj = _poa->id_to_reference(*id);
970 //                iobject = Engines::Component::_narrow( obj ) ;
971                   
972 //                // register the engine under the name containerName.dir/genericRegisterName.object
973 //                _NS->Register( iobject , component_registerName.c_str() ) ;
974 //                MESSAGE( "Container_i::instance " << component_registerName.c_str() << " registered" ) ;
975 //                _handle_map[instanceName] = handle;
976 //              }
977 //            else
978 //              {
979 //                INFOS("Can't resolve symbol: " + factory_name);
980 //                SCRUTE(error);
981 //              }  
982 //          }
983 //        else
984 //          {
985 //            INFOS("Can't load shared library : " << _impl_name);
986 //            INFOS("error dlopen: " << dlerror());
987 //          }      
988 //      }
989 //     }
990 //   catch (...)
991 //     {
992 //       INFOS( "Container_i::instance exception caught" ) ;
993 //     }
994 //   END_OF("Container_i::instance");
995 //   _numInstanceMutex.unlock() ;
996 //   return Engines::Component::_duplicate(iobject);
997 // }
998
999 //=============================================================================
1000 /*! 
1001  *  CORBA attribute: Machine Name (hostname without domain extensions)
1002  */
1003 //=============================================================================
1004
1005 // char* Engines_Container_i::machineName()
1006 // {
1007 //   string s = GetHostname();
1008 //   MESSAGE("Engines_Container_i::machineName " << s);
1009 //    return CORBA::string_dup(s.c_str()) ;
1010 // }
1011
1012