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