Back to index

salome-kernel  6.5.0
SALOME_ParallelContainerProxy_i.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  SALOME_ParallelContainerProxy : implementation of container and engine for Parallel Kernel
00024 //  File   : SALOME_ParallelContainerProxy_i.cxx
00025 //  Author : André RIBES, EDF
00026 //
00027 #include "SALOME_ParallelContainerProxy_i.hxx"
00028 
00029 Container_proxy_impl_final::Container_proxy_impl_final(CORBA::ORB_ptr orb, 
00030                                                        paco_fabrique_thread * fab_thread, 
00031                                                        PortableServer::POA_ptr poa,
00032                                                        std::string containerName,
00033                                                        bool is_a_return_proxy) :
00034   Engines::PACO_Container_proxy_impl(orb, fab_thread, is_a_return_proxy),
00035   Engines::Container_proxy_impl(orb, fab_thread, is_a_return_proxy),
00036   InterfaceManager_impl(orb, fab_thread, is_a_return_proxy)
00037 {
00038   _numInstance = 0;
00039   _hostname = Kernel_Utils::GetHostname();
00040   _containerName = _NS->BuildContainerNameForNS(containerName.c_str(), _hostname.c_str());
00041   _poa = PortableServer::POA::_duplicate(poa);
00042 
00043   _fab_thread = fab_thread;
00044 
00045   // Add CORBA object to the poa
00046   _id = _poa->activate_object(this);
00047   this->_remove_ref();
00048 
00049   // Init SALOME Naming Service
00050   _NS = new SALOME_NamingService();
00051   _NS->init_orb(_orb);
00052 
00053   // Init Python container part
00054   CORBA::Object_var container_node = _poa->id_to_reference(*_id);
00055   CORBA::String_var sior =  _orb->object_to_string(container_node);
00056   std::string myCommand="pyCont = SALOME_Container.SALOME_Container_i('";
00057   myCommand += _containerName + "','";
00058   myCommand += sior;
00059   myCommand += "')\n";
00060   Py_ACQUIRE_NEW_THREAD;
00061   PyRun_SimpleString("import SALOME_Container\n");
00062   PyRun_SimpleString((char*)myCommand.c_str());
00063   Py_RELEASE_NEW_THREAD;
00064 }
00065 
00066 Container_proxy_impl_final:: ~Container_proxy_impl_final() {
00067   if (_id)
00068     delete _id;
00069   if (_NS)
00070     delete _NS;
00071 
00072   // _fab_thread not deleted beacause fab_thread is managed
00073   // by paco_fabrique_manager
00074 }
00075 
00076 void
00077 Container_proxy_impl_final::Shutdown()
00078 {
00079   // We Start by destroying all the parallel object
00080   std::list<Container_proxy_impl_final::proxy_object>::iterator itm;
00081   for (itm = _par_obj_inst_list.begin(); itm != _par_obj_inst_list.end(); itm++)
00082   {
00083     try
00084     {
00085       ((*itm).proxy_corba_ref)->destroy();
00086     }
00087     catch(const CORBA::Exception& e)
00088     {
00089       // ignore this entry and continue
00090     }
00091     catch(...)
00092     {
00093       // ignore this entry and continue
00094     }
00095 
00096     // Destroy proxy object... parallel object nodes are
00097     // destroyed into the Shutdown of each container nodes
00098     _poa->deactivate_object(*((*itm).proxy_id));
00099     if ((*itm).proxy_id)
00100       delete (*itm).proxy_id;
00101     if ((*itm).proxy_regist)
00102       delete (*itm).proxy_regist;
00103   }
00104 
00105   // We call shutdown in each node
00106   for (CORBA::ULong i = 0; i < _infos.nodes.length(); i++)
00107   {
00108     MESSAGE("Shutdown work node : " << i);
00109     CORBA::Object_var object = _orb->string_to_object(_infos.nodes[i]);
00110     Engines::Container_var node = Engines::Container::_narrow(object);
00111     if (!CORBA::is_nil(node))
00112     {
00113       try 
00114       {
00115         node->Shutdown();
00116         MESSAGE("Shutdown done node : " << i);
00117       }
00118       catch (...)
00119       {
00120         INFOS("Exception catch during Shutdown of node : " << i);
00121       }
00122     }
00123     else
00124     {
00125       INFOS("Cannot shutdown node " << i << " ref is nil !");
00126     }
00127   }
00128 
00129   INFOS("Shutdown Parallel Proxy");
00130   _NS->Destroy_FullDirectory(_containerName.c_str());
00131   _NS->Destroy_Name(_containerName.c_str());
00132   if(!CORBA::is_nil(_orb))
00133     _orb->shutdown(0);
00134 }
00135 
00136 // On intercepte cette méthode pour pouvoir ensuite
00137 // déterminer si on doit créer une instance sequentielle
00138 // ou parallèle d'un composant dans la méthode create_component_instance
00139 CORBA::Boolean 
00140 Container_proxy_impl_final::load_component_Library(const char* componentName, CORBA::String_out reason)
00141 {
00142   MESSAGE("Begin of load_component_Library on proxy : " << componentName);
00143   reason=CORBA::string_dup("");
00144 
00145   std::string aCompName = componentName;
00146 
00147   CORBA::Boolean ret = true;
00148   if (_libtype_map.count(aCompName) == 0)
00149   {
00150     _numInstanceMutex.lock(); // lock to be alone
00151 
00152     // Default lib is seq
00153     _libtype_map[aCompName] = "seq";
00154 
00155     // --- try dlopen C++ component
00156     // If is not a C++ or failed then is maybe 
00157     // a seq component...
00158 
00159     MESSAGE("Try to load C++ component");
00160 #ifndef WIN32
00161     std::string impl_name = string ("lib") + aCompName + string("Engine.so");
00162 #else
00163     std::string impl_name = aCompName + string("Engine.dll");
00164 #endif
00165     void* handle;
00166 #ifndef WIN32
00167     handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ;
00168 #else
00169     handle = dlopen( impl_name.c_str() , 0 ) ;
00170 #endif
00171     if ( handle )
00172     {
00173       _library_map[impl_name] = handle;
00174       MESSAGE("Library " << impl_name << " loaded");
00175 
00176       //Test if lib could contain a parallel component
00177 
00178       std::string paco_test_fct_signature = aCompName + std::string("_isAPACO_Component");
00179       INFOS("SIG is : " << paco_test_fct_signature);
00180       PACO_TEST_FUNCTION paco_test_fct = NULL;
00181 #ifndef WIN32
00182       paco_test_fct = (PACO_TEST_FUNCTION)dlsym(handle, paco_test_fct_signature.c_str());
00183 #else
00184       paco_test_fct = (PACO_TEST_FUNCTION)GetProcAddress((HINSTANCE)handle, paco_test_fct_signature.c_str());
00185 #endif
00186       if (paco_test_fct)
00187       {
00188         // PaCO Component found
00189         MESSAGE("PACO LIB FOUND");
00190         _libtype_map[aCompName] = "par";
00191       }
00192       else
00193       {
00194         MESSAGE("SEQ LIB FOUND");
00195 #ifndef WIN32
00196         MESSAGE("dlerror() result is : " << dlerror());
00197 #endif
00198       }
00199     }
00200     else
00201     {
00202       MESSAGE("Error in importing Cpp component : " << impl_name);
00203 #ifndef WIN32
00204       MESSAGE("dlerror() result is : " << dlerror());
00205 #endif
00206 
00207       MESSAGE("Try to import Python component "<<componentName);
00208       Py_ACQUIRE_NEW_THREAD;
00209       PyObject *mainmod = PyImport_AddModule("__main__");
00210       PyObject *globals = PyModule_GetDict(mainmod);
00211       PyObject *pyCont = PyDict_GetItemString(globals, "pyCont");
00212       PyObject *result = PyObject_CallMethod(pyCont,
00213                                              (char*)"import_component",
00214                                              (char*)"s",componentName);
00215       std::string ret_p= PyString_AsString(result);
00216       Py_XDECREF(result);
00217       Py_RELEASE_NEW_THREAD;
00218 
00219       if (ret_p=="") // import possible: Python component
00220       {
00221         MESSAGE("import Python: " << aCompName <<" OK");
00222       }
00223       else
00224       {
00225         MESSAGE("Error in importing Python component : " << aCompName);
00226         ret = false;
00227       }
00228     }
00229     _numInstanceMutex.unlock();
00230   }
00231 
00232   // Call load_component_Library in each node
00233   if (ret)
00234   {
00235     for (CORBA::ULong i = 0; i < _infos.nodes.length(); i++)
00236     {
00237       MESSAGE("Call load_component_Library work node : " << i);
00238       CORBA::Object_var object = _orb->string_to_object(_infos.nodes[i]);
00239       Engines::Container_var node = Engines::Container::_narrow(object);
00240       if (!CORBA::is_nil(node))
00241       {
00242         char* reason;
00243         try 
00244         {
00245           node->load_component_Library(componentName,reason);
00246           MESSAGE("Call load_component_Library done node : " << i);
00247           CORBA::string_free(reason);
00248         }
00249         catch (...)
00250         {
00251           INFOS("Exception catch during load_component_Library of node : " << i);
00252           CORBA::string_free(reason);
00253           ret = false;
00254         }
00255       }
00256       else
00257       {
00258         INFOS("Cannot call load_component_Library node " << i << " ref is nil !");
00259         ret = false;
00260       }
00261     }
00262   }
00263 
00264   // If ret is false -> lib is not loaded !
00265   if (!ret)
00266   {
00267     INFOS("Cannot call load_component_Library " << aCompName);
00268     _libtype_map.erase(aCompName);
00269   }
00270   return ret;
00271 }
00272 
00273 Engines::EngineComponent_ptr 
00274 Container_proxy_impl_final::create_component_instance(const char* componentName, ::CORBA::Long studyId)
00275 {
00276   Engines::FieldsDict_var env = new Engines::FieldsDict;
00277   char* reason;
00278   Engines::EngineComponent_ptr compo = create_component_instance_env(componentName, studyId, env, reason);
00279   CORBA::string_free(reason);
00280   return compo;
00281 }
00282 
00283 // Il y a deux cas :
00284 // Composant sequentiel -> on le créer sur le noeud 0 (on pourrait faire une répartition de charge)
00285 // Composant parallèle -> création du proxy ici puis appel de la création de chaque objet participant
00286 // au composant parallèle
00287 Engines::EngineComponent_ptr 
00288 Container_proxy_impl_final::create_component_instance_env(const char* componentName, ::CORBA::Long studyId,
00289                                                           const Engines::FieldsDict& env, CORBA::String_out reason)
00290 {
00291   reason=CORBA::string_dup("");
00292 
00293   std::string aCompName = componentName;
00294   if (_libtype_map.count(aCompName) == 0)
00295   {
00296     // Component is not loaded !
00297     INFOS("Proxy: component is not loaded ! : " << aCompName);
00298     return Engines::EngineComponent::_nil();
00299   }
00300 
00301   // If it is a sequential component
00302   if (_libtype_map[aCompName] == "seq")
00303   {
00304     _numInstanceMutex.lock(); // lock on the instance number
00305     _numInstance++;
00306     _numInstanceMutex.unlock();
00307     Engines::PACO_Container_proxy_impl::updateInstanceNumber();
00308     return Engines::Container_proxy_impl::create_component_instance(componentName, studyId);
00309   }
00310 
00311   // Parallel Component !
00312   Engines::EngineComponent_var component_proxy = Engines::EngineComponent::_nil();
00313 
00314   // On commence par créer le proxy
00315 #ifndef WIN32
00316   std::string impl_name = string ("lib") + aCompName + string("Engine.so");
00317 #else
00318   std::string impl_name = aCompName + string("Engine.dll");
00319 #endif
00320   void* handle = _library_map[impl_name];
00321   std::string factory_name = aCompName + std::string("EngineProxy_factory");
00322 
00323   MESSAGE("Creating component proxy : " << factory_name);
00324   FACTORY_FUNCTION component_proxy_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
00325 
00326   if (!component_proxy_factory)
00327   {
00328     INFOS("Can't resolve symbol: " + factory_name);
00329 #ifndef WIN32
00330     INFOS("dlerror() result is : " << dlerror());
00331 #endif
00332     return Engines::EngineComponent::_nil() ;
00333   }
00334   try {
00335     _numInstanceMutex.lock() ; // lock on the instance number
00336     _numInstance++ ;
00337     int numInstance = _numInstance ;
00338     _numInstanceMutex.unlock() ;
00339 
00340     char aNumI[12];
00341     sprintf( aNumI , "%d" , numInstance ) ;
00342     string instanceName = aCompName + "_inst_" + aNumI ;
00343     string component_registerName = _containerName + "/" + instanceName;
00344 
00345     // --- Instanciate required CORBA object
00346     Container_proxy_impl_final::proxy_object * proxy = new Container_proxy_impl_final::proxy_object();
00347     
00348     proxy->proxy_id = (component_proxy_factory) (_orb, 
00349                                                  _fab_thread,
00350                                                  _poa, 
00351                                                  _id,
00352                                                  &(proxy->proxy_regist),
00353                                                  instanceName.c_str(), 
00354                                                  _parallel_object_topology.total);
00355 
00356     // --- get reference & servant from id
00357     CORBA::Object_var obj = _poa->id_to_reference(*(proxy->proxy_id));
00358     component_proxy = Engines::EngineComponent::_narrow(obj);
00359     proxy->proxy_corba_ref = component_proxy;
00360 
00361     if (!CORBA::is_nil(component_proxy))
00362     {
00363       _cntInstances_map[impl_name] += 1;
00364       _par_obj_inst_list.push_back(*proxy);
00365       delete proxy;
00366 
00367       // --- register the engine under the name
00368       //     containerName(.dir)/instanceName(.object)
00369       _NS->Register(component_proxy , component_registerName.c_str()) ;
00370       MESSAGE(component_registerName.c_str() << " bound" ) ;
00371     }
00372     else
00373     {
00374       INFOS("The factory returns a nil object !");
00375       return Engines::EngineComponent::_nil();
00376     }
00377       
00378   }
00379   catch (...)
00380   {
00381     INFOS( "Exception catched in Proxy creation" );
00382     return Engines::EngineComponent::_nil();
00383   }
00384 
00385   // Create on each node a work node
00386   for (CORBA::ULong i = 0; i < _infos.nodes.length(); i++)
00387   {
00388     MESSAGE("Call create_paco_component_node_instance on work node : " << i);
00389     CORBA::Object_var object = _orb->string_to_object(_infos.nodes[i]);
00390     Engines::PACO_Container_var node = Engines::PACO_Container::_narrow(object);
00391     if (!CORBA::is_nil(node))
00392     {
00393       try 
00394       {
00395         node->create_paco_component_node_instance(componentName, _containerName.c_str(), studyId);
00396         MESSAGE("Call create_paco_component_node_instance done on node : " << i);
00397       }
00398       catch (SALOME::SALOME_Exception & ex)
00399       {
00400         INFOS("SALOME_EXCEPTION : " << ex.details.text);
00401         return Engines::EngineComponent::_nil();
00402       }
00403       catch (...)
00404       {
00405         INFOS("Unknown Exception catch during create_paco_component_node_instance on node : " << i);
00406         return Engines::EngineComponent::_nil();
00407       }
00408     }
00409     else
00410     {
00411       INFOS("Cannot call create_paco_component_node_instance on node " << i << " ref is nil !");
00412       return Engines::EngineComponent::_nil();
00413     }
00414   }
00415 
00416   // Start Parallel object
00417   PaCO::InterfaceManager_var paco_proxy = PaCO::InterfaceManager::_narrow(component_proxy);
00418   paco_proxy->start();
00419 
00420   return component_proxy;
00421 }