1 // SALOME Container : implementation of container and engine for Kernel
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : Container_i.cxx
25 // Author : Paul RASCLE, EDF - MARC TAJCHMAN, CEA
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"
40 #include "utilities.h"
43 bool _Sleeping = false ;
45 // Needed by multi-threaded Python
50 // Containers with name FactoryServer are started via rsh in LifeCycleCORBA
51 // Other Containers are started via start_impl of FactoryServer
53 extern "C" {void ActSigIntHandler() ; }
54 extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; }
56 const char *Engines_Container_i::_defaultContainerName="FactoryServer";
58 Engines_Container_i::Engines_Container_i () :
63 Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb,
64 PortableServer::POA_ptr poa,
66 int argc , char* argv[],
68 bool isServantAloneInProcess
70 _numInstance(0),_isServantAloneInProcess(isServantAloneInProcess)
72 _pid = (long)getpid();
82 int i = strlen( _argv[ 0 ] ) - 1 ;
84 if ( _argv[ 0 ][ i ] == '/' ) {
85 _argv[ 0 ][ i+1 ] = '\0' ;
90 string hostname = GetHostname();
91 MESSAGE(hostname << " " << getpid() << " Engines_Container_i starting argc "
92 << _argc << " Thread " << pthread_self() ) ;
94 while ( _argv[ i ] ) {
95 MESSAGE(" argv" << i << " " << _argv[ i ]) ;
99 MESSAGE("SALOME_Container usage : SALOME_Container ServerName -ORBInitRef NameService=corbaname::hostname:tcpipPortNumber") ;
105 _containerName = BuildContainerNameForNS(containerName,hostname.c_str());
107 _orb = CORBA::ORB::_duplicate(orb) ;
108 _poa = PortableServer::POA::_duplicate(poa) ;
110 // Pour les containers paralleles: il ne faut pas enregistrer et activer le container generique, mais le container specialise
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());
124 Engines_Container_i::~Engines_Container_i()
126 MESSAGE("Container_i::~Container_i()");
130 char* Engines_Container_i::name()
132 return CORBA::string_dup(_containerName.c_str()) ;
135 char* Engines_Container_i::machineName()
137 string s = GetHostname();
138 MESSAGE("Engines_Container_i::machineName " << s);
139 return CORBA::string_dup(s.c_str()) ;
142 void Engines_Container_i::ping()
144 MESSAGE("Engines_Container_i::ping() pid "<< getpid());
147 // shutdown corba server
148 void Engines_Container_i::Shutdown()
150 MESSAGE("Engines_Container_i::Shutdown()");
151 _NS->Destroy_Name(_containerName.c_str());
153 //_poa->deactivate_object(*_id);
154 if(_isServantAloneInProcess)
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());
166 Engines::Component_ptr Engines_Container_i::load_impl( const char* nameToRegister,
167 const char* componentName ) {
169 _numInstanceMutex.lock() ; // lock on the instance number
170 BEGIN_OF( "Container_i::load_impl " << componentName ) ;
173 sprintf( _aNumI , "%d" , _numInstance ) ;
175 string _impl_name = componentName;
176 string _nameToRegister = nameToRegister;
177 string instanceName = _nameToRegister + "_inst_" + _aNumI ;
178 //SCRUTE(instanceName);
180 //string absolute_impl_name = _library_path + "lib" + _impl_name + ".so";
181 string absolute_impl_name( _impl_name ) ;
182 SCRUTE(absolute_impl_name);
184 handle = dlopen( absolute_impl_name.c_str() , RTLD_LAZY ) ;
186 INFOS("Can't load shared library : " << absolute_impl_name);
187 INFOS("error dlopen: " << dlerror());
188 _numInstanceMutex.unlock() ;
189 return Engines::Component::_nil() ;
192 string factory_name = _nameToRegister + string("Engine_factory");
193 // SCRUTE(factory_name) ;
195 typedef PortableServer::ObjectId * (*FACTORY_FUNCTION)
197 PortableServer::POA_ptr,
198 PortableServer::ObjectId *,
201 FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
204 if ( (error = dlerror() ) != NULL) {
205 INFOS("Can't resolve symbol: " + factory_name);
207 _numInstanceMutex.unlock() ;
208 return Engines::Component::_nil() ;
211 string component_registerName = _containerName + "/" + _nameToRegister;
212 Engines::Component_var iobject = Engines::Component::_nil() ;
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 ) ;
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" ) ;
229 else { // JR : No ReBind !!!
230 MESSAGE( "Container_i::load_impl " << component_registerName.c_str() << " already bound" ) ;
231 iobject = Engines::Component::_narrow( obj ) ;
235 INFOS( "Container_i::load_impl catched" ) ;
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);
245 void Engines_Container_i::remove_impl(Engines::Component_ptr component_i)
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
255 remove_map[instanceName] = handle_map[instanceName] ;
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 ++)
264 MESSAGE("reste " << (*im).first);
268 void Engines_Container_i::finalize_removal()
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 ++)
275 void * handle = (*im).second ;
277 MESSAGE("dlclose " << (*im).first);
280 _numInstanceMutex.unlock() ;
281 MESSAGE("remove_map.clear()");
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 ") ;
294 if ( sigaction( SIGUSR1 , &SigIntAct, NULL ) ) {
295 perror("SALOME_Container main ") ;
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") ;
309 void SigIntHandler(int what , siginfo_t * siginfo ,
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) ;
323 // MESSAGE("SigIntHandler END sleeping.") ;
328 if ( siginfo->si_signo == SIGUSR1 ) {
333 // MESSAGE("SigIntHandler BEGIN sleeping.") ;
339 // MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
345 // Get the PID of the Container
347 CORBA::Long Engines_Container_i::getPID() {
348 return (CORBA::Long)getpid();
351 // Get the hostName of the Container
353 char* Engines_Container_i::getHostName() {
354 return((char*)(GetHostname().c_str()));
357 // Retrieves only with container naming convention if it is a python container
358 bool Engines_Container_i::isPythonContainer(const char* ContainerName)
361 int len=strlen(ContainerName);
363 if(strcmp(ContainerName+len-2,"Py")==0)
368 string Engines_Container_i::BuildContainerNameForNS(const char *ContainerName, const char *hostname)
370 string ret="/Containers/";
373 if (strlen(ContainerName)== 0)
374 ret+=_defaultContainerName;
376 ret += ContainerName;
382 * Create one instance of componentName component and register it
383 * as nameToRegister in naming service
385 Engines::Component_ptr Engines_Container_i::instance( const char* nameToRegister,
386 const char* componentName ) {
388 _numInstanceMutex.lock() ; // lock on the instance number
389 BEGIN_OF( "Container_i::instance " << componentName ) ;
391 string _nameToRegister = nameToRegister;
392 string component_registerName = _containerName + "/" + _nameToRegister;
394 Engines::Component_var iobject = Engines::Component::_nil() ;
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 ) ;
403 string _compo_name = componentName;
404 string _impl_name = "lib" + _compo_name + "Engine.so";
408 handle = dlopen( _impl_name.c_str() , RTLD_LAZY ) ;
411 string factory_name = _compo_name + "Engine_factory";
412 SCRUTE(factory_name) ;
414 typedef PortableServer::ObjectId * (*FACTORY_FUNCTION)
416 PortableServer::POA_ptr,
417 PortableServer::ObjectId *,
420 FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
423 if ( (error = dlerror() ) == NULL) {
424 // Instanciate required CORBA object
427 sprintf( _aNumI , "%d" , _numInstance ) ;
428 string instanceName = _compo_name + "_inst_" + _aNumI ;
429 SCRUTE(instanceName);
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 ) ;
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;
444 INFOS("Can't resolve symbol: " + factory_name);
449 INFOS("Can't load shared library : " << _impl_name);
450 INFOS("error dlopen: " << dlerror());
455 INFOS( "Container_i::instance exception caught" ) ;
457 END_OF("Container_i::instance");
458 _numInstanceMutex.unlock() ;
459 return Engines::Component::_duplicate(iobject);