]> SALOME platform Git repositories - modules/kernel.git/blob - src/ParallelContainer/SALOME_ParallelContainerProxy_i.cxx
Salome HOME
Improve a little message readibility
[modules/kernel.git] / src / ParallelContainer / SALOME_ParallelContainerProxy_i.cxx
1 // Copyright (C) 2007-2024  CEA, EDF, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  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, or (at your option) any later version.
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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SALOME_ParallelContainerProxy : implementation of container and engine for Parallel Kernel
24 //  File   : SALOME_ParallelContainerProxy_i.cxx
25 //  Author : André RIBES, EDF
26 //
27 #include "SALOME_ParallelContainerProxy_i.hxx"
28
29 Container_proxy_impl_final::Container_proxy_impl_final(CORBA::ORB_ptr orb, 
30                                                        paco_fabrique_thread * fab_thread, 
31                                                        PortableServer::POA_ptr poa,
32                                                        std::string containerName,
33                                                        bool is_a_return_proxy) :
34   Engines::PACO_Container_proxy_impl(orb, fab_thread, is_a_return_proxy),
35   Engines::Container_proxy_impl(orb, fab_thread, is_a_return_proxy),
36   InterfaceManager_impl(orb, fab_thread, is_a_return_proxy)
37 {
38   _numInstance = 0;
39   _hostname = Kernel_Utils::GetHostname();
40   _containerName = _NS->BuildContainerNameForNS(containerName.c_str(), _hostname.c_str());
41   _poa = PortableServer::POA::_duplicate(poa);
42
43   _fab_thread = fab_thread;
44
45   // Add CORBA object to the poa
46   _id = _poa->activate_object(this);
47   this->_remove_ref();
48
49   // Init SALOME Naming Service
50   _NS = new SALOME_NamingService();
51   _NS->init_orb(_orb);
52
53   // Init Python container part
54   CORBA::Object_var container_node = _poa->id_to_reference(*_id);
55   CORBA::String_var sior =  _orb->object_to_string(container_node);
56   std::string myCommand="pyCont = SALOME_Container.SALOME_Container_i('";
57   myCommand += _containerName + "','";
58   myCommand += sior;
59   myCommand += "')\n";
60   {
61     AutoGIL agil;
62     PyRun_SimpleString("import SALOME_Container\n");
63     PyRun_SimpleString((char*)myCommand.c_str());
64   }
65 }
66
67 Container_proxy_impl_final:: ~Container_proxy_impl_final() {
68   if (_id)
69     delete _id;
70   if (_NS)
71     delete _NS;
72
73   // _fab_thread not deleted because fab_thread is managed
74   // by paco_fabrique_manager
75 }
76
77 void
78 Container_proxy_impl_final::Shutdown()
79 {
80   // We Start by destroying all the parallel object
81   std::list<Container_proxy_impl_final::proxy_object>::iterator itm;
82   for (itm = _par_obj_inst_list.begin(); itm != _par_obj_inst_list.end(); itm++)
83   {
84     try
85     {
86       ((*itm).proxy_corba_ref)->destroy();
87     }
88     catch(const CORBA::Exception& e)
89     {
90       // ignore this entry and continue
91     }
92     catch(...)
93     {
94       // ignore this entry and continue
95     }
96
97     // Destroy proxy object... parallel object nodes are
98     // destroyed into the Shutdown of each container nodes
99     _poa->deactivate_object(*((*itm).proxy_id));
100     if ((*itm).proxy_id)
101       delete (*itm).proxy_id;
102     if ((*itm).proxy_regist)
103       delete (*itm).proxy_regist;
104   }
105
106   // We call shutdown in each node
107   for (CORBA::ULong i = 0; i < _infos.nodes.length(); i++)
108   {
109     MESSAGE("Shutdown work node : " << i);
110     CORBA::Object_var object = _orb->string_to_object(_infos.nodes[i]);
111     Engines::Container_var node = Engines::Container::_narrow(object);
112     if (!CORBA::is_nil(node))
113     {
114       try 
115       {
116         node->Shutdown();
117         MESSAGE("Shutdown done node : " << i);
118       }
119       catch (...)
120       {
121         INFOS("Exception catch during Shutdown of node : " << i);
122       }
123     }
124     else
125     {
126       INFOS("Cannot shutdown node " << i << " ref is nil !");
127     }
128   }
129
130   INFOS("Shutdown Parallel Proxy");
131   _NS->Destroy_FullDirectory(_containerName.c_str());
132   _NS->Destroy_Name(_containerName.c_str());
133   if(!CORBA::is_nil(_orb))
134     _orb->shutdown(0);
135 }
136
137 // On intercepte cette méthode pour pouvoir ensuite
138 // déterminer si on doit créer une instance sequentielle
139 // ou parallèle d'un composant dans la méthode create_component_instance
140 CORBA::Boolean 
141 Container_proxy_impl_final::load_component_Library(const char* componentName, CORBA::String_out reason)
142 {
143   MESSAGE("Begin of load_component_Library on proxy : " << componentName);
144   reason=CORBA::string_dup("");
145
146   std::string aCompName = componentName;
147
148   CORBA::Boolean ret = true;
149   if (_libtype_map.count(aCompName) == 0)
150   {
151     _numInstanceMutex.lock(); // lock to be alone
152
153     // Default lib is seq
154     _libtype_map[aCompName] = "seq";
155
156     // --- try dlopen C++ component
157     // If is not a C++ or failed then is maybe 
158     // a seq component...
159
160     MESSAGE("Try to load C++ component");
161 #ifndef WIN32
162 #ifdef __APPLE__
163     std::string impl_name = string ("lib") + aCompName + string("Engine.dylib");
164 #else
165     std::string impl_name = string ("lib") + aCompName + string("Engine.so");
166 #endif
167 #else
168     std::string impl_name = aCompName + string("Engine.dll");
169 #endif
170     void* handle;
171 #ifndef WIN32
172     handle = dlopen( impl_name.c_str() , RTLD_LAZY | RTLD_GLOBAL ) ;
173 #else
174     handle = dlopen( impl_name.c_str() , 0 ) ;
175 #endif
176     if ( handle )
177     {
178       _library_map[impl_name] = handle;
179       MESSAGE("Library " << impl_name << " loaded");
180
181       //Test if lib could contain a parallel component
182
183       std::string paco_test_fct_signature = aCompName + std::string("_isAPACO_Component");
184       INFOS("SIG is : " << paco_test_fct_signature);
185       PACO_TEST_FUNCTION paco_test_fct = NULL;
186 #ifndef WIN32
187       paco_test_fct = (PACO_TEST_FUNCTION)dlsym(handle, paco_test_fct_signature.c_str());
188 #else
189       paco_test_fct = (PACO_TEST_FUNCTION)GetProcAddress((HINSTANCE)handle, paco_test_fct_signature.c_str());
190 #endif
191       if (paco_test_fct)
192       {
193         // PaCO Component found
194         MESSAGE("PACO LIB FOUND");
195         _libtype_map[aCompName] = "par";
196       }
197       else
198       {
199         MESSAGE("SEQ LIB FOUND");
200 #ifndef WIN32
201         MESSAGE("dlerror() result is : " << dlerror());
202 #endif
203       }
204     }
205     else
206     {
207       MESSAGE("Error in importing Cpp component : " << impl_name);
208 #ifndef WIN32
209       MESSAGE("dlerror() result is : " << dlerror());
210 #endif
211
212       MESSAGE("Try to import Python component "<<componentName);
213       {
214         AutoGIL agil;
215         PyObject *mainmod = PyImport_AddModule("__main__");
216         PyObject *globals = PyModule_GetDict(mainmod);
217         PyObject *pyCont = PyDict_GetItemString(globals, "pyCont");
218         PyObject *result = PyObject_CallMethod(pyCont,
219                                               (char*)"import_component",
220                                               (char*)"s",componentName);
221         std::string ret_p= PyUnicode_AsUTF8(result);
222         Py_XDECREF(result);
223       }
224
225       if (ret_p=="") // import possible: Python component
226       {
227         MESSAGE("import Python: " << aCompName <<" OK");
228       }
229       else
230       {
231         MESSAGE("Error in importing Python component : " << aCompName);
232         ret = false;
233       }
234     }
235     _numInstanceMutex.unlock();
236   }
237
238   // Call load_component_Library in each node
239   if (ret)
240   {
241     for (CORBA::ULong i = 0; i < _infos.nodes.length(); i++)
242     {
243       MESSAGE("Call load_component_Library work node : " << i);
244       CORBA::Object_var object = _orb->string_to_object(_infos.nodes[i]);
245       Engines::Container_var node = Engines::Container::_narrow(object);
246       if (!CORBA::is_nil(node))
247       {
248         char* reason;
249         try 
250         {
251           node->load_component_Library(componentName,reason);
252           MESSAGE("Call load_component_Library done node : " << i);
253           CORBA::string_free(reason);
254         }
255         catch (...)
256         {
257           INFOS("Exception catch during load_component_Library of node : " << i);
258           CORBA::string_free(reason);
259           ret = false;
260         }
261       }
262       else
263       {
264         INFOS("Cannot call load_component_Library node " << i << " ref is nil !");
265         ret = false;
266       }
267     }
268   }
269
270   // If ret is false -> lib is not loaded !
271   if (!ret)
272   {
273     INFOS("Cannot call load_component_Library " << aCompName);
274     _libtype_map.erase(aCompName);
275   }
276   return ret;
277 }
278
279 Engines::EngineComponent_ptr 
280 Container_proxy_impl_final::create_component_instance(const char* componentName)
281 {
282   Engines::FieldsDict_var env = new Engines::FieldsDict;
283   char* reason;
284   Engines::EngineComponent_ptr compo = create_component_instance_env(componentName, env, reason);
285   CORBA::string_free(reason);
286   return compo;
287 }
288
289 // Il y a deux cas :
290 // Composant sequentiel -> on le créer sur le noeud 0 (on pourrait faire une répartition de charge)
291 // Composant parallèle -> création du proxy ici puis appel de la création de chaque objet participant
292 // au composant parallèle
293 Engines::EngineComponent_ptr 
294 Container_proxy_impl_final::create_component_instance_env(const char* componentName,
295                                                           const Engines::FieldsDict& env, CORBA::String_out reason)
296 {
297   reason=CORBA::string_dup("");
298
299   std::string aCompName = componentName;
300   if (_libtype_map.count(aCompName) == 0)
301   {
302     // Component is not loaded !
303     INFOS("Proxy: component is not loaded ! : " << aCompName);
304     return Engines::EngineComponent::_nil();
305   }
306
307   // If it is a sequential component
308   if (_libtype_map[aCompName] == "seq")
309   {
310     _numInstanceMutex.lock(); // lock on the instance number
311     _numInstance++;
312     _numInstanceMutex.unlock();
313     Engines::PACO_Container_proxy_impl::updateInstanceNumber();
314     return Engines::Container_proxy_impl::create_component_instance(componentName);
315   }
316
317   // Parallel Component !
318   Engines::EngineComponent_var component_proxy = Engines::EngineComponent::_nil();
319
320   // On commence par créer le proxy
321 #ifndef WIN32
322 #ifdef __APPLE__
323   std::string impl_name = string ("lib") + aCompName + string("Engine.dylib");
324 #else
325   std::string impl_name = string ("lib") + aCompName + string("Engine.so");
326 #endif
327 #else
328   std::string impl_name = aCompName + string("Engine.dll");
329 #endif
330   void* handle = _library_map[impl_name];
331   std::string factory_name = aCompName + std::string("EngineProxy_factory");
332
333   MESSAGE("Creating component proxy : " << factory_name);
334   FACTORY_FUNCTION component_proxy_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
335
336   if (!component_proxy_factory)
337   {
338     INFOS("Can't resolve symbol: " + factory_name);
339 #ifndef WIN32
340     INFOS("dlerror() result is : " << dlerror());
341 #endif
342     return Engines::EngineComponent::_nil() ;
343   }
344   try {
345     _numInstanceMutex.lock() ; // lock on the instance number
346     _numInstance++ ;
347     int numInstance = _numInstance ;
348     _numInstanceMutex.unlock() ;
349
350     char aNumI[12];
351     sprintf( aNumI , "%d" , numInstance ) ;
352     string instanceName = aCompName + "_inst_" + aNumI ;
353     string component_registerName = _containerName + "/" + instanceName;
354
355     // --- Instantiate required CORBA object
356     Container_proxy_impl_final::proxy_object * proxy = new Container_proxy_impl_final::proxy_object();
357     
358     proxy->proxy_id = (component_proxy_factory) (_orb, 
359                                                  _fab_thread,
360                                                  _poa, 
361                                                  _id,
362                                                  &(proxy->proxy_regist),
363                                                  instanceName.c_str(), 
364                                                  _parallel_object_topology.total);
365
366     // --- get reference from id
367     CORBA::Object_var obj = _poa->id_to_reference(*(proxy->proxy_id));
368     component_proxy = Engines::EngineComponent::_narrow(obj);
369     proxy->proxy_corba_ref = component_proxy;
370
371     if (!CORBA::is_nil(component_proxy))
372     {
373       _cntInstances_map[impl_name] += 1;
374       _par_obj_inst_list.push_back(*proxy);
375       delete proxy;
376
377       // --- register the engine under the name
378       //     containerName(.dir)/instanceName(.object)
379       _NS->Register(component_proxy , component_registerName.c_str()) ;
380       MESSAGE(component_registerName.c_str() << " bound" ) ;
381     }
382     else
383     {
384       INFOS("The factory returns a nil object !");
385       return Engines::EngineComponent::_nil();
386     }
387       
388   }
389   catch (...)
390   {
391     INFOS( "Exception caught in Proxy creation" );
392     return Engines::EngineComponent::_nil();
393   }
394
395   // Create on each node a work node
396   for (CORBA::ULong i = 0; i < _infos.nodes.length(); i++)
397   {
398     MESSAGE("Call create_paco_component_node_instance on work node : " << i);
399     CORBA::Object_var object = _orb->string_to_object(_infos.nodes[i]);
400     Engines::PACO_Container_var node = Engines::PACO_Container::_narrow(object);
401     if (!CORBA::is_nil(node))
402     {
403       try 
404       {
405         node->create_paco_component_node_instance(componentName, _containerName.c_str());
406         MESSAGE("Call create_paco_component_node_instance done on node : " << i);
407       }
408       catch (SALOME::SALOME_Exception & ex)
409       {
410         INFOS("SALOME_EXCEPTION : " << ex.details.text);
411         return Engines::EngineComponent::_nil();
412       }
413       catch (...)
414       {
415         INFOS("Unknown Exception catch during create_paco_component_node_instance on node : " << i);
416         return Engines::EngineComponent::_nil();
417       }
418     }
419     else
420     {
421       INFOS("Cannot call create_paco_component_node_instance on node " << i << " ref is nil !");
422       return Engines::EngineComponent::_nil();
423     }
424   }
425
426   // Start Parallel object
427   PaCO::InterfaceManager_var paco_proxy = PaCO::InterfaceManager::_narrow(component_proxy);
428   paco_proxy->start();
429
430   return component_proxy;
431 }