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"
39 #include "utilities.h"
42 bool _Sleeping = false ;
44 // Needed by multi-threaded Python
49 // Containers with name FactoryServer are started via rsh in LifeCycleCORBA
50 // Other Containers are started via start_impl of FactoryServer
52 extern "C" {void ActSigIntHandler() ; }
53 extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; }
55 Engines_Container_i::Engines_Container_i () :
60 Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb,
61 PortableServer::POA_ptr poa,
63 int argc , char* argv[],
68 _pid = (long)getpid();
78 int i = strlen( _argv[ 0 ] ) - 1 ;
80 if ( _argv[ 0 ][ i ] == '/' ) {
81 _argv[ 0 ][ i+1 ] = '\0' ;
86 string hostname = GetHostname();
87 MESSAGE(hostname << " " << getpid() << " Engines_Container_i starting argc "
88 << _argc << " Thread " << pthread_self() ) ;
90 while ( _argv[ i ] ) {
91 MESSAGE(" argv" << i << " " << _argv[ i ]) ;
95 MESSAGE("SALOME_Container usage : SALOME_Container ServerName -ORBInitRef NameService=corbaname::hostname:tcpipPortNumber") ;
101 _containerName = "/Containers/";
102 if (strlen(containerName)== 0)
104 _containerName += hostname;
108 _containerName += hostname;
109 _containerName += "/" ;
110 _containerName += containerName;
113 _orb = CORBA::ORB::_duplicate(orb) ;
114 _poa = PortableServer::POA::_duplicate(poa) ;
115 // Pour les containers paralleles: il ne faut pas activer le container generique, mais le container specialise
117 MESSAGE("activate object");
118 _id = _poa->activate_object(this);
121 // Pour les containers paralleles: il ne faut pas enregistrer le container generique, mais le container specialise
123 // _NS = new SALOME_NamingService(_orb);
124 _NS = SINGLETON_<SALOME_NamingService>::Instance() ;
125 ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
126 _NS->init_orb( orb ) ;
128 Engines::Container_ptr pCont
129 = Engines::Container::_narrow(_this());
130 SCRUTE(_containerName);
131 _NS->Register(pCont, _containerName.c_str());
135 Engines_Container_i::~Engines_Container_i()
137 MESSAGE("Container_i::~Container_i()");
140 char* Engines_Container_i::name()
142 return CORBA::string_dup(_containerName.c_str()) ;
145 char* Engines_Container_i::machineName()
147 string s = GetHostname();
148 MESSAGE("Engines_Container_i::machineName " << s);
149 return CORBA::string_dup(s.c_str()) ;
152 void Engines_Container_i::ping()
154 MESSAGE("Engines_Container_i::ping() pid "<< getpid());
157 //! Kill current container
158 bool Engines_Container_i::Kill_impl() {
159 MESSAGE("Engines_Container_i::Kill() pid "<< getpid() << " containerName "
160 << _containerName.c_str() << " machineName "
161 << GetHostname().c_str());
165 //! Launch a new container from the current container
166 Engines::Container_ptr Engines_Container_i::start_impl(
167 const char* ContainerName ) {
168 MESSAGE("start_impl argc " << _argc << " ContainerName " << ContainerName
169 << hex << this << dec) ;
170 _numInstanceMutex.lock() ; // lock on the instance number
172 CORBA::Object_var obj = Engines::Container::_nil() ;
175 string cont("/Containers/");
176 cont += machineName() ;
178 cont += ContainerName;
179 INFOS(machineName() << " start_impl unknown container " << cont.c_str()
180 << " try to Resolve" );
181 obj = _NS->Resolve( cont.c_str() );
182 nilvar = CORBA::is_nil( obj ) ;
184 INFOS(machineName() << " start_impl unknown container "
188 catch (ServiceUnreachable&) {
189 INFOS(machineName() << "Caught exception: Naming Service Unreachable");
192 INFOS(machineName() << "Caught unknown exception.");
195 _numInstanceMutex.unlock() ;
196 MESSAGE("start_impl container found without new launch") ;
197 return Engines::Container::_narrow(obj);
200 while ( _argv[ i ] ) {
201 MESSAGE(" argv" << i << " " << _argv[ i ]) ;
204 string shstr = string(getenv("KERNEL_ROOT_DIR")) + "/bin/salome/SALOME_Container ";
205 // string shstr( "./runSession SALOME_Container " ) ;
206 shstr += ContainerName ;
209 shstr += _argv[ 2 ] ;
211 shstr += _argv[ 3 ] ;
214 // asv : 16.11.04 : creation of log file in /tmp/logs/$USER dir.
215 // "/tmp/logs/$USER" was created by runSalome.py -> orbmodule.py.
216 string tempfilename = "/tmp/logs/";
217 tempfilename += getenv( "USER" ) ;
218 tempfilename += "/" ;
219 tempfilename += ContainerName ;
220 tempfilename += ".log" ;
221 FILE* f = fopen ( tempfilename.c_str(), "a" );
222 if ( f ) { // check if file can be opened for writing
225 shstr += tempfilename;
228 else { // if file can't be opened - use a guaranteed temp file name
229 char* tmpFileName = tempnam( NULL, ContainerName );
231 shstr += tmpFileName;
236 MESSAGE("system(" << shstr << ")") ;
237 int status = system( shstr.c_str() ) ;
239 INFOS("Engines_Container_i::start_impl SALOME_Container failed (system command status -1)") ;
241 else if (status == 217) {
242 INFOS("Engines_Container_i::start_impl SALOME_Container failed (system command status 217)") ;
244 INFOS(machineName() << " Engines_Container_i::start_impl SALOME_Container launch done");
246 // pid_t pid = fork() ;
248 // string anExe( _argv[ 0 ] ) ;
249 // anExe += "runSession" ;
250 // char * args[ 6 ] ;
251 // args[ 0 ] = "runSession" ;
252 // args[ 1 ] = "SALOME_Container" ;
253 // args[ 2 ] = strdup( ContainerName ) ;
254 // args[ 3 ] = strdup( _argv[ 2 ] ) ;
255 // args[ 4 ] = strdup( _argv[ 3 ] ) ;
256 // args[ 5 ] = NULL ;
257 // MESSAGE("execl(" << anExe.c_str() << " , " << args[ 0 ] << " , "
258 // << args[ 1 ] << " , " << args[ 2 ] << " , " << args[ 3 ]
259 // << " , " << args[ 4 ] << ")") ;
260 // int status = execv( anExe.c_str() , args ) ;
261 // if (status == -1) {
262 // INFOS("Engines_Container_i::start_impl execl failed (system command status -1)") ;
263 // perror( "Engines_Container_i::start_impl execl error ") ;
266 // INFOS(machineName() << " Engines_Container_i::start_impl execl done");
271 obj = Engines::Container::_nil() ;
273 string cont("/Containers/");
274 cont += machineName() ;
276 cont += ContainerName;
279 while ( nilvar && count >= 0) {
281 obj = _NS->Resolve(cont.c_str());
282 nilvar = CORBA::is_nil( obj ) ;
284 INFOS(count << ". " << machineName()
285 << " start_impl unknown container " << cont.c_str());
289 _numInstanceMutex.unlock() ;
291 MESSAGE("start_impl container found after new launch of SALOME_Container") ;
293 return Engines::Container::_narrow(obj);
295 catch (ServiceUnreachable&) {
296 INFOS(machineName() << "Caught exception: Naming Service Unreachable");
299 INFOS(machineName() << "Caught unknown exception.");
301 _numInstanceMutex.unlock() ;
302 MESSAGE("start_impl container not found after new launch of SALOME_Container") ;
303 return Engines::Container::_nil() ;
306 Engines::Component_ptr Engines_Container_i::load_impl( const char* nameToRegister,
307 const char* componentName ) {
309 _numInstanceMutex.lock() ; // lock on the instance number
310 BEGIN_OF( "Container_i::load_impl " << componentName ) ;
313 sprintf( _aNumI , "%d" , _numInstance ) ;
315 string _impl_name = componentName;
316 string _nameToRegister = nameToRegister;
317 string instanceName = _nameToRegister + "_inst_" + _aNumI ;
318 //SCRUTE(instanceName);
320 //string absolute_impl_name = _library_path + "lib" + _impl_name + ".so";
321 string absolute_impl_name( _impl_name ) ;
322 SCRUTE(absolute_impl_name);
324 handle = dlopen( absolute_impl_name.c_str() , RTLD_LAZY ) ;
326 INFOS("Can't load shared library : " << absolute_impl_name);
327 INFOS("error dlopen: " << dlerror());
328 _numInstanceMutex.unlock() ;
329 return Engines::Component::_nil() ;
332 string factory_name = _nameToRegister + string("Engine_factory");
333 // SCRUTE(factory_name) ;
335 typedef PortableServer::ObjectId * (*FACTORY_FUNCTION)
337 PortableServer::POA_ptr,
338 PortableServer::ObjectId *,
341 FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
344 if ( (error = dlerror() ) != NULL) {
345 INFOS("Can't resolve symbol: " + factory_name);
347 _numInstanceMutex.unlock() ;
348 return Engines::Component::_nil() ;
351 string component_registerName = _containerName + "/" + _nameToRegister;
352 Engines::Component_var iobject = Engines::Component::_nil() ;
354 CORBA::Object_var obj = _NS->Resolve( component_registerName.c_str() ) ;
355 if ( CORBA::is_nil( obj ) ) {
356 // Instanciate required CORBA object
357 PortableServer::ObjectId * id ;
358 id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str() ,
359 _nameToRegister.c_str() ) ;
360 // get reference from id
361 obj = _poa->id_to_reference(*id);
362 iobject = Engines::Component::_narrow( obj ) ;
364 // _numInstanceMutex.lock() ; // lock on the add on handle_map (necessary ?)
365 // register the engine under the name containerName.dir/nameToRegister.object
366 _NS->Register( iobject , component_registerName.c_str() ) ;
367 MESSAGE( "Container_i::load_impl " << component_registerName.c_str() << " bound" ) ;
369 else { // JR : No ReBind !!!
370 MESSAGE( "Container_i::load_impl " << component_registerName.c_str() << " already bound" ) ;
371 iobject = Engines::Component::_narrow( obj ) ;
375 INFOS( "Container_i::load_impl catched" ) ;
378 //Jr _numInstanceMutex.lock() ; // lock on the add on handle_map (necessary ?)
379 handle_map[instanceName] = handle;
380 END_OF("Container_i::load_impl");
381 _numInstanceMutex.unlock() ;
382 return Engines::Component::_duplicate(iobject);
385 void Engines_Container_i::remove_impl(Engines::Component_ptr component_i)
387 ASSERT(! CORBA::is_nil(component_i));
388 string instanceName = component_i->instanceName() ;
389 MESSAGE("unload component " << instanceName);
390 component_i->destroy() ;
391 MESSAGE("test key handle_map");
392 _numInstanceMutex.lock() ; // lock on the remove on handle_map
393 if (handle_map[instanceName]) // if key does not exist, created & initialized null
395 remove_map[instanceName] = handle_map[instanceName] ;
397 else MESSAGE("pas d'entree handle_map");
398 handle_map.erase(instanceName) ;
399 _numInstanceMutex.unlock() ;
400 MESSAGE("contenu handle_map");
401 map<string, void *>::iterator im ;
402 for (im = handle_map.begin() ; im != handle_map.end() ; im ++)
404 MESSAGE("reste " << (*im).first);
408 void Engines_Container_i::finalize_removal()
410 MESSAGE("finalize unload : dlclose");
411 map<string, void *>::iterator im ;
412 _numInstanceMutex.lock() ; // lock on the explore remove_map & dlclose
413 for (im = remove_map.begin() ; im != remove_map.end() ; im ++)
415 void * handle = (*im).second ;
417 MESSAGE("dlclose " << (*im).first);
420 _numInstanceMutex.unlock() ;
421 MESSAGE("remove_map.clear()");
424 void ActSigIntHandler() {
425 struct sigaction SigIntAct ;
426 SigIntAct.sa_sigaction = &SigIntHandler ;
427 SigIntAct.sa_flags = SA_SIGINFO ;
428 if ( sigaction( SIGINT | SIGUSR1 , &SigIntAct, NULL ) ) {
429 perror("SALOME_Container main ") ;
433 INFOS(pthread_self() << "SigIntHandler activated") ;
439 void SigIntHandler(int what , siginfo_t * siginfo ,
441 MESSAGE(pthread_self() << "SigIntHandler what " << what << endl
442 << " si_signo " << siginfo->si_signo << endl
443 << " si_code " << siginfo->si_code << endl
444 << " si_pid " << siginfo->si_pid) ;
447 MESSAGE("SigIntHandler END sleeping.") ;
452 if ( siginfo->si_signo == SIGUSR1 ) {
457 MESSAGE("SigIntHandler BEGIN sleeping.") ;
463 MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
469 // Get the PID of the Container
471 long Engines_Container_i::getPID() {
472 return (long)getpid();
475 // Get the hostName of the Container
477 char* Engines_Container_i::getHostName() {
478 return((char*)(GetHostname().c_str()));