From a6e69d107ff10ff9de9475a9c381b535d5baea5c Mon Sep 17 00:00:00 2001 From: prascle Date: Mon, 18 Apr 2005 06:02:43 +0000 Subject: [PATCH] PR: container lifecycle, new design, first part --- idl/SALOME_Component.idl | 291 ++++--- idl/SALOME_ContainerManager.idl | 11 +- src/Container/Component_i.cxx | 521 ++++++++--- src/Container/Container_i.cxx | 809 ++++++++++++------ src/Container/SALOME_Component_i.hxx | 11 +- src/Container/SALOME_Container_i.hxx | 65 +- src/LifeCycleCORBA/SALOME_LifeCycleCORBA.cxx | 497 +++++++---- src/LifeCycleCORBA/SALOME_LifeCycleCORBA.hxx | 59 +- .../NamingService_WaitForServerReadiness.cxx | 1 - src/NamingService/SALOME_NamingService.cxx | 76 +- src/NamingService/SALOME_NamingService.hxx | 6 + src/Session/Session_ServerThread.cxx | 2 +- src/TestContainer/SALOME_TestComponent_i.cxx | 7 +- src/TestContainer/TestContainer.cxx | 161 ++-- 14 files changed, 1736 insertions(+), 781 deletions(-) diff --git a/idl/SALOME_Component.idl b/idl/SALOME_Component.idl index f60922c42..eae1f3d97 100644 --- a/idl/SALOME_Component.idl +++ b/idl/SALOME_Component.idl @@ -26,15 +26,15 @@ #ifndef _SALOME_COMPONENT_IDL_ #define _SALOME_COMPONENT_IDL_ /*! - -This is a package of interfaces used for connecting new components to %SALOME application. It also contains a set of interfaces used -for management of %MED component in %SALOME application. +This is a package of interfaces used for connecting new components to %SALOME +application. It also contains a set of interfaces used for management of %MED +component in %SALOME application. */ module Engines { -/*! + /*! General Key Value Structure to set or get properties, for component -*/ + */ struct KeyValuePair { string key; @@ -45,134 +45,221 @@ module Engines interface Component ; -/*! \brief Interface of the %Container + /*! \brief Interface of the %Container + This interface defines the process of loading and registration + of new components in %SALOME application + */ - This interface defines the process of loading and registration - of new components in %SALOME application -*/ interface Container { -/*! - Loads into the container a new component, registers it and starts it's CORBA servant. - \param nameToRegister Name of the component which will be registered in Registry (or Name Service) - \param componentName Name of the constructed library of the %component - \return a loaded component -*/ - Component load_impl(in string nameToRegister, in string componentName); + /*! + Loads a new component class (dynamic library). + \param componentLibraryName like libCOMPONENTEngine.so + \return true if load successfull or already done, false otherwise + */ + boolean load_component_Library(in string componentLibraryName); -/*! - Loads into the container a new component, registers it and starts it's CORBA servant. - \param nameToRegister Name used to register in Naming Service, the component instance - \param componentName Name of the %component - \return a new instance of the component or the registered component if already registered or Nil if not possible -*/ - Component instance(in string nameToRegister, in string componentName); + /*! + Creates a new servant instance of a component. + Component library must be loaded. + \param nameToRegister Name of the component which will be registered + in Registry and Name Service, + (instance bumber suffix added to the registered name) + \param componentName Name of the constructed library of the %component + \param studyId 0 if instance is not associated to a study, + >0 otherwise (== study id) + \return a loaded component + */ + Component create_component_instance(in string nameToRegister, + in string componentLibraryName, + in long studyId); -/*! - Stops the component servant, and deletes all related objects - \param component_i Component to be removed -*/ + /*! + Finds a servant instance of a component + \param registeredName Name of the component in Registry or Name Service, + without instance suffix number + \param studyId 0 if instance is not associated to a study, + >0 otherwise (== study id) + \return the first instance found with same studyId + */ + Component find_component_instance(in string registeredName, + in long studyId); + + /*! + Find a servant instance of a component, or create a new one. + Loads the component library if needed. + Only applicable to multiStudy components. + \param nameToRegister Name of the component which will be registered + in Registry (or Name Service) + \param componentName Name of the constructed library of the %component + \return a loaded component + */ + Component load_impl(in string nameToRegister, + in string componentName); + + /*! + Stops the component servant, and deletes all related objects + \param component_i Component to be removed + */ void remove_impl(in Component component_i); -/*! - Discharges all components from the container. -*/ + /*! + Discharges all components from the container. + */ void finalize_removal() ; -/*! - Determines whether the server has been loaded or not. -*/ + /*! + Determines whether the server has been loaded or not. + */ void ping(); -/*! - Name of the %container -*/ + + /*! + Name of the %container + */ readonly attribute string name ; -/*! - Name of the machine containing this container (location of the container). -*/ - readonly attribute string machineName ; -/*! - Returns True if the %container has been killed -*/ - boolean Kill_impl() ; -/*! - Shutdown the Container process. -*/ + + /*! + Shutdown the Container process. + */ oneway void Shutdown(); -/*! - Returns the hostname of the container -*/ + + /*! + Returns the hostname of the container + */ string getHostName(); -/*! - Returns the PID of the container -*/ + + /*! + Returns the PID of the container + */ long getPID(); + + /*! + Returns True if the %container has been killed. + Kept for Superv compilation but can't work, unless oneway... + TO REMOVE ! + */ + boolean Kill_impl() ; + + // -------------------------- removed ------------------------------- + + /*! + Loads into the container a new component, registers it and starts it's + CORBA servant. + \param nameToRegister Name used to register in Naming Service, + the component instance + \param componentName Name of the %component + \return a new instance of the component or the registered component + if already registered or Nil if not possible + */ + // Component instance(in string nameToRegister, in string componentName); + + + /*! + Name of the machine containing this container (location of the container). + */ + // readonly attribute string machineName ; + + }; -/*! \brief Interface of the %component - This interface is used for interaction between the %container and the %component and between - the components inside the container. -*/ + + + /*! \brief Interface of the %component + This interface is used for interaction between the %container and the + %component and between the components inside the container. + */ interface Component { -/*! - The name of the instance of the %Component -*/ + /*! + The name of the instance of the %Component + */ readonly attribute string instanceName ; -/*! - The name of the interface of the %Component -*/ + + /*! + The name of the interface of the %Component + */ readonly attribute string interfaceName ; -/*! - Determines whether the server has already been loaded or not. -*/ + + /*! + Determines whether the server has already been loaded or not. + */ void ping(); -/*! - Deactivates the %Component. -*/ + +// /*! +// Set study associated to component instance +// \param studyId +// (=0: multistudy component instance, +// >0: study id associated to this instance +// \return false if already set with a different value (change not possible) +// */ +// boolean setStudyId(in long studyId); + + /*! + get study associated to component instance + \return -1: not initialised (Internal Error) + 0: multistudy component instance + >0: study id associated to this instance + */ + long getStudyId(); + + /*! + Deactivates the %Component. + */ void destroy() ; -/*! - Returns the container that the %Component refers to. -*/ + + /*! + Returns the container that the %Component refers to. + */ Container GetContainerRef() ; -/*! - Gives a sequence of (key=string,value=any) to the component. - Base class component stores the sequence in a map. - The map is cleared before. - This map is for use by derived classes. -*/ + + /*! + Gives a sequence of (key=string,value=any) to the component. + Base class component stores the sequence in a map. + The map is cleared before. + This map is for use by derived classes. + */ void setProperties(in FieldsDict dico); -/*! - returns a previously stored map (key=string,value=any) as a sequence. - See setProperties(in FieldsDict dico). -*/ + + /*! + returns a previously stored map (key=string,value=any) as a sequence. + See setProperties(in FieldsDict dico). + */ FieldsDict getProperties(); -/*! - This method is used by the %SUPERVISOR component. It sets the names of the graph and of the node. - \param aGraphName Name of graph - \param aNodeName Name of node -*/ + + /*! + This method is used by the %SUPERVISOR component. It sets the names of + the graph and of the node. + \param aGraphName Name of graph + \param aNodeName Name of node + */ void Names( in string aGraphName , in string aNodeName ) ; -/*! - Returns True if the %Component has been killed. -*/ + + /*! + Returns True if the %Component has been killed. + */ boolean Kill_impl() ; -/*! - Returns True if the activity of the %Component has been stopped. (It's action can't be resumed) -*/ + + /*! + Returns True if the activity of the %Component has been stopped. + (It's action can't be resumed) + */ boolean Stop_impl() ; -/*! - Returns True if the activity of the %Component has been suspended. (It's action can be resumed) -*/ + + /*! + Returns True if the activity of the %Component has been suspended. + (It's action can be resumed) + */ boolean Suspend_impl() ; -/*! - Returns True if the activity of the %Component has been resumed. -*/ + + /*! + Returns True if the activity of the %Component has been resumed. + */ boolean Resume_impl() ; -/*! - Returns the Cpu used (long does not run with python !...) -*/ + + /*! + Returns the Cpu used (long does not run with python !...) + */ long CpuUsed_impl() ; } ; } ; diff --git a/idl/SALOME_ContainerManager.idl b/idl/SALOME_ContainerManager.idl index d8a57247e..9e9ca413a 100644 --- a/idl/SALOME_ContainerManager.idl +++ b/idl/SALOME_ContainerManager.idl @@ -9,7 +9,8 @@ module Engines /*! Type to describe properties of wanted resource. */ -struct MachineParameters { +struct MachineParameters +{ string container_name; string hostname; string OS; @@ -29,9 +30,13 @@ struct MachineParameters { */ interface ContainerManager { - Container FindOrStartContainer( in string containerName, in MachineList possibleComputers); + Container FindOrStartContainer( in string containerName, + in MachineList possibleComputers); + string FindBest(in MachineList possibleComputers); - MachineList GetFittingResources( in MachineParameters params, in string componentName ); + + MachineList GetFittingResources( in MachineParameters params, + in string componentName ); void Shutdown(); void ShutdownContainers(); } ; diff --git a/src/Container/Component_i.cxx b/src/Container/Component_i.cxx index ff343a2cc..04eff5a0d 100644 --- a/src/Container/Component_i.cxx +++ b/src/Container/Component_i.cxx @@ -26,6 +26,7 @@ // Module : SALOME // $Header$ +#define private protected #include "SALOME_Component_i.hxx" #include "SALOME_Container_i.hxx" #include "RegistryConnexion.hxx" @@ -34,16 +35,36 @@ #include #include #include "utilities.h" + +#include +#include +#include + using namespace std; extern bool _Sleeping ; static Engines_Component_i * theEngines_Component ; +bool Engines_Component_i::_isMultiStudy = true; +bool Engines_Component_i::_isMultiInstance = false; + +//============================================================================= +/*! + * + */ +//============================================================================= + Engines_Component_i::Engines_Component_i() { // MESSAGE("Component constructor"); } +//============================================================================= +/*! + * + */ +//============================================================================= + Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb, PortableServer::POA_ptr poa, PortableServer::ObjectId * contId, @@ -53,18 +74,33 @@ Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb, _instanceName(instanceName), _interfaceName(interfaceName), _myConnexionToRegistry(0), - _ThreadId(0) , _ThreadCpuUsed(0) , _Executed(false) , _graphName("") , _nodeName("") { + _ThreadId(0) , + _ThreadCpuUsed(0) , + _Executed(false) , + _graphName("") , + _nodeName(""), + _studyId(-1) +{ MESSAGE("Component constructor with instanceName "<< _instanceName); + SCRUTE(pd_refCount); _orb = CORBA::ORB::_duplicate(orb); _poa = PortableServer::POA::_duplicate(poa); _contId = contId ; CORBA::Object_var o = _poa->id_to_reference(*contId); // container ior... const CORBA::String_var ior = _orb->object_to_string(o); - _myConnexionToRegistry = new RegistryConnexion(0, 0, ior, "theSession", _instanceName.c_str()); + _myConnexionToRegistry = new RegistryConnexion(0, 0, ior,"theSession", + _instanceName.c_str()); _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif); + SCRUTE(pd_refCount); } +//============================================================================= +/*! + * + */ +//============================================================================= + // Constructeur pour composant parallele: ne pas faire appel au registry!! Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb, PortableServer::POA_ptr poa, @@ -72,44 +108,111 @@ Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb, const char *instanceName, const char *interfaceName, int flag, - bool notif ) - : _instanceName(instanceName), - _interfaceName(interfaceName), - _myConnexionToRegistry(0), - _ThreadId(0) , _ThreadCpuUsed(0) , _Executed(false) , _graphName("") , _nodeName("") { -// MESSAGE("Component constructor with instanceName "<< _instanceName); + bool notif ) : + _instanceName(instanceName), + _interfaceName(interfaceName), + _myConnexionToRegistry(0), + _ThreadId(0) , + _ThreadCpuUsed(0) , + _Executed(false) , + _graphName("") , + _nodeName(""), + _studyId(-1) +{ + // MESSAGE("Component constructor with instanceName "<< _instanceName); _orb = CORBA::ORB::_duplicate(orb); _poa = PortableServer::POA::_duplicate(poa); _contId = contId ; - // CORBA::Object_var myself = this->_this(); //appel a _this = increment reference _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif); } +//============================================================================= +/*! + * + */ +//============================================================================= + Engines_Component_i::~Engines_Component_i() { MESSAGE("Component destructor"); -// delete _myConnexionToRegistry; -// _myConnexionToRegistry = 0 ; } -char* Engines_Component_i::instanceName() { +//============================================================================= +/*! + * + */ +//============================================================================= + +char* Engines_Component_i::instanceName() +{ return CORBA::string_dup(_instanceName.c_str()) ; } -char* Engines_Component_i::interfaceName() { - return CORBA::string_dup(_interfaceName.c_str()) ; +//============================================================================= +/*! + * + */ +//============================================================================= + +char* Engines_Component_i::interfaceName() +{ + return CORBA::string_dup(_interfaceName.c_str()) ; +} + +//============================================================================= +/*! + * + */ +//============================================================================= + +CORBA::Boolean Engines_Component_i::setStudyId(CORBA::Long studyId) +{ + ASSERT( studyId >= 0); + CORBA::Boolean ret = false; + if (_studyId < 0) + { + _studyId = studyId; + ret = true; + } + else + if ( _studyId == studyId) ret = true; + return ret; } +//============================================================================= +/*! + * + */ +//============================================================================= + +CORBA::Long Engines_Component_i::getStudyId() +{ + return _studyId; +} + +//============================================================================= +/*! + * + */ +//============================================================================= + void Engines_Component_i::ping() { MESSAGE("Engines_Component_i::ping() pid "<< getpid() << " threadid " << pthread_self()); } +//============================================================================= +/*! + * + */ +//============================================================================= + void Engines_Component_i::destroy() { MESSAGE("Engines_Component_i::destroy()"); + SCRUTE(pd_refCount); delete _notifSupplier; _notifSupplier = 0; @@ -119,10 +222,18 @@ void Engines_Component_i::destroy() _poa->deactivate_object(*_id) ; CORBA::release(_poa) ; delete(_id) ; + SCRUTE(pd_refCount); _thisObj->_remove_ref(); + SCRUTE(pd_refCount); MESSAGE("Engines_Component_i::destroyed") ; } +//============================================================================= +/*! + * + */ +//============================================================================= + Engines::Container_ptr Engines_Component_i::GetContainerRef() { MESSAGE("Engines_Component_i::GetContainerRef"); @@ -130,12 +241,24 @@ Engines::Container_ptr Engines_Component_i::GetContainerRef() return Engines::Container::_narrow(o); } +//============================================================================= +/*! + * + */ +//============================================================================= + PortableServer::ObjectId * Engines_Component_i::getId() { // MESSAGE("PortableServer::ObjectId * Engines_Component_i::getId()"); return _id ; } +//============================================================================= +/*! + * + */ +//============================================================================= + void Engines_Component_i::setProperties(const Engines::FieldsDict& dico) { _fieldsDict.clear(); @@ -146,6 +269,12 @@ void Engines_Component_i::setProperties(const Engines::FieldsDict& dico) } } +//============================================================================= +/*! + * + */ +//============================================================================= + Engines::FieldsDict* Engines_Component_i::getProperties() { Engines::FieldsDict_var copie = new Engines::FieldsDict; @@ -161,24 +290,32 @@ Engines::FieldsDict* Engines_Component_i::getProperties() return copie._retn(); } +//============================================================================= +/*! + * + */ +//============================================================================= + void Engines_Component_i::beginService(const char *serviceName) { - MESSAGE(pthread_self() << "Send BeginService notification for " << serviceName << endl - << "Component instance : " << _instanceName << endl << endl); + MESSAGE(pthread_self() << "Send BeginService notification for " <>= value; - // --- todo: replace __GNUC__ test by an autoconf macro AC_CHECK_FUNC... + // --- todo: replace __GNUC__ test by an autoconf macro AC_CHECK_FUNC. #if defined __GNUC__ int ret = setenv(cle.c_str(), value, overwrite); #else @@ -202,7 +339,7 @@ void Engines_Component_i::beginService(const char *serviceName) std::string s(cle); s+='='; s+=value; - //char* cast because 1st arg of linux putenv function is not a const char* !!! + //char* cast because 1st arg of linux putenv function is not a const char* ! int ret=putenv((char *)s.c_str()); //End of CCRT porting #endif @@ -211,56 +348,104 @@ void Engines_Component_i::beginService(const char *serviceName) } } +//============================================================================= +/*! + * + */ +//============================================================================= + void Engines_Component_i::endService(const char *serviceName) { _ThreadCpuUsed = CpuUsed_impl() ; - MESSAGE(pthread_self() << " Send EndService notification for " << serviceName << endl - << " Component instance : " << _instanceName << " StartUsed " << _StartUsed << " _ThreadCpuUsed " - << _ThreadCpuUsed << endl << endl); + MESSAGE(pthread_self() << " Send EndService notification for " << serviceName + << endl << " Component instance : " << _instanceName << " StartUsed " + << _StartUsed << " _ThreadCpuUsed "<< _ThreadCpuUsed << endl < 0 && pthread_self() != _ThreadId ) { - RetVal = Killer( _ThreadId , 0 ) ; - _ThreadId = (pthread_t ) -1 ; - } + if ( _ThreadId > 0 && pthread_self() != _ThreadId ) + { + RetVal = Killer( _ThreadId , 0 ) ; + _ThreadId = (pthread_t ) -1 ; + } return RetVal ; } -bool Engines_Component_i::Suspend_impl() { +//============================================================================= +/*! + * + */ +//============================================================================= + +bool Engines_Component_i::Suspend_impl() +{ MESSAGE("Engines_Component_i::Suspend_i() pthread_t "<< pthread_self() << " pid " << getpid() << " instanceName " << _instanceName.c_str() << " interface " << _interfaceName.c_str() << " machineName " << GetHostname().c_str()<< " _id " << hex << _id << dec << " _ThreadId " << _ThreadId ); bool RetVal = false ; - if ( _ThreadId > 0 && pthread_self() != _ThreadId ) { - if ( _Sleeping ) { - return false ; - } - else { - RetVal = Killer( _ThreadId ,SIGINT ) ; + if ( _ThreadId > 0 && pthread_self() != _ThreadId ) + { + if ( _Sleeping ) + { + return false ; + } + else + { + RetVal = Killer( _ThreadId ,SIGINT ) ; + } } - } return RetVal ; } -bool Engines_Component_i::Resume_impl() { +//============================================================================= +/*! + * + */ +//============================================================================= + +bool Engines_Component_i::Resume_impl() +{ MESSAGE("Engines_Component_i::Resume_i() pthread_t "<< pthread_self() << " pid " << getpid() << " instanceName " << _instanceName.c_str() << " interface " << _interfaceName.c_str() << " machineName " << GetHostname().c_str()<< " _id " << hex << _id << dec << " _ThreadId " << _ThreadId ); bool RetVal = false ; - if ( _ThreadId > 0 && pthread_self() != _ThreadId ) { - if ( _Sleeping ) { - _Sleeping = false ; - RetVal = true ; - } - else { - RetVal = false ; + if ( _ThreadId > 0 && pthread_self() != _ThreadId ) + { + if ( _Sleeping ) + { + _Sleeping = false ; + RetVal = true ; + } + else + { + RetVal = false ; + } } - } return RetVal ; } -void SetCpuUsed() { +//============================================================================= +/*! + * + */ +//============================================================================= + +void SetCpuUsed() +{ theEngines_Component->SetCurCpu() ; } -void Engines_Component_i::SetCurCpu() { + +//============================================================================= +/*! + * + */ +//============================================================================= + +void Engines_Component_i::SetCurCpu() +{ _ThreadCpuUsed = CpuUsed() ; -// MESSAGE(pthread_self() << " Engines_Component_i::SetCurCpu() _ThreadCpuUsed " << _ThreadCpuUsed) ; + // MESSAGE(pthread_self() << + // " Engines_Component_i::SetCurCpu() _ThreadCpuUsed " << _ThreadCpuUsed) ; } -#include -#include -#include +//============================================================================= +/*! + * + */ +//============================================================================= -long Engines_Component_i::CpuUsed() { +long Engines_Component_i::CpuUsed() +{ long cpu = 0 ; struct rusage usage ; - if ( _ThreadId || _Executed ) { - if ( getrusage( RUSAGE_SELF , &usage ) == -1 ) { - perror("Engines_Component_i::CpuUsed") ; - return 0 ; + if ( _ThreadId || _Executed ) + { + if ( getrusage( RUSAGE_SELF , &usage ) == -1 ) + { + perror("Engines_Component_i::CpuUsed") ; + return 0 ; + } + cpu = usage.ru_utime.tv_sec - _StartUsed ; + // cout << pthread_self() << " Engines_Component_i::CpuUsed " << " " + // << _serviceName << usage.ru_utime.tv_sec << " - " << _StartUsed + // << " = " << cpu << endl ; + } + else + { + // cout << pthread_self() << "Engines_Component_i::CpuUsed _ThreadId " + // << _ThreadId << " " << _serviceName<< " _StartUsed " + // << _StartUsed << endl ; } - cpu = usage.ru_utime.tv_sec - _StartUsed ; -// cout << pthread_self() << " Engines_Component_i::CpuUsed " << " " << _serviceName -// << usage.ru_utime.tv_sec << " - " << _StartUsed << " = " << cpu << endl ; - } - else { -// cout << pthread_self() << "Engines_Component_i::CpuUsed _ThreadId " << _ThreadId << " " << _serviceName -// << " _StartUsed " << _StartUsed << endl ; - } return cpu ; } -CORBA::Long Engines_Component_i::CpuUsed_impl() { +//============================================================================= +/*! + * + */ +//============================================================================= + +CORBA::Long Engines_Component_i::CpuUsed_impl() +{ long cpu = 0 ; - if ( _ThreadId || _Executed ) { - if ( _ThreadId > 0 ) { - if ( pthread_self() != _ThreadId ) { - if ( _Sleeping ) { - } - else { -// Get Cpu in the appropriate thread with that object !... - theEngines_Component = this ; - Killer( _ThreadId ,SIGUSR1 ) ; - } + if ( _ThreadId || _Executed ) + { + if ( _ThreadId > 0 ) + { + if ( pthread_self() != _ThreadId ) + { + if ( _Sleeping ) + { + } + else + { + // Get Cpu in the appropriate thread with that object !... + theEngines_Component = this ; + Killer( _ThreadId ,SIGUSR1 ) ; + } cpu = _ThreadCpuUsed ; + } + else + { + _ThreadCpuUsed = CpuUsed() ; + cpu = _ThreadCpuUsed ; + // cout << pthread_self() << " Engines_Component_i::CpuUsed_impl " + // << _serviceName << " " << cpu << endl ; } - else { - _ThreadCpuUsed = CpuUsed() ; - cpu = _ThreadCpuUsed ; -// cout << pthread_self() << " Engines_Component_i::CpuUsed_impl " << _serviceName << " " << cpu -// << endl ; + } + else + { + cpu = _ThreadCpuUsed ; + // cout << pthread_self() << " Engines_Component_i::CpuUsed_impl " + // << _serviceName << " " << cpu<< endl ; } } - else { - cpu = _ThreadCpuUsed ; -// cout << pthread_self() << " Engines_Component_i::CpuUsed_impl " << _serviceName << " " << cpu -// << endl ; + else + { + // cout << pthread_self()<<"Engines_Component_i::CpuUsed_impl _ThreadId " + // <<_ThreadId <<" "<<_serviceName<<" _StartUsed "<<_StartUsed<Send(graphName(), nodeName(), event_type, message); } +//============================================================================= +/*! + * + */ +//============================================================================= + string Engines_Component_i::GetDynLibraryName(const char *componentName) { string ret="lib"; @@ -407,7 +672,15 @@ string Engines_Component_i::GetDynLibraryName(const char *componentName) return ret; } -string Engines_Component_i::BuildComponentNameForNS(const char *ComponentName, const char *ContainerName, const char *hostname) +//============================================================================= +/*! + * + */ +//============================================================================= + +string Engines_Component_i::BuildComponentNameForNS(const char *ComponentName, + const char *ContainerName, + const char *hostname) { string ret=Engines_Container_i::BuildContainerNameForNS(ContainerName,hostname); ret+="/"; diff --git a/src/Container/Container_i.cxx b/src/Container/Container_i.cxx index 2a4257217..c8528d979 100644 --- a/src/Container/Container_i.cxx +++ b/src/Container/Container_i.cxx @@ -26,11 +26,12 @@ // Module : SALOME // $Header$ +#define private public #include #include CORBA_SERVER_HEADER(SALOME_Component) #include "SALOME_Container_i.hxx" +#include "SALOME_Component_i.hxx" #include "SALOME_NamingService.hxx" -//#include "Utils_SINGLETON.hxx" #include "OpUtil.hxx" #include #include @@ -55,11 +56,23 @@ extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; } const char *Engines_Container_i::_defaultContainerName="FactoryServer"; +//============================================================================= +/*! + * Default constructor, not for use + */ +//============================================================================= + Engines_Container_i::Engines_Container_i () : - _numInstance(0) + _numInstance(0) { } +//============================================================================= +/*! + * Construtor to use + */ +//============================================================================= + Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb, PortableServer::POA_ptr poa, char *containerName , @@ -80,71 +93,119 @@ Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb, _argc = argc ; _argv = argv ; int i = strlen( _argv[ 0 ] ) - 1 ; - while ( i >= 0 ) { - if ( _argv[ 0 ][ i ] == '/' ) { - _argv[ 0 ][ i+1 ] = '\0' ; - break ; + while ( i >= 0 ) + { + if ( _argv[ 0 ][ i ] == '/' ) + { + _argv[ 0 ][ i+1 ] = '\0' ; + break ; + } + i -= 1 ; } - i -= 1 ; - } string hostname = GetHostname(); MESSAGE(hostname << " " << getpid() << " Engines_Container_i starting argc " << _argc << " Thread " << pthread_self() ) ; i = 0 ; - while ( _argv[ i ] ) { - MESSAGE(" argv" << i << " " << _argv[ i ]) ; - i++ ; - } - if ( argc != 4 ) { - MESSAGE("SALOME_Container usage : SALOME_Container ServerName -ORBInitRef NameService=corbaname::hostname:tcpipPortNumber") ; -// exit(0) ; - } - - SCRUTE(hostname); + while ( _argv[ i ] ) + { + MESSAGE(" argv" << i << " " << _argv[ i ]) ; + i++ ; + } + if ( argc != 4 ) + { + MESSAGE("SALOME_Container usage : SALOME_Container ServerName " << + "-ORBInitRef NameService=corbaname::hostname:tcpipPortNumber") ; + // exit(0) ; + } _containerName = BuildContainerNameForNS(containerName,hostname.c_str()); - + _orb = CORBA::ORB::_duplicate(orb) ; _poa = PortableServer::POA::_duplicate(poa) ; + + // Pour les containers paralleles: il ne faut pas enregistrer et activer + // le container generique, mais le container specialise - // Pour les containers paralleles: il ne faut pas enregistrer et activer le container generique, mais le container specialise - if(activAndRegist){ - _id = _poa->activate_object(this); - _NS = new SALOME_NamingService();//SINGLETON_::Instance() ; - //ASSERT(SINGLETON_::IsAlreadyExisting()) ; - _NS->init_orb( CORBA::ORB::_duplicate(_orb) ) ; - CORBA::Object_var obj=_poa->id_to_reference(*_id); - Engines::Container_var pCont - = Engines::Container::_narrow(obj); - SCRUTE(_containerName); - _NS->Register(pCont, _containerName.c_str()); - } + if(activAndRegist) + { + _id = _poa->activate_object(this); + _NS = new SALOME_NamingService(); + _NS->init_orb( CORBA::ORB::_duplicate(_orb) ) ; + CORBA::Object_var obj=_poa->id_to_reference(*_id); + Engines::Container_var pCont + = Engines::Container::_narrow(obj); + SCRUTE(_containerName); + _NS->Register(pCont, _containerName.c_str()); + } } +//============================================================================= +/*! + * Destructor + */ +//============================================================================= + Engines_Container_i::~Engines_Container_i() { MESSAGE("Container_i::~Container_i()"); delete _id; } +//============================================================================= +/*! + * CORBA attribute: Container name (see constructor) + */ +//============================================================================= + char* Engines_Container_i::name() { return CORBA::string_dup(_containerName.c_str()) ; } -char* Engines_Container_i::machineName() +//============================================================================= +/*! + * CORBA method: Get the hostName of the Container (without domain extensions) + */ +//============================================================================= + +char* Engines_Container_i::getHostName() { string s = GetHostname(); - MESSAGE("Engines_Container_i::machineName " << s); - return CORBA::string_dup(s.c_str()) ; + MESSAGE("Engines_Container_i::getHostName " << s); + return CORBA::string_dup(s.c_str()) ; } +//============================================================================= +/*! + * CORBA method: Get the PID (process identification) of the Container + */ +//============================================================================= + +CORBA::Long Engines_Container_i::getPID() +{ + return (CORBA::Long)getpid(); +} + +//============================================================================= +/*! + * CORBA method: check if servant is still alive + */ +//============================================================================= + void Engines_Container_i::ping() { MESSAGE("Engines_Container_i::ping() pid "<< getpid()); } -// shutdown corba server +//============================================================================= +/*! + * CORBA method, oneway: Server shutdown. + * - Container name removed from naming service, + * - servant deactivation, + * - orb shutdown if no other servants in the process + */ +//============================================================================= + void Engines_Container_i::Shutdown() { MESSAGE("Engines_Container_i::Shutdown()"); @@ -155,138 +216,414 @@ void Engines_Container_i::Shutdown() _orb->shutdown(0); } -//! Kill current container -bool Engines_Container_i::Kill_impl() { - MESSAGE("Engines_Container_i::Kill() pid "<< getpid() << " containerName " - << _containerName.c_str() << " machineName " - << GetHostname().c_str()); - exit( 0 ) ; -} -Engines::Component_ptr Engines_Container_i::load_impl( const char* nameToRegister, - const char* componentName ) { - - _numInstanceMutex.lock() ; // lock on the instance number - BEGIN_OF( "Container_i::load_impl " << componentName ) ; - _numInstance++ ; - char _aNumI[12]; - sprintf( _aNumI , "%d" , _numInstance ) ; +//============================================================================= +/*! + * CORBA method: load a new component class (dynamic library) + * \param componentLibraryName like "libCOMPONENTEngine.so" + * \return true if dlopen successfull or already done, false otherwise + */ +//============================================================================= - string _impl_name = componentName; - string _nameToRegister = nameToRegister; - string instanceName = _nameToRegister + "_inst_" + _aNumI ; - //SCRUTE(instanceName); +bool +Engines_Container_i::load_component_Library(const char* componentLibraryName) +{ + string impl_name = componentLibraryName; + SCRUTE(impl_name); - //string absolute_impl_name = _library_path + "lib" + _impl_name + ".so"; - string absolute_impl_name( _impl_name ) ; - SCRUTE(absolute_impl_name); + if (_library_map[impl_name]) + { + MESSAGE("Library " << impl_name << " already loaded"); + return true; + } void* handle; - handle = dlopen( absolute_impl_name.c_str() , RTLD_LAZY ) ; - if ( !handle ) { - INFOS("Can't load shared library : " << absolute_impl_name); - INFOS("error dlopen: " << dlerror()); - _numInstanceMutex.unlock() ; - return Engines::Component::_nil() ; - } - - string factory_name = _nameToRegister + string("Engine_factory"); - // SCRUTE(factory_name) ; + handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ; + if ( !handle ) + { + INFOS("Can't load shared library : " << impl_name); + INFOS("error dlopen: " << dlerror()); + return false; + } + else + { + _library_map[impl_name] = handle; + return true; + } +} - typedef PortableServer::ObjectId * (*FACTORY_FUNCTION) - (CORBA::ORB_ptr, - PortableServer::POA_ptr, - PortableServer::ObjectId *, - const char *, - const char *) ; - FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str()); +//============================================================================= +/*! + * CORBA method: Creates a new servant instance of a component. + * The servant registers itself to naming service and Registry. + * \param genericRegisterName Name of the component instance to register + * in Registry & Name Service (without _inst_n suffix) + * \param componentName Name of the constructed library of the component + * \param studyId 0 for multiStudy instance, + * study Id (>0) otherwise + * \return a loaded component + */ +//============================================================================= - char *error ; - if ( (error = dlerror() ) != NULL) { - INFOS("Can't resolve symbol: " + factory_name); - SCRUTE(error); - _numInstanceMutex.unlock() ; +Engines::Component_ptr +Engines_Container_i::create_component_instance(const char*genericRegisterName, + const char*componentLibraryName, + CORBA::Long studyId) +{ + if (studyId < 0) + { + INFOS("studyId must be > 0 for mono study instance, =0 for multiStudy"); return Engines::Component::_nil() ; } - string component_registerName = _containerName + "/" + _nameToRegister; - Engines::Component_var iobject = Engines::Component::_nil() ; - try { - CORBA::Object_var obj = _NS->Resolve( component_registerName.c_str() ) ; - if ( CORBA::is_nil( obj ) ) { -// Instanciate required CORBA object - PortableServer::ObjectId * id ; - id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str() , - _nameToRegister.c_str() ) ; - // get reference from id - obj = _poa->id_to_reference(*id); - iobject = Engines::Component::_narrow( obj ) ; - -// _numInstanceMutex.lock() ; // lock on the add on handle_map (necessary ?) - // register the engine under the name containerName.dir/nameToRegister.object - _NS->Register( iobject , component_registerName.c_str() ) ; - MESSAGE( "Container_i::load_impl " << component_registerName.c_str() << " bound" ) ; + string impl_name = componentLibraryName; + void* handle = _library_map[impl_name]; + if ( !handle ) + { + INFOS("shared library " << impl_name <<"must be loaded before instance"); + return Engines::Component::_nil() ; } - else { // JR : No ReBind !!! - MESSAGE( "Container_i::load_impl " << component_registerName.c_str() << " already bound" ) ; - iobject = Engines::Component::_narrow( obj ) ; + else + { + Engines::Component_var iobject = Engines::Component::_nil() ; + iobject = createInstance(genericRegisterName, + handle, + studyId); + return iobject._retn(); } - } - catch (...) { - INFOS( "Container_i::load_impl catched" ) ; - } +} -//Jr _numInstanceMutex.lock() ; // lock on the add on handle_map (necessary ?) - handle_map[instanceName] = handle; - END_OF("Container_i::load_impl"); - _numInstanceMutex.unlock() ; - return Engines::Component::_duplicate(iobject); +//============================================================================= +/*! + * CORBA method: Finds a servant instance of a component + * \param registeredName Name of the component in Registry or Name Service, + * without instance suffix number + * \param studyId 0 if instance is not associated to a study, + * >0 otherwise (== study id) + * \return the first instance found with same studyId + */ +//============================================================================= + +Engines::Component_ptr +Engines_Container_i::find_component_instance( const char* registeredName, + CORBA::Long studyId) +{ + ASSERT(0); +} + +//============================================================================= +/*! + * CORBA method: find or create an instance of the component (servant), + * load a new component class (dynamic library) if required, + * ---- FOR COMPATIBILITY WITH 2.2 ---- + * ---- USE ONLY FOR MULTISTUDY INSTANCES ! -------- + * The servant registers itself to naming service and Registry. + * \param genericRegisterName Name of the component to register + * in Registry & Name Service + * \param componentName Name of the constructed library of the component + * \return a loaded component + */ +//============================================================================= + +Engines::Component_ptr +Engines_Container_i::load_impl( const char* genericRegisterName, + const char* componentName ) +{ + Engines::Component_var iobject = Engines::Component::_nil() ; + if (load_component_Library(componentName)) + iobject = find_or_create_instance(genericRegisterName, componentName); + return iobject._retn(); } + + +//============================================================================= +/*! + * CORBA method: Stops the component servant, and deletes all related objects + * \param component_i Component to be removed + */ +//============================================================================= void Engines_Container_i::remove_impl(Engines::Component_ptr component_i) { ASSERT(! CORBA::is_nil(component_i)); string instanceName = component_i->instanceName() ; MESSAGE("unload component " << instanceName); + _listInstances_map.erase(instanceName); component_i->destroy() ; - MESSAGE("test key handle_map"); - _numInstanceMutex.lock() ; // lock on the remove on handle_map - if (handle_map[instanceName]) // if key does not exist, created & initialized null - { - remove_map[instanceName] = handle_map[instanceName] ; - } - else MESSAGE("pas d'entree handle_map"); - handle_map.erase(instanceName) ; - _numInstanceMutex.unlock() ; - MESSAGE("contenu handle_map"); - map::iterator im ; - for (im = handle_map.begin() ; im != handle_map.end() ; im ++) - { - MESSAGE("reste " << (*im).first); - } } +//============================================================================= +/*! + * CORBA method: Discharges all components from the container. + */ +//============================================================================= + void Engines_Container_i::finalize_removal() { MESSAGE("finalize unload : dlclose"); map::iterator im ; - _numInstanceMutex.lock() ; // lock on the explore remove_map & dlclose - for (im = remove_map.begin() ; im != remove_map.end() ; im ++) + _numInstanceMutex.lock() ; // lock on the explore _remove_map & dlclose + for (im = _remove_map.begin() ; im != _remove_map.end() ; im ++) { void * handle = (*im).second ; dlclose(handle) ; MESSAGE("dlclose " << (*im).first); } - remove_map.clear() ; + _remove_map.clear() ; _numInstanceMutex.unlock() ; - MESSAGE("remove_map.clear()"); + MESSAGE("_remove_map.clear()"); +} + +//============================================================================= +/*! + * CORBA method: Kill the container process with exit(0). + * To remove : never returns ! + */ +//============================================================================= + +bool Engines_Container_i::Kill_impl() +{ + MESSAGE("Engines_Container_i::Kill() pid "<< getpid() << " containerName " + << _containerName.c_str() << " machineName " + << GetHostname().c_str()); + INFOS("==============================================================="); + INFOS("= REMOVE calls to Kill_impl in C++ container ="); + INFOS("==============================================================="); + //exit( 0 ) ; + ASSERT(0); +} + +//============================================================================= +/*! + * C++ method: Finds an already existing servant instance of a component, or + * create an instance. + * ---- USE ONLY FOR MULTISTUDY INSTANCES ! -------- + * \param genericRegisterName Name of the component instance to register + * in Registry & Name Service, + * (without _inst_n suffix, like "COMPONENT") + * \param componentLibraryName like "libCOMPONENTEngine.so" + * \return a loaded component + * + * example with names: + * aGenRegisterName = COMPONENT (= first argument) + * impl_name = libCOMPONENTEngine.so (= second argument) + * _containerName = /Containers/cli76ce/FactoryServer + * factoryName = COMPONENTEngine_factory + * component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT + * + * instanceName = COMPONENT_inst_1 + * component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1 + */ +//============================================================================= + +Engines::Component_ptr +Engines_Container_i::find_or_create_instance(string genericRegisterName, + string componentLibraryName) +{ + string aGenRegisterName = genericRegisterName; + string impl_name = componentLibraryName; + void* handle = _library_map[impl_name]; + if ( !handle ) + { + INFOS("shared library " << impl_name <<"must be loaded before instance"); + return Engines::Component::_nil() ; + } + else + { + // --- find a registered instance in naming service, or create + + string component_registerBase = + _containerName + "/" + aGenRegisterName; + Engines::Component_var iobject = Engines::Component::_nil() ; + try + { + CORBA::Object_var obj = + _NS->ResolveFirst( component_registerBase.c_str()); + if ( CORBA::is_nil( obj ) ) + { + iobject = createInstance(genericRegisterName, + handle, + 0); // force multiStudy instance here ! + } + else + { + iobject = Engines::Component::_narrow( obj ) ; + Engines_Component_i *servant = + dynamic_cast + (_poa->reference_to_servant(iobject)); + ASSERT(servant) + int studyId = servant->getStudyId(); + ASSERT (studyId >= 0); + if (studyId == 0) // multiStudy instance, OK + { + // No ReBind ! + MESSAGE(component_registerBase.c_str()<<" already bound"); + } + else // monoStudy instance: NOK + { + iobject = Engines::Component::_nil(); + INFOS("load_impl & find_component_instance methods " + << "NOT SUITABLE for mono study components"); + } + } + } + catch (...) + { + INFOS( "Container_i::load_impl catched" ) ; + } + return iobject._retn(); + } } -void ActSigIntHandler() { +//============================================================================= +/*! + * C++ method: create a servant instance of a component. + * \param genericRegisterName Name of the component instance to register + * in Registry & Name Service, + * (without _inst_n suffix, like "COMPONENT") + * \param handle loaded library handle + * \param studyId 0 for multiStudy instance, + * study Id (>0) otherwise + * \return a loaded component + * + * example with names: + * aGenRegisterName = COMPONENT (= first argument) + * _containerName = /Containers/cli76ce/FactoryServer + * factoryName = COMPONENTEngine_factory + * component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT + * instanceName = COMPONENT_inst_1 + * component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1 + */ +//============================================================================= + +Engines::Component_ptr +Engines_Container_i::createInstance(string genericRegisterName, + void *handle, + int studyId) +{ + // --- find the factory + + string aGenRegisterName = genericRegisterName; + string factory_name = aGenRegisterName + string("Engine_factory"); + SCRUTE(factory_name) ; + + typedef PortableServer::ObjectId * (*FACTORY_FUNCTION) + (CORBA::ORB_ptr, + PortableServer::POA_ptr, + PortableServer::ObjectId *, + const char *, + const char *) ; + + FACTORY_FUNCTION Component_factory + = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str()); + + char *error ; + if ( (error = dlerror() ) != NULL) + { + INFOS("Can't resolve symbol: " + factory_name); + SCRUTE(error); + return Engines::Component::_nil() ; + } + + // --- create instance + + Engines::Component_var iobject = Engines::Component::_nil() ; + + try + { + _numInstanceMutex.lock() ; // lock on the instance number + _numInstance++ ; + int numInstance = _numInstance ; + _numInstanceMutex.unlock() ; + + char aNumI[12]; + sprintf( aNumI , "%d" , numInstance ) ; + string instanceName = aGenRegisterName + "_inst_" + aNumI ; + string component_registerName = + _containerName + "/" + instanceName; + + // --- Instanciate required CORBA object + + PortableServer::ObjectId * id ; + id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str(), + aGenRegisterName.c_str() ) ; + + // --- get reference & servant from id + + CORBA::Object_var obj = _poa->id_to_reference(*id); + iobject = Engines::Component::_narrow( obj ) ; + + Engines_Component_i *servant = + dynamic_cast(_poa->reference_to_servant(iobject)); + ASSERT(servant); + SCRUTE(servant->pd_refCount); + servant->_remove_ref(); // compensate previous id_to_reference + SCRUTE(servant->pd_refCount); + _listInstances_map[instanceName] = iobject; + SCRUTE(servant->pd_refCount); + ASSERT(servant->setStudyId(studyId)); + + // --- register the engine under the name + // containerName(.dir)/instanceName(.object) + + _NS->Register( iobject , component_registerName.c_str() ) ; + MESSAGE( component_registerName.c_str() << " bound" ) ; + } + catch (...) + { + INFOS( "Container_i::createInstance exception catched" ) ; + } + return iobject._retn(); +} + + +//============================================================================= +/*! + * Retrieves only with container naming convention if it is a python container + */ +//============================================================================= + +bool Engines_Container_i::isPythonContainer(const char* ContainerName) +{ + bool ret=false; + int len=strlen(ContainerName); + if(len>=2) + if(strcmp(ContainerName+len-2,"Py")==0) + ret=true; + return ret; +} + +//============================================================================= +/*! + * Returns string = container path + name, to use in Naming service + */ +//============================================================================= + +string Engines_Container_i::BuildContainerNameForNS(const char *ContainerName, + const char *hostname) +{ + string ret="/Containers/"; + ret += hostname; + ret+="/"; + if (strlen(ContainerName)== 0) + ret+=_defaultContainerName; + else + ret += ContainerName; + return ret; +} + +//============================================================================= +/*! + * + */ +//============================================================================= + +void ActSigIntHandler() +{ struct sigaction SigIntAct ; SigIntAct.sa_sigaction = &SigIntHandler ; SigIntAct.sa_flags = SA_SIGINFO ; -// DEBUG 03.02.2005 : the first parameter of sigaction is not a mask of signals (SIGINT | SIGUSR1) : -// it must be only one signal ===> one call for SIGINT and an other one for SIGUSR1 + // DEBUG 03.02.2005 : the first parameter of sigaction is not a mask of signals (SIGINT | SIGUSR1) : + // it must be only one signal ===> one call for SIGINT and an other one for SIGUSR1 if ( sigaction( SIGINT , &SigIntAct, NULL ) ) { perror("SALOME_Container main ") ; exit(0) ; @@ -301,7 +638,8 @@ void ActSigIntHandler() { void SetCpuUsed() ; void SigIntHandler(int what , siginfo_t * siginfo , - void * toto ) { + void * toto ) +{ MESSAGE(pthread_self() << "SigIntHandler what " << what << endl << " si_signo " << siginfo->si_signo << endl << " si_code " << siginfo->si_code << endl @@ -330,120 +668,107 @@ void SigIntHandler(int what , siginfo_t * siginfo , } } -// Get the PID of the Container - -CORBA::Long Engines_Container_i::getPID() { - return (CORBA::Long)getpid(); -} - -// Get the hostName of the Container - -char* Engines_Container_i::getHostName() { - return((char*)(GetHostname().c_str())); -} - -// Retrieves only with container naming convention if it is a python container -bool Engines_Container_i::isPythonContainer(const char* ContainerName) -{ - bool ret=false; - int len=strlen(ContainerName); - if(len>=2) - if(strcmp(ContainerName+len-2,"Py")==0) - ret=true; - return ret; -} - -string Engines_Container_i::BuildContainerNameForNS(const char *ContainerName, const char *hostname) -{ - string ret="/Containers/"; - ret += hostname; - ret+="/"; - if (strlen(ContainerName)== 0) - ret+=_defaultContainerName; - else - ret += ContainerName; - return ret; -} - - -/* - * Create one instance of componentName component and register it - * as nameToRegister in naming service +//============================================================================= +/*! + * CORBA method: Create one instance of componentName component + * and register it as genericRegisterName in naming service */ -Engines::Component_ptr Engines_Container_i::instance( const char* nameToRegister, - const char* componentName ) { +//============================================================================= - _numInstanceMutex.lock() ; // lock on the instance number - BEGIN_OF( "Container_i::instance " << componentName ) ; +// Engines::Component_ptr Engines_Container_i::instance( const char* genericRegisterName, +// const char* componentName ) +// { +// _numInstanceMutex.lock() ; // lock on the instance number +// BEGIN_OF( "Container_i::instance " << componentName ) ; - string _nameToRegister = nameToRegister; - string component_registerName = _containerName + "/" + _nameToRegister; +// string _genericRegisterName = genericRegisterName; +// string component_registerName = _containerName + "/" + _genericRegisterName; - Engines::Component_var iobject = Engines::Component::_nil() ; +// Engines::Component_var iobject = Engines::Component::_nil() ; - try { - CORBA::Object_var obj = _NS->Resolve( component_registerName.c_str() ) ; - if (! CORBA::is_nil( obj ) ) { - MESSAGE( "Container_i::instance " << component_registerName.c_str() << " already registered" ) ; - iobject = Engines::Component::_narrow( obj ) ; - } - else{ - string _compo_name = componentName; - string _impl_name = "lib" + _compo_name + "Engine.so"; - SCRUTE(_impl_name); +// try +// { +// CORBA::Object_var obj = _NS->Resolve( component_registerName.c_str() ) ; +// if (! CORBA::is_nil( obj ) ) +// { +// MESSAGE( "Container_i::instance " << component_registerName.c_str() << " already registered" ) ; +// iobject = Engines::Component::_narrow( obj ) ; +// } +// else +// { +// string _compo_name = componentName; +// string _impl_name = "lib" + _compo_name + "Engine.so"; +// SCRUTE(_impl_name); - void* handle; - handle = dlopen( _impl_name.c_str() , RTLD_LAZY ) ; - - if ( handle ) { - string factory_name = _compo_name + "Engine_factory"; - SCRUTE(factory_name) ; - - typedef PortableServer::ObjectId * (*FACTORY_FUNCTION) - (CORBA::ORB_ptr, - PortableServer::POA_ptr, - PortableServer::ObjectId *, - const char *, - const char *) ; - FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str()); - - char *error ; - if ( (error = dlerror() ) == NULL) { - // Instanciate required CORBA object - _numInstance++ ; - char _aNumI[12]; - sprintf( _aNumI , "%d" , _numInstance ) ; - string instanceName = _compo_name + "_inst_" + _aNumI ; - SCRUTE(instanceName); - - PortableServer::ObjectId * id ; - id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str() , - _nameToRegister.c_str() ) ; - // get reference from id - obj = _poa->id_to_reference(*id); - iobject = Engines::Component::_narrow( obj ) ; - - // register the engine under the name containerName.dir/nameToRegister.object - _NS->Register( iobject , component_registerName.c_str() ) ; - MESSAGE( "Container_i::instance " << component_registerName.c_str() << " registered" ) ; - handle_map[instanceName] = handle; - } - else{ - INFOS("Can't resolve symbol: " + factory_name); - SCRUTE(error); - } - } - else{ - INFOS("Can't load shared library : " << _impl_name); - INFOS("error dlopen: " << dlerror()); - } - } - } - catch (...) { - INFOS( "Container_i::instance exception caught" ) ; - } - END_OF("Container_i::instance"); - _numInstanceMutex.unlock() ; - return Engines::Component::_duplicate(iobject); -} - +// void* handle; +// handle = dlopen( _impl_name.c_str() , RTLD_LAZY ) ; + +// if ( handle ) +// { +// string factory_name = _compo_name + "Engine_factory"; +// SCRUTE(factory_name) ; + +// typedef PortableServer::ObjectId * (*FACTORY_FUNCTION) +// (CORBA::ORB_ptr, +// PortableServer::POA_ptr, +// PortableServer::ObjectId *, +// const char *, +// const char *) ; +// FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str()); + +// char *error ; +// if ( (error = dlerror() ) == NULL) +// { +// // Instanciate required CORBA object +// _numInstance++ ; +// char _aNumI[12]; +// sprintf( _aNumI , "%d" , _numInstance ) ; +// string instanceName = _compo_name + "_inst_" + _aNumI ; +// SCRUTE(instanceName); + +// PortableServer::ObjectId * id ; +// id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str() , +// _genericRegisterName.c_str() ) ; +// // get reference from id +// obj = _poa->id_to_reference(*id); +// iobject = Engines::Component::_narrow( obj ) ; + +// // register the engine under the name containerName.dir/genericRegisterName.object +// _NS->Register( iobject , component_registerName.c_str() ) ; +// MESSAGE( "Container_i::instance " << component_registerName.c_str() << " registered" ) ; +// _handle_map[instanceName] = handle; +// } +// else +// { +// INFOS("Can't resolve symbol: " + factory_name); +// SCRUTE(error); +// } +// } +// else +// { +// INFOS("Can't load shared library : " << _impl_name); +// INFOS("error dlopen: " << dlerror()); +// } +// } +// } +// catch (...) +// { +// INFOS( "Container_i::instance exception caught" ) ; +// } +// END_OF("Container_i::instance"); +// _numInstanceMutex.unlock() ; +// return Engines::Component::_duplicate(iobject); +// } + +//============================================================================= +/*! + * CORBA attribute: Machine Name (hostname without domain extensions) + */ +//============================================================================= + +// char* Engines_Container_i::machineName() +// { +// string s = GetHostname(); +// MESSAGE("Engines_Container_i::machineName " << s); +// return CORBA::string_dup(s.c_str()) ; +// } diff --git a/src/Container/SALOME_Component_i.hxx b/src/Container/SALOME_Component_i.hxx index 620ca1499..3c4c78b3d 100644 --- a/src/Container/SALOME_Component_i.hxx +++ b/src/Container/SALOME_Component_i.hxx @@ -91,15 +91,24 @@ public: void SetCurCpu() ; long CpuUsed() ; CORBA::Long CpuUsed_impl() ; + CORBA::Long getStudyId(); + bool setStudyId(CORBA::Long studyId); + static bool isMultiStudy(); + static bool isMultiInstance(); static std::string GetDynLibraryName(const char *componentName); - static std::string BuildComponentNameForNS(const char *ComponentName, const char *ContainerName, const char *hostname); + static std::string BuildComponentNameForNS(const char *ComponentName, + const char *ContainerName, + const char *hostname); protected: + static bool _isMultiStudy; + static bool _isMultiInstance; std::string _instanceName ; std::string _interfaceName ; std::string _serviceName ; std::string _graphName ; std::string _nodeName ; + int _studyId; // -1: not initialised; 0: multiStudy; >0: study CORBA::ORB_ptr _orb; PortableServer::POA_ptr _poa; PortableServer::ObjectId * _id; diff --git a/src/Container/SALOME_Container_i.hxx b/src/Container/SALOME_Container_i.hxx index 1f0eb93cc..6fcfafdda 100644 --- a/src/Container/SALOME_Container_i.hxx +++ b/src/Container/SALOME_Container_i.hxx @@ -56,33 +56,58 @@ public: bool isServantAloneInProcess = true); virtual ~Engines_Container_i(); + // --- CORBA methods - //! Load component in current container - Engines::Component_ptr load_impl(const char* nameToRegister, - const char* componentName); + bool load_component_Library(const char* componentLibraryName); + + Engines::Component_ptr + create_component_instance( const char* nameToRegister, + const char* componentLibraryName, + CORBA::Long studyId); // 0 for multiStudy + + Engines::Component_ptr + find_component_instance( const char* registeredName, + CORBA::Long studyId); // 0 for multiStudy + + Engines::Component_ptr + load_impl(const char* nameToRegister, + const char* componentName); - Engines::Component_ptr instance(const char* nameToRegister, - const char* componentName); - //! Unload component from current container void remove_impl(Engines::Component_ptr component_i); void finalize_removal(); + void Shutdown(); + char* getHostName(); + CORBA::Long getPID(); char* name(); - char* machineName(); void ping(); - void Shutdown(); - //! Kill current container + bool Kill_impl() ; - char* getHostName(); - CORBA::Long getPID(); + //char* machineName(); + //Engines::Component_ptr instance(const char* nameToRegister, + // const char* componentName); + + // --- local C++ methods + + Engines::Component_ptr + find_or_create_instance( std::string genericRegisterName, + std::string componentLibraryName); + + Engines::Component_ptr + createInstance(std::string genericRegisterName, + void *handle, + int studyId); + static bool isPythonContainer(const char* ContainerName); + static std::string BuildContainerNameForNS(const char *ContainerName, + const char *hostname); - static std::string BuildContainerNameForNS(const char *ContainerName, const char *hostname); - static const char *_defaultContainerName; protected: + static const char *_defaultContainerName; + SALOME_NamingService *_NS ; std::string _library_path; std::string _containerName; @@ -90,16 +115,18 @@ protected: PortableServer::POA_var _poa; PortableServer::ObjectId * _id ; int _numInstance ; - std::map handle_map ; - std::map remove_map ; - omni_mutex _numInstanceMutex ; // if several threads on the same object + std::map _library_map; // library names, loaded + std::map _listInstances_map; + std::map _handle_map ; + std::map _remove_map ; + omni_mutex _numInstanceMutex ; // if several threads on the same object //private: - int _argc ; + int _argc ; char** _argv ; - long _pid; - bool _isServantAloneInProcess; + long _pid; + bool _isServantAloneInProcess; }; #endif diff --git a/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.cxx b/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.cxx index af5848155..00dfee502 100644 --- a/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.cxx +++ b/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.cxx @@ -44,69 +44,75 @@ #include "SALOME_NamingService.hxx" using namespace std; +//============================================================================= +/*! + * Constructor + */ +//============================================================================= + SALOME_LifeCycleCORBA::SALOME_LifeCycleCORBA(SALOME_NamingService *ns) { _NS = ns; //add try catch - _NS->Change_Directory("/"); // mpv 250105: current directory may be not root (in SALOMEDS for an example) - CORBA::Object_var obj=_NS->Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS); + _NS->Change_Directory("/"); // mpv 250105: current directory may be not root + // (in SALOMEDS for an example) + // not enough: set a current directory in naming service is not thread safe + // if naming service instance is shared among several threads... + // ==> allways use absolute path and dot rely on current directory! + + CORBA::Object_var obj = + _NS->Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS); ASSERT( !CORBA::is_nil(obj)); _ContManager=Engines::ContainerManager::_narrow(obj); } +//============================================================================= +/*! + * Destructor + */ +//============================================================================= + SALOME_LifeCycleCORBA::~SALOME_LifeCycleCORBA() { } -string SALOME_LifeCycleCORBA::ContainerName( - const char * aComputerContainer , - string * theComputer , - string * theContainer ) { - char * ContainerName = new char [ strlen( aComputerContainer ) + 1 ] ; - strcpy( ContainerName , aComputerContainer ) ; - string theComputerContainer("/Containers/"); - char * slash = strchr( ContainerName , '/' ) ; - if ( !slash ) { - *theComputer = GetHostname() ; - theComputerContainer += *theComputer ; - theComputerContainer += "/" ; - *theContainer = ContainerName ; - theComputerContainer += *theContainer ; - } - else { - slash[ 0 ] = '\0' ; - slash += 1 ; - *theContainer = slash ; - if ( !strcmp( ContainerName , "localhost" ) ) { - *theComputer = GetHostname() ; - } - else { - *theComputer = ContainerName ; - } - theComputerContainer += *theComputer ; - theComputerContainer += "/" ; - theComputerContainer += *theContainer ; - } - delete [] ContainerName; - return theComputerContainer ; -} +//============================================================================= +/*! Public - + * Look for a fully qualified container name in Naming Service + * \param containerName name of the container to find. + * if containerName begins with "/Containers/" it's used as it is. + * We assume string = "/Containers/machine/aContainerName" + * else + * we assume string = "aContainerName" or "machine/aContainerName". + * string "/Containers/machine/aContainerName" is rebuilt. + * if machine = "localhost", machine replaced by GetHostname() + * \return Container CORBA reference or _nil if not found in Naming Service + */ +//============================================================================= -bool SALOME_LifeCycleCORBA::isKnownComponentClass(const char *componentName) +Engines::Container_ptr +SALOME_LifeCycleCORBA::FindContainer(const char *containerName) { - + ASSERT(_NS != NULL); + string cont ; + if ( strncmp( containerName , "/Containers/" , 12 ) ) + { // Compatibility ... + string theComputer ; + string theContainer ; + cont = ContainerName( containerName , &theComputer , &theContainer ) ; + } + else + { + cont = containerName ; + } try { - CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog"); - SALOME_ModuleCatalog::ModuleCatalog_var Catalog = - SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ; - SALOME_ModuleCatalog::Acomponent_ptr compoInfo = - Catalog->GetComponent(componentName); - if (CORBA::is_nil (compoInfo)) + SCRUTE( cont ); + CORBA::Object_var obj = _NS->Resolve( cont.c_str() ); + if( !CORBA::is_nil( obj ) ) { - INFOS("Catalog Error : Component not found in the catalog"); - return false; + return Engines::Container::_narrow( obj ) ; } - else return true; } catch (ServiceUnreachable&) { @@ -116,61 +122,98 @@ bool SALOME_LifeCycleCORBA::isKnownComponentClass(const char *componentName) { INFOS("Caught unknown exception."); } - return false; + return Engines::Container::_nil(); } -string SALOME_LifeCycleCORBA::ComputerPath( - const char * theComputer ) { - CORBA::String_var path; - CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog"); - SALOME_ModuleCatalog::ModuleCatalog_var Catalog = - SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ; - try { - path = Catalog->GetPathPrefix( theComputer ); - } - catch (SALOME_ModuleCatalog::NotFound&) { - INFOS("GetPathPrefix(" << theComputer << ") not found!"); - path = "" ; - } - SCRUTE( path ) ; - return CORBA::string_dup( path ) ; +//============================================================================= +/*! Public - + * Find and aready existing and registered component instance. + * \param params machine parameters like type or name... + * \param componentName the name of component class + * \param studyId default = 0 : multistudy instance + * \param instanceName default = "" : to retrieve a specific instance + * \return a CORBA reference of the component instance, or _nil if not found + */ +//============================================================================= + +Engines::Component_ptr +SALOME_LifeCycleCORBA::FindComponent(const Engines::MachineParameters& params, + const char *componentName, + int studyId, + const char *instanceName) +{ + ASSERT(0); } -Engines::Container_ptr SALOME_LifeCycleCORBA::FindContainer(const char *containerName) +//============================================================================= +/*! Public - + * Load a component instance on a container defined by machine parameters + * \param params machine parameters like type or name... + * \param componentName the name of component class + * \param studyId default = 0 : multistudy instance + * \return a CORBA reference of the component instance, or _nil if problem + */ +//============================================================================= + +Engines::Component_ptr +SALOME_LifeCycleCORBA::LoadComponent(const Engines::MachineParameters& params, + const char *componentName, + int studyId) { - ASSERT(_NS != NULL); - string cont ; - if ( strncmp( containerName , "/Containers/" , 12 ) ) { // Compatibility ... - string theComputer ; - string theContainer ; - cont = ContainerName( containerName , &theComputer , &theContainer ) ; - } - else { - cont = containerName ; - } - try { + ASSERT(0); +} - SCRUTE( cont ); +//============================================================================= +/*! Public - + * Find and aready existing and registered component instance or load a new + * component instance on a container defined by machine parameters + * \param params machine parameters like type or name... + * \param componentName the name of component class + * \param studyId default = 0 : multistudy instance + * \return a CORBA reference of the component instance, or _nil if problem + */ +//============================================================================= - CORBA::Object_var obj = _NS->Resolve( cont.c_str() ); - if( !CORBA::is_nil( obj ) ) { - return Engines::Container::_narrow( obj ) ; - } - } - catch (ServiceUnreachable&) { - INFOS("Caught exception: Naming Service Unreachable"); - } - catch (...) { - INFOS("Caught unknown exception."); - } - return Engines::Container::_nil(); +Engines::Component_ptr +SALOME_LifeCycleCORBA:: +FindOrLoad_Component(const Engines::MachineParameters& params, + const char *componentName, + int studyId) +{ + if (! isKnownComponentClass(componentName)) + return Engines::Component::_nil(); + + Engines::MachineList_var listOfMachine = + _ContManager->GetFittingResources(params,componentName); + Engines::Component_ptr ret= + FindComponent(params.container_name,componentName,listOfMachine); + if(CORBA::is_nil(ret)) + return LoadComponent(params.container_name,componentName,listOfMachine); + else + return ret; } -Engines::Component_ptr SALOME_LifeCycleCORBA::FindOrLoad_Component - (const char *containerName, - const char *componentName) +//============================================================================= +/*! Public - + * Find and aready existing and registered component instance or load a new + * component instance on a container defined by name + * \param containerName the name of container, under one of the forms + * - 1 localhost/aContainer + * - 2 aContainer + * - 3 /machine/aContainer + * (not the same rules as FindContainer() method base on protected method + * ContainerName() -- MUST BE CORRECTED --) + * \param componentName the name of component class + * \return a CORBA reference of the component instance, or _nil if problem + */ +//============================================================================= + +Engines::Component_ptr +SALOME_LifeCycleCORBA::FindOrLoad_Component(const char *containerName, + const char *componentName) { - if (! isKnownComponentClass(componentName)) return Engines::Component::_nil(); + if (!isKnownComponentClass(componentName)) return Engines::Component::_nil(); + char *stContainer=strdup(containerName); string st2Container(stContainer); int rg=st2Container.find("/"); @@ -179,50 +222,87 @@ Engines::Component_ptr SALOME_LifeCycleCORBA::FindOrLoad_Component stContainer[rg]='\0'; if(strcmp(stContainer,"localhost")==0) { - Engines::Component_ptr ret=FindOrLoad_Component(stContainer+rg+1,componentName); + Engines::Component_ptr ret=FindOrLoad_Component(stContainer+rg+1, + componentName); free(stContainer); return ret; } + else ASSERT(0); // no return in that case... + } + if(rg<0) + { + //containerName doesn't contain "/" => Local container + free(stContainer); + Engines::MachineList_var listOfMachine=new Engines::MachineList; + listOfMachine->length(1); + listOfMachine[0]=CORBA::string_dup(GetHostname().c_str()); + Engines::Component_ptr ret = FindComponent(containerName, + componentName, + listOfMachine.in()); + if(CORBA::is_nil(ret)) + return LoadComponent(containerName,componentName,listOfMachine); + else + return ret; + } + else + { + //containerName contains "/" => Remote container + stContainer[rg]='\0'; + Engines::MachineParameters_var params=new Engines::MachineParameters; + params->container_name=CORBA::string_dup(stContainer+rg+1); + params->hostname=CORBA::string_dup(stContainer); + params->OS=CORBA::string_dup("LINUX"); + free(stContainer); + return FindOrLoad_Component(params,componentName); } - if(rg<0) { - //containerName doesn't contain "/" => Local container - free(stContainer); - Engines::MachineList_var listOfMachine=new Engines::MachineList; - listOfMachine->length(1); - listOfMachine[0]=CORBA::string_dup(GetHostname().c_str()); - Engines::Component_ptr ret=FindComponent(containerName,componentName,listOfMachine.in()); - if(CORBA::is_nil(ret)) - return LoadComponent(containerName,componentName,listOfMachine); - else - return ret; - } - else { - //containerName contains "/" => Remote container - stContainer[rg]='\0'; - Engines::MachineParameters_var params=new Engines::MachineParameters; - params->container_name=CORBA::string_dup(stContainer+rg+1); - params->hostname=CORBA::string_dup(stContainer); - params->OS=CORBA::string_dup("LINUX"); - free(stContainer); - return FindOrLoad_Component(params,componentName); - } } -Engines::Component_ptr SALOME_LifeCycleCORBA::FindOrLoad_Component(const Engines::MachineParameters& params, - const char *componentName) +//============================================================================= +/*! Public - + * Check if the component class is known in module catalog + * \param componentName the name of component class + * \return true if found, false otherwise + */ +//============================================================================= + +bool SALOME_LifeCycleCORBA::isKnownComponentClass(const char *componentName) { - if (! isKnownComponentClass(componentName)) return Engines::Component::_nil(); - Engines::MachineList_var listOfMachine=_ContManager->GetFittingResources(params,componentName); - Engines::Component_ptr ret=FindComponent(params.container_name,componentName,listOfMachine); - if(CORBA::is_nil(ret)) - return LoadComponent(params.container_name,componentName,listOfMachine); - else - return ret; + + try + { + CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog"); + SALOME_ModuleCatalog::ModuleCatalog_var Catalog = + SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ; + SALOME_ModuleCatalog::Acomponent_ptr compoInfo = + Catalog->GetComponent(componentName); + if (CORBA::is_nil (compoInfo)) + { + INFOS("Catalog Error : Component not found in the catalog"); + return false; + } + else return true; + } + catch (ServiceUnreachable&) + { + INFOS("Caught exception: Naming Service Unreachable"); + } + catch (...) + { + INFOS("Caught unknown exception."); + } + return false; } -Engines::Component_ptr SALOME_LifeCycleCORBA::FindComponent(const char *containerName, - const char *componentName, - const Engines::MachineList& listOfMachines) +//============================================================================= +/*! Protected - + * + */ +//============================================================================= + +Engines::Component_ptr +SALOME_LifeCycleCORBA::FindComponent(const char *containerName, + const char *componentName, + const Engines::MachineList& listOfMachines) { if (! isKnownComponentClass(componentName)) return Engines::Component::_nil(); if(containerName[0]!='\0') @@ -233,8 +313,12 @@ Engines::Component_ptr SALOME_LifeCycleCORBA::FindComponent(const char *containe for(unsigned int i=0;iResolve(componentNameForNS.c_str()); + string componentNameForNS = + Engines_Component_i::BuildComponentNameForNS(componentName, + containerName, + currentMachine); + SCRUTE(componentNameForNS); + CORBA::Object_var obj=_NS->ResolveFirst(componentNameForNS.c_str()); if(!CORBA::is_nil(obj)) { machinesOK[lghtOfmachinesOK++]=CORBA::string_dup(currentMachine); @@ -244,8 +328,12 @@ Engines::Component_ptr SALOME_LifeCycleCORBA::FindComponent(const char *containe { machinesOK->length(lghtOfmachinesOK); CORBA::String_var bestMachine=_ContManager->FindBest(machinesOK); - string componentNameForNS=Engines_Component_i::BuildComponentNameForNS(componentName,containerName,bestMachine); - CORBA::Object_var obj=_NS->Resolve(componentNameForNS.c_str()); + string componentNameForNS = + Engines_Component_i::BuildComponentNameForNS(componentName, + containerName, + bestMachine); + SCRUTE(componentNameForNS); + CORBA::Object_var obj=_NS->ResolveFirst(componentNameForNS.c_str()); return Engines::Component::_narrow(obj); } else @@ -253,44 +341,69 @@ Engines::Component_ptr SALOME_LifeCycleCORBA::FindComponent(const char *containe } else { - //user specified no container name so trying to find a component in the best machine among listOfMachines + //user specified no container name so trying to find a component in + //the best machine among listOfMachines CORBA::String_var bestMachine=_ContManager->FindBest(listOfMachines); - //Normally look at all containers launched on bestMachine to see if componentName is already launched on one of them. To do.. - string componentNameForNS=Engines_Component_i::BuildComponentNameForNS(componentName,containerName,bestMachine); - CORBA::Object_var obj = _NS->Resolve(componentNameForNS.c_str()); + //Normally look at all containers launched on bestMachine to see if + //componentName is already launched on one of them. To do.. + string componentNameForNS = + Engines_Component_i::BuildComponentNameForNS(componentName, + containerName, + bestMachine); + SCRUTE(componentNameForNS); + CORBA::Object_var obj = _NS->ResolveFirst(componentNameForNS.c_str()); return Engines::Component::_narrow(obj); } } -Engines::Component_ptr SALOME_LifeCycleCORBA::LoadComponent(const char *containerName, const char *componentName, const Engines::MachineList& listOfMachines) +//============================================================================= +/*! Protected - + * + */ +//============================================================================= + +Engines::Component_ptr +SALOME_LifeCycleCORBA::LoadComponent(const char *containerName, + const char *componentName, + const Engines::MachineList& listOfMachines) { - Engines::Container_var cont=_ContManager->FindOrStartContainer(containerName,listOfMachines); + Engines::Container_var cont=_ContManager->FindOrStartContainer(containerName, + listOfMachines); string implementation=Engines_Component_i::GetDynLibraryName(componentName); return cont->load_impl(componentName, implementation.c_str()); } -Engines::Container_ptr SALOME_LifeCycleCORBA::FindOrStartContainer( - const string aComputerContainer , - const string theComputer , - const string theContainer ) { +//============================================================================= +/*! Protected - + * + */ +//============================================================================= + +Engines::Container_ptr +SALOME_LifeCycleCORBA::FindOrStartContainer(const string aComputerContainer , + const string theComputer , + const string theContainer ) +{ SCRUTE( aComputerContainer ) ; SCRUTE( theComputer ) ; SCRUTE( theContainer ) ; - Engines::Container_var aContainer = FindContainer( aComputerContainer.c_str() ) ; + Engines::Container_var aContainer = FindContainer(aComputerContainer.c_str()); - if ( !CORBA::is_nil( aContainer ) ) { - return aContainer ; - } + if ( !CORBA::is_nil( aContainer ) ) + { + return aContainer ; + } Engines::Container_var aFactoryServer ; bool pyCont = false ; int len = theContainer.length() ; - if ( !strcmp( &theContainer.c_str()[len-2] , "Py" ) ) { - pyCont = true ; - } + if ( !strcmp( &theContainer.c_str()[len-2] , "Py" ) ) + { + pyCont = true ; + } string addr=_NS->getIORaddr(); string CMD="SALOME_Container"; @@ -309,16 +422,94 @@ Engines::Container_ptr SALOME_LifeCycleCORBA::FindOrStartContainer( * Wait until the container is registered in Naming Service */ int count = 5 ; - while ( CORBA::is_nil( aFactoryServer ) && count ) { + while ( CORBA::is_nil( aFactoryServer ) && count ) + { sleep( 1 ) ; count-- ; if ( count != 10 ) - MESSAGE( count << ". Waiting for FactoryServer on " << theComputer) - aFactoryServer = FindContainer( aComputerContainer.c_str() ) ; - } - if ( !CORBA::is_nil( aFactoryServer ) ) { - return aFactoryServer; - } + MESSAGE( count << ". Waiting for FactoryServer on " << theComputer) + aFactoryServer = FindContainer( aComputerContainer.c_str() ) ; + } + if ( !CORBA::is_nil( aFactoryServer ) ) + { + return aFactoryServer; + } MESSAGE("SALOME_LifeCycleCORBA::StartOrFindContainer rsh failed") ; return Engines::Container::_nil(); } + +//============================================================================= +/*! Protected - + * \param aComputerContainer container name under one of the forms: + * - 1 aContainer + * - 2 machine/aContainer + * \param theComputer return computer name: + * - 1 machine = GetHostname() + * - 2 machine (localhost replaced by GetHostName()) + * \param theContainer return container name: + * - 1 aContainer + * - 2 aContainer + * \return /Containers/machine/aContainer + */ +//============================================================================= + +string SALOME_LifeCycleCORBA::ContainerName(const char *aComputerContainer , + string * theComputer , + string * theContainer ) +{ + char * ContainerName = new char [ strlen( aComputerContainer ) + 1 ] ; + strcpy( ContainerName , aComputerContainer ) ; + string theComputerContainer("/Containers/"); + char *slash = strchr( ContainerName , '/' ) ; // first occurence of '/' + if ( !slash ) // no '/', only the name, without path + { + *theComputer = GetHostname() ; + theComputerContainer += *theComputer ; + theComputerContainer += "/" ; + *theContainer = ContainerName ; + theComputerContainer += *theContainer ; + } + else + { + ASSERT( slash != aComputerContainer); // "/something..." not OK + slash[ 0 ] = '\0' ; + slash += 1 ; + *theContainer = slash ; + if ( !strcmp( ContainerName , "localhost" ) ) + { + *theComputer = GetHostname() ; + } + else + { + *theComputer = ContainerName ; + } + theComputerContainer += *theComputer ; + theComputerContainer += "/" ; + theComputerContainer += *theContainer ; + } + delete [] ContainerName; + return theComputerContainer ; +} + +//============================================================================= +/*! Protected - + * + */ +//============================================================================= + +string SALOME_LifeCycleCORBA::ComputerPath(const char * theComputer ) +{ + CORBA::String_var path; + CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog"); + SALOME_ModuleCatalog::ModuleCatalog_var Catalog = + SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ; + try { + path = Catalog->GetPathPrefix( theComputer ); + } + catch (SALOME_ModuleCatalog::NotFound&) { + INFOS("GetPathPrefix(" << theComputer << ") not found!"); + path = "" ; + } + SCRUTE( path ) ; + return CORBA::string_dup( path ) ; +} diff --git a/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.hxx b/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.hxx index ca91a238f..fc4e9d479 100644 --- a/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.hxx +++ b/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.hxx @@ -44,32 +44,63 @@ class SALOME_LifeCycleCORBA public: SALOME_LifeCycleCORBA(SALOME_NamingService *ns); virtual ~SALOME_LifeCycleCORBA(); - Engines::Container_ptr FindContainer(const char *containerName); // for supervision - Engines::Component_ptr FindOrLoad_Component(const Engines::MachineParameters& params, - const char *componentName); - Engines::Component_ptr FindOrLoad_Component(const char *containerName, - const char *componentName); + + Engines::Container_ptr + FindContainer(const char *containerName); // for supervision + + Engines::Component_ptr + FindComponent(const Engines::MachineParameters& params, + const char *componentName, + int studyId=0, + const char *instanceName=""); + + Engines::Component_ptr + LoadComponent(const Engines::MachineParameters& params, + const char *componentName, + int studyId=0); + + Engines::Component_ptr + FindOrLoad_Component(const Engines::MachineParameters& params, + const char *componentName, + int studyId=0); + + Engines::Component_ptr + FindOrLoad_Component(const char *containerName, + const char *componentName); // for compatibility + bool isKnownComponentClass(const char *componentName); + protected: - //! Establish if a component called "componentName" in a container called "containerName" exists among the list of resources - //! in "listOfMachines". This method uses Naming Service to find the component. - Engines::Component_ptr FindComponent(const char *containerName, - const char *componentName, - const Engines::MachineList& listOfMachines); - Engines::Component_ptr LoadComponent(const char *containerName, const char *componentName, const Engines::MachineList& listOfMachines); + /*! Establish if a component called "componentName" in a container called + * "containerName" + * exists among the list of resources in "listOfMachines". + * This method uses Naming Service to find the component. + */ + Engines::Component_ptr + FindComponent(const char *containerName, + const char *componentName, + const Engines::MachineList& listOfMachines); + Engines::Component_ptr + LoadComponent(const char *containerName, + const char *componentName, + const Engines::MachineList& listOfMachines); + SALOME_NamingService *_NS; Engines::ContainerManager_var _ContManager; //private: + std::string ContainerName( const char * aComputerContainer , std::string * theComputer , std::string * theContainer ) ; std::string ComputerPath( const char * theComputer ) ; - Engines::Container_ptr FindOrStartContainer(const std::string aComputerContainer , - const std::string theComputer , - const std::string theContainer ) ; + + Engines::Container_ptr + FindOrStartContainer(const std::string aComputerContainer , + const std::string theComputer , + const std::string theContainer ) ; } ; #endif diff --git a/src/NamingService/NamingService_WaitForServerReadiness.cxx b/src/NamingService/NamingService_WaitForServerReadiness.cxx index fcdf75f13..6108b2dc3 100644 --- a/src/NamingService/NamingService_WaitForServerReadiness.cxx +++ b/src/NamingService/NamingService_WaitForServerReadiness.cxx @@ -66,7 +66,6 @@ void NamingService_WaitForServerReadiness(SALOME_NamingService* NS, { if (serverName.length() == 0) { - //string curdir = NS->Current_Directory(); // to wait for naming service string dummyadr = NS->getIORaddr(); // to wait for naming service found = 1; break; // naming service found diff --git a/src/NamingService/SALOME_NamingService.cxx b/src/NamingService/SALOME_NamingService.cxx index 4beb6d4e3..47cab4451 100644 --- a/src/NamingService/SALOME_NamingService.cxx +++ b/src/NamingService/SALOME_NamingService.cxx @@ -80,7 +80,8 @@ SALOME_NamingService::~SALOME_NamingService() void SALOME_NamingService::init_orb(CORBA::ORB_ptr orb) { - // MESSAGE("SALOME_NamingService initialisation"); + MESSAGE("SALOME_NamingService initialisation"); + Utils_Locker lock(&_myMutex); _orb = orb ; _initialize_root_context(); } @@ -100,7 +101,8 @@ void SALOME_NamingService::Register(CORBA::Object_ptr ObjRef, const char* Path) throw(ServiceUnreachable) { - // MESSAGE("BEGIN OF Register: "<< Path); + MESSAGE("BEGIN OF Register: "<< Path); + Utils_Locker lock(&_myMutex); int dimension_Path = strlen(Path) + 1; char** resultat_resolve_Path = new char* [dimension_Path]; @@ -298,7 +300,8 @@ void SALOME_NamingService::Register(CORBA::Object_ptr ObjRef, CORBA::Object_ptr SALOME_NamingService::Resolve(const char* Path) throw(ServiceUnreachable) { - //MESSAGE("BEGIN OF Resolve: " << Path); + MESSAGE("BEGIN OF Resolve: " << Path); + Utils_Locker lock(&_myMutex); int dimension_Path = strlen(Path) + 1; char** resultat_resolve_Path = new char* [dimension_Path]; @@ -368,6 +371,53 @@ CORBA::Object_ptr SALOME_NamingService::Resolve(const char* Path) return _obj; } +//---------------------------------------------------------------------- +/*! Function : ResolveFirst + * Purpose : method to get an ObjRef with a symbolic name + * \param Path const char* argument like "/path/name" + * search the fist reference like "/path(.dir)/name*(.kind)" + * If the NamingService is out, the exception ServiceUnreachable is thrown + * \return the object reference + */ +//---------------------------------------------------------------------- + +CORBA::Object_ptr SALOME_NamingService::ResolveFirst(const char* Path) + throw(ServiceUnreachable) +{ + MESSAGE("ResolveFirst"); + Utils_Locker lock(&_myMutex); + SCRUTE(Path); + string thePath =Path; + string basePath ="/"; + string name = thePath; + string::size_type idx = thePath.rfind('/'); + if (idx != string::npos) // at least one '/' found + { + basePath = thePath.substr(0,idx); + name = thePath.substr(idx+1); + SCRUTE(basePath); + } + SCRUTE(name); + CORBA::Object_ptr obj = CORBA::Object::_nil(); + bool isOk = Change_Directory(basePath.c_str()); + if (isOk) + { + vector listElem = list_directory(); + vector::iterator its = listElem.begin(); + while (its != listElem.end()) + { + MESSAGE(*its); + if ((*its).find(name) == 0) + { + //string instance = basePath + "/" + *its; + return Resolve((*its).c_str()); + } + its++; + } + } + return obj; +} + //---------------------------------------------------------------------- /*! Function : Find * Purpose : method to research a name from the current directory @@ -384,7 +434,8 @@ CORBA::Object_ptr SALOME_NamingService::Resolve(const char* Path) int SALOME_NamingService::Find(const char* name) throw(ServiceUnreachable) { - // MESSAGE("BEGIN OF Find " << name); + MESSAGE("BEGIN OF Find " << name); + Utils_Locker lock(&_myMutex); CORBA::Long occurence_number = 0 ; try { @@ -411,7 +462,8 @@ int SALOME_NamingService::Find(const char* name) bool SALOME_NamingService::Create_Directory(const char* Path) throw(ServiceUnreachable) { - //MESSAGE("BEGIN OF Create_Directory"); + MESSAGE("BEGIN OF Create_Directory"); + Utils_Locker lock(&_myMutex); int dimension_Path = strlen(Path) + 1; char** resultat_resolve_Path= new char* [dimension_Path];; CORBA::Boolean _return_code = true ; @@ -525,7 +577,8 @@ bool SALOME_NamingService::Create_Directory(const char* Path) bool SALOME_NamingService::Change_Directory(const char* Path) throw(ServiceUnreachable) { - //MESSAGE("BEGIN OF Change_Directory " << Path); + MESSAGE("BEGIN OF Change_Directory " << Path); + Utils_Locker lock(&_myMutex); int dimension_Path = strlen(Path) + 1; char** resultat_resolve_Path = new char* [dimension_Path]; CORBA::Boolean _return_code = true ; @@ -617,7 +670,8 @@ bool SALOME_NamingService::Change_Directory(const char* Path) char* SALOME_NamingService::Current_Directory() throw(ServiceUnreachable) { - //MESSAGE("BEGIN OF Current_Directory"); + MESSAGE("BEGIN OF Current_Directory"); + Utils_Locker lock(&_myMutex); CosNaming::NamingContext_var _ref_context = _current_context; @@ -672,6 +726,7 @@ void SALOME_NamingService::list() throw(ServiceUnreachable) { MESSAGE("Begin of list"); + Utils_Locker lock(&_myMutex); CosNaming::BindingList_var _binding_list; CosNaming::BindingIterator_var _binding_iterator; unsigned long nb=0 ; // for using only the BindingIterator to access the bindings @@ -748,6 +803,8 @@ vector SALOME_NamingService::list_directory() vector SALOME_NamingService::list_directory_recurs() throw(ServiceUnreachable) { + MESSAGE("list_directory_recurs"); + Utils_Locker lock(&_myMutex); vector _list ; char *currentDir=Current_Directory(); _list_directory_recurs(_list,0,currentDir); @@ -768,6 +825,7 @@ void SALOME_NamingService::Destroy_Name(const char* Path) throw(ServiceUnreachable) { MESSAGE("BEGIN OF Destroy_Name"); + Utils_Locker lock(&_myMutex); int dimension_Path = strlen(Path) + 1; char** resultat_resolve_Path = new char* [dimension_Path]; @@ -889,6 +947,7 @@ void SALOME_NamingService::Destroy_Directory(const char* Path) throw(ServiceUnreachable) { MESSAGE("BEGIN OF Destroy_Directory"); + Utils_Locker lock(&_myMutex); int dimension_Path = strlen(Path) + 1; char** resultat_resolve_Path = new char* [dimension_Path]; @@ -1383,6 +1442,7 @@ void SALOME_NamingService::_list_directory_recurs(vector& myList, const //---------------------------------------------------------------------- -char * SALOME_NamingService::getIORaddr(){ +char * SALOME_NamingService::getIORaddr() +{ return _orb->object_to_string(_root_context); } diff --git a/src/NamingService/SALOME_NamingService.hxx b/src/NamingService/SALOME_NamingService.hxx index db9c39e17..1f3205498 100644 --- a/src/NamingService/SALOME_NamingService.hxx +++ b/src/NamingService/SALOME_NamingService.hxx @@ -33,6 +33,7 @@ #include #include #include +#include "Utils_Mutex.hxx" //class ServiceUnreachable; #include "ServiceUnreachable.hxx" @@ -60,6 +61,10 @@ public: CORBA::Object_ptr Resolve(const char* Path) throw( ServiceUnreachable); + //! method to get an ObjRef, given a symbolic name without instance suffix "/Path/Name*.kind" + CORBA::Object_ptr ResolveFirst(const char* Path) + throw( ServiceUnreachable); + //! method to research a name from the naming service's current directory int Find(const char* name) throw(ServiceUnreachable); @@ -101,6 +106,7 @@ public: char * getIORaddr(); protected: + Utils_Mutex _myMutex; CORBA::ORB_ptr _orb; CosNaming::NamingContext_var _root_context, _current_context; diff --git a/src/Session/Session_ServerThread.cxx b/src/Session/Session_ServerThread.cxx index d3bf23b36..1b01f3152 100644 --- a/src/Session/Session_ServerThread.cxx +++ b/src/Session/Session_ServerThread.cxx @@ -385,7 +385,7 @@ void Session_ServerThread::ActivateContainer(int argc, } Engines_Container_i * myContainer - = new Engines_Container_i(_orb, factory_poa, containerName , argc , argv , true , false); + = new Engines_Container_i(_orb, _root_poa, containerName , argc , argv , true , false); } catch(CORBA::SystemException&) { diff --git a/src/TestContainer/SALOME_TestComponent_i.cxx b/src/TestContainer/SALOME_TestComponent_i.cxx index 413fd2fa0..64772b14e 100644 --- a/src/TestContainer/SALOME_TestComponent_i.cxx +++ b/src/TestContainer/SALOME_TestComponent_i.cxx @@ -26,6 +26,7 @@ // Module : SALOME // $Header$ +#define private protected #include "utilities.h" #include "SALOME_TestComponent_i.hxx" #include @@ -40,10 +41,10 @@ Engines_TestComponent_i::Engines_TestComponent_i(CORBA::ORB_ptr orb, const char *interfaceName) : Engines_Component_i(orb, poa, contId, instanceName, interfaceName) { - MESSAGE("activate object") + MESSAGE("activate object"); _thisObj = this ; _id = _poa->activate_object(_thisObj); - //SCRUTE(this) + SCRUTE(pd_refCount); } Engines_TestComponent_i::Engines_TestComponent_i() @@ -52,12 +53,14 @@ Engines_TestComponent_i::Engines_TestComponent_i() Engines_TestComponent_i::~Engines_TestComponent_i() { + MESSAGE("~Engines_TestComponent_i()"); } char* Engines_TestComponent_i::Coucou(CORBA::Long L) { char s[100]; sprintf(s, "TestComponent_i : L = %ld", (long) L); + SCRUTE(pd_refCount); return CORBA::string_dup(s); } diff --git a/src/TestContainer/TestContainer.cxx b/src/TestContainer/TestContainer.cxx index b668b740b..4bd9135fe 100644 --- a/src/TestContainer/TestContainer.cxx +++ b/src/TestContainer/TestContainer.cxx @@ -34,6 +34,7 @@ #include CORBA_CLIENT_HEADER(SALOME_TestComponent) #include "SALOME_NamingService.hxx" +#include "NamingService_WaitForServerReadiness.hxx" #include "OpUtil.hxx" #include "Utils_ORB_INIT.hxx" #include "Utils_SINGLETON.hxx" @@ -59,10 +60,23 @@ static ostream& operator<<(ostream& os, const CORBA::Exception& e) return os; } +Engines::TestComponent_ptr create_intance(Engines::Container_ptr iGenFact) +{ + bool isLib = + iGenFact->load_component_Library("libSalomeTestComponentEngine.so"); + ASSERT(isLib); + CORBA::Object_var obj = + iGenFact->create_component_instance("SalomeTestComponent", + "libSalomeTestComponentEngine.so", + 0); + Engines::TestComponent_var anInstance = Engines::TestComponent::_narrow(obj); + MESSAGE("create anInstance"); + SCRUTE(anInstance->instanceName()); + return anInstance._retn(); +} int main (int argc, char * argv[]) { - // Initializing omniORB ORB_INIT &init = *SINGLETON_::Instance() ; CORBA::ORB_var &orb = init( argc , argv ) ; @@ -70,115 +84,30 @@ int main (int argc, char * argv[]) try { - - - - // use IOR to find container - //if (argc != 2) { return 1; } - //CORBA::Object_var obj = orb->string_to_object(argv[1]); - //Engines::Container_var iGenFact = Engines::Container::_narrow(obj); - - // Obtain a reference to the root POA - // - long TIMESleep = 250000000; - int NumberOfTries = 40; - int a; - timespec ts_req; - ts_req.tv_nsec=TIMESleep; - ts_req.tv_sec=0; - timespec ts_rem; - ts_rem.tv_nsec=0; - ts_rem.tv_sec=0; - CosNaming::NamingContext_var inc; - PortableServer::POA_var poa; - CORBA::Object_var theObj; - CORBA::Object_var obj; - CORBA::Object_var object; - SALOME_NamingService &naming = *SINGLETON_::Instance() ; - int TEST_CONTAINER=0; - const char * Env = getenv("USE_LOGGER"); - int EnvL =0; - if ((Env!=NULL) && (strlen(Env))) - EnvL=1; - CosNaming::Name name; - name.length(1); - name[0].id=CORBA::string_dup("Logger"); - PortableServer::POAManager_var manager; - for (int i = 1; i<=NumberOfTries; i++) - { - if (i!=1) - a=nanosleep(&ts_req,&ts_rem); - try - { - obj = orb->resolve_initial_references("RootPOA"); - if(!CORBA::is_nil(obj)) - poa = PortableServer::POA::_narrow(obj); - if(!CORBA::is_nil(poa)) - manager = poa->the_POAManager(); - if(!CORBA::is_nil(orb)) - theObj = orb->resolve_initial_references("NameService"); - if (!CORBA::is_nil(theObj)) - inc = CosNaming::NamingContext::_narrow(theObj); - } - catch( CORBA::SystemException& ) - { - INFOS( "Test Container: CORBA::SystemException: Unable to contact the Naming Service" ) - } - if(!CORBA::is_nil(inc)) - { - MESSAGE( "Test Container: Naming Service was found" ) - if(EnvL==1) - { - for(int j=1; j<=NumberOfTries; j++) - { - if (j!=1) - a=nanosleep(&ts_req, &ts_rem); - try - { - object = inc->resolve(name); - } - catch(CosNaming::NamingContext::NotFound) - { - INFOS( "Test Container: Logger Server wasn't found" ); - } - catch(...) - { - INFOS( "Test Container: Unknown exception" ); - } - if (!CORBA::is_nil(object)) - { - MESSAGE( "Test Container: Loger Server was found" ); - TEST_CONTAINER=1; - break; - } - } - } - } - if ((TEST_CONTAINER==1)||((EnvL==0)&&(!CORBA::is_nil(inc)))) - break; - } - - // Use Name Service to find container SALOME_NamingService _NS(orb) ; string containerName = "/Containers/" ; string hostName = GetHostname(); containerName += hostName + "/FactoryServer"; + NamingService_WaitForServerReadiness(&_NS,containerName); - obj = _NS.Resolve(containerName.c_str()) ; + CORBA::Object_var obj = _NS.Resolve(containerName.c_str()) ; Engines::Container_var iGenFact = Engines::Container::_narrow(obj); - Engines::TestComponent_var m1; + int nbInstances = 5; + + vector instances(nbInstances); - for (int iter = 0; iter < 3 ; iter++) + MESSAGE("------------------------------- create instances "); + for (int iter = 0; iter < nbInstances ; iter++) { - MESSAGE("----------------------------------------------------" << iter); - string dirn = getenv("KERNEL_ROOT_DIR"); - dirn += "/lib/salome/libSalomeTestComponentEngine.so"; - obj = iGenFact->load_impl("SalomeTestComponent",dirn.c_str()); - m1 = Engines::TestComponent::_narrow(obj); - MESSAGE("recup m1"); - SCRUTE(m1->instanceName()); + instances[iter] = create_intance(iGenFact); + } + MESSAGE("------------------------------ set env instances "); + for (int iter = 0; iter < nbInstances ; iter++) + { + Engines::TestComponent_var anInstance = instances[iter]; + SCRUTE(anInstance->instanceName()); Engines::FieldsDict_var dico = new Engines::FieldsDict; dico->length(3); dico[0].key=CORBA::string_dup("key_0"); @@ -186,14 +115,18 @@ int main (int argc, char * argv[]) dico[1].key=CORBA::string_dup("key_1"); dico[1].value <<=(CORBA::UShort)72; dico[2].key=CORBA::string_dup("key_2"); - dico[2].value <<="value_2"; - m1->setProperties(dico); - - MESSAGE("Coucou " << m1->Coucou(1L)); - - m1->Setenv(); + dico[2].value <<=(CORBA::ULong)iter; + anInstance->setProperties(dico); + MESSAGE("Coucou " << anInstance->Coucou(iter)); + anInstance->Setenv(); + } - Engines::FieldsDict_var dico2 = m1->getProperties(); + MESSAGE("---------------------------------- get instances "); + for (int iter = 0; iter < nbInstances ; iter++) + { + Engines::TestComponent_var anInstance = instances[iter]; + SCRUTE(anInstance->instanceName()); + Engines::FieldsDict_var dico2 = anInstance->getProperties(); for (CORBA::ULong i=0; ilength(); i++) { MESSAGE("dico2["<instanceName()); + iGenFact->remove_impl(anInstance) ; //iGenFact->finalize_removal() ; // unpredictable results ... - sleep(5); - } + } + // Clean-up. iGenFact->finalize_removal() ; - orb->destroy(); + orb->shutdown(0); } catch(CORBA::COMM_FAILURE& ex) { INFOS("Caught system exception COMM_FAILURE -- unable to contact the object.") -- 2.39.2