1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // SALOME_ParallelContainerProxy : implementation of container and engine for Parallel Kernel
24 // File : SALOME_ParallelContainerProxy_i.cxx
25 // Author : André RIBES, EDF
27 #include "SALOME_ParallelContainerProxy_i.hxx"
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)
39 _hostname = Kernel_Utils::GetHostname();
40 _containerName = _NS->BuildContainerNameForNS(containerName.c_str(), _hostname.c_str());
41 _poa = PortableServer::POA::_duplicate(poa);
43 _fab_thread = fab_thread;
45 // Add CORBA object to the poa
46 _id = _poa->activate_object(this);
49 // Init SALOME Naming Service
50 _NS = new SALOME_NamingService();
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 + "','";
60 Py_ACQUIRE_NEW_THREAD;
61 PyRun_SimpleString("import SALOME_Container\n");
62 PyRun_SimpleString((char*)myCommand.c_str());
63 Py_RELEASE_NEW_THREAD;
66 Container_proxy_impl_final:: ~Container_proxy_impl_final() {
72 // _fab_thread not deleted because fab_thread is managed
73 // by paco_fabrique_manager
77 Container_proxy_impl_final::Shutdown()
79 // We Start by destroying all the parallel object
80 std::list<Container_proxy_impl_final::proxy_object>::iterator itm;
81 for (itm = _par_obj_inst_list.begin(); itm != _par_obj_inst_list.end(); itm++)
85 ((*itm).proxy_corba_ref)->destroy();
87 catch(const CORBA::Exception& e)
89 // ignore this entry and continue
93 // ignore this entry and continue
96 // Destroy proxy object... parallel object nodes are
97 // destroyed into the Shutdown of each container nodes
98 _poa->deactivate_object(*((*itm).proxy_id));
100 delete (*itm).proxy_id;
101 if ((*itm).proxy_regist)
102 delete (*itm).proxy_regist;
105 // We call shutdown in each node
106 for (CORBA::ULong i = 0; i < _infos.nodes.length(); i++)
108 MESSAGE("Shutdown work node : " << i);
109 CORBA::Object_var object = _orb->string_to_object(_infos.nodes[i]);
110 Engines::Container_var node = Engines::Container::_narrow(object);
111 if (!CORBA::is_nil(node))
116 MESSAGE("Shutdown done node : " << i);
120 INFOS("Exception catch during Shutdown of node : " << i);
125 INFOS("Cannot shutdown node " << i << " ref is nil !");
129 INFOS("Shutdown Parallel Proxy");
130 _NS->Destroy_FullDirectory(_containerName.c_str());
131 _NS->Destroy_Name(_containerName.c_str());
132 if(!CORBA::is_nil(_orb))
136 // On intercepte cette méthode pour pouvoir ensuite
137 // déterminer si on doit créer une instance sequentielle
138 // ou parallèle d'un composant dans la méthode create_component_instance
140 Container_proxy_impl_final::load_component_Library(const char* componentName, CORBA::String_out reason)
142 MESSAGE("Begin of load_component_Library on proxy : " << componentName);
143 reason=CORBA::string_dup("");
145 std::string aCompName = componentName;
147 CORBA::Boolean ret = true;
148 if (_libtype_map.count(aCompName) == 0)
150 _numInstanceMutex.lock(); // lock to be alone
152 // Default lib is seq
153 _libtype_map[aCompName] = "seq";
155 // --- try dlopen C++ component
156 // If is not a C++ or failed then is maybe
157 // a seq component...
159 MESSAGE("Try to load C++ component");
162 std::string impl_name = string ("lib") + aCompName + string("Engine.dylib");
164 std::string impl_name = string ("lib") + aCompName + string("Engine.so");
167 std::string impl_name = aCompName + string("Engine.dll");
171 handle = dlopen( impl_name.c_str() , RTLD_LAZY | RTLD_GLOBAL ) ;
173 handle = dlopen( impl_name.c_str() , 0 ) ;
177 _library_map[impl_name] = handle;
178 MESSAGE("Library " << impl_name << " loaded");
180 //Test if lib could contain a parallel component
182 std::string paco_test_fct_signature = aCompName + std::string("_isAPACO_Component");
183 INFOS("SIG is : " << paco_test_fct_signature);
184 PACO_TEST_FUNCTION paco_test_fct = NULL;
186 paco_test_fct = (PACO_TEST_FUNCTION)dlsym(handle, paco_test_fct_signature.c_str());
188 paco_test_fct = (PACO_TEST_FUNCTION)GetProcAddress((HINSTANCE)handle, paco_test_fct_signature.c_str());
192 // PaCO Component found
193 MESSAGE("PACO LIB FOUND");
194 _libtype_map[aCompName] = "par";
198 MESSAGE("SEQ LIB FOUND");
200 MESSAGE("dlerror() result is : " << dlerror());
206 MESSAGE("Error in importing Cpp component : " << impl_name);
208 MESSAGE("dlerror() result is : " << dlerror());
211 MESSAGE("Try to import Python component "<<componentName);
212 Py_ACQUIRE_NEW_THREAD;
213 PyObject *mainmod = PyImport_AddModule("__main__");
214 PyObject *globals = PyModule_GetDict(mainmod);
215 PyObject *pyCont = PyDict_GetItemString(globals, "pyCont");
216 PyObject *result = PyObject_CallMethod(pyCont,
217 (char*)"import_component",
218 (char*)"s",componentName);
219 std::string ret_p= PyString_AsString(result);
221 Py_RELEASE_NEW_THREAD;
223 if (ret_p=="") // import possible: Python component
225 MESSAGE("import Python: " << aCompName <<" OK");
229 MESSAGE("Error in importing Python component : " << aCompName);
233 _numInstanceMutex.unlock();
236 // Call load_component_Library in each node
239 for (CORBA::ULong i = 0; i < _infos.nodes.length(); i++)
241 MESSAGE("Call load_component_Library work node : " << i);
242 CORBA::Object_var object = _orb->string_to_object(_infos.nodes[i]);
243 Engines::Container_var node = Engines::Container::_narrow(object);
244 if (!CORBA::is_nil(node))
249 node->load_component_Library(componentName,reason);
250 MESSAGE("Call load_component_Library done node : " << i);
251 CORBA::string_free(reason);
255 INFOS("Exception catch during load_component_Library of node : " << i);
256 CORBA::string_free(reason);
262 INFOS("Cannot call load_component_Library node " << i << " ref is nil !");
268 // If ret is false -> lib is not loaded !
271 INFOS("Cannot call load_component_Library " << aCompName);
272 _libtype_map.erase(aCompName);
277 Engines::EngineComponent_ptr
278 Container_proxy_impl_final::create_component_instance(const char* componentName, ::CORBA::Long studyId)
280 Engines::FieldsDict_var env = new Engines::FieldsDict;
282 Engines::EngineComponent_ptr compo = create_component_instance_env(componentName, studyId, env, reason);
283 CORBA::string_free(reason);
288 // Composant sequentiel -> on le créer sur le noeud 0 (on pourrait faire une répartition de charge)
289 // Composant parallèle -> création du proxy ici puis appel de la création de chaque objet participant
290 // au composant parallèle
291 Engines::EngineComponent_ptr
292 Container_proxy_impl_final::create_component_instance_env(const char* componentName, ::CORBA::Long studyId,
293 const Engines::FieldsDict& env, CORBA::String_out reason)
295 reason=CORBA::string_dup("");
297 std::string aCompName = componentName;
298 if (_libtype_map.count(aCompName) == 0)
300 // Component is not loaded !
301 INFOS("Proxy: component is not loaded ! : " << aCompName);
302 return Engines::EngineComponent::_nil();
305 // If it is a sequential component
306 if (_libtype_map[aCompName] == "seq")
308 _numInstanceMutex.lock(); // lock on the instance number
310 _numInstanceMutex.unlock();
311 Engines::PACO_Container_proxy_impl::updateInstanceNumber();
312 return Engines::Container_proxy_impl::create_component_instance(componentName, studyId);
315 // Parallel Component !
316 Engines::EngineComponent_var component_proxy = Engines::EngineComponent::_nil();
318 // On commence par créer le proxy
321 std::string impl_name = string ("lib") + aCompName + string("Engine.dylib");
323 std::string impl_name = string ("lib") + aCompName + string("Engine.so");
326 std::string impl_name = aCompName + string("Engine.dll");
328 void* handle = _library_map[impl_name];
329 std::string factory_name = aCompName + std::string("EngineProxy_factory");
331 MESSAGE("Creating component proxy : " << factory_name);
332 FACTORY_FUNCTION component_proxy_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
334 if (!component_proxy_factory)
336 INFOS("Can't resolve symbol: " + factory_name);
338 INFOS("dlerror() result is : " << dlerror());
340 return Engines::EngineComponent::_nil() ;
343 _numInstanceMutex.lock() ; // lock on the instance number
345 int numInstance = _numInstance ;
346 _numInstanceMutex.unlock() ;
349 sprintf( aNumI , "%d" , numInstance ) ;
350 string instanceName = aCompName + "_inst_" + aNumI ;
351 string component_registerName = _containerName + "/" + instanceName;
353 // --- Instantiate required CORBA object
354 Container_proxy_impl_final::proxy_object * proxy = new Container_proxy_impl_final::proxy_object();
356 proxy->proxy_id = (component_proxy_factory) (_orb,
360 &(proxy->proxy_regist),
361 instanceName.c_str(),
362 _parallel_object_topology.total);
364 // --- get reference & servant from id
365 CORBA::Object_var obj = _poa->id_to_reference(*(proxy->proxy_id));
366 component_proxy = Engines::EngineComponent::_narrow(obj);
367 proxy->proxy_corba_ref = component_proxy;
369 if (!CORBA::is_nil(component_proxy))
371 _cntInstances_map[impl_name] += 1;
372 _par_obj_inst_list.push_back(*proxy);
375 // --- register the engine under the name
376 // containerName(.dir)/instanceName(.object)
377 _NS->Register(component_proxy , component_registerName.c_str()) ;
378 MESSAGE(component_registerName.c_str() << " bound" ) ;
382 INFOS("The factory returns a nil object !");
383 return Engines::EngineComponent::_nil();
389 INFOS( "Exception caught in Proxy creation" );
390 return Engines::EngineComponent::_nil();
393 // Create on each node a work node
394 for (CORBA::ULong i = 0; i < _infos.nodes.length(); i++)
396 MESSAGE("Call create_paco_component_node_instance on work node : " << i);
397 CORBA::Object_var object = _orb->string_to_object(_infos.nodes[i]);
398 Engines::PACO_Container_var node = Engines::PACO_Container::_narrow(object);
399 if (!CORBA::is_nil(node))
403 node->create_paco_component_node_instance(componentName, _containerName.c_str(), studyId);
404 MESSAGE("Call create_paco_component_node_instance done on node : " << i);
406 catch (SALOME::SALOME_Exception & ex)
408 INFOS("SALOME_EXCEPTION : " << ex.details.text);
409 return Engines::EngineComponent::_nil();
413 INFOS("Unknown Exception catch during create_paco_component_node_instance on node : " << i);
414 return Engines::EngineComponent::_nil();
419 INFOS("Cannot call create_paco_component_node_instance on node " << i << " ref is nil !");
420 return Engines::EngineComponent::_nil();
424 // Start Parallel object
425 PaCO::InterfaceManager_var paco_proxy = PaCO::InterfaceManager::_narrow(component_proxy);
428 return component_proxy;