1 // Copyright (C) 2007-2010 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.
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_ParallelContainer : implementation of container and engine for ParallelKernel
24 // File : SALOME_ParallelContainer_i.cxx
25 // Author : André RIBES, EDF
27 #include "SALOME_ParallelContainer_i.hxx"
28 #include "SALOME_Component_i.hxx"
29 #include "SALOME_FileRef_i.hxx"
30 #include "SALOME_FileTransfer_i.hxx"
31 #include "SALOME_NamingService.hxx"
33 #include "utilities.h"
34 #include "Basics_Utils.hxx"
49 #include <paco_omni.h>
52 #include "Container_init_python.hxx"
55 bool _Sleeping = false ;
57 extern "C" {void ActSigIntHandler() ; }
59 extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; }
61 extern "C" {void SigIntHandler( int ) ; }
64 /*! \class Engines_Parallel_Container_i
65 * \brief C++ implementation of Engines::Container interface for parallel
66 * container implemented with PaCO++
69 //=============================================================================
73 //=============================================================================
75 Engines_Parallel_Container_i::Engines_Parallel_Container_i (CORBA::ORB_ptr orb,
78 PortableServer::POA_ptr poa,
79 std::string containerName,
80 bool isServantAloneInProcess) :
81 InterfaceParallel_impl(orb,ior,rank),
82 Engines::PACO_Container_serv(orb,ior,rank),
83 Engines::PACO_Container_base_serv(orb,ior,rank),
84 Engines::Container_serv(orb,ior,rank),
85 Engines::Container_base_serv(orb,ior,rank),
86 _numInstance(0),_isServantAloneInProcess(isServantAloneInProcess)
90 _hostname = Kernel_Utils::GetHostname();
91 _orb = CORBA::ORB::_duplicate(orb);
92 _poa = PortableServer::POA::_duplicate(poa);
94 // Add CORBA object to the poa
95 _id = _poa->activate_object(this);
97 CORBA::Object_var container_node = _poa->id_to_reference(*_id);
99 // Adding this servant to SALOME
100 _NS = new SALOME_NamingService();
102 _containerName = _NS->BuildContainerNameForNS(containerName.c_str(), _hostname.c_str());
104 // Ajout du numero de noeud
105 char node_number[12];
106 sprintf(node_number, "%d", getMyRank());
107 _containerName = _containerName + node_number;
109 // Init Python container part
110 CORBA::String_var sior = _orb->object_to_string(container_node);
111 std::string myCommand="pyCont = SALOME_Container.SALOME_Container_i('";
112 myCommand += _containerName + "','";
115 Py_ACQUIRE_NEW_THREAD;
116 PyRun_SimpleString("import SALOME_Container\n");
117 PyRun_SimpleString((char*)myCommand.c_str());
118 Py_RELEASE_NEW_THREAD;
120 // Init FileTransfer service
121 fileTransfer_i* aFileTransfer = new fileTransfer_i();
122 _fileTransfer = aFileTransfer->_this();
123 aFileTransfer->_remove_ref();
125 // Some signal handlers
129 //=============================================================================
133 //=============================================================================
135 Engines_Parallel_Container_i::~Engines_Parallel_Container_i()
137 MESSAGE("Container_i::~Container_i()");
144 //=============================================================================
145 //! Get container name
147 * CORBA attribute: Container name (see constructor)
149 //=============================================================================
151 char* Engines_Parallel_Container_i::name()
153 return CORBA::string_dup(_containerName.c_str()) ;
156 //=============================================================================
157 //! Get container working directory
159 * CORBA attribute: Container working directory
161 //=============================================================================
164 Engines_Parallel_Container_i::workingdir()
168 return CORBA::string_dup(wd) ;
171 //=============================================================================
172 //! Get container log file name
174 * CORBA attribute: Container log file name
176 //=============================================================================
179 Engines_Parallel_Container_i::logfilename()
181 return CORBA::string_dup(_logfilename.c_str()) ;
184 //! Set container log file name
186 Engines_Parallel_Container_i::logfilename(const char* name)
191 //=============================================================================
192 //! Get container host name
194 * CORBA method: Get the hostName of the Container (without domain extensions)
196 //=============================================================================
198 char* Engines_Parallel_Container_i::getHostName()
200 MESSAGE("Warning: getHostName of a parallel container returns the hostname of the first servant node");
201 return CORBA::string_dup(_hostname.c_str()) ;
204 //=============================================================================
205 //! Get container PID
207 * CORBA method: Get the PID (process identification) of the Container
209 //=============================================================================
211 CORBA::Long Engines_Parallel_Container_i::getPID()
213 MESSAGE("Warning: getPID of a parallel container returns the PID of the first servant node");
217 //=============================================================================
218 //! Ping the servant to check it is still alive
220 * CORBA method: check if servant is still alive
222 //=============================================================================
224 void Engines_Parallel_Container_i::ping()
226 MESSAGE("Engines_Parallel_Container_i::ping() my pid is "<< _pid);
229 //=============================================================================
230 //! Shutdown the container
232 * CORBA method, oneway: Server shutdown.
233 * - Container name removed from naming service,
234 * - servant deactivation,
235 * - orb shutdown if no other servants in the process
237 //=============================================================================
239 void Engines_Parallel_Container_i::Shutdown()
241 MESSAGE("Engines_Parallel_Container_i::Shutdown()");
243 /* For each seq component contained in this container
244 * tell it to self-destroy
246 std::map<std::string, Engines::Component_var>::iterator itm;
247 for (itm = _listInstances_map.begin(); itm != _listInstances_map.end(); itm++)
251 itm->second->destroy();
253 catch(const CORBA::Exception& e)
255 // ignore this entry and continue
259 // ignore this entry and continue
263 // Destroy each parallel component node...
264 std::map<std::string, PortableServer::ObjectId *>::iterator i;
265 for (i = _par_obj_inst_map.begin(); i != _par_obj_inst_map.end(); i++)
266 _poa->deactivate_object(*(i->second));
268 _NS->Destroy_FullDirectory(_containerName.c_str());
269 _NS->Destroy_Name(_containerName.c_str());
271 if(_isServantAloneInProcess)
273 MESSAGE("Effective Shutdown of container Begins...");
274 if(!CORBA::is_nil(_orb))
280 //=============================================================================
281 //! load a new component class
283 * CORBA method: load a new component class (Python or C++ implementation)
284 * \param componentName like COMPONENT
285 * try to make a Python import of COMPONENT,
286 * then a lib open of libCOMPONENTEngine.so
287 * \return true if dlopen successfull or already done, false otherwise
289 //=============================================================================
292 Engines_Parallel_Container_i::load_component_Library(const char* componentName, CORBA::String_out reason)
294 reason=CORBA::string_dup("");
296 MESSAGE("Begin of load_component_Library : " << componentName)
298 std::string aCompName = componentName;
300 std::string impl_name = string ("lib") + aCompName + string("Engine.so");
302 std::string impl_name = aCompName + string("Engine.dll");
305 _numInstanceMutex.lock(); // lock to be alone
307 // Check if already loaded or imported in the container
308 if (_toRemove_map.count(impl_name) != 0) _toRemove_map.erase(impl_name);
309 if (_library_map.count(impl_name) != 0)
311 MESSAGE("Library " << impl_name << " already loaded");
314 if (_library_map.count(aCompName) != 0)
316 MESSAGE("Python component already imported");
320 // --- try dlopen C++ component
323 MESSAGE("Try to load C++ component");
326 handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ;
328 handle = dlopen( impl_name.c_str() , 0 ) ;
332 _library_map[impl_name] = handle;
333 MESSAGE("Library " << impl_name << " loaded");
338 std::cerr << "Can't load shared library : " << impl_name << std::endl;
339 std::cerr << "error of dlopen: " << dlerror() << std::endl;
343 // --- try import Python component
346 MESSAGE("Try to import Python component "<<componentName);
347 Py_ACQUIRE_NEW_THREAD;
348 PyObject *mainmod = PyImport_AddModule("__main__");
349 PyObject *globals = PyModule_GetDict(mainmod);
350 PyObject *pyCont = PyDict_GetItemString(globals, "pyCont");
351 PyObject *result = PyObject_CallMethod(pyCont,
352 (char*)"import_component",
353 (char*)"s",componentName);
354 std::string ret_p= PyString_AsString(result);
356 Py_RELEASE_NEW_THREAD;
358 if (ret_p=="") // import possible: Python component
360 _library_map[aCompName] = (void *)pyCont; // any non O value OK
361 MESSAGE("import Python: " << aCompName <<" OK");
366 std::cerr << "Error in importing Python component : " << aCompName << std::endl;
370 _numInstanceMutex.unlock();
374 //=============================================================================
375 //! Create a new component instance
377 * CORBA method: Creates a new servant instance of a component.
378 * The servant registers itself to naming service and Registry.
379 * \param genericRegisterName Name of the component instance to register
380 * in Registry & Name Service (without _inst_n suffix)
381 * \param studyId 0 for multiStudy instance,
382 * study Id (>0) otherwise
383 * \return a loaded component
385 //=============================================================================
386 Engines::Component_ptr
387 Engines_Parallel_Container_i::create_component_instance(const char*genericRegisterName,
390 Engines::FieldsDict_var env = new Engines::FieldsDict;
392 Engines::Component_ptr compo = create_component_instance_env(genericRegisterName,studyId,env, reason);
393 CORBA::string_free(reason);
397 //=============================================================================
398 //! Create a new component instance
400 * CORBA method: Creates a new servant instance of a component.
401 * The servant registers itself to naming service and Registry.
402 * \param genericRegisterName Name of the component instance to register
403 * in Registry & Name Service (without _inst_n suffix)
404 * \param studyId 0 for multiStudy instance,
405 * study Id (>0) otherwise
406 * \param env dict of environment variables
407 * \return a loaded component
409 //=============================================================================
411 Engines::Component_ptr
412 Engines_Parallel_Container_i::create_component_instance_env(const char*genericRegisterName,
414 const Engines::FieldsDict& env,
415 CORBA::String_out reason)
417 MESSAGE("Begin of create_component_instance in node : " << getMyRank());
418 reason=CORBA::string_dup("");
422 INFOS("studyId must be > 0 for mono study instance, =0 for multiStudy");
423 return Engines::Component::_nil() ;
426 std::string aCompName = genericRegisterName;
428 std::string impl_name = string ("lib") + aCompName +string("Engine.so");
430 std::string impl_name = aCompName +string("Engine.dll");
433 _numInstanceMutex.lock();
436 // Test if the component lib is loaded
437 std::string type_of_lib("Not Loaded");
438 void* handle = _library_map[impl_name];
441 if (_library_map.count(aCompName) != 0 and !handle)
442 type_of_lib = "python";
444 if (type_of_lib == "Not Loaded")
446 std::cerr << "Component library is not loaded or imported ! lib was : " << aCompName << std::endl;
447 _numInstanceMutex.unlock();
448 return Engines::Component::_nil();
451 Engines::Component_var iobject = Engines::Component::_nil();
452 if (type_of_lib == "cpp")
453 iobject = createCPPInstance(aCompName, handle, studyId);
455 iobject = createPythonInstance(aCompName, studyId);
457 _numInstanceMutex.unlock();
458 return iobject._retn();
461 //=============================================================================
462 //! Find an existing (in the container) component instance
464 * CORBA method: Finds a servant instance of a component
465 * \param registeredName Name of the component in Registry or Name Service,
466 * without instance suffix number
467 * \param studyId 0 if instance is not associated to a study,
468 * >0 otherwise (== study id)
469 * \return the first instance found with same studyId
471 //=============================================================================
473 Engines::Component_ptr Engines_Parallel_Container_i::find_component_instance( const char* registeredName,
476 Engines::Component_var anEngine = Engines::Component::_nil();
477 std::map<std::string,Engines::Component_var>::iterator itm =_listInstances_map.begin();
478 while (itm != _listInstances_map.end())
480 std::string instance = (*itm).first;
482 if (instance.find(registeredName) == 0)
484 anEngine = (*itm).second;
485 if (studyId == anEngine->getStudyId())
487 return anEngine._retn();
492 return anEngine._retn();
495 //=============================================================================
496 //! Find or create a new component instance
498 * CORBA method: find or create an instance of the component (servant),
499 * load a new component class (dynamic library) if required,
500 * ---- FOR COMPATIBILITY WITH 2.2 ----
501 * ---- USE ONLY FOR MULTISTUDY INSTANCES ! --------
502 * The servant registers itself to naming service and Registry.
503 * \param genericRegisterName Name of the component to register
504 * in Registry & Name Service
505 * \param componentName Name of the constructed library of the component
506 * \return a loaded component
508 //=============================================================================
510 Engines::Component_ptr Engines_Parallel_Container_i::load_impl( const char* genericRegisterName,
511 const char* componentName )
513 Engines::Component_var iobject = Engines::Component::_nil();
515 if (load_component_Library(genericRegisterName,reason))
516 iobject = find_or_create_instance(genericRegisterName);
517 CORBA::string_free(reason);
518 return iobject._retn();
522 //=============================================================================
523 //! Remove the component instance from container
525 * CORBA method: Stops the component servant, and deletes all related objects
526 * \param component_i Component to be removed
528 //=============================================================================
530 void Engines_Parallel_Container_i::remove_impl(Engines::Component_ptr component_i)
532 ASSERT(!CORBA::is_nil(component_i));
533 std::string instanceName = component_i->instanceName();
534 _numInstanceMutex.lock() ; // lock to be alone (stl container write)
535 // Test if the component is in this container
536 std::map<std::string, Engines::Component_var>::iterator itm;
537 itm = _listInstances_map.find(instanceName);
538 if (itm != _listInstances_map.end())
540 MESSAGE("Unloading component " << instanceName);
541 _listInstances_map.erase(instanceName);
542 component_i->destroy() ;
543 _NS->Destroy_Name(instanceName.c_str());
546 std::cerr << "WARNING !!!! component instance was not in this container !!!" << std::endl;
547 _numInstanceMutex.unlock() ;
550 //=============================================================================
551 //! Unload component libraries from the container
553 * CORBA method: Discharges unused libraries from the container.
555 //=============================================================================
557 void Engines_Parallel_Container_i::finalize_removal()
559 MESSAGE("Finalize removal : dlclose");
560 MESSAGE("WARNING FINALIZE DOES CURRENTLY NOTHING !!!");
562 // (see decInstanceCnt, load_component_Library)
563 //std::map<std::string, void *>::iterator ith;
564 //for (ith = _toRemove_map.begin(); ith != _toRemove_map.end(); ith++)
566 // void *handle = (*ith).second;
567 // std::string impl_name= (*ith).first;
571 // SCRUTE(impl_name);
572 // dlclose(handle); // SALOME unstable after ...
573 // _library_map.erase(impl_name);
577 _numInstanceMutex.lock(); // lock to be alone
578 _toRemove_map.clear();
579 _numInstanceMutex.unlock();
582 //=============================================================================
583 //! Kill the container
585 * CORBA method: Kill the container process with exit(0).
586 * To remove : never returns !
588 //=============================================================================
590 bool Engines_Parallel_Container_i::Kill_impl()
592 MESSAGE("Engines_Parallel_Container_i::Kill() my pid is "<< _pid
593 << " my containerName is " << _containerName.c_str()
594 << " my machineName is " << _hostname.c_str());
595 INFOS("===============================================================");
596 INFOS("= REMOVE calls to Kill_impl in C++ container =");
597 INFOS("===============================================================");
603 //=============================================================================
604 //! Get or create a file reference object associated to a local file (to transfer it)
606 * CORBA method: get or create a fileRef object associated to a local file
607 * (a file on the computer on which runs the container server), which stores
608 * a list of (machine, localFileName) corresponding to copies already done.
610 * \param origFileName absolute path for a local file to copy on other
612 * \return a fileRef object associated to the file.
614 //=============================================================================
617 Engines_Parallel_Container_i::createFileRef(const char* origFileName)
619 std::string origName(origFileName);
620 Engines::fileRef_var theFileRef = Engines::fileRef::_nil();
622 if (origName[0] != '/')
624 INFOS("path of file to copy must be an absolute path begining with '/'");
625 return Engines::fileRef::_nil();
628 if (CORBA::is_nil(_fileRef_map[origName]))
630 CORBA::Object_var obj=_poa->id_to_reference(*_id);
631 Engines::Container_var pCont = Engines::Container::_narrow(obj);
632 fileRef_i* aFileRef = new fileRef_i(pCont, origFileName);
633 theFileRef = Engines::fileRef::_narrow(aFileRef->_this());
634 _numInstanceMutex.lock() ; // lock to be alone (stl container write)
635 _fileRef_map[origName] = theFileRef;
636 _numInstanceMutex.unlock() ;
639 theFileRef = Engines::fileRef::_duplicate(_fileRef_map[origName]);
640 ASSERT(! CORBA::is_nil(theFileRef));
641 return theFileRef._retn();
644 //=============================================================================
647 * \return a reference to the fileTransfer object
649 //=============================================================================
651 Engines::fileTransfer_ptr
652 Engines_Parallel_Container_i::getFileTransfer()
654 Engines::fileTransfer_var aFileTransfer
655 = Engines::fileTransfer::_duplicate(_fileTransfer);
656 return aFileTransfer._retn();
660 Engines::Salome_file_ptr
661 Engines_Parallel_Container_i::createSalome_file(const char* origFileName)
663 string origName(origFileName);
664 if (CORBA::is_nil(_Salome_file_map[origName]))
666 Salome_file_i* aSalome_file = new Salome_file_i();
669 aSalome_file->setLocalFile(origFileName);
670 aSalome_file->recvFiles();
672 catch (const SALOME::SALOME_Exception& e)
674 return Engines::Salome_file::_nil();
677 Engines::Salome_file_var theSalome_file = Engines::Salome_file::_nil();
678 theSalome_file = Engines::Salome_file::_narrow(aSalome_file->_this());
679 _numInstanceMutex.lock() ; // lock to be alone (stl container write)
680 _Salome_file_map[origName] = theSalome_file;
681 _numInstanceMutex.unlock() ;
684 Engines::Salome_file_ptr theSalome_file =
685 Engines::Salome_file::_duplicate(_Salome_file_map[origName]);
686 ASSERT(!CORBA::is_nil(theSalome_file));
687 return theSalome_file;
691 //=============================================================================
692 //! Finds an already existing component instance or create a new instance
694 * C++ method: Finds an already existing servant instance of a component, or
695 * create an instance.
696 * ---- USE ONLY FOR MULTISTUDY INSTANCES ! --------
697 * \param genericRegisterName Name of the component instance to register
698 * in Registry & Name Service,
699 * (without _inst_n suffix, like "COMPONENT")
700 * \return a loaded component
702 * example with names:
703 * aGenRegisterName = COMPONENT (= first argument)
704 * impl_name = libCOMPONENTEngine.so (= second argument)
705 * _containerName = /Containers/cli76ce/FactoryServer
706 * factoryName = COMPONENTEngine_factory
707 * component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
709 * instanceName = COMPONENT_inst_1
710 * component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
712 //=============================================================================
714 Engines::Component_ptr
715 Engines_Parallel_Container_i::find_or_create_instance(std::string genericRegisterName)
717 Engines::Component_var iobject = Engines::Component::_nil();
720 std::string aGenRegisterName = genericRegisterName;
721 // --- find a registered instance in naming service, or create
722 std::string component_registerBase = _containerName + "/" + aGenRegisterName;
723 CORBA::Object_var obj = _NS->ResolveFirst(component_registerBase.c_str());
724 if (CORBA::is_nil( obj ))
726 iobject = create_component_instance(genericRegisterName.c_str(),
727 0); // force multiStudy instance here !
731 iobject = Engines::Component::_narrow(obj) ;
732 Engines_Component_i *servant = dynamic_cast<Engines_Component_i*>(_poa->reference_to_servant(iobject));
734 int studyId = servant->getStudyId();
735 ASSERT (studyId >= 0);
736 if (studyId != 0) // monoStudy instance: NOK
738 iobject = Engines::Component::_nil();
739 INFOS("load_impl & find_component_instance methods "
740 << "NOT SUITABLE for mono study components");
746 INFOS( "Container_i::load_impl catched" ) ;
748 return iobject._retn();
751 //=============================================================================
752 //! Create a new Python component instance
754 * C++ method: create a servant instance of a component.
755 * \param genericRegisterName Name of the component instance to register
756 * in Registry & Name Service,
757 * (without _inst_n suffix, like "COMPONENT")
758 * \param handle loaded library handle
759 * \param studyId 0 for multiStudy instance,
760 * study Id (>0) otherwise
761 * \return a loaded component
763 * example with names:
764 * aGenRegisterName = COMPONENT (= first argument)
765 * _containerName = /Containers/cli76ce/FactoryServer
766 * factoryName = COMPONENTEngine_factory
767 * component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
768 * instanceName = COMPONENT_inst_1
769 * component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
771 //=============================================================================
772 Engines::Component_ptr
773 Engines_Parallel_Container_i::createPythonInstance(std::string genericRegisterName, int studyId)
776 Engines::Component_var iobject = Engines::Component::_nil();
778 int numInstance = _numInstance;
780 sprintf( aNumI , "%d" , numInstance ) ;
781 std::string instanceName = genericRegisterName + "_inst_" + aNumI ;
782 std::string component_registerName = _containerName + "/" + instanceName;
784 Py_ACQUIRE_NEW_THREAD;
785 PyObject *mainmod = PyImport_AddModule("__main__");
786 PyObject *globals = PyModule_GetDict(mainmod);
787 PyObject *pyCont = PyDict_GetItemString(globals, "pyCont");
788 PyObject *result = PyObject_CallMethod(pyCont,
789 (char*)"create_component_instance",
791 genericRegisterName.c_str(),
792 instanceName.c_str(),
796 PyArg_ParseTuple(result,"ss", &ior, &error);
799 Py_RELEASE_NEW_THREAD;
803 CORBA::Object_var obj = _orb->string_to_object(iors.c_str());
804 iobject = Engines::Component::_narrow(obj);
805 _listInstances_map[instanceName] = iobject;
808 std::cerr << "createPythonInstance ior is empty ! Error in creation" << std::endl;
810 return iobject._retn();
813 //=============================================================================
814 //! Create a new CPP component instance
816 * C++ method: create a servant instance of a component.
817 * \param genericRegisterName Name of the component instance to register
818 * in Registry & Name Service,
819 * (without _inst_n suffix, like "COMPONENT")
820 * \param handle loaded library handle
821 * \param studyId 0 for multiStudy instance,
822 * study Id (>0) otherwise
823 * \return a loaded component
825 * example with names:
826 * aGenRegisterName = COMPONENT (= first argument)
827 * _containerName = /Containers/cli76ce/FactoryServer
828 * factoryName = COMPONENTEngine_factory
829 * component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
830 * instanceName = COMPONENT_inst_1
831 * component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
833 //=============================================================================
834 Engines::Component_ptr
835 Engines_Parallel_Container_i::createCPPInstance(std::string genericRegisterName,
839 MESSAGE("Entering Engines_Parallel_Container_i::createCPPInstance");
841 // --- find the factory
843 std::string aGenRegisterName = genericRegisterName;
844 std::string factory_name = aGenRegisterName + string("Engine_factory");
846 typedef PortableServer::ObjectId * (*FACTORY_FUNCTION_2)
848 PortableServer::POA_ptr,
849 PortableServer::ObjectId *,
853 FACTORY_FUNCTION_2 Component_factory = NULL;
855 Component_factory = (FACTORY_FUNCTION_2)dlsym( handle, factory_name.c_str() );
857 Component_factory = (FACTORY_FUNCTION_2)GetProcAddress( (HINSTANCE)handle, factory_name.c_str() );
860 if (!Component_factory)
862 INFOS("Can't resolve symbol: " + factory_name);
864 INFOS("dlerror() result is : " << dlerror());
866 return Engines::Component::_nil() ;
869 // --- create instance
870 Engines::Component_var iobject = Engines::Component::_nil() ;
873 int numInstance = _numInstance;
875 sprintf( aNumI , "%d" , numInstance );
876 std::string instanceName = aGenRegisterName + "_inst_" + aNumI;
877 std::string component_registerName =
878 _containerName + "/" + instanceName;
880 // --- Instanciate required CORBA object
882 PortableServer::ObjectId *id; //not owner, do not delete (nore use var)
883 id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str(),
884 aGenRegisterName.c_str() );
887 INFOS("Factory function returns NULL !");
888 return iobject._retn();
891 // --- get reference & servant from id
892 CORBA::Object_var obj = _poa->id_to_reference(*id);
893 iobject = Engines::Component::_narrow(obj);
895 Engines_Component_i *servant =
896 dynamic_cast<Engines_Component_i*>(_poa->reference_to_servant(iobject));
898 servant->_remove_ref(); // compensate previous id_to_reference
899 _listInstances_map[instanceName] = iobject;
900 _cntInstances_map[aGenRegisterName] += 1;
901 #if defined(_DEBUG_) || defined(_DEBUG)
902 bool ret_studyId = servant->setStudyId(studyId);
905 servant->setStudyId(studyId);
908 // --- register the engine under the name
909 // containerName(.dir)/instanceName(.object)
910 _NS->Register(iobject , component_registerName.c_str());
911 MESSAGE( component_registerName.c_str() << " bound" );
915 INFOS( "Container_i::createInstance exception catched" );
917 return iobject._retn();
921 Engines_Parallel_Container_i::create_paco_component_node_instance(const char* componentName,
922 const char* proxy_containerName,
925 // Init de la méthode
927 Engines::Component_PaCO_var work_node;
928 std::string aCompName = componentName;
929 std::string _proxy_containerName = proxy_containerName;
932 string impl_name = string ("lib") + aCompName +string("Engine.so");
934 string impl_name = aCompName +string("Engine.dll");
936 void* handle = _library_map[impl_name];
937 _numInstanceMutex.lock() ; // lock on the instance number
939 int numInstance = _numInstance ;
940 _numInstanceMutex.unlock() ;
942 sprintf( aNumI , "%d" , numInstance ) ;
943 string instanceName = aCompName + "_inst_" + aNumI ;
945 // Step 1 : Get proxy !
946 string component_registerName = _proxy_containerName + "/" + instanceName;
947 CORBA::Object_var temp = _NS->Resolve(component_registerName.c_str());
948 Engines::Component_var obj_proxy = Engines::Component::_narrow(temp);
949 if (CORBA::is_nil(obj_proxy))
951 INFOS("Proxy reference from NamingService is nil !");
952 INFOS("Proxy name was : " << component_registerName);
953 SALOME::ExceptionStruct es;
954 es.type = SALOME::INTERNAL_ERROR;
955 es.text = "Proxy reference from NamingService is nil !";
956 throw SALOME::SALOME_Exception(es);
958 proxy_ior = _orb->object_to_string(obj_proxy);
961 string factory_name = aCompName + string("Engine_factory");
962 FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
963 if (!Component_factory)
965 INFOS("Can't resolve symbol : " + factory_name);
967 INFOS("dlerror() result is : " << dlerror());
969 std::string ex_text = "Can't resolve symbol : " + factory_name;
970 SALOME::ExceptionStruct es;
971 es.type = SALOME::INTERNAL_ERROR;
972 es.text = CORBA::string_dup(ex_text.c_str());
973 throw SALOME::SALOME_Exception(es);
979 sprintf(aNumI2 , "%d" , getMyRank()) ;
980 std::string instanceName = aCompName + "_inst_" + aNumI + "_work_node_" + aNumI2;
981 std::string component_registerName = _containerName + "/" + instanceName;
983 // --- Instanciate work node
984 PortableServer::ObjectId *id ; //not owner, do not delete (nore use var)
985 id = (Component_factory) (_orb, proxy_ior, getMyRank(), _poa, _id, instanceName.c_str(), componentName);
986 CORBA::string_free(proxy_ior);
988 // --- get reference & servant from id
989 CORBA::Object_var obj = _poa->id_to_reference(*id);
990 work_node = Engines::Component_PaCO::_narrow(obj) ;
991 if (CORBA::is_nil(work_node))
993 INFOS("work_node reference from factory is nil !");
994 SALOME::ExceptionStruct es;
995 es.type = SALOME::INTERNAL_ERROR;
996 es.text = "work_node reference from factory is nil !";
997 throw SALOME::SALOME_Exception(es);
1000 _NS->Register(work_node, component_registerName.c_str());
1001 _par_obj_inst_map[instanceName] = id;
1002 MESSAGE(component_registerName.c_str() << " bound" );
1006 INFOS("Container_i::create_paco_component_node_instance exception catched");
1007 SALOME::ExceptionStruct es;
1008 es.type = SALOME::INTERNAL_ERROR;
1009 es.text = "Container_i::create_paco_component_node_instance exception catched";
1010 throw SALOME::SALOME_Exception(es);
1014 //=============================================================================
1015 //! Decrement component instance reference count
1019 //=============================================================================
1021 void Engines_Parallel_Container_i::decInstanceCnt(std::string genericRegisterName)
1023 if(_cntInstances_map.count(genericRegisterName) !=0 )
1025 std::string aGenRegisterName =genericRegisterName;
1026 MESSAGE("Engines_Parallel_Container_i::decInstanceCnt " << aGenRegisterName);
1027 ASSERT(_cntInstances_map[aGenRegisterName] > 0);
1028 _numInstanceMutex.lock(); // lock to be alone
1029 // (see finalize_removal, load_component_Library)
1030 _cntInstances_map[aGenRegisterName] -= 1;
1031 SCRUTE(_cntInstances_map[aGenRegisterName]);
1032 if (_cntInstances_map[aGenRegisterName] == 0)
1034 std::string impl_name =
1035 Engines_Component_i::GetDynLibraryName(aGenRegisterName.c_str());
1037 void* handle = _library_map[impl_name];
1039 _toRemove_map[impl_name] = handle;
1041 _numInstanceMutex.unlock();
1045 //=============================================================================
1046 //! Indicate if container is a python one
1048 * Retrieves only with container naming convention if it is a python container
1050 //=============================================================================
1052 bool Engines_Parallel_Container_i::isPythonContainer(const char* ContainerName)
1059 // Cette méthode permet de tenir à jour le compteur des
1060 // instances pour le container parallèle.
1061 // En effet losrque l'on charge un composant séquentielle seul
1062 // le compteur du noeud 0 est augmenté, il faut donc tenir les autres
1065 Engines_Parallel_Container_i::updateInstanceNumber()
1067 if (getMyRank() != 0)
1069 _numInstanceMutex.lock();
1071 _numInstanceMutex.unlock();
1075 /*! \brief copy a file from a remote host (container) to the local host
1076 * \param container the remote container
1077 * \param remoteFile the file to copy locally from the remote host into localFile
1078 * \param localFile the local file
1081 Engines_Parallel_Container_i::copyFile(Engines::Container_ptr container, const char* remoteFile, const char* localFile)
1083 Engines::fileTransfer_var fileTransfer = container->getFileTransfer();
1086 if ((fp = fopen(localFile,"wb")) == NULL)
1088 INFOS("file " << localFile << " cannot be open for writing");
1092 CORBA::Long fileId = fileTransfer->open(remoteFile);
1095 Engines::fileBlock* aBlock;
1102 aBlock = fileTransfer->getBlock(fileId);
1103 toFollow = aBlock->length();
1105 CORBA::Octet *buf = aBlock->get_buffer();
1106 fwrite(buf, sizeof(CORBA::Octet), toFollow, fp);
1110 MESSAGE("end of transfer");
1111 fileTransfer->close(fileId);
1115 INFOS("open reference file for copy impossible");
1119 /*! \brief create a PyNode object to execute remote python code
1120 * \param nodeName the name of the node
1121 * \param code the python code to load
1122 * \return the PyNode
1125 Engines_Parallel_Container_i::createPyNode(const char* nodeName, const char* code)
1127 INFOS("Python component not yet implemented");
1128 Engines::PyNode_var node= Engines::PyNode::_nil();
1129 return node._retn();
1132 //=============================================================================
1136 //=============================================================================
1138 void ActSigIntHandler()
1141 struct sigaction SigIntAct ;
1142 SigIntAct.sa_sigaction = &SigIntHandler ;
1143 SigIntAct.sa_flags = SA_SIGINFO ;
1146 // DEBUG 03.02.2005 : the first parameter of sigaction is not a mask of signals
1147 // (SIGINT | SIGUSR1) :
1148 // it must be only one signal ===> one call for SIGINT
1149 // and an other one for SIGUSR1
1152 if ( sigaction( SIGINT , &SigIntAct, NULL ) ) {
1153 perror("SALOME_Container main ") ;
1156 if ( sigaction( SIGUSR1 , &SigIntAct, NULL ) ) {
1157 perror("SALOME_Container main ") ;
1160 if ( sigaction( SIGUSR2 , &SigIntAct, NULL ) )
1162 perror("SALOME_Container main ") ;
1166 //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
1167 // use of streams (and so on) should never be used because :
1168 // streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
1169 // A stream operation may be interrupted by a signal and if the Handler use stream we
1170 // may have a "Dead-Lock" ===HangUp
1171 //==INFOS is commented
1172 // INFOS(pthread_self() << "SigIntHandler activated") ;
1174 signal( SIGINT, SigIntHandler );
1175 signal( SIGUSR1, SigIntHandler );
1181 void CallCancelThread();
1184 void SigIntHandler(int what , siginfo_t * siginfo ,
1186 //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
1187 // use of streams (and so on) should never be used because :
1188 // streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
1189 // A stream operation may be interrupted by a signal and if the Handler use stream we
1190 // may have a "Dead-Lock" ===HangUp
1191 //==MESSAGE is commented
1192 // MESSAGE(pthread_self() << "SigIntHandler what " << what << endl
1193 // << " si_signo " << siginfo->si_signo << endl
1194 // << " si_code " << siginfo->si_code << endl
1195 // << " si_pid " << siginfo->si_pid) ;
1198 // MESSAGE("SigIntHandler END sleeping.") ;
1202 ActSigIntHandler() ;
1203 if ( siginfo->si_signo == SIGUSR1 ) {
1206 else if ( siginfo->si_signo == SIGUSR2 )
1208 CallCancelThread() ;
1212 // MESSAGE("SigIntHandler BEGIN sleeping.") ;
1214 while( _Sleeping ) {
1218 // MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
1224 void SigIntHandler( int what ) {
1225 MESSAGE( pthread_self() << "SigIntHandler what " << what << endl );
1228 MESSAGE("SigIntHandler END sleeping.") ;
1232 ActSigIntHandler() ;
1233 if ( what == SIGUSR1 ) {
1238 MESSAGE("SigIntHandler BEGIN sleeping.") ;
1240 while( _Sleeping ) {
1244 MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;