]> SALOME platform Git repositories - modules/kernel.git/blob - src/Container/Container_i.cxx
Salome HOME
Porting to Mandrake 10.1 and new products:
[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 #include <SALOMEconfig.h>
30 #include CORBA_SERVER_HEADER(SALOME_Component)
31 #include "SALOME_Container_i.hxx"
32 #include "SALOME_NamingService.hxx"
33 //#include "Utils_SINGLETON.hxx"
34 #include "OpUtil.hxx"
35 #include <string.h>
36 #include <stdio.h>
37 #include <dlfcn.h>
38 #include <unistd.h>
39
40 #include "utilities.h"
41 using namespace std;
42
43 bool _Sleeping = false ;
44
45 // Needed by multi-threaded Python
46 int _ArgC ;
47 char ** _ArgV ;
48
49
50 // Containers with name FactoryServer are started via rsh in LifeCycleCORBA
51 // Other Containers are started via start_impl of FactoryServer
52
53 extern "C" {void ActSigIntHandler() ; }
54 extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; }
55
56 const char *Engines_Container_i::_defaultContainerName="FactoryServer";
57
58 Engines_Container_i::Engines_Container_i () :
59  _numInstance(0)
60 {
61 }
62
63 Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb, 
64                                           PortableServer::POA_ptr poa,
65                                           char *containerName ,
66                                           int argc , char* argv[],
67                                           bool activAndRegist,
68                                           bool isServantAloneInProcess
69                                           ) :
70   _numInstance(0),_isServantAloneInProcess(isServantAloneInProcess)
71 {
72   _pid = (long)getpid();
73
74   if(activAndRegist)
75     ActSigIntHandler() ;
76
77   _ArgC = argc ;
78   _ArgV = argv ;
79
80   _argc = argc ;
81   _argv = argv ;
82   int i = strlen( _argv[ 0 ] ) - 1 ;
83   while ( i >= 0 ) {
84     if ( _argv[ 0 ][ i ] == '/' ) {
85       _argv[ 0 ][ i+1 ] = '\0' ;
86       break ;
87     }
88     i -= 1 ;
89   }
90   string hostname = GetHostname();
91   MESSAGE(hostname << " " << getpid() << " Engines_Container_i starting argc "
92           << _argc << " Thread " << pthread_self() ) ;
93   i = 0 ;
94   while ( _argv[ i ] ) {
95     MESSAGE("           argv" << i << " " << _argv[ i ]) ;
96     i++ ;
97   }
98   if ( argc != 4 ) {
99     MESSAGE("SALOME_Container usage : SALOME_Container ServerName -ORBInitRef NameService=corbaname::hostname:tcpipPortNumber") ;
100 //    exit(0) ;
101   }
102
103   SCRUTE(hostname);
104
105   _containerName = BuildContainerNameForNS(containerName,hostname.c_str());
106
107   _orb = CORBA::ORB::_duplicate(orb) ;
108   _poa = PortableServer::POA::_duplicate(poa) ;
109
110   // Pour les containers paralleles: il ne faut pas enregistrer et activer le container generique, mais le container specialise
111   if(activAndRegist){
112     _id = _poa->activate_object(this);
113     _NS = new SALOME_NamingService();//SINGLETON_<SALOME_NamingService>::Instance() ;
114     //ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
115     _NS->init_orb( CORBA::ORB::_duplicate(_orb) ) ;
116     CORBA::Object_var obj=_poa->id_to_reference(*_id);
117     Engines::Container_var pCont 
118       = Engines::Container::_narrow(obj);
119     SCRUTE(_containerName);
120     _NS->Register(pCont, _containerName.c_str()); 
121   }
122 }
123
124 Engines_Container_i::~Engines_Container_i()
125 {
126   MESSAGE("Container_i::~Container_i()");
127   delete _id;
128 }
129
130 char* Engines_Container_i::name()
131 {
132    return CORBA::string_dup(_containerName.c_str()) ;
133 }
134
135 char* Engines_Container_i::machineName()
136 {
137   string s = GetHostname();
138   MESSAGE("Engines_Container_i::machineName " << s);
139    return CORBA::string_dup(s.c_str()) ;
140 }
141
142 void Engines_Container_i::ping()
143 {
144   MESSAGE("Engines_Container_i::ping() pid "<< getpid());
145 }
146
147 // shutdown corba server
148 void Engines_Container_i::Shutdown()
149 {
150   MESSAGE("Engines_Container_i::Shutdown()");
151   _NS->Destroy_Name(_containerName.c_str());
152   //_remove_ref();
153   //_poa->deactivate_object(*_id);
154   if(_isServantAloneInProcess)
155     _orb->shutdown(0);
156 }
157
158 //! Kill current container
159 bool Engines_Container_i::Kill_impl() {
160   MESSAGE("Engines_Container_i::Kill() pid "<< getpid() << " containerName "
161           << _containerName.c_str() << " machineName "
162           << GetHostname().c_str());
163   exit( 0 ) ;
164 }
165
166 Engines::Component_ptr Engines_Container_i::load_impl( const char* nameToRegister,
167                                                        const char* componentName ) {
168
169   _numInstanceMutex.lock() ; // lock on the instance number
170   BEGIN_OF( "Container_i::load_impl " << componentName ) ;
171   _numInstance++ ;
172   char _aNumI[12];
173   sprintf( _aNumI , "%d" , _numInstance ) ;
174
175   string _impl_name = componentName;
176   string _nameToRegister = nameToRegister;
177   string instanceName = _nameToRegister + "_inst_" + _aNumI ;
178   //SCRUTE(instanceName);
179
180   //string absolute_impl_name = _library_path + "lib" + _impl_name + ".so";
181   string absolute_impl_name( _impl_name ) ;
182   SCRUTE(absolute_impl_name);
183   void* handle;
184   handle = dlopen( absolute_impl_name.c_str() , RTLD_LAZY ) ;
185   if ( !handle ) {
186     INFOS("Can't load shared library : " << absolute_impl_name);
187     INFOS("error dlopen: " << dlerror());
188     _numInstanceMutex.unlock() ;
189     return Engines::Component::_nil() ;
190   }
191   
192   string factory_name = _nameToRegister + string("Engine_factory");
193   //  SCRUTE(factory_name) ;
194
195   typedef  PortableServer::ObjectId * (*FACTORY_FUNCTION)
196                             (CORBA::ORB_ptr,
197                              PortableServer::POA_ptr, 
198                              PortableServer::ObjectId *, 
199                              const char *, 
200                              const char *) ; 
201   FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
202
203   char *error ;
204   if ( (error = dlerror() ) != NULL) {
205       INFOS("Can't resolve symbol: " + factory_name);
206       SCRUTE(error);
207       _numInstanceMutex.unlock() ;
208       return Engines::Component::_nil() ;
209     }
210
211   string component_registerName = _containerName + "/" + _nameToRegister;
212   Engines::Component_var iobject = Engines::Component::_nil() ;
213   try {
214     CORBA::Object_var obj = _NS->Resolve( component_registerName.c_str() ) ;
215     if ( CORBA::is_nil( obj ) ) {
216 // Instanciate required CORBA object
217       PortableServer::ObjectId * id ;
218       id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str() ,
219                                  _nameToRegister.c_str() ) ;
220   // get reference from id
221       obj = _poa->id_to_reference(*id);
222       iobject = Engines::Component::_narrow( obj ) ;
223
224 //  _numInstanceMutex.lock() ; // lock on the add on handle_map (necessary ?)
225   // register the engine under the name containerName.dir/nameToRegister.object
226       _NS->Register( iobject , component_registerName.c_str() ) ;
227       MESSAGE( "Container_i::load_impl " << component_registerName.c_str() << " bound" ) ;
228     }
229     else { // JR : No ReBind !!!
230       MESSAGE( "Container_i::load_impl " << component_registerName.c_str() << " already bound" ) ;
231       iobject = Engines::Component::_narrow( obj ) ;
232     }
233   }
234   catch (...) {
235     INFOS( "Container_i::load_impl catched" ) ;
236   }
237
238 //Jr  _numInstanceMutex.lock() ; // lock on the add on handle_map (necessary ?)
239   handle_map[instanceName] = handle;
240   END_OF("Container_i::load_impl");
241   _numInstanceMutex.unlock() ;
242   return Engines::Component::_duplicate(iobject);
243 }
244
245 void Engines_Container_i::remove_impl(Engines::Component_ptr component_i)
246 {
247   ASSERT(! CORBA::is_nil(component_i));
248   string instanceName = component_i->instanceName() ;
249   MESSAGE("unload component " << instanceName);
250   component_i->destroy() ;
251   MESSAGE("test key handle_map");
252   _numInstanceMutex.lock() ; // lock on the remove on handle_map
253   if (handle_map[instanceName]) // if key does not exist, created & initialized null
254     {
255       remove_map[instanceName] = handle_map[instanceName] ;
256     }
257   else MESSAGE("pas d'entree handle_map");
258   handle_map.erase(instanceName) ;   
259   _numInstanceMutex.unlock() ;
260   MESSAGE("contenu handle_map");
261   map<string, void *>::iterator im ;
262   for (im = handle_map.begin() ; im != handle_map.end() ; im ++)
263     {
264       MESSAGE("reste " << (*im).first);
265     }
266 }
267
268 void Engines_Container_i::finalize_removal()
269 {
270   MESSAGE("finalize unload : dlclose");
271   map<string, void *>::iterator im ;
272   _numInstanceMutex.lock() ; // lock on the explore remove_map & dlclose
273   for (im = remove_map.begin() ; im != remove_map.end() ; im ++)
274     {
275       void * handle = (*im).second ;
276       dlclose(handle) ;
277       MESSAGE("dlclose " << (*im).first);
278     }
279   remove_map.clear() ;  
280   _numInstanceMutex.unlock() ;
281   MESSAGE("remove_map.clear()");
282 }
283
284 void ActSigIntHandler() {
285   struct sigaction SigIntAct ;
286   SigIntAct.sa_sigaction = &SigIntHandler ;
287   SigIntAct.sa_flags = SA_SIGINFO ;
288 // DEBUG 03.02.2005 : the first parameter of sigaction is not a mask of signals (SIGINT | SIGUSR1) :
289 // it must be only one signal ===> one call for SIGINT and an other one for SIGUSR1
290   if ( sigaction( SIGINT , &SigIntAct, NULL ) ) {
291     perror("SALOME_Container main ") ;
292     exit(0) ;
293   }
294   if ( sigaction( SIGUSR1 , &SigIntAct, NULL ) ) {
295     perror("SALOME_Container main ") ;
296     exit(0) ;
297   }
298   //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
299   //             use of streams (and so on) should never be used because :
300   //             streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
301   //             A stream operation may be interrupted by a signal and if the Handler use stream we
302   //             may have a "Dead-Lock" ===HangUp
303   //==INFOS is commented
304   //  INFOS(pthread_self() << "SigIntHandler activated") ;
305 }
306
307 void SetCpuUsed() ;
308
309 void SigIntHandler(int what , siginfo_t * siginfo ,
310                                         void * toto ) {
311   //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
312   //             use of streams (and so on) should never be used because :
313   //             streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
314   //             A stream operation may be interrupted by a signal and if the Handler use stream we
315   //             may have a "Dead-Lock" ===HangUp
316   //==MESSAGE is commented
317   //  MESSAGE(pthread_self() << "SigIntHandler what     " << what << endl
318   //          << "              si_signo " << siginfo->si_signo << endl
319   //          << "              si_code  " << siginfo->si_code << endl
320   //          << "              si_pid   " << siginfo->si_pid) ;
321   if ( _Sleeping ) {
322     _Sleeping = false ;
323     //     MESSAGE("SigIntHandler END sleeping.") ;
324     return ;
325   }
326   else {
327     ActSigIntHandler() ;
328     if ( siginfo->si_signo == SIGUSR1 ) {
329       SetCpuUsed() ;
330     }
331     else {
332       _Sleeping = true ;
333       //      MESSAGE("SigIntHandler BEGIN sleeping.") ;
334       int count = 0 ;
335       while( _Sleeping ) {
336         sleep( 1 ) ;
337         count += 1 ;
338       }
339       //      MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
340     }
341     return ;
342   }
343 }
344
345 // Get the PID of the Container
346
347 CORBA::Long Engines_Container_i::getPID() {
348     return (CORBA::Long)getpid();
349 }
350
351 // Get the hostName of the Container
352
353 char* Engines_Container_i::getHostName() {
354     return((char*)(GetHostname().c_str()));
355 }
356
357 // Retrieves only with container naming convention if it is a python container
358 bool Engines_Container_i::isPythonContainer(const char* ContainerName)
359 {
360   bool ret=false;
361   int len=strlen(ContainerName);
362   if(len>=2)
363     if(strcmp(ContainerName+len-2,"Py")==0)
364       ret=true;
365   return ret;
366 }
367
368 string Engines_Container_i::BuildContainerNameForNS(const char *ContainerName, const char *hostname)
369 {
370   string ret="/Containers/";
371   ret += hostname;
372   ret+="/";
373   if (strlen(ContainerName)== 0)
374     ret+=_defaultContainerName;
375   else
376     ret += ContainerName;
377   return ret;
378 }
379
380
381 /*
382  *  Create one instance of componentName component and register it 
383  *  as nameToRegister in naming service
384  */
385 Engines::Component_ptr Engines_Container_i::instance( const char* nameToRegister,
386                                                       const char* componentName ) {
387
388   _numInstanceMutex.lock() ; // lock on the instance number
389   BEGIN_OF( "Container_i::instance " << componentName ) ;
390
391   string _nameToRegister = nameToRegister;
392   string component_registerName = _containerName + "/" + _nameToRegister;
393   
394   Engines::Component_var iobject = Engines::Component::_nil() ;
395   
396   try {
397     CORBA::Object_var obj = _NS->Resolve( component_registerName.c_str() ) ;
398     if (! CORBA::is_nil( obj ) ) {
399       MESSAGE( "Container_i::instance " << component_registerName.c_str() << " already registered" ) ;
400       iobject = Engines::Component::_narrow( obj ) ;
401     }
402     else{
403       string _compo_name = componentName;
404       string _impl_name = "lib" + _compo_name + "Engine.so";
405       SCRUTE(_impl_name);
406       
407       void* handle;
408       handle = dlopen( _impl_name.c_str() , RTLD_LAZY ) ;
409       
410       if ( handle ) {
411          string factory_name = _compo_name + "Engine_factory";
412          SCRUTE(factory_name) ;
413
414          typedef  PortableServer::ObjectId * (*FACTORY_FUNCTION)
415                                    (CORBA::ORB_ptr,
416                                     PortableServer::POA_ptr, 
417                                     PortableServer::ObjectId *, 
418                                     const char *, 
419                                     const char *) ; 
420          FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
421
422          char *error ;
423          if ( (error = dlerror() ) == NULL) {
424              // Instanciate required CORBA object
425              _numInstance++ ;
426              char _aNumI[12];
427              sprintf( _aNumI , "%d" , _numInstance ) ;
428              string instanceName = _compo_name + "_inst_" + _aNumI ;
429              SCRUTE(instanceName);
430
431              PortableServer::ObjectId * id ;
432              id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str() ,
433                                  _nameToRegister.c_str() ) ;
434              // get reference from id
435              obj = _poa->id_to_reference(*id);
436              iobject = Engines::Component::_narrow( obj ) ;
437
438              // register the engine under the name containerName.dir/nameToRegister.object
439              _NS->Register( iobject , component_registerName.c_str() ) ;
440              MESSAGE( "Container_i::instance " << component_registerName.c_str() << " registered" ) ;
441              handle_map[instanceName] = handle;
442          }
443          else{
444              INFOS("Can't resolve symbol: " + factory_name);
445              SCRUTE(error);
446          }  
447       }
448       else{
449         INFOS("Can't load shared library : " << _impl_name);
450         INFOS("error dlopen: " << dlerror());
451       }      
452     }
453   }
454   catch (...) {
455     INFOS( "Container_i::instance exception caught" ) ;
456   }
457   END_OF("Container_i::instance");
458   _numInstanceMutex.unlock() ;
459   return Engines::Component::_duplicate(iobject);
460 }
461