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