Back to index

salome-kernel  6.5.0
SALOME_ParallelContainer_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 //  File   : SALOME_ParallelContainer_i.cxx
00023 //  Author : André RIBES, EDF
00024 
00025 #include "SALOME_ParallelContainer_i.hxx"
00026 #include "SALOME_Component_i.hxx"
00027 #include "SALOME_FileRef_i.hxx"
00028 #include "SALOME_FileTransfer_i.hxx"
00029 #include "SALOME_NamingService.hxx"
00030 #include "OpUtil.hxx"
00031 #include "utilities.h"
00032 #include "Basics_Utils.hxx"
00033 
00034 #include <string.h>
00035 #include <stdio.h>
00036 #ifndef WIN32
00037 #include <sys/time.h>
00038 #include <dlfcn.h>
00039 #include <unistd.h>
00040 #else
00041 #include <signal.h>
00042 #include <process.h>
00043 #include <direct.h>
00044 int SIGUSR1 = 1000;
00045 #endif
00046 
00047 #include <paco_omni.h>
00048 
00049 #include <Python.h>
00050 #include "Container_init_python.hxx"
00051 
00052 
00053 bool _Sleeping = false ;
00054 
00055 extern "C" {void ActSigIntHandler() ; }
00056 #ifndef WIN32
00057 extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; }
00058 #else
00059 extern "C" {void SigIntHandler( int ) ; }
00060 #endif
00061 
00067 //=============================================================================
00071 //=============================================================================
00072 
00073 Engines_Parallel_Container_i::Engines_Parallel_Container_i (CORBA::ORB_ptr orb, 
00074                                                             char * ior, 
00075                                                             int rank,
00076                                                             PortableServer::POA_ptr poa,
00077                                                             std::string containerName,
00078                                                             bool isServantAloneInProcess) :
00079   InterfaceParallel_impl(orb,ior,rank), 
00080   Engines::PACO_Container_serv(orb,ior,rank),
00081   Engines::PACO_Container_base_serv(orb,ior,rank),
00082   Engines::Container_serv(orb,ior,rank),
00083   Engines::Container_base_serv(orb,ior,rank),
00084   _numInstance(0),_isServantAloneInProcess(isServantAloneInProcess)
00085 {
00086   // Members init
00087   _pid = getpid();
00088   _hostname = Kernel_Utils::GetHostname();
00089   _orb = CORBA::ORB::_duplicate(orb);
00090   _poa = PortableServer::POA::_duplicate(poa);
00091 
00092   // Add CORBA object to the poa
00093   _id = _poa->activate_object(this);
00094   this->_remove_ref();
00095   CORBA::Object_var container_node = _poa->id_to_reference(*_id);
00096 
00097   // Adding this servant to SALOME
00098   _NS = new SALOME_NamingService();
00099   _NS->init_orb(_orb);
00100   _containerName = _NS->BuildContainerNameForNS(containerName.c_str(), _hostname.c_str());
00101 
00102   // Ajout du numero de noeud
00103   char node_number[12];
00104   sprintf(node_number, "%d", getMyRank());
00105   _containerName = _containerName + node_number;
00106 
00107   // Init Python container part
00108   CORBA::String_var sior =  _orb->object_to_string(container_node);
00109   std::string myCommand="pyCont = SALOME_Container.SALOME_Container_i('";
00110   myCommand += _containerName + "','";
00111   myCommand += sior;
00112   myCommand += "')\n";
00113   Py_ACQUIRE_NEW_THREAD;
00114   PyRun_SimpleString("import SALOME_Container\n");
00115   PyRun_SimpleString((char*)myCommand.c_str());
00116   Py_RELEASE_NEW_THREAD;
00117 
00118   // Init FileTransfer service
00119   fileTransfer_i* aFileTransfer = new fileTransfer_i();
00120   _fileTransfer = aFileTransfer->_this();
00121   aFileTransfer->_remove_ref();
00122 
00123   // Some signal handlers
00124   ActSigIntHandler();
00125 }
00126 
00127 //=============================================================================
00131 //=============================================================================
00132 
00133 Engines_Parallel_Container_i::~Engines_Parallel_Container_i()
00134 {
00135   MESSAGE("Container_i::~Container_i()");
00136   if (_id)
00137     delete _id;
00138   if(_NS)
00139     delete _NS;
00140 }
00141 
00142 //=============================================================================
00144 
00147 //=============================================================================
00148 
00149 char* Engines_Parallel_Container_i::name()
00150 {
00151   return CORBA::string_dup(_containerName.c_str()) ;
00152 }
00153 
00154 //=============================================================================
00156 
00159 //=============================================================================
00160 
00161 char* 
00162 Engines_Parallel_Container_i::workingdir()
00163 {
00164   char wd[256];
00165   getcwd (wd,256);
00166   return CORBA::string_dup(wd) ;
00167 }
00168 
00169 //=============================================================================
00171 
00174 //=============================================================================
00175 
00176 char* 
00177 Engines_Parallel_Container_i::logfilename()
00178 {
00179   return CORBA::string_dup(_logfilename.c_str()) ;
00180 }
00181 
00183 void 
00184 Engines_Parallel_Container_i::logfilename(const char* name)
00185 {
00186   _logfilename=name;
00187 }
00188 
00189 //=============================================================================
00191 
00194 //=============================================================================
00195 
00196 char* Engines_Parallel_Container_i::getHostName()
00197 {
00198   MESSAGE("Warning: getHostName of a parallel container returns the hostname of the first servant node");
00199   return CORBA::string_dup(_hostname.c_str()) ;
00200 }
00201 
00202 //=============================================================================
00204 
00207 //=============================================================================
00208 
00209 CORBA::Long Engines_Parallel_Container_i::getPID()
00210 {
00211   MESSAGE("Warning: getPID of a parallel container returns the PID of the first servant node");
00212   return _pid;
00213 }
00214 
00215 //=============================================================================
00217 
00220 //=============================================================================
00221 
00222 void Engines_Parallel_Container_i::ping()
00223 {
00224   MESSAGE("Engines_Parallel_Container_i::ping() my pid is "<< _pid);
00225 }
00226 
00227 //=============================================================================
00229 
00235 //=============================================================================
00236 
00237 void Engines_Parallel_Container_i::Shutdown()
00238 {
00239   MESSAGE("Engines_Parallel_Container_i::Shutdown()");
00240 
00241   /* For each seq component contained in this container
00242   * tell it to self-destroy
00243   */
00244   std::map<std::string, Engines::EngineComponent_var>::iterator itm;
00245   for (itm = _listInstances_map.begin(); itm != _listInstances_map.end(); itm++)
00246   {
00247     try
00248     {
00249       itm->second->destroy();
00250     }
00251     catch(const CORBA::Exception& e)
00252     {
00253       // ignore this entry and continue
00254     }
00255     catch(...)
00256     {
00257       // ignore this entry and continue
00258     }
00259   }
00260 
00261   // Destroy each parallel component node...
00262   std::map<std::string, PortableServer::ObjectId *>::iterator i;
00263   for (i = _par_obj_inst_map.begin(); i != _par_obj_inst_map.end(); i++)
00264     _poa->deactivate_object(*(i->second));
00265 
00266   _NS->Destroy_FullDirectory(_containerName.c_str());
00267   _NS->Destroy_Name(_containerName.c_str());
00268 
00269   if(_isServantAloneInProcess)
00270   {
00271     MESSAGE("Effective Shutdown of container Begins...");
00272     if(!CORBA::is_nil(_orb))
00273       _orb->shutdown(0);
00274   }
00275 }
00276 
00277 
00278 //=============================================================================
00280 
00287 //=============================================================================
00288 
00289 bool
00290 Engines_Parallel_Container_i::load_component_Library(const char* componentName, CORBA::String_out reason)
00291 {
00292   reason=CORBA::string_dup("");
00293 
00294   MESSAGE("Begin of load_component_Library : " << componentName)
00295   bool ret = false;
00296   std::string aCompName = componentName;
00297 #ifndef WIN32
00298   std::string impl_name = string ("lib") + aCompName + string("Engine.so");
00299 #else
00300   std::string impl_name = aCompName + string("Engine.dll");
00301 #endif
00302 
00303   _numInstanceMutex.lock(); // lock to be alone 
00304 
00305   // Check if already loaded or imported in the container
00306   if (_toRemove_map.count(impl_name) != 0) _toRemove_map.erase(impl_name);
00307   if (_library_map.count(impl_name) != 0)
00308   {
00309     MESSAGE("Library " << impl_name << " already loaded");
00310     ret = true;
00311   }
00312   if (_library_map.count(aCompName) != 0)
00313   {
00314     MESSAGE("Python component already imported");
00315     ret = true;
00316   }
00317 
00318   // --- try dlopen C++ component
00319   if (!ret)
00320   {
00321     MESSAGE("Try to load C++ component");
00322     void* handle;
00323 #ifndef WIN32
00324     handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ;
00325 #else
00326     handle = dlopen( impl_name.c_str() , 0 ) ;
00327 #endif
00328     if ( handle )
00329     {
00330       _library_map[impl_name] = handle;
00331       MESSAGE("Library " << impl_name << " loaded");
00332       ret = true;
00333     }
00334     else
00335     {
00336       std::cerr << "Can't load shared library : " << impl_name << std::endl;
00337       std::cerr << "error of dlopen: " << dlerror() << std::endl;
00338     }
00339   }
00340 
00341   // --- try import Python component
00342   if (!ret)
00343   {
00344     MESSAGE("Try to import Python component "<<componentName);
00345     Py_ACQUIRE_NEW_THREAD;
00346     PyObject *mainmod = PyImport_AddModule("__main__");
00347     PyObject *globals = PyModule_GetDict(mainmod);
00348     PyObject *pyCont = PyDict_GetItemString(globals, "pyCont");
00349     PyObject *result = PyObject_CallMethod(pyCont,
00350                                            (char*)"import_component",
00351                                            (char*)"s",componentName);
00352     std::string ret_p= PyString_AsString(result);
00353     Py_XDECREF(result);
00354     Py_RELEASE_NEW_THREAD;
00355 
00356     if (ret_p=="") // import possible: Python component
00357     {
00358       _library_map[aCompName] = (void *)pyCont; // any non O value OK
00359       MESSAGE("import Python: " << aCompName <<" OK");
00360       ret = true;
00361     }
00362     else
00363     {
00364       std::cerr << "Error in importing Python component : " << aCompName << std::endl;
00365     }
00366   }
00367 
00368   _numInstanceMutex.unlock();
00369   return ret;
00370 }
00371 
00372 //=============================================================================
00374 
00383 //=============================================================================
00384 Engines::EngineComponent_ptr
00385 Engines_Parallel_Container_i::create_component_instance(const char*genericRegisterName,
00386                                                         CORBA::Long studyId)
00387 {
00388   Engines::FieldsDict_var env = new Engines::FieldsDict;
00389   char* reason;
00390   Engines::EngineComponent_ptr compo = create_component_instance_env(genericRegisterName,studyId,env, reason);
00391   CORBA::string_free(reason);
00392   return compo;
00393 }
00394 
00395 //=============================================================================
00397 
00407 //=============================================================================
00408 
00409 Engines::EngineComponent_ptr
00410 Engines_Parallel_Container_i::create_component_instance_env(const char*genericRegisterName,
00411                                                             CORBA::Long studyId,
00412                                                             const Engines::FieldsDict& env,
00413                                                             CORBA::String_out reason)
00414 {
00415   MESSAGE("Begin of create_component_instance in node : " << getMyRank());
00416   reason=CORBA::string_dup("");
00417 
00418   if (studyId < 0)
00419   {
00420     INFOS("studyId must be > 0 for mono study instance, =0 for multiStudy");
00421     return Engines::EngineComponent::_nil() ;
00422   }
00423 
00424   std::string aCompName = genericRegisterName;
00425 #ifndef WIN32
00426   std::string impl_name = string ("lib") + aCompName +string("Engine.so");
00427 #else
00428   std::string impl_name = aCompName +string("Engine.dll");
00429 #endif
00430 
00431   _numInstanceMutex.lock();
00432   _numInstance++;
00433 
00434   // Test if the component lib is loaded
00435   std::string type_of_lib("Not Loaded");
00436   void* handle = _library_map[impl_name];
00437   if (handle)
00438     type_of_lib = "cpp";
00439   if (_library_map.count(aCompName) != 0 and !handle)
00440     type_of_lib = "python";
00441   
00442   if (type_of_lib == "Not Loaded")
00443   {
00444     std::cerr << "Component library is not loaded or imported ! lib was : " << aCompName << std::endl;
00445     _numInstanceMutex.unlock();
00446     return Engines::EngineComponent::_nil();
00447   }
00448 
00449   Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil();
00450   if (type_of_lib == "cpp")
00451     iobject = createCPPInstance(aCompName, handle, studyId);
00452   else
00453     iobject = createPythonInstance(aCompName, studyId);
00454 
00455   _numInstanceMutex.unlock();
00456   return iobject._retn();
00457 }
00458 
00459 //=============================================================================
00461 
00469 //=============================================================================
00470 
00471 Engines::EngineComponent_ptr Engines_Parallel_Container_i::find_component_instance( const char* registeredName,
00472                                                                               CORBA::Long studyId)
00473 {
00474   Engines::EngineComponent_var anEngine = Engines::EngineComponent::_nil();
00475   std::map<std::string,Engines::EngineComponent_var>::iterator itm =_listInstances_map.begin();
00476   while (itm != _listInstances_map.end())
00477   {
00478     std::string instance = (*itm).first;
00479     SCRUTE(instance);
00480     if (instance.find(registeredName) == 0)
00481     {
00482       anEngine = (*itm).second;
00483       if (studyId == anEngine->getStudyId())
00484       {
00485         return anEngine._retn();
00486       }
00487     }
00488     itm++;
00489   }
00490   return anEngine._retn();  
00491 }
00492 
00493 //=============================================================================
00495 
00506 //=============================================================================
00507 
00508 Engines::EngineComponent_ptr Engines_Parallel_Container_i::load_impl( const char* genericRegisterName,
00509                                                                 const char* componentName )
00510 {
00511   Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil();
00512   char* reason;
00513   if (load_component_Library(genericRegisterName,reason))
00514     iobject = find_or_create_instance(genericRegisterName);
00515   CORBA::string_free(reason);
00516   return iobject._retn();
00517 }
00518 
00519 
00520 //=============================================================================
00522 
00526 //=============================================================================
00527 
00528 void Engines_Parallel_Container_i::remove_impl(Engines::EngineComponent_ptr component_i)
00529 {
00530   ASSERT(!CORBA::is_nil(component_i));
00531   std::string instanceName = component_i->instanceName();
00532   _numInstanceMutex.lock() ; // lock to be alone (stl container write)
00533   // Test if the component is in this container
00534   std::map<std::string, Engines::EngineComponent_var>::iterator itm;
00535   itm = _listInstances_map.find(instanceName);
00536   if (itm != _listInstances_map.end())
00537   {
00538     MESSAGE("Unloading component " << instanceName);
00539     _listInstances_map.erase(instanceName);
00540     component_i->destroy() ;
00541     _NS->Destroy_Name(instanceName.c_str());
00542   }
00543   else
00544     std::cerr << "WARNING !!!! component instance was not in this container !!!" << std::endl;
00545   _numInstanceMutex.unlock() ;
00546 }
00547 
00548 //=============================================================================
00550 
00553 //=============================================================================
00554 
00555 void Engines_Parallel_Container_i::finalize_removal()
00556 {
00557   MESSAGE("Finalize removal : dlclose");
00558   MESSAGE("WARNING FINALIZE DOES CURRENTLY NOTHING !!!");
00559 
00560   // (see decInstanceCnt, load_component_Library)
00561   //std::map<std::string, void *>::iterator ith;
00562   //for (ith = _toRemove_map.begin(); ith != _toRemove_map.end(); ith++)
00563   //{
00564   //  void *handle = (*ith).second;
00565   //  std::string impl_name= (*ith).first;
00566   //  if (handle)
00567   //  {
00568   //    SCRUTE(handle);
00569   //    SCRUTE(impl_name);
00570   //    dlclose(handle);                // SALOME unstable after ...
00571   //    _library_map.erase(impl_name);
00572   //  }
00573   //}
00574 
00575   _numInstanceMutex.lock(); // lock to be alone
00576   _toRemove_map.clear();
00577   _numInstanceMutex.unlock();
00578 }
00579 
00580 //=============================================================================
00582 
00586 //=============================================================================
00587 
00588 bool Engines_Parallel_Container_i::Kill_impl()
00589 {
00590   MESSAGE("Engines_Parallel_Container_i::Kill() my pid is "<< _pid 
00591           << " my containerName is " << _containerName.c_str() 
00592           << " my machineName is " << _hostname.c_str());
00593   INFOS("===============================================================");
00594   INFOS("= REMOVE calls to Kill_impl in C++ container                  =");
00595   INFOS("===============================================================");
00596   //exit( 0 ) ;
00597   ASSERT(0);
00598   return false;
00599 }
00600 
00601 //=============================================================================
00603 
00612 //=============================================================================
00613 
00614 Engines::fileRef_ptr
00615 Engines_Parallel_Container_i::createFileRef(const char* origFileName)
00616 {
00617   std::string origName(origFileName);
00618   Engines::fileRef_var theFileRef = Engines::fileRef::_nil();
00619 
00620   if (origName[0] != '/')
00621   {
00622     INFOS("path of file to copy must be an absolute path begining with '/'");
00623     return Engines::fileRef::_nil();
00624   }
00625 
00626   if (CORBA::is_nil(_fileRef_map[origName]))
00627   {
00628     CORBA::Object_var obj=_poa->id_to_reference(*_id);
00629     Engines::Container_var pCont = Engines::Container::_narrow(obj);
00630     fileRef_i* aFileRef = new fileRef_i(pCont, origFileName);
00631     theFileRef = Engines::fileRef::_narrow(aFileRef->_this());
00632     _numInstanceMutex.lock() ; // lock to be alone (stl container write)
00633     _fileRef_map[origName] = theFileRef;
00634     _numInstanceMutex.unlock() ;
00635   }
00636 
00637   theFileRef =  Engines::fileRef::_duplicate(_fileRef_map[origName]);
00638   ASSERT(! CORBA::is_nil(theFileRef));
00639   return theFileRef._retn();
00640 }
00641 
00642 //=============================================================================
00647 //=============================================================================
00648 
00649 Engines::fileTransfer_ptr
00650 Engines_Parallel_Container_i::getFileTransfer()
00651 {
00652   Engines::fileTransfer_var aFileTransfer
00653     = Engines::fileTransfer::_duplicate(_fileTransfer);
00654   return aFileTransfer._retn();
00655 }
00656 
00657 
00658 Engines::Salome_file_ptr 
00659 Engines_Parallel_Container_i::createSalome_file(const char* origFileName) 
00660 {
00661   string origName(origFileName);
00662   if (CORBA::is_nil(_Salome_file_map[origName]))
00663   {
00664     Salome_file_i* aSalome_file = new Salome_file_i();
00665     try 
00666     {
00667       aSalome_file->setLocalFile(origFileName);
00668       aSalome_file->recvFiles();
00669     }
00670     catch (const SALOME::SALOME_Exception& e)
00671     {
00672       return Engines::Salome_file::_nil();
00673     }
00674 
00675     Engines::Salome_file_var theSalome_file = Engines::Salome_file::_nil();
00676     theSalome_file = Engines::Salome_file::_narrow(aSalome_file->_this());
00677     _numInstanceMutex.lock() ; // lock to be alone (stl container write)
00678     _Salome_file_map[origName] = theSalome_file;
00679     _numInstanceMutex.unlock() ;
00680   }
00681 
00682   Engines::Salome_file_ptr theSalome_file =  
00683     Engines::Salome_file::_duplicate(_Salome_file_map[origName]);
00684   ASSERT(!CORBA::is_nil(theSalome_file));
00685   return theSalome_file;
00686 }
00687 
00688 
00689 //=============================================================================
00691 
00710 //=============================================================================
00711 
00712 Engines::EngineComponent_ptr
00713 Engines_Parallel_Container_i::find_or_create_instance(std::string genericRegisterName)
00714 {
00715   Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil();
00716   try
00717   {
00718     std::string aGenRegisterName = genericRegisterName;
00719     // --- find a registered instance in naming service, or create
00720     std::string component_registerBase = _containerName + "/" + aGenRegisterName;
00721     CORBA::Object_var obj = _NS->ResolveFirst(component_registerBase.c_str());
00722     if (CORBA::is_nil( obj ))
00723     {
00724       iobject = create_component_instance(genericRegisterName.c_str(), 
00725                                           0); // force multiStudy instance here !
00726     }
00727     else
00728     { 
00729       iobject = Engines::EngineComponent::_narrow(obj) ;
00730       Engines_Component_i *servant = dynamic_cast<Engines_Component_i*>(_poa->reference_to_servant(iobject));
00731       ASSERT(servant)
00732       int studyId = servant->getStudyId();
00733       ASSERT (studyId >= 0);
00734       if (studyId != 0)  // monoStudy instance: NOK
00735       {
00736         iobject = Engines::EngineComponent::_nil();
00737         INFOS("load_impl & find_component_instance methods "
00738               << "NOT SUITABLE for mono study components");
00739       }
00740     }
00741   }
00742   catch (...)
00743   {
00744     INFOS( "Container_i::load_impl catched" ) ;
00745   }
00746   return iobject._retn();
00747 }
00748 
00749 //=============================================================================
00751 
00769 //=============================================================================
00770 Engines::EngineComponent_ptr
00771 Engines_Parallel_Container_i::createPythonInstance(std::string genericRegisterName, int studyId)
00772 {
00773 
00774   Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil();
00775 
00776   int numInstance = _numInstance;
00777   char aNumI[12];
00778   sprintf( aNumI , "%d" , numInstance ) ;
00779   std::string instanceName = genericRegisterName + "_inst_" + aNumI ;
00780   std::string component_registerName = _containerName + "/" + instanceName;
00781 
00782   Py_ACQUIRE_NEW_THREAD;
00783   PyObject *mainmod = PyImport_AddModule("__main__");
00784   PyObject *globals = PyModule_GetDict(mainmod);
00785   PyObject *pyCont = PyDict_GetItemString(globals, "pyCont");
00786   PyObject *result = PyObject_CallMethod(pyCont,
00787                                          (char*)"create_component_instance",
00788                                          (char*)"ssl",
00789                                          genericRegisterName.c_str(),
00790                                          instanceName.c_str(),
00791                                          studyId);
00792   const char *ior;
00793   const char *error;
00794   PyArg_ParseTuple(result,"ss", &ior, &error);
00795   string iors = ior;
00796   Py_DECREF(result);
00797   Py_RELEASE_NEW_THREAD;
00798 
00799   if( iors!="" )
00800   {
00801     CORBA::Object_var obj = _orb->string_to_object(iors.c_str());
00802     iobject = Engines::EngineComponent::_narrow(obj);
00803     _listInstances_map[instanceName] = iobject;
00804   }
00805   else
00806     std::cerr << "createPythonInstance ior is empty ! Error in creation" << std::endl;
00807 
00808   return iobject._retn();
00809 }
00810 
00811 //=============================================================================
00813 
00831 //=============================================================================
00832 Engines::EngineComponent_ptr
00833 Engines_Parallel_Container_i::createCPPInstance(std::string genericRegisterName,
00834                                                 void *handle,
00835                                                 int studyId)
00836 {
00837   MESSAGE("Entering Engines_Parallel_Container_i::createCPPInstance");
00838 
00839   // --- find the factory
00840 
00841   std::string aGenRegisterName = genericRegisterName;
00842   std::string factory_name = aGenRegisterName + string("Engine_factory");
00843 
00844   typedef  PortableServer::ObjectId * (*FACTORY_FUNCTION_2)
00845     (CORBA::ORB_ptr,
00846      PortableServer::POA_ptr, 
00847      PortableServer::ObjectId *, 
00848      const char *, 
00849      const char *) ;
00850 
00851   FACTORY_FUNCTION_2 Component_factory = NULL;
00852 #ifndef WIN32
00853   Component_factory = (FACTORY_FUNCTION_2)dlsym( handle, factory_name.c_str() );
00854 #else
00855   Component_factory = (FACTORY_FUNCTION_2)GetProcAddress( (HINSTANCE)handle, factory_name.c_str() );
00856 #endif
00857 
00858   if (!Component_factory)
00859   {
00860     INFOS("Can't resolve symbol: " + factory_name);
00861 #ifndef WIN32
00862     INFOS("dlerror() result is : " << dlerror());
00863 #endif
00864     return Engines::EngineComponent::_nil() ;
00865   }
00866 
00867   // --- create instance
00868   Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil() ;
00869   try
00870   {
00871     int numInstance = _numInstance;
00872     char aNumI[12];
00873     sprintf( aNumI , "%d" , numInstance );
00874     std::string instanceName = aGenRegisterName + "_inst_" + aNumI;
00875     std::string component_registerName =
00876       _containerName + "/" + instanceName;
00877 
00878     // --- Instanciate required CORBA object
00879 
00880     PortableServer::ObjectId *id; //not owner, do not delete (nore use var)
00881     id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str(),
00882                                aGenRegisterName.c_str() );
00883     if (id == NULL)
00884     {
00885       INFOS("Factory function returns NULL !");
00886       return iobject._retn();
00887     }
00888 
00889     // --- get reference & servant from id
00890     CORBA::Object_var obj = _poa->id_to_reference(*id);
00891     iobject = Engines::EngineComponent::_narrow(obj);
00892 
00893     Engines_Component_i *servant = 
00894       dynamic_cast<Engines_Component_i*>(_poa->reference_to_servant(iobject));
00895     ASSERT(servant);
00896     servant->_remove_ref(); // compensate previous id_to_reference 
00897     _listInstances_map[instanceName] = iobject;
00898     _cntInstances_map[aGenRegisterName] += 1;
00899 #if defined(_DEBUG_) || defined(_DEBUG)
00900     bool ret_studyId = servant->setStudyId(studyId);
00901     ASSERT(ret_studyId);
00902 #else
00903     servant->setStudyId(studyId);
00904 #endif
00905 
00906     // --- register the engine under the name
00907     //     containerName(.dir)/instanceName(.object)
00908     _NS->Register(iobject , component_registerName.c_str());
00909     MESSAGE( component_registerName.c_str() << " bound" );
00910   }
00911   catch (...)
00912   {
00913     INFOS( "Container_i::createInstance exception catched" );
00914   }
00915   return iobject._retn();
00916 }
00917 
00918 void
00919 Engines_Parallel_Container_i::create_paco_component_node_instance(const char* componentName,
00920                                                                   const char* proxy_containerName,
00921                                                                   CORBA::Long studyId)
00922 {
00923   // Init de la méthode
00924   char * proxy_ior;
00925   Engines::EngineComponent_PaCO_var work_node;
00926   std::string aCompName = componentName;
00927   std::string _proxy_containerName = proxy_containerName;
00928 
00929 #ifndef WIN32
00930   string impl_name = string ("lib") + aCompName +string("Engine.so");
00931 #else
00932   string impl_name = aCompName +string("Engine.dll");
00933 #endif
00934   void* handle = _library_map[impl_name];
00935   _numInstanceMutex.lock() ; // lock on the instance number
00936   _numInstance++ ;
00937   int numInstance = _numInstance ;
00938   _numInstanceMutex.unlock() ;
00939   char aNumI[12];
00940   sprintf( aNumI , "%d" , numInstance ) ;
00941   string instanceName = aCompName + "_inst_" + aNumI ;
00942 
00943   // Step 1 : Get proxy !
00944   string component_registerName = _proxy_containerName + "/" + instanceName;
00945   CORBA::Object_var temp = _NS->Resolve(component_registerName.c_str());
00946   Engines::EngineComponent_var obj_proxy = Engines::EngineComponent::_narrow(temp);
00947   if (CORBA::is_nil(obj_proxy))
00948   {
00949     INFOS("Proxy reference from NamingService is nil !");
00950     INFOS("Proxy name was : " << component_registerName);
00951     SALOME::ExceptionStruct es;
00952     es.type = SALOME::INTERNAL_ERROR;
00953     es.text = "Proxy reference from NamingService is nil !";
00954     throw SALOME::SALOME_Exception(es);
00955   }
00956   proxy_ior = _orb->object_to_string(obj_proxy);
00957 
00958   // Get factory
00959   string factory_name = aCompName + string("Engine_factory");
00960   FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
00961   if (!Component_factory)
00962   {
00963     INFOS("Can't resolve symbol : " + factory_name);
00964 #ifndef WIN32
00965     INFOS("dlerror() result is : " << dlerror());
00966 #endif
00967     std::string ex_text = "Can't resolve symbol : " + factory_name;
00968     SALOME::ExceptionStruct es;
00969     es.type = SALOME::INTERNAL_ERROR;
00970     es.text = CORBA::string_dup(ex_text.c_str());
00971     throw SALOME::SALOME_Exception(es);
00972   }
00973 
00974   try
00975   {
00976     char aNumI2[12];
00977     sprintf(aNumI2 , "%d" , getMyRank()) ;
00978     std::string instanceName = aCompName + "_inst_" + aNumI + "_work_node_" + aNumI2;
00979     std::string component_registerName = _containerName + "/" + instanceName;
00980 
00981     // --- Instanciate work node
00982     PortableServer::ObjectId *id ; //not owner, do not delete (nore use var)
00983     id = (Component_factory) (_orb, proxy_ior, getMyRank(), _poa, _id, instanceName.c_str(), componentName);
00984     CORBA::string_free(proxy_ior);
00985 
00986     // --- get reference & servant from id
00987     CORBA::Object_var obj = _poa->id_to_reference(*id);
00988     work_node = Engines::EngineComponent_PaCO::_narrow(obj) ;
00989     if (CORBA::is_nil(work_node))
00990     {
00991       INFOS("work_node reference from factory is nil !");
00992       SALOME::ExceptionStruct es;
00993       es.type = SALOME::INTERNAL_ERROR;
00994       es.text = "work_node reference from factory is nil !";
00995       throw SALOME::SALOME_Exception(es);
00996     }
00997     work_node->deploy();
00998     _NS->Register(work_node, component_registerName.c_str());
00999     _par_obj_inst_map[instanceName] = id;
01000     MESSAGE(component_registerName.c_str() << " bound" );
01001   }
01002   catch (...)
01003   {
01004     INFOS("Container_i::create_paco_component_node_instance exception catched");
01005     SALOME::ExceptionStruct es;
01006     es.type = SALOME::INTERNAL_ERROR;
01007     es.text = "Container_i::create_paco_component_node_instance exception catched";
01008     throw SALOME::SALOME_Exception(es);
01009   }
01010 }
01011 
01012 //=============================================================================
01014 
01017 //=============================================================================
01018 
01019 void Engines_Parallel_Container_i::decInstanceCnt(std::string genericRegisterName)
01020 {
01021   if(_cntInstances_map.count(genericRegisterName) !=0 )
01022   {
01023     std::string aGenRegisterName =genericRegisterName;
01024     MESSAGE("Engines_Parallel_Container_i::decInstanceCnt " << aGenRegisterName);
01025     ASSERT(_cntInstances_map[aGenRegisterName] > 0); 
01026     _numInstanceMutex.lock(); // lock to be alone
01027     // (see finalize_removal, load_component_Library)
01028     _cntInstances_map[aGenRegisterName] -= 1;
01029     SCRUTE(_cntInstances_map[aGenRegisterName]);
01030     if (_cntInstances_map[aGenRegisterName] == 0)
01031     {
01032       std::string impl_name =
01033         Engines_Component_i::GetDynLibraryName(aGenRegisterName.c_str());
01034       SCRUTE(impl_name);
01035       void* handle = _library_map[impl_name];
01036       ASSERT(handle);
01037       _toRemove_map[impl_name] = handle;
01038     }
01039     _numInstanceMutex.unlock();
01040   }
01041 }
01042 
01043 //=============================================================================
01045 
01048 //=============================================================================
01049 
01050 bool Engines_Parallel_Container_i::isPythonContainer(const char* ContainerName)
01051 {
01052   bool ret=false;
01053   return ret;
01054 }
01055 
01056 
01057 // Cette méthode permet de tenir à jour le compteur des
01058 // instances pour le container parallèle.
01059 // En effet losrque l'on charge un composant séquentielle seul
01060 // le compteur du noeud 0 est augmenté, il faut donc tenir les autres 
01061 // noeuds à jour.
01062 void
01063 Engines_Parallel_Container_i::updateInstanceNumber()
01064 {
01065   if (getMyRank() != 0)
01066   {
01067     _numInstanceMutex.lock();
01068     _numInstance++;
01069     _numInstanceMutex.unlock();
01070   }
01071 }
01072 
01078 void 
01079 Engines_Parallel_Container_i::copyFile(Engines::Container_ptr container, const char* remoteFile, const char* localFile)
01080 {
01081   Engines::fileTransfer_var fileTransfer = container->getFileTransfer();
01082 
01083   FILE* fp;
01084   if ((fp = fopen(localFile,"wb")) == NULL)
01085     {
01086       INFOS("file " << localFile << " cannot be open for writing");
01087       return;
01088     }
01089 
01090   CORBA::Long fileId = fileTransfer->open(remoteFile);
01091   if (fileId > 0)
01092     {
01093       Engines::fileBlock* aBlock;
01094       int toFollow = 1;
01095       int ctr=0;
01096       while (toFollow)
01097         {
01098           ctr++;
01099           SCRUTE(ctr);
01100           aBlock = fileTransfer->getBlock(fileId);
01101           toFollow = aBlock->length();
01102           SCRUTE(toFollow);
01103           CORBA::Octet *buf = aBlock->get_buffer();
01104           fwrite(buf, sizeof(CORBA::Octet), toFollow, fp);
01105           delete aBlock;
01106         }
01107       fclose(fp);
01108       MESSAGE("end of transfer");
01109       fileTransfer->close(fileId);
01110     }
01111   else
01112     {
01113       INFOS("open reference file for copy impossible");
01114     }
01115 }
01116 
01122 Engines::PyNode_ptr 
01123 Engines_Parallel_Container_i::createPyNode(const char* nodeName, const char* code)
01124 {
01125   INFOS("Python component not yet implemented");
01126   Engines::PyNode_var node= Engines::PyNode::_nil();
01127   return node._retn();
01128 }
01129 
01130 Engines::PyScriptNode_ptr 
01131 Engines_Parallel_Container_i::createPyScriptNode(const char* nodeName, const char* cod)
01132 {
01133   INFOS("Python script node not yet implemented");
01134   Engines::PyScriptNode_var node= Engines::PyScriptNode::_nil();
01135   return node._retn();
01136 }
01137 
01138 //=============================================================================
01142 //=============================================================================
01143 
01144 void ActSigIntHandler()
01145 {
01146 #ifndef WIN32
01147   struct sigaction SigIntAct ;
01148   SigIntAct.sa_sigaction = &SigIntHandler ;
01149   SigIntAct.sa_flags = SA_SIGINFO ;
01150 #endif
01151 
01152   // DEBUG 03.02.2005 : the first parameter of sigaction is not a mask of signals
01153   // (SIGINT | SIGUSR1) :
01154   // it must be only one signal ===> one call for SIGINT 
01155   // and an other one for SIGUSR1
01156 
01157 #ifndef WIN32
01158   if ( sigaction( SIGINT , &SigIntAct, NULL ) ) {
01159     perror("SALOME_Container main ") ;
01160     exit(0) ;
01161   }
01162   if ( sigaction( SIGUSR1 , &SigIntAct, NULL ) ) {
01163     perror("SALOME_Container main ") ;
01164     exit(0) ;
01165   }
01166   if ( sigaction( SIGUSR2 , &SigIntAct, NULL ) )
01167   {
01168     perror("SALOME_Container main ") ;
01169     exit(0) ;
01170   }
01171 
01172   //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
01173   //             use of streams (and so on) should never be used because :
01174   //             streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
01175   //             A stream operation may be interrupted by a signal and if the Handler use stream we
01176   //             may have a "Dead-Lock" ===HangUp
01177   //==INFOS is commented
01178   //  INFOS(pthread_self() << "SigIntHandler activated") ;
01179 #else  
01180   signal( SIGINT, SigIntHandler );
01181   signal( SIGUSR1, SigIntHandler );
01182 #endif
01183 
01184 }
01185 
01186 void SetCpuUsed();
01187 void CallCancelThread();
01188 
01189 #ifndef WIN32
01190 void SigIntHandler(int what , siginfo_t * siginfo ,
01191                    void * toto ) {
01192   //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
01193   //             use of streams (and so on) should never be used because :
01194   //             streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
01195   //             A stream operation may be interrupted by a signal and if the Handler use stream we
01196   //             may have a "Dead-Lock" ===HangUp
01197   //==MESSAGE is commented
01198   //  MESSAGE(pthread_self() << "SigIntHandler what     " << what << endl
01199   //          << "              si_signo " << siginfo->si_signo << endl
01200   //          << "              si_code  " << siginfo->si_code << endl
01201   //          << "              si_pid   " << siginfo->si_pid) ;
01202   if ( _Sleeping ) {
01203     _Sleeping = false ;
01204     //     MESSAGE("SigIntHandler END sleeping.") ;
01205     return ;
01206   }
01207   else {
01208     ActSigIntHandler() ;
01209     if ( siginfo->si_signo == SIGUSR1 ) {
01210       SetCpuUsed() ;
01211     }
01212     else if ( siginfo->si_signo == SIGUSR2 )
01213     {
01214       CallCancelThread() ;
01215     }
01216     else {
01217       _Sleeping = true ;
01218       //      MESSAGE("SigIntHandler BEGIN sleeping.") ;
01219       int count = 0 ;
01220       while( _Sleeping ) {
01221         sleep( 1 ) ;
01222         count += 1 ;
01223       }
01224       //      MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
01225     }
01226     return ;
01227   }
01228 }
01229 #else // Case WIN32
01230 void SigIntHandler( int what ) {
01231   MESSAGE( pthread_self() << "SigIntHandler what     " << what << endl );
01232   if ( _Sleeping ) {
01233     _Sleeping = false ;
01234     MESSAGE("SigIntHandler END sleeping.") ;
01235     return ;
01236   }
01237   else {
01238     ActSigIntHandler() ;
01239     if ( what == SIGUSR1 ) {
01240       SetCpuUsed() ;
01241     }
01242     else {
01243       _Sleeping = true ;
01244       MESSAGE("SigIntHandler BEGIN sleeping.") ;
01245       int count = 0 ;
01246       while( _Sleeping ) {
01247         Sleep( 1000 ) ;
01248         count += 1 ;
01249       }
01250       MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
01251     }
01252     return ;
01253   }
01254 }
01255 #endif