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
30 #include <SALOMEconfig.h>
31 #include CORBA_SERVER_HEADER(SALOME_Component)
32 #include "SALOME_Container_i.hxx"
33 #include "SALOME_NamingService.hxx"
34 #include "Utils_SINGLETON.hxx"
40 #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 (CORBA::ORB_ptr orb,
56 PortableServer::POA_ptr poa,
58 int argc , char* argv[] ) :
69 int i = strlen( _argv[ 0 ] ) - 1 ;
71 if ( _argv[ 0 ][ i ] == '/' ) {
72 _argv[ 0 ][ i+1 ] = '\0' ;
77 string hostname = GetHostname();
78 MESSAGE(hostname << " " << getpid() << " Engines_Container_i starting argc "
79 << _argc << " Thread " << pthread_self() ) ;
81 while ( _argv[ i ] ) {
82 MESSAGE(" argv" << i << " " << _argv[ i ]) ;
86 MESSAGE("SALOME_Container usage : SALOME_Container ServerName -ORBInitRef NameService=corbaname::hostname:tcpipPortNumber") ;
92 _containerName = "/Containers/";
93 if (strlen(containerName)== 0)
95 _containerName += hostname;
99 _containerName += hostname;
100 _containerName += "/" ;
101 _containerName += containerName;
104 _orb = CORBA::ORB::_duplicate(orb) ;
105 _poa = PortableServer::POA::_duplicate(poa) ;
106 MESSAGE("activate object");
107 _id = _poa->activate_object(this);
109 // _NS = new SALOME_NamingService(_orb);
110 _NS = SINGLETON_<SALOME_NamingService>::Instance() ;
111 ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
112 _NS->init_orb( orb ) ;
114 Engines::Container_ptr pCont
115 = Engines::Container::_narrow(_this());
116 SCRUTE(_containerName);
117 _NS->Register(pCont, _containerName.c_str());
120 // Constructeur pour composant parallele : ne pas faire appel au naming service
121 Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb,
122 PortableServer::POA_ptr poa,
127 string hostname = GetHostname();
130 _containerName = "/Containers/";
131 if (strlen(containerName)== 0)
133 _containerName += hostname;
137 _containerName += containerName;
140 _orb = CORBA::ORB::_duplicate(orb) ;
141 _poa = PortableServer::POA::_duplicate(poa) ;
145 Engines_Container_i::~Engines_Container_i()
147 MESSAGE("Container_i::~Container_i()");
150 char* Engines_Container_i::name()
152 return CORBA::string_dup(_containerName.c_str()) ;
155 char* Engines_Container_i::machineName()
157 string s = GetHostname();
158 MESSAGE("Engines_Container_i::machineName " << s);
159 return CORBA::string_dup(s.c_str()) ;
162 void Engines_Container_i::ping()
164 MESSAGE("Engines_Container_i::ping() pid "<< getpid());
167 bool Engines_Container_i::Kill_impl() {
168 MESSAGE("Engines_Container_i::Kill() pid "<< getpid() << " containerName "
169 << _containerName.c_str() << " machineName "
170 << GetHostname().c_str());
174 Engines::Container_ptr Engines_Container_i::start_impl(
175 const char* ContainerName ) {
176 MESSAGE("start_impl argc " << _argc << " ContainerName " << ContainerName
177 << hex << this << dec) ;
178 _numInstanceMutex.lock() ; // lock on the instance number
180 CORBA::Object_var obj = Engines::Container::_nil() ;
183 string cont("/Containers/");
184 cont += machineName() ;
186 cont += ContainerName;
187 INFOS(machineName() << " start_impl unknown container " << cont.c_str()
188 << " try to Resolve" );
189 obj = _NS->Resolve( cont.c_str() );
190 nilvar = CORBA::is_nil( obj ) ;
192 INFOS(machineName() << " start_impl unknown container "
196 catch (ServiceUnreachable&) {
197 INFOS(machineName() << "Caught exception: Naming Service Unreachable");
200 INFOS(machineName() << "Caught unknown exception.");
203 _numInstanceMutex.unlock() ;
204 MESSAGE("start_impl container found without runSession") ;
205 return Engines::Container::_narrow(obj);
208 while ( _argv[ i ] ) {
209 MESSAGE(" argv" << i << " " << _argv[ i ]) ;
212 // string shstr( "rsh -n " ) ;
213 // shstr += machineName() ;
215 // shstr += _argv[ 0 ] ;
216 // string shstr( _argv[ 0 ] ) ;
217 string shstr( "./runSession SALOME_Container " ) ;
218 shstr += ContainerName ;
221 shstr += _argv[ 2 ] ;
223 shstr += _argv[ 3 ] ;
225 shstr += " > /tmp/" ;
226 shstr += ContainerName ;
227 shstr += ".log 2>&1 &" ;
228 MESSAGE("system(" << shstr << ")") ;
229 int status = system( shstr.c_str() ) ;
231 INFOS("Engines_Container_i::start_impl runSession(SALOME_Container) failed (system command status -1)") ;
233 else if (status == 217) {
234 INFOS("Engines_Container_i::start_impl runSession(SALOME_Container) failed (system command status 217)") ;
236 INFOS(machineName() << " Engines_Container_i::start_impl runSession(SALOME_Container) done");
240 string anExe( _argv[ 0 ] ) ;
241 anExe += "runSession" ;
243 args[ 0 ] = "runSession" ;
244 args[ 1 ] = "SALOME_Container" ;
245 args[ 2 ] = strdup( ContainerName ) ;
246 args[ 3 ] = strdup( _argv[ 2 ] ) ;
247 args[ 4 ] = strdup( _argv[ 3 ] ) ;
249 MESSAGE("execl(" << anExe.c_str() << " , " << args[ 0 ] << " , "
250 << args[ 1 ] << " , " << args[ 2 ] << " , " << args[ 3 ]
251 << " , " << args[ 4 ] << ")") ;
252 int status = execv( anExe.c_str() , args ) ;
254 INFOS("Engines_Container_i::start_impl execl failed (system command status -1)") ;
255 perror( "Engines_Container_i::start_impl execl error ") ;
258 INFOS(machineName() << " Engines_Container_i::start_impl execl done");
264 obj = Engines::Container::_nil() ;
266 string cont("/Containers/");
267 cont += machineName() ;
269 cont += ContainerName;
272 while ( nilvar && count >= 0) {
274 obj = _NS->Resolve(cont.c_str());
275 nilvar = CORBA::is_nil( obj ) ;
277 INFOS(count << ". " << machineName()
278 << " start_impl unknown container " << cont.c_str());
282 _numInstanceMutex.unlock() ;
284 MESSAGE("start_impl container found after runSession(SALOME_Container)") ;
286 return Engines::Container::_narrow(obj);
288 catch (ServiceUnreachable&) {
289 INFOS(machineName() << "Caught exception: Naming Service Unreachable");
292 INFOS(machineName() << "Caught unknown exception.");
294 _numInstanceMutex.unlock() ;
295 MESSAGE("start_impl container not found after runSession(SALOME_Container)") ;
296 return Engines::Container::_nil() ;
299 Engines::Component_ptr Engines_Container_i::load_impl
300 (const char* nameToRegister,
301 const char* componentName)
303 BEGIN_OF("Container_i::load_impl");
305 _numInstanceMutex.lock() ; // lock on the instance number
308 sprintf(_aNumI,"%d",_numInstance) ;
310 string _impl_name = componentName;
311 string _nameToRegister = nameToRegister;
312 string instanceName = _nameToRegister + "_inst_" + _aNumI ;
313 //SCRUTE(instanceName);
315 //string absolute_impl_name = _library_path + "lib" + _impl_name + ".so";
316 string absolute_impl_name(_impl_name);
317 // SCRUTE(absolute_impl_name);
319 handle = dlopen(absolute_impl_name.c_str(), RTLD_LAZY);
322 INFOS("Can't load shared library : " << absolute_impl_name);
323 INFOS("error dlopen: " << dlerror());
324 _numInstanceMutex.unlock() ;
325 return Engines::Component::_nil() ;
328 string factory_name = _nameToRegister + string("Engine_factory");
329 // SCRUTE(factory_name) ;
331 typedef PortableServer::ObjectId * (*FACTORY_FUNCTION)
333 PortableServer::POA_ptr,
334 PortableServer::ObjectId *,
337 // typedef PortableServer::ObjectId * (*FACTORY_FUNCTION_SUPERV)
339 // PortableServer::POA_ptr,
340 // PortableServer::ObjectId *,
345 FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
346 // FACTORY_FUNCTION_SUPERV Component_factory_superv = (FACTORY_FUNCTION_SUPERV) Component_factory ;
348 // PortableServer::ObjectId * (*Component_factory) (CORBA::ORB_ptr,
349 // PortableServer::POA_ptr,
350 // PortableServer::ObjectId *,
353 // (PortableServer::ObjectId * (*) (CORBA::ORB_ptr,
354 // PortableServer::POA_ptr,
355 // PortableServer::ObjectId *,
358 // dlsym(handle, factory_name.c_str());
361 if ((error = dlerror()) != NULL)
363 INFOS("Can't resolve symbol: " + factory_name);
365 _numInstanceMutex.unlock() ;
366 return Engines::Component::_nil() ;
369 // Instanciate required CORBA object
370 PortableServer::ObjectId * id ;
371 // if ( factory_name == "SupervisionEngine_factory" ) { // for Python ...
372 // id = (Component_factory_superv) (_orb, _poa, _id, instanceName.c_str(),
373 // _nameToRegister.c_str(), _argc , _argv );
376 id = (Component_factory) (_orb, _poa, _id, instanceName.c_str(),
377 _nameToRegister.c_str());
379 // get reference from id
380 CORBA::Object_var o = _poa->id_to_reference(*id);
381 Engines::Component_var iobject = Engines::Component::_narrow(o) ;
383 // _numInstanceMutex.lock() ; // lock on the add on handle_map (necessary ?)
384 // register the engine under the name containerName.dir/nameToRegister.object
385 string component_registerName = _containerName + "/" + _nameToRegister;
386 _NS->Register(iobject, component_registerName.c_str()) ;
388 //Jr _numInstanceMutex.lock() ; // lock on the add on handle_map (necessary ?)
389 handle_map[instanceName] = handle;
390 _numInstanceMutex.unlock() ;
391 // END_OF("Container_i::load_impl");
392 return Engines::Component::_duplicate(iobject);
395 void Engines_Container_i::remove_impl(Engines::Component_ptr component_i)
397 ASSERT(! CORBA::is_nil(component_i));
398 string instanceName = component_i->instanceName() ;
399 MESSAGE("unload component " << instanceName);
400 component_i->destroy() ;
401 MESSAGE("test key handle_map");
402 _numInstanceMutex.lock() ; // lock on the remove on handle_map
403 if (handle_map[instanceName]) // if key does not exist, created & initialized null
405 remove_map[instanceName] = handle_map[instanceName] ;
407 else MESSAGE("pas d'entree handle_map");
408 handle_map.erase(instanceName) ;
409 _numInstanceMutex.unlock() ;
410 MESSAGE("contenu handle_map");
411 map<string, void *>::iterator im ;
412 for (im = handle_map.begin() ; im != handle_map.end() ; im ++)
414 MESSAGE("reste " << (*im).first);
418 void Engines_Container_i::finalize_removal()
420 MESSAGE("finalize unload : dlclose");
421 map<string, void *>::iterator im ;
422 _numInstanceMutex.lock() ; // lock on the explore remove_map & dlclose
423 for (im = remove_map.begin() ; im != remove_map.end() ; im ++)
425 void * handle = (*im).second ;
427 MESSAGE("dlclose " << (*im).first);
430 _numInstanceMutex.unlock() ;
431 MESSAGE("remove_map.clear()");
434 void ActSigIntHandler() {
435 struct sigaction SigIntAct ;
436 SigIntAct.sa_sigaction = &SigIntHandler ;
437 SigIntAct.sa_flags = SA_SIGINFO ;
438 if ( sigaction( SIGINT , &SigIntAct, NULL ) ) {
439 perror("SALOME_Container main ") ;
443 INFOS("SigIntHandler activated") ;
447 void SigIntHandler(int what , siginfo_t * siginfo ,
449 MESSAGE("SigIntHandler what " << what << endl
450 << " si_signo " << siginfo->si_signo << endl
451 << " si_code " << siginfo->si_code << endl
452 << " si_pid " << siginfo->si_pid) ;
455 INFOS("SigIntHandler END sleeping.")
456 MESSAGE("SigIntHandler END sleeping.") ;
462 INFOS("SigIntHandler BEGIN sleeping.")
463 MESSAGE("SigIntHandler BEGIN sleeping.") ;
469 INFOS("SigIntHandler LEAVE sleeping after " << count << " s.")
470 MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;