Salome HOME
DCQ : Merge with Ecole_ete_a6.
[modules/kernel.git] / src / MPIContainer / MPIContainer_i.cxx
1 //  SALOME MPIContainer : implemenation of container based on MPI libraries
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   : MPIContainer_i.cxx
25 //  Module : SALOME
26
27 using namespace std;
28 #include <iostream.h>
29 #include <dlfcn.h>
30 #include <stdio.h>
31 #include "MPIContainer_i.hxx"
32 #include "utilities.h"
33
34 MPIContainer_i::MPIContainer_i(int nbproc, int numproc,
35                                CORBA::ORB_ptr orb, 
36                                PortableServer::POA_ptr poa,
37                                char * containerName) 
38   : Engines_Container_i(orb,poa,containerName,0), MPIObject_i(nbproc,numproc)
39 {
40   _id = _poa->activate_object(this);
41
42   MESSAGE("[" << _numproc << "] containerName=" << _containerName);
43   if( _numproc ==  0 ){
44     _NS = SINGLETON_<SALOME_NamingService>::Instance() ;
45     ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
46     _NS->init_orb( orb ) ;
47
48     Engines::Container_ptr pCont 
49       = Engines::Container::_narrow(POA_Engines::MPIContainer::_this());
50     _NS->Register(pCont, _containerName.c_str()); 
51   }
52
53   // Root recupere les ior des container des autre process
54   Engines::MPIObject_var pobj = POA_Engines::MPIContainer::_this();
55   BCastIOR(_orb,pobj,true);
56 }
57
58 MPIContainer_i::~MPIContainer_i(void)
59 {
60   if( !handle_map.empty() ){
61     MESSAGE("[" << _numproc << "] MPIContainer_i::~MPIContainer_i: warning destroy a not empty container");
62   }
63 }
64
65 // Load component
66 Engines::Component_ptr MPIContainer_i::load_impl(const char* nameToRegister,
67                                                  const char* componentName)
68 {
69   int ip;
70   Engines::Component_var iobject;
71   Engines::MPIObject_var pobj;
72   char cproc[4];
73
74   if( _numproc == 0 ){
75     // Invocation du chargement du composant dans les autres process
76     for(ip= 1;ip<_nbproc;ip++)
77       (Engines::MPIContainer::_narrow((*_tior)[ip]))->load_impl(nameToRegister,
78                                                                 componentName);
79   }
80
81   sprintf(cproc,"_%d",_numproc);
82
83   BEGIN_OF("[" << _numproc << "] MPIContainer_i::load_impl");
84
85   _numInstanceMutex.lock() ; // lock on the instance number
86   _numInstance++ ;
87   char _aNumI[12];
88   sprintf(_aNumI,"%d",_numInstance) ;
89   _numInstanceMutex.unlock() ;
90
91   string _impl_name = componentName;
92   string instanceName = string(nameToRegister) + "_inst_" + _aNumI + cproc;
93
94   string absolute_impl_name(_impl_name);
95   MESSAGE("[" << _numproc << "] absolute_impl_name=" << absolute_impl_name);
96   void * handle = dlopen(absolute_impl_name.c_str(), RTLD_LAZY);
97   if(!handle){
98     MESSAGE("[" << _numproc << "] Can't load shared library : " << absolute_impl_name);
99     MESSAGE("[" << _numproc << "] error dlopen: " << dlerror());
100     return Engines::Component::_nil() ;
101   }
102
103   string factory_name = string(nameToRegister) + string("Engine_factory");
104   MESSAGE("[" << _numproc << "] factory_name=" << factory_name) ;
105
106   PortableServer::ObjectId * (*MPIComponent_factory) (int,int,
107                                                   CORBA::ORB_ptr,
108                                                   PortableServer::POA_ptr,
109                                                   PortableServer::ObjectId *,
110                                                   const char *,
111                                                   const char *) =
112     (PortableServer::ObjectId * (*) (int,int,
113                                      CORBA::ORB_ptr,
114                                      PortableServer::POA_ptr, 
115                                      PortableServer::ObjectId *, 
116                                      const char *, 
117                                      const char *)) 
118     dlsym(handle, factory_name.c_str());
119
120   char *error ;
121   if ((error = dlerror()) != NULL){
122     // Try to load a sequential component
123     MESSAGE("[" << _numproc << "] Try to load a sequential component");
124     iobject = Engines_Container_i::load_impl(nameToRegister,componentName);
125     if( CORBA::is_nil(iobject) ) return Engines::Component::_duplicate(iobject);
126   }
127   else{
128     // Instanciation du composant parallele
129     MESSAGE("[" << _numproc << "] Try to load a parallel component");
130     PortableServer::ObjectId * id = (MPIComponent_factory)
131       (_nbproc,_numproc,_orb, _poa, _id, instanceName.c_str(), nameToRegister);
132     // get reference from id
133     CORBA::Object_var o = _poa->id_to_reference(*id);
134     pobj = Engines::MPIObject::_narrow(o) ;
135     iobject = Engines::Component::_narrow(pobj) ;
136   }
137
138   // Root recupere les ior des composants des autre process
139   BCastIOR(_orb,pobj,false);
140
141   if( _numproc == 0 ){
142     // utiliser + tard le registry ici :
143     // register the engine under the name containerName.dir/nameToRegister.object
144     string component_registerName = _containerName + "/" + nameToRegister;
145     _NS->Register(iobject, component_registerName.c_str()) ;
146   }
147
148   _numInstanceMutex.lock() ; // lock on the add on handle_map (necessary ?)
149   handle_map[instanceName] = handle;
150   _numInstanceMutex.unlock() ;
151   END_OF("[" <<_numproc << "] MPIContainer_i::load_impl");
152   return Engines::Component::_duplicate(iobject);
153
154 }
155
156 void MPIContainer_i::remove_impl(Engines::Component_ptr component_i)
157 {
158   int ip;
159   Engines::Component_ptr cptr;
160   Engines::MPIObject_ptr pcptr;
161   Engines::MPIObject_ptr spcptr;
162
163   ASSERT(! CORBA::is_nil(component_i));
164
165   if( _numproc == 0 ){
166     // Invocation de la destruction du composant dans les autres process
167     pcptr = (Engines::MPIObject_ptr)component_i;
168     for(ip= 1;ip<_nbproc;ip++){
169       spcptr = Engines::MPIObject::_narrow((*(pcptr->tior()))[ip]);
170       cptr = (Engines::Component_ptr)spcptr;
171       (Engines::MPIContainer::_narrow((*_tior)[ip]))->remove_impl(cptr);
172     }
173   }
174
175   string instanceName = component_i->instanceName() ;
176   MESSAGE("[" << _numproc << "] unload component " << instanceName);
177   component_i->destroy() ;
178   MESSAGE("[" << _numproc << "] test key handle_map");
179   _numInstanceMutex.lock() ; // lock on the remove on handle_map
180   if (handle_map[instanceName]) // if key does not exist, created & initialized null
181     {
182       remove_map[instanceName] = handle_map[instanceName] ;
183     }
184   else MESSAGE("[" << _numproc << "] no key handle_map");
185   handle_map.erase(instanceName) ;   
186   _numInstanceMutex.unlock() ;
187   MESSAGE("[" << _numproc << "] list handle_map");
188   map<string, void *>::iterator im ;
189   for (im = handle_map.begin() ; im != handle_map.end() ; im ++)
190     {
191       MESSAGE("[" << _numproc << "] stay " << (*im).first);
192     }
193 }
194
195 void MPIContainer_i::finalize_removal()
196 {
197   int ip;
198
199   MESSAGE("[" << _numproc << "] finalize unload : dlclose");
200
201   if( _numproc == 0 ){
202     // Invocation de la destruction du composant dans les autres process
203     for(ip= 1;ip<_nbproc;ip++)
204       (Engines::MPIContainer::_narrow((*_tior)[ip]))->finalize_removal();
205   }
206
207   map<string, void *>::iterator im ;
208   _numInstanceMutex.lock() ; // lock on the explore remove_map & dlclose
209   for (im = remove_map.begin() ; im != remove_map.end() ; im ++)
210     {
211       void * handle = (*im).second ;
212       dlclose(handle) ;
213       MESSAGE("[" << _numproc << "] dlclose " << (*im).first);
214     }
215   remove_map.clear() ;  
216   _numInstanceMutex.unlock() ;
217   MESSAGE("[" << _numproc << "] remove_map.clear()");
218 }