]> SALOME platform Git repositories - modules/yacs.git/blob - src/Container/Container_i.cxx
Salome HOME
sources v1.2
[modules/yacs.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
62   ActSigIntHandler() ;
63
64   _ArgC = argc ;
65   _ArgV = argv ;
66
67   _argc = argc ;
68   _argv = argv ;
69   int i = strlen( _argv[ 0 ] ) - 1 ;
70   while ( i >= 0 ) {
71     if ( _argv[ 0 ][ i ] == '/' ) {
72       _argv[ 0 ][ i+1 ] = '\0' ;
73       break ;
74     }
75     i -= 1 ;
76   }
77   string hostname = GetHostname();
78   MESSAGE(hostname << " " << getpid() << " Engines_Container_i starting argc "
79           << _argc << " Thread " << pthread_self() ) ;
80   i = 0 ;
81   while ( _argv[ i ] ) {
82     MESSAGE("           argv" << i << " " << _argv[ i ]) ;
83     i++ ;
84   }
85   if ( argc != 4 ) {
86     MESSAGE("SALOME_Container usage : SALOME_Container ServerName -ORBInitRef NameService=corbaname::hostname:tcpipPortNumber") ;
87 //    exit(0) ;
88   }
89
90   SCRUTE(hostname);
91
92   _containerName = "/Containers/";
93   if (strlen(containerName)== 0)
94     {
95       _containerName += hostname;
96     }
97   else
98     {
99       _containerName += hostname;
100       _containerName += "/" ;
101       _containerName += containerName;
102     }
103
104   _orb = CORBA::ORB::_duplicate(orb) ;
105   _poa = PortableServer::POA::_duplicate(poa) ;
106   MESSAGE("activate object");
107   _id = _poa->activate_object(this);
108
109 //   _NS = new SALOME_NamingService(_orb);
110   _NS = SINGLETON_<SALOME_NamingService>::Instance() ;
111   ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
112   _NS->init_orb( orb ) ;
113
114   Engines::Container_ptr pCont 
115     = Engines::Container::_narrow(_this());
116   SCRUTE(_containerName);
117   _NS->Register(pCont, _containerName.c_str()); 
118 }
119
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,
123                                           char *containerName,
124                                           int flag ) 
125   : _numInstance(0)
126 {
127   string hostname = GetHostname();
128   SCRUTE(hostname);
129
130   _containerName = "/Containers/";
131   if (strlen(containerName)== 0)
132     {
133       _containerName += hostname;
134     }
135   else
136     {
137       _containerName += containerName;
138     }
139
140   _orb = CORBA::ORB::_duplicate(orb) ;
141   _poa = PortableServer::POA::_duplicate(poa) ;
142
143 }
144
145 Engines_Container_i::~Engines_Container_i()
146 {
147   MESSAGE("Container_i::~Container_i()");
148 }
149
150 char* Engines_Container_i::name()
151 {
152    return CORBA::string_dup(_containerName.c_str()) ;
153 }
154
155 char* Engines_Container_i::machineName()
156 {
157   string s = GetHostname();
158   MESSAGE("Engines_Container_i::machineName " << s);
159    return CORBA::string_dup(s.c_str()) ;
160 }
161
162 void Engines_Container_i::ping()
163 {
164   MESSAGE("Engines_Container_i::ping() pid "<< getpid());
165 }
166
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());
171   exit( 0 ) ;
172 }
173
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
179
180   CORBA::Object_var obj = Engines::Container::_nil() ;
181   bool nilvar = true ;
182   try {
183     string cont("/Containers/");
184     cont += machineName() ;
185     cont += "/" ;
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 ) ;
191     if ( nilvar ) {
192       INFOS(machineName() << " start_impl unknown container "
193             << ContainerName);
194     }
195   }
196   catch (ServiceUnreachable&) {
197     INFOS(machineName() << "Caught exception: Naming Service Unreachable");
198   }
199   catch (...) {
200     INFOS(machineName() << "Caught unknown exception.");
201   }
202   if ( !nilvar ) {
203     _numInstanceMutex.unlock() ;
204     MESSAGE("start_impl container found without runSession") ;
205     return Engines::Container::_narrow(obj);
206   }
207   int i = 0 ;
208   while ( _argv[ i ] ) {
209     MESSAGE("           argv" << i << " " << _argv[ i ]) ;
210     i++ ;
211   }
212 //  string shstr( "rsh -n " ) ;
213 //  shstr += machineName() ;
214 //  shstr += " " ;
215 //  shstr += _argv[ 0 ] ;
216 //  string shstr( _argv[ 0 ] ) ;
217   string shstr( "./runSession SALOME_Container " ) ;
218   shstr += ContainerName ;
219   if ( _argc == 4 ) {
220     shstr += " " ;
221     shstr += _argv[ 2 ] ;
222     shstr += " " ;
223     shstr += _argv[ 3 ] ;
224   }
225   shstr += " > /tmp/" ;
226   shstr += ContainerName ;
227   shstr += ".log 2>&1 &" ;
228   MESSAGE("system(" << shstr << ")") ;
229   int status = system( shstr.c_str() ) ;
230   if (status == -1) {
231     INFOS("Engines_Container_i::start_impl runSession(SALOME_Container) failed (system command status -1)") ;
232   }
233   else if (status == 217) {
234     INFOS("Engines_Container_i::start_impl runSession(SALOME_Container) failed (system command status 217)") ;
235   }
236   INFOS(machineName() << " Engines_Container_i::start_impl runSession(SALOME_Container) done");
237 #if 0
238   pid_t pid = fork() ;
239   if ( pid == 0 ) {
240     string anExe( _argv[ 0 ] ) ;
241     anExe += "runSession" ;
242     char * args[ 6 ] ;
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 ] ) ;
248     args[ 5 ] = NULL ;
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 ) ;
253     if (status == -1) {
254       INFOS("Engines_Container_i::start_impl execl failed (system command status -1)") ;
255       perror( "Engines_Container_i::start_impl execl error ") ;
256     }
257     else {
258       INFOS(machineName() << " Engines_Container_i::start_impl execl done");
259     }
260     exit(0) ;
261   }
262 #endif
263
264   obj = Engines::Container::_nil() ;
265   try {
266     string cont("/Containers/");
267     cont += machineName() ;
268     cont += "/" ;
269     cont += ContainerName;
270     nilvar = true ;
271     int count = 20 ;
272     while ( nilvar && count >= 0) {
273       sleep( 1 ) ;
274       obj = _NS->Resolve(cont.c_str());
275       nilvar = CORBA::is_nil( obj ) ;
276       if ( nilvar ) {
277         INFOS(count << ". " << machineName()
278               << " start_impl unknown container " << cont.c_str());
279         count -= 1 ;
280       }
281     }
282     _numInstanceMutex.unlock() ;
283     if ( !nilvar ) {
284       MESSAGE("start_impl container found after runSession(SALOME_Container)") ;
285     }
286     return Engines::Container::_narrow(obj);
287   }
288   catch (ServiceUnreachable&) {
289     INFOS(machineName() << "Caught exception: Naming Service Unreachable");
290   }
291   catch (...) {
292     INFOS(machineName() << "Caught unknown exception.");
293   }
294   _numInstanceMutex.unlock() ;
295   MESSAGE("start_impl container not found after runSession(SALOME_Container)") ;
296   return Engines::Container::_nil() ;
297 }
298
299 Engines::Component_ptr Engines_Container_i::load_impl
300          (const char* nameToRegister,
301           const char* componentName)
302 {
303   BEGIN_OF("Container_i::load_impl");
304
305   _numInstanceMutex.lock() ; // lock on the instance number
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     {
322       INFOS("Can't load shared library : " << absolute_impl_name);
323       INFOS("error dlopen: " << dlerror());
324       _numInstanceMutex.unlock() ;
325       return Engines::Component::_nil() ;
326     }
327   
328   string factory_name = _nameToRegister + string("Engine_factory");
329   //  SCRUTE(factory_name) ;
330
331   typedef  PortableServer::ObjectId * (*FACTORY_FUNCTION)
332                             (CORBA::ORB_ptr,
333                              PortableServer::POA_ptr, 
334                              PortableServer::ObjectId *, 
335                              const char *, 
336                              const char *) ; 
337 //  typedef  PortableServer::ObjectId * (*FACTORY_FUNCTION_SUPERV)
338 //                            (CORBA::ORB_ptr,
339 //                           PortableServer::POA_ptr, 
340 //                           PortableServer::ObjectId *, 
341 //                           const char *, 
342 //                           const char * ,
343 //                             int , char ** ) ; 
344
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 ;
347
348 //   PortableServer::ObjectId * (*Component_factory) (CORBA::ORB_ptr,
349 //                                                 PortableServer::POA_ptr,
350 //                                                 PortableServer::ObjectId *,
351 //                                                 const char *,
352 //                                                 const char *) =
353 //     (PortableServer::ObjectId * (*) (CORBA::ORB_ptr,
354 //                                   PortableServer::POA_ptr, 
355 //                                   PortableServer::ObjectId *, 
356 //                                   const char *, 
357 //                                   const char *)) 
358 //     dlsym(handle, factory_name.c_str());
359
360   char *error ;
361   if ((error = dlerror()) != NULL)
362     {
363       INFOS("Can't resolve symbol: " + factory_name);
364       SCRUTE(error);
365       _numInstanceMutex.unlock() ;
366       return Engines::Component::_nil() ;
367     }
368
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 );
374 //  }
375 //  else {
376     id = (Component_factory) (_orb, _poa, _id, instanceName.c_str(),
377                               _nameToRegister.c_str());
378 //  }
379   // get reference from id
380   CORBA::Object_var o = _poa->id_to_reference(*id);
381   Engines::Component_var iobject = Engines::Component::_narrow(o) ;
382
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()) ;
387
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);
393 }
394
395 void Engines_Container_i::remove_impl(Engines::Component_ptr component_i)
396 {
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
404     {
405       remove_map[instanceName] = handle_map[instanceName] ;
406     }
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 ++)
413     {
414       MESSAGE("reste " << (*im).first);
415     }
416 }
417
418 void Engines_Container_i::finalize_removal()
419 {
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 ++)
424     {
425       void * handle = (*im).second ;
426       dlclose(handle) ;
427       MESSAGE("dlclose " << (*im).first);
428     }
429   remove_map.clear() ;  
430   _numInstanceMutex.unlock() ;
431   MESSAGE("remove_map.clear()");
432 }
433
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 ") ;
440     exit(0) ;
441   }
442   else {
443     INFOS("SigIntHandler activated") ;
444   }
445 }
446
447 void SigIntHandler(int what , siginfo_t * siginfo ,
448                                         void * toto ) {
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) ;
453   if ( _Sleeping ) {
454     _Sleeping = false ;
455     INFOS("SigIntHandler END sleeping.")
456     MESSAGE("SigIntHandler END sleeping.") ;
457     return ;
458   }
459   else {
460     ActSigIntHandler() ;
461     _Sleeping = true ;
462     INFOS("SigIntHandler BEGIN sleeping.")
463     MESSAGE("SigIntHandler BEGIN sleeping.") ;
464     int count = 0 ;
465     while( _Sleeping ) {
466       sleep( 1 ) ;
467       count += 1 ;
468     }
469     INFOS("SigIntHandler LEAVE sleeping after " << count << " s.")
470     MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
471     return ;
472   }
473 }