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