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