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