Salome HOME
NRI : Check if a component-username is already associated with a component-name.
[modules/kernel.git] / src / Container / Container_i.cxx
1 using namespace std;
2 //=============================================================================
3 // File      : Container_i.cxx
4 // Created   : jeu jui 12 08:04:40 CEST 2001
5 // Author    : Paul RASCLE, EDF - MARC TAJCHMAN, CEA 
6 // Project   : SALOME
7 // Copyright : EDF 2001 - CEA 2001
8 // $Header$
9 //=============================================================================
10
11 #include <SALOMEconfig.h>
12 #include CORBA_SERVER_HEADER(SALOME_Component)
13 #include "SALOME_Container_i.hxx"
14 #include "SALOME_NamingService.hxx"
15 #include "Utils_SINGLETON.hxx"
16 #include "OpUtil.hxx"
17 #include <stdio.h>
18 #include <dlfcn.h>
19 #include <unistd.h>
20
21 #include "utilities.h"
22
23 bool _Sleeping = false ;
24
25 // Containers with name FactoryServer are started via rsh in LifeCycleCORBA
26 // Other Containers are started via start_impl of FactoryServer
27
28 extern "C" {void ActSigIntHandler() ; }
29 extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; }
30
31 Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb, 
32                                           PortableServer::POA_ptr poa,
33                                           char *containerName ,
34                                           int argc , char* argv[] ) :
35  _numInstance(0)
36 {
37
38   ActSigIntHandler() ;
39
40   _argc = argc ;
41   _argv = argv ;
42   int i = strlen( _argv[ 0 ] ) - 1 ;
43   while ( i >= 0 ) {
44     if ( _argv[ 0 ][ i ] == '/' ) {
45       _argv[ 0 ][ i+1 ] = '\0' ;
46       break ;
47     }
48     i -= 1 ;
49   }
50   string hostname = GetHostname();
51   MESSAGE(hostname << " " << getpid() << " Engines_Container_i starting argc "
52           << _argc) ;
53   i = 0 ;
54   while ( _argv[ i ] ) {
55     MESSAGE("           argv" << i << " " << _argv[ i ]) ;
56     i++ ;
57   }
58   if ( argc != 4 ) {
59     MESSAGE("SALOME_Container usage : SALOME_Container ServerName -ORBInitRef NameService=corbaname::hostname:tcpipPortNumber") ;
60 //    exit(0) ;
61   }
62
63   SCRUTE(hostname);
64
65   _containerName = "/Containers/";
66   if (strlen(containerName)== 0)
67     {
68       _containerName += hostname;
69     }
70   else
71     {
72       _containerName += hostname;
73       _containerName += "/" ;
74       _containerName += containerName;
75     }
76
77   _orb = CORBA::ORB::_duplicate(orb) ;
78   _poa = PortableServer::POA::_duplicate(poa) ;
79   MESSAGE("activate object");
80   _id = _poa->activate_object(this);
81
82 //   _NS = new SALOME_NamingService(_orb);
83   _NS = SINGLETON_<SALOME_NamingService>::Instance() ;
84   ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
85   _NS->init_orb( orb ) ;
86
87   Engines::Container_ptr pCont 
88     = Engines::Container::_narrow(_this());
89   SCRUTE(_containerName);
90   _NS->Register(pCont, _containerName.c_str()); 
91 }
92
93 // Constructeur pour composant parallele : ne pas faire appel au naming service
94 Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb, 
95                                           PortableServer::POA_ptr poa,
96                                           char *containerName,
97                                           int flag ) 
98   : _numInstance(0)
99 {
100   string hostname = GetHostname();
101   SCRUTE(hostname);
102
103   _containerName = "/Containers/";
104   if (strlen(containerName)== 0)
105     {
106       _containerName += hostname;
107     }
108   else
109     {
110       _containerName += containerName;
111     }
112
113   _orb = CORBA::ORB::_duplicate(orb) ;
114   _poa = PortableServer::POA::_duplicate(poa) ;
115
116 }
117
118 Engines_Container_i::~Engines_Container_i()
119 {
120   MESSAGE("Container_i::~Container_i()");
121 }
122
123 char* Engines_Container_i::name()
124 {
125    return CORBA::string_dup(_containerName.c_str()) ;
126 }
127
128 char* Engines_Container_i::machineName()
129 {
130   string s = GetHostname();
131   MESSAGE("Engines_Container_i::machineName " << s);
132    return CORBA::string_dup(s.c_str()) ;
133 }
134
135 void Engines_Container_i::ping()
136 {
137   MESSAGE("Engines_Container_i::ping() pid "<< getpid());
138 }
139
140 bool Engines_Container_i::Kill_impl() {
141   MESSAGE("Engines_Container_i::Kill() pid "<< getpid() << " containerName "
142           << _containerName.c_str() << " machineName "
143           << GetHostname().c_str());
144   exit( 0 ) ;
145 }
146
147 Engines::Container_ptr Engines_Container_i::start_impl(
148                                       const char* ContainerName ) {
149   MESSAGE("start_impl argc " << _argc << " ContainerName " << ContainerName
150           << hex << this << dec) ;
151   _numInstanceMutex.lock() ; // lock on the instance number
152
153   CORBA::Object_var obj = Engines::Container::_nil() ;
154   bool nilvar = true ;
155   try {
156     string cont("/Containers/");
157     cont += machineName() ;
158     cont += "/" ;
159     cont += ContainerName;
160     INFOS(machineName() << " start_impl unknown container " << cont.c_str()
161           << " try to Resolve" );
162     obj = _NS->Resolve( cont.c_str() );
163     nilvar = CORBA::is_nil( obj ) ;
164     if ( nilvar ) {
165       INFOS(machineName() << " start_impl unknown container "
166             << ContainerName);
167     }
168   }
169   catch (ServiceUnreachable&) {
170     INFOS(machineName() << "Caught exception: Naming Service Unreachable");
171   }
172   catch (...) {
173     INFOS(machineName() << "Caught unknown exception.");
174   }
175   if ( !nilvar ) {
176     _numInstanceMutex.unlock() ;
177     MESSAGE("start_impl container found without runSession") ;
178     return Engines::Container::_narrow(obj);
179   }
180   int i = 0 ;
181   while ( _argv[ i ] ) {
182     MESSAGE("           argv" << i << " " << _argv[ i ]) ;
183     i++ ;
184   }
185 //  string shstr( "rsh -n " ) ;
186 //  shstr += machineName() ;
187 //  shstr += " " ;
188 //  shstr += _argv[ 0 ] ;
189 //  string shstr( _argv[ 0 ] ) ;
190   string shstr( "./runSession SALOME_Container " ) ;
191   shstr += ContainerName ;
192   if ( _argc == 4 ) {
193     shstr += " " ;
194     shstr += _argv[ 2 ] ;
195     shstr += " " ;
196     shstr += _argv[ 3 ] ;
197   }
198   shstr += " > /tmp/" ;
199   shstr += ContainerName ;
200   shstr += ".log 2>&1 &" ;
201   MESSAGE("system(" << shstr << ")") ;
202   int status = system( shstr.c_str() ) ;
203   if (status == -1) {
204     INFOS("Engines_Container_i::start_impl runSession(SALOME_Container) failed (system command status -1)") ;
205   }
206   else if (status == 217) {
207     INFOS("Engines_Container_i::start_impl runSession(SALOME_Container) failed (system command status 217)") ;
208   }
209   INFOS(machineName() << " Engines_Container_i::start_impl runSession(SALOME_Container) done");
210 #if 0
211   pid_t pid = fork() ;
212   if ( pid == 0 ) {
213     string anExe( _argv[ 0 ] ) ;
214     anExe += "runSession" ;
215     char * args[ 6 ] ;
216     args[ 0 ] = "runSession" ;
217     args[ 1 ] = "SALOME_Container" ;
218     args[ 2 ] = strdup( ContainerName ) ;
219     args[ 3 ] = strdup( _argv[ 2 ] ) ;
220     args[ 4 ] = strdup( _argv[ 3 ] ) ;
221     args[ 5 ] = NULL ;
222     MESSAGE("execl(" << anExe.c_str() << " , " << args[ 0 ] << " , "
223                      << args[ 1 ] << " , " << args[ 2 ] << " , " << args[ 3 ]
224                      << " , " << args[ 4 ] << ")") ;
225     int status = execv( anExe.c_str() , args ) ;
226     if (status == -1) {
227       INFOS("Engines_Container_i::start_impl execl failed (system command status -1)") ;
228       perror( "Engines_Container_i::start_impl execl error ") ;
229     }
230     else {
231       INFOS(machineName() << " Engines_Container_i::start_impl execl done");
232     }
233     exit(0) ;
234   }
235 #endif
236
237   obj = Engines::Container::_nil() ;
238   try {
239     string cont("/Containers/");
240     cont += machineName() ;
241     cont += "/" ;
242     cont += ContainerName;
243     nilvar = true ;
244     int count = 20 ;
245     while ( nilvar && count >= 0) {
246       sleep( 1 ) ;
247       obj = _NS->Resolve(cont.c_str());
248       nilvar = CORBA::is_nil( obj ) ;
249       if ( nilvar ) {
250         INFOS(count << ". " << machineName()
251               << " start_impl unknown container " << cont.c_str());
252         count -= 1 ;
253       }
254     }
255     _numInstanceMutex.unlock() ;
256     if ( !nilvar ) {
257       MESSAGE("start_impl container found after runSession(SALOME_Container)") ;
258     }
259     return Engines::Container::_narrow(obj);
260   }
261   catch (ServiceUnreachable&) {
262     INFOS(machineName() << "Caught exception: Naming Service Unreachable");
263   }
264   catch (...) {
265     INFOS(machineName() << "Caught unknown exception.");
266   }
267   _numInstanceMutex.unlock() ;
268   MESSAGE("start_impl container not found after runSession(SALOME_Container)") ;
269   return Engines::Container::_nil() ;
270 }
271
272 Engines::Component_ptr Engines_Container_i::load_impl
273          (const char* nameToRegister,
274           const char* componentName)
275 {
276   BEGIN_OF("Container_i::load_impl");
277
278   _numInstanceMutex.lock() ; // lock on the instance number
279   _numInstance++ ;
280   char _aNumI[12];
281   sprintf(_aNumI,"%d",_numInstance) ;
282
283   string _impl_name = componentName;
284   string _nameToRegister = nameToRegister;
285   string instanceName = _nameToRegister + "_inst_" + _aNumI ;
286   //SCRUTE(instanceName);
287
288   //string absolute_impl_name = _library_path + "lib" + _impl_name + ".so";
289   string absolute_impl_name(_impl_name);
290   //  SCRUTE(absolute_impl_name);
291   void* handle;
292   handle = dlopen(absolute_impl_name.c_str(), RTLD_LAZY);
293   if (!handle)
294     {
295       INFOS("Can't load shared library : " << absolute_impl_name);
296       INFOS("error dlopen: " << dlerror());
297       _numInstanceMutex.unlock() ;
298       return Engines::Component::_nil() ;
299     }
300   
301   string factory_name = _nameToRegister + string("Engine_factory");
302   //  SCRUTE(factory_name) ;
303
304   typedef  PortableServer::ObjectId * (*FACTORY_FUNCTION)
305                             (CORBA::ORB_ptr,
306                              PortableServer::POA_ptr, 
307                              PortableServer::ObjectId *, 
308                              const char *, 
309                              const char *) ; 
310 //  typedef  PortableServer::ObjectId * (*FACTORY_FUNCTION_SUPERV)
311 //                            (CORBA::ORB_ptr,
312 //                           PortableServer::POA_ptr, 
313 //                           PortableServer::ObjectId *, 
314 //                           const char *, 
315 //                           const char * ,
316 //                             int , char ** ) ; 
317
318   FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
319 //  FACTORY_FUNCTION_SUPERV Component_factory_superv = (FACTORY_FUNCTION_SUPERV) Component_factory ;
320
321 //   PortableServer::ObjectId * (*Component_factory) (CORBA::ORB_ptr,
322 //                                                 PortableServer::POA_ptr,
323 //                                                 PortableServer::ObjectId *,
324 //                                                 const char *,
325 //                                                 const char *) =
326 //     (PortableServer::ObjectId * (*) (CORBA::ORB_ptr,
327 //                                   PortableServer::POA_ptr, 
328 //                                   PortableServer::ObjectId *, 
329 //                                   const char *, 
330 //                                   const char *)) 
331 //     dlsym(handle, factory_name.c_str());
332
333   char *error ;
334   if ((error = dlerror()) != NULL)
335     {
336       INFOS("Can't resolve symbol: " + factory_name);
337       SCRUTE(error);
338       _numInstanceMutex.unlock() ;
339       return Engines::Component::_nil() ;
340     }
341
342   // Instanciate required CORBA object
343   PortableServer::ObjectId * id ;
344 //  if ( factory_name == "SupervisionEngine_factory" ) { // for Python ...
345 //    id = (Component_factory_superv) (_orb, _poa, _id, instanceName.c_str(),
346 //                                     _nameToRegister.c_str(), _argc , _argv );
347 //  }
348 //  else {
349     id = (Component_factory) (_orb, _poa, _id, instanceName.c_str(),
350                               _nameToRegister.c_str());
351 //  }
352   // get reference from id
353   CORBA::Object_var o = _poa->id_to_reference(*id);
354   Engines::Component_var iobject = Engines::Component::_narrow(o) ;
355
356 //  _numInstanceMutex.lock() ; // lock on the add on handle_map (necessary ?)
357   // register the engine under the name containerName.dir/nameToRegister.object
358   string component_registerName = _containerName + "/" + _nameToRegister;
359   _NS->Register(iobject, component_registerName.c_str()) ;
360
361 //Jr  _numInstanceMutex.lock() ; // lock on the add on handle_map (necessary ?)
362   handle_map[instanceName] = handle;
363   _numInstanceMutex.unlock() ;
364 //  END_OF("Container_i::load_impl");
365   return Engines::Component::_duplicate(iobject);
366 }
367
368 void Engines_Container_i::remove_impl(Engines::Component_ptr component_i)
369 {
370   ASSERT(! CORBA::is_nil(component_i));
371   string instanceName = component_i->instanceName() ;
372   MESSAGE("unload component " << instanceName);
373   component_i->destroy() ;
374   MESSAGE("test key handle_map");
375   _numInstanceMutex.lock() ; // lock on the remove on handle_map
376   if (handle_map[instanceName]) // if key does not exist, created & initialized null
377     {
378       remove_map[instanceName] = handle_map[instanceName] ;
379     }
380   else MESSAGE("pas d'entree handle_map");
381   handle_map.erase(instanceName) ;   
382   _numInstanceMutex.unlock() ;
383   MESSAGE("contenu handle_map");
384   map<string, void *>::iterator im ;
385   for (im = handle_map.begin() ; im != handle_map.end() ; im ++)
386     {
387       MESSAGE("reste " << (*im).first);
388     }
389 }
390
391 void Engines_Container_i::finalize_removal()
392 {
393   MESSAGE("finalize unload : dlclose");
394   map<string, void *>::iterator im ;
395   _numInstanceMutex.lock() ; // lock on the explore remove_map & dlclose
396   for (im = remove_map.begin() ; im != remove_map.end() ; im ++)
397     {
398       void * handle = (*im).second ;
399       dlclose(handle) ;
400       MESSAGE("dlclose " << (*im).first);
401     }
402   remove_map.clear() ;  
403   _numInstanceMutex.unlock() ;
404   MESSAGE("remove_map.clear()");
405 }
406
407 void ActSigIntHandler() {
408   struct sigaction SigIntAct ;
409   SigIntAct.sa_sigaction = &SigIntHandler ;
410   SigIntAct.sa_flags = SA_SIGINFO ;
411   if ( sigaction( SIGINT , &SigIntAct, NULL ) ) {
412     perror("SALOME_Container main ") ;
413     exit(0) ;
414   }
415   else {
416     INFOS("SigIntHandler activated") ;
417   }
418 }
419
420 void SigIntHandler(int what , siginfo_t * siginfo ,
421                                         void * toto ) {
422   MESSAGE("SigIntHandler what     " << what << endl
423           << "              si_signo " << siginfo->si_signo << endl
424           << "              si_code  " << siginfo->si_code << endl
425           << "              si_pid   " << siginfo->si_pid) ;
426   if ( _Sleeping ) {
427     _Sleeping = false ;
428     INFOS("SigIntHandler END sleeping.")
429     MESSAGE("SigIntHandler END sleeping.") ;
430     return ;
431   }
432   else {
433     ActSigIntHandler() ;
434     _Sleeping = true ;
435     INFOS("SigIntHandler BEGIN sleeping.")
436     MESSAGE("SigIntHandler BEGIN sleeping.") ;
437     int count = 0 ;
438     while( _Sleeping ) {
439       sleep( 1 ) ;
440       count += 1 ;
441     }
442     INFOS("SigIntHandler LEAVE sleeping after " << count << " s.")
443     MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
444     return ;
445   }
446 }