X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FContainer%2FContainer_i.cxx;h=a893cbf03851b51028f55f91d8d7a8a6a19c1b80;hb=2b75f5184257a44bcde209c818f7ccaf65174759;hp=ca47f23d9da2532f8aa3c385cf20e820ec7a2e30;hpb=ca921d4a4fa66c9dfe515a6f31bee1817601dfb9;p=modules%2Fyacs.git diff --git a/src/Container/Container_i.cxx b/src/Container/Container_i.cxx index ca47f23d9..a893cbf03 100644 --- a/src/Container/Container_i.cxx +++ b/src/Container/Container_i.cxx @@ -26,22 +26,37 @@ // Module : SALOME // $Header$ +//#define private public #include +#ifndef WNT #include CORBA_SERVER_HEADER(SALOME_Component) +#else +#include +#endif #include "SALOME_Container_i.hxx" +#include "SALOME_Component_i.hxx" #include "SALOME_NamingService.hxx" -#include "Utils_SINGLETON.hxx" #include "OpUtil.hxx" +#include #include +#ifndef WNT #include #include +#else +#include "../../adm/win32/SALOME_WNT.hxx" +#include +#include +int SIGUSR1 = 1000; +#endif +#include +#include "Container_init_python.hxx" #include "utilities.h" using namespace std; bool _Sleeping = false ; -// Needed by multi-threaded Python +// // Needed by multi-threaded Python --- Supervision int _ArgC ; char ** _ArgV ; @@ -50,381 +65,798 @@ char ** _ArgV ; // Other Containers are started via start_impl of FactoryServer extern "C" {void ActSigIntHandler() ; } +#ifndef WNT extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; } +#else + extern "C" {void SigIntHandler( int ) ; } +#endif + + +map Engines_Container_i::_cntInstances_map; +map Engines_Container_i::_library_map; +map Engines_Container_i::_toRemove_map; +omni_mutex Engines_Container_i::_numInstanceMutex ; + +//============================================================================= +/*! + * 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 , int argc , char* argv[], - bool regist, - bool activ ) : - _numInstance(0) + bool activAndRegist, + bool isServantAloneInProcess + ) : + _numInstance(0),_isServantAloneInProcess(isServantAloneInProcess) { _pid = (long)getpid(); - if(regist) + if(activAndRegist) ActSigIntHandler() ; - _ArgC = argc ; - _ArgV = argv ; - _argc = argc ; _argv = argv ; - int i = strlen( _argv[ 0 ] ) - 1 ; - while ( i >= 0 ) { - if ( _argv[ 0 ][ i ] == '/' ) { - _argv[ 0 ][ i+1 ] = '\0' ; - break ; - } - 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); + int i = 0 ; + while ( _argv[ i ] ) + { + MESSAGE(" argv" << i << " " << _argv[ i ]) ; + i++ ; + } - _containerName = "/Containers/"; - if (strlen(containerName)== 0) + if ( argc < 2 ) { - _containerName += hostname; + INFOS("SALOME_Container usage : SALOME_Container ServerName"); + ASSERT(0) ; } - else + SCRUTE(argv[1]); + _isSupervContainer = false; + if (strcmp(argv[1],"SuperVisionContainer") == 0) _isSupervContainer = true; + + if (_isSupervContainer) { - _containerName += hostname; - _containerName += "/" ; - _containerName += containerName; + _ArgC = argc ; + _ArgV = argv ; } _orb = CORBA::ORB::_duplicate(orb) ; _poa = PortableServer::POA::_duplicate(poa) ; - // Pour les containers paralleles: il ne faut pas activer le container generique, mais le container specialise - if(activ){ - MESSAGE("activate object"); - _id = _poa->activate_object(this); - } + + // 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 le container generique, mais le container specialise - if(regist){ - // _NS = new SALOME_NamingService(_orb); - _NS = SINGLETON_::Instance() ; - ASSERT(SINGLETON_::IsAlreadyExisting()) ; - _NS->init_orb( orb ) ; - - Engines::Container_ptr pCont - = Engines::Container::_narrow(_this()); - 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); + + _containerName = _NS->BuildContainerNameForNS(containerName, + hostname.c_str()); + SCRUTE(_containerName); + _NS->Register(pCont, _containerName.c_str()); + MESSAGE("Engines_Container_i::Engines_Container_i : Container name " + << _containerName); + + // Python: + // import SALOME_Container + // pycont = SALOME_Container.SALOME_Container_i(containerIORStr) + + CORBA::String_var sior = _orb->object_to_string(pCont); + string myCommand="pyCont = SALOME_Container.SALOME_Container_i('"; + myCommand += _containerName + "','"; + myCommand += sior; + myCommand += "')\n"; + SCRUTE(myCommand); + + if (!_isSupervContainer) + { + Py_ACQUIRE_NEW_THREAD; +#ifdef WNT + // mpv: this is temporary solution: there is a unregular crash if not + Sleep(2000); + PyRun_SimpleString("import sys\n"); + // first element is the path to Registry.dll, but it's wrong + PyRun_SimpleString("sys.path = sys.path[1:]\n"); +#endif + PyRun_SimpleString("import SALOME_Container\n"); + PyRun_SimpleString((char*)myCommand.c_str()); + Py_RELEASE_NEW_THREAD; + } + } } +//============================================================================= +/*! + * 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()); } -//! 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 ) ; -} +//============================================================================= +/*! + * CORBA method, oneway: Server shutdown. + * - Container name removed from naming service, + * - servant deactivation, + * - orb shutdown if no other servants in the process + */ +//============================================================================= -//! Launch a new container from the current container -Engines::Container_ptr Engines_Container_i::start_impl( - const char* ContainerName ) { - MESSAGE("start_impl argc " << _argc << " ContainerName " << ContainerName - << hex << this << dec) ; - _numInstanceMutex.lock() ; // lock on the instance number - - CORBA::Object_var obj = Engines::Container::_nil() ; - bool nilvar = true ; - try { - string cont("/Containers/"); - cont += machineName() ; - cont += "/" ; - cont += ContainerName; - INFOS(machineName() << " start_impl unknown container " << cont.c_str() - << " try to Resolve" ); - obj = _NS->Resolve( cont.c_str() ); - nilvar = CORBA::is_nil( obj ) ; - if ( nilvar ) { - INFOS(machineName() << " start_impl unknown container " - << ContainerName); - } - } - catch (ServiceUnreachable&) { - INFOS(machineName() << "Caught exception: Naming Service Unreachable"); - } - catch (...) { - INFOS(machineName() << "Caught unknown exception."); - } - if ( !nilvar ) { - _numInstanceMutex.unlock() ; - MESSAGE("start_impl container found without new launch") ; - return Engines::Container::_narrow(obj); - } - int i = 0 ; - while ( _argv[ i ] ) { - MESSAGE(" argv" << i << " " << _argv[ i ]) ; - i++ ; - } - string shstr = string(getenv("KERNEL_ROOT_DIR")) + "/bin/salome/SALOME_Container "; -// string shstr( "./runSession SALOME_Container " ) ; - shstr += ContainerName ; - if ( _argc == 4 ) { - shstr += " " ; - shstr += _argv[ 2 ] ; - shstr += " " ; - shstr += _argv[ 3 ] ; - } - shstr += " > /tmp/" ; - shstr += ContainerName ; - shstr += ".log 2>&1 &" ; - MESSAGE("system(" << shstr << ")") ; - int status = system( shstr.c_str() ) ; - if (status == -1) { - INFOS("Engines_Container_i::start_impl SALOME_Container failed (system command status -1)") ; - } - else if (status == 217) { - INFOS("Engines_Container_i::start_impl SALOME_Container failed (system command status 217)") ; - } - INFOS(machineName() << " Engines_Container_i::start_impl SALOME_Container launch done"); - -// pid_t pid = fork() ; -// if ( pid == 0 ) { -// string anExe( _argv[ 0 ] ) ; -// anExe += "runSession" ; -// char * args[ 6 ] ; -// args[ 0 ] = "runSession" ; -// args[ 1 ] = "SALOME_Container" ; -// args[ 2 ] = strdup( ContainerName ) ; -// args[ 3 ] = strdup( _argv[ 2 ] ) ; -// args[ 4 ] = strdup( _argv[ 3 ] ) ; -// args[ 5 ] = NULL ; -// MESSAGE("execl(" << anExe.c_str() << " , " << args[ 0 ] << " , " -// << args[ 1 ] << " , " << args[ 2 ] << " , " << args[ 3 ] -// << " , " << args[ 4 ] << ")") ; -// int status = execv( anExe.c_str() , args ) ; -// if (status == -1) { -// INFOS("Engines_Container_i::start_impl execl failed (system command status -1)") ; -// perror( "Engines_Container_i::start_impl execl error ") ; -// } -// else { -// INFOS(machineName() << " Engines_Container_i::start_impl execl done"); -// } -// exit(0) ; -// } - - obj = Engines::Container::_nil() ; - try { - string cont("/Containers/"); - cont += machineName() ; - cont += "/" ; - cont += ContainerName; - nilvar = true ; - int count = 20 ; - while ( nilvar && count >= 0) { - sleep( 1 ) ; - obj = _NS->Resolve(cont.c_str()); - nilvar = CORBA::is_nil( obj ) ; - if ( nilvar ) { - INFOS(count << ". " << machineName() - << " start_impl unknown container " << cont.c_str()); - count -= 1 ; - } - } - _numInstanceMutex.unlock() ; - if ( !nilvar ) { - MESSAGE("start_impl container found after new launch of SALOME_Container") ; +void Engines_Container_i::Shutdown() +{ + MESSAGE("Engines_Container_i::Shutdown()"); + _NS->Destroy_FullDirectory(_containerName.c_str()); + //_remove_ref(); + //_poa->deactivate_object(*_id); + if(_isServantAloneInProcess) + { + MESSAGE("Effective Shutdown of container Begins..."); + LocalTraceBufferPool* bp1 = LocalTraceBufferPool::instance(); + bp1->deleteInstance(bp1); + _orb->shutdown(0); } - return Engines::Container::_narrow(obj); - } - catch (ServiceUnreachable&) { - INFOS(machineName() << "Caught exception: Naming Service Unreachable"); - } - catch (...) { - INFOS(machineName() << "Caught unknown exception."); - } - _numInstanceMutex.unlock() ; - MESSAGE("start_impl container not found after new launch of SALOME_Container") ; - return Engines::Container::_nil() ; } -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 (Python or C++ implementation) + * \param componentName like COMPONENT + * try to make a Python import of COMPONENT, + * then a lib open of 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* componentName) +{ - //string absolute_impl_name = _library_path + "lib" + _impl_name + ".so"; - string absolute_impl_name( _impl_name ) ; - SCRUTE(absolute_impl_name); - 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 aCompName = componentName; + + // --- try dlopen C++ component + +#ifndef WNT + string impl_name = string ("lib") + aCompName + string("Engine.so"); +#else + string impl_name = aCompName + string("Engine.dll"); +#endif + SCRUTE(impl_name); - string factory_name = _nameToRegister + string("Engine_factory"); - // SCRUTE(factory_name) ; + _numInstanceMutex.lock(); // lock to be alone + // (see decInstanceCnt, finalize_removal)) + if (_toRemove_map[impl_name]) _toRemove_map.erase(impl_name); + if (_library_map[impl_name]) + { + MESSAGE("Library " << impl_name << " already loaded"); + _numInstanceMutex.unlock(); + return true; + } + + void* handle; +#ifndef WNT + handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ; +#else + handle = dlopen( impl_name.c_str() , 0 ) ; +#endif + if ( handle ) + { + _library_map[impl_name] = handle; + _numInstanceMutex.unlock(); + return true; + } + else + { + INFOS("Can't load shared library : " << impl_name); + INFOS("error dlopen: " << dlerror()); + } + _numInstanceMutex.unlock(); - 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()); + // --- try import Python component - char *error ; - if ( (error = dlerror() ) != NULL) { - INFOS("Can't resolve symbol: " + factory_name); - SCRUTE(error); - _numInstanceMutex.unlock() ; + INFOS("try import Python component "<0) otherwise + * \return a loaded component + */ +//============================================================================= + +Engines::Component_ptr +Engines_Container_i::create_component_instance(const char*genericRegisterName, + 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" ) ; - } - else { // JR : No ReBind !!! - MESSAGE( "Container_i::load_impl " << component_registerName.c_str() << " already bound" ) ; + string aCompName = genericRegisterName; + if (_library_map[aCompName]) // Python component + { + if (_isSupervContainer) + { + INFOS("Supervision Container does not support Python Component Engines"); + return Engines::Component::_nil(); + } + _numInstanceMutex.lock() ; // lock on the instance number + _numInstance++ ; + int numInstance = _numInstance ; + _numInstanceMutex.unlock() ; + + char aNumI[12]; + sprintf( aNumI , "%d" , numInstance ) ; + string instanceName = aCompName + "_inst_" + aNumI ; + string component_registerName = + _containerName + "/" + instanceName; + + Py_ACQUIRE_NEW_THREAD; + PyObject *mainmod = PyImport_AddModule("__main__"); + PyObject *globals = PyModule_GetDict(mainmod); + PyObject *pyCont = PyDict_GetItemString(globals, "pyCont"); + PyObject *result = PyObject_CallMethod(pyCont, + "create_component_instance", + "ssl", + aCompName.c_str(), + instanceName.c_str(), + studyId); + string iors = PyString_AsString(result); + SCRUTE(iors); + Py_RELEASE_NEW_THREAD; + + CORBA::Object_var obj = _orb->string_to_object(iors.c_str()); iobject = Engines::Component::_narrow( obj ) ; + return iobject._retn(); } - } - catch (...) { - INFOS( "Container_i::load_impl catched" ) ; - } + + //--- try C++ + +#ifndef WNT + string impl_name = string ("lib") + genericRegisterName +string("Engine.so"); +#else + string impl_name = genericRegisterName +string("Engine.dll"); +#endif + void* handle = _library_map[impl_name]; + if ( !handle ) + { + INFOS("shared library " << impl_name <<"must be loaded before instance"); + return Engines::Component::_nil() ; + } + else + { + iobject = createInstance(genericRegisterName, + handle, + studyId); + return iobject._retn(); + } +} + +//============================================================================= +/*! + * 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) +{ + Engines::Component_var anEngine = Engines::Component::_nil(); + map::iterator itm =_listInstances_map.begin(); + while (itm != _listInstances_map.end()) + { + string instance = (*itm).first; + SCRUTE(instance); + if (instance.find(registeredName) == 0) + { + anEngine = (*itm).second; + if (studyId == anEngine->getStudyId()) + { + return anEngine._retn(); + } + } + itm++; + } + return anEngine._retn(); +} -//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: 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 ) +{ + string impl_name = string ("lib") + genericRegisterName +string("Engine.so"); + Engines::Component_var iobject = Engines::Component::_nil() ; + if (load_component_Library(genericRegisterName)) + iobject = find_or_create_instance(genericRegisterName, impl_name); + 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 + _NS->Destroy_Name(instanceName.c_str()); +} + +//============================================================================= +/*! + * CORBA method: Discharges unused libraries from the container. + */ +//============================================================================= + +void Engines_Container_i::finalize_removal() +{ + MESSAGE("finalize unload : dlclose"); + _numInstanceMutex.lock(); // lock to be alone + // (see decInstanceCnt, load_component_Library) + map::iterator ith; + for (ith = _toRemove_map.begin(); ith != _toRemove_map.end(); ith++) + { + void *handle = (*ith).second; + string impl_name= (*ith).first; + if (handle) + { + SCRUTE(handle); + SCRUTE(impl_name); +// dlclose(handle); // SALOME unstable after ... +// _library_map.erase(impl_name); + } + } + _toRemove_map.clear(); + _numInstanceMutex.unlock(); +} + +//============================================================================= +/*! + * 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); + return false; +} + +//============================================================================= +/*! + * 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 ) { - remove_map[instanceName] = handle_map[instanceName] ; + INFOS("shared library " << impl_name <<"must be loaded before instance"); + return Engines::Component::_nil() ; } - 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 ++) + else { - MESSAGE("reste " << (*im).first); + // --- 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 Engines_Container_i::finalize_removal() +//============================================================================= +/*! + * 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) { - 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 ++) + // --- 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 ; //not owner, do not delete (nore use var) + 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; + _cntInstances_map[aGenRegisterName] += 1; + SCRUTE(aGenRegisterName); + SCRUTE(_cntInstances_map[aGenRegisterName]); + //SCRUTE(servant->pd_refCount); + bool ret_studyId = servant->setStudyId(studyId); + ASSERT(ret_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 (...) { - void * handle = (*im).second ; - dlclose(handle) ; - MESSAGE("dlclose " << (*im).first); + INFOS( "Container_i::createInstance exception catched" ) ; } - remove_map.clear() ; - _numInstanceMutex.unlock() ; - MESSAGE("remove_map.clear()"); + return iobject._retn(); } -void ActSigIntHandler() { +//============================================================================= +/*! + * + */ +//============================================================================= + +void Engines_Container_i::decInstanceCnt(string genericRegisterName) +{ + string aGenRegisterName =genericRegisterName; + MESSAGE("Engines_Container_i::decInstanceCnt " << aGenRegisterName); + ASSERT(_cntInstances_map[aGenRegisterName] > 0); + _numInstanceMutex.lock(); // lock to be alone + // (see finalize_removal, load_component_Library) + _cntInstances_map[aGenRegisterName] -= 1; + SCRUTE(_cntInstances_map[aGenRegisterName]); + if (_cntInstances_map[aGenRegisterName] == 0) + { + string impl_name = + Engines_Component_i::GetDynLibraryName(aGenRegisterName.c_str()); + SCRUTE(impl_name); + void* handle = _library_map[impl_name]; + ASSERT(handle); + _toRemove_map[impl_name] = handle; + } + _numInstanceMutex.unlock(); +} + +//============================================================================= +/*! + * 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; +} + +//============================================================================= +/*! + * + */ +//============================================================================= + +void ActSigIntHandler() +{ +#ifndef WNT struct sigaction SigIntAct ; SigIntAct.sa_sigaction = &SigIntHandler ; SigIntAct.sa_flags = SA_SIGINFO ; - if ( sigaction( SIGINT | SIGUSR1 , &SigIntAct, NULL ) ) { +#endif + +// 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 +#ifndef WNT + if ( sigaction( SIGINT , &SigIntAct, NULL ) ) { perror("SALOME_Container main ") ; exit(0) ; } - else { - INFOS(pthread_self() << "SigIntHandler activated") ; + if ( sigaction( SIGUSR1 , &SigIntAct, NULL ) ) { + perror("SALOME_Container main ") ; + exit(0) ; } + //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers) + // use of streams (and so on) should never be used because : + // streams of C++ are naturally thread-safe and use pthread_mutex_lock ===> + // A stream operation may be interrupted by a signal and if the Handler use stream we + // may have a "Dead-Lock" ===HangUp + //==INFOS is commented + // INFOS(pthread_self() << "SigIntHandler activated") ; +#else + signal( SIGINT, SigIntHandler ); + signal( SIGUSR1, SigIntHandler ); +#endif + } void SetCpuUsed() ; +#ifndef WNT void SigIntHandler(int what , siginfo_t * siginfo , void * toto ) { - MESSAGE(pthread_self() << "SigIntHandler what " << what << endl - << " si_signo " << siginfo->si_signo << endl - << " si_code " << siginfo->si_code << endl - << " si_pid " << siginfo->si_pid) ; + //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers) + // use of streams (and so on) should never be used because : + // streams of C++ are naturally thread-safe and use pthread_mutex_lock ===> + // A stream operation may be interrupted by a signal and if the Handler use stream we + // may have a "Dead-Lock" ===HangUp + //==MESSAGE is commented + // MESSAGE(pthread_self() << "SigIntHandler what " << what << endl + // << " si_signo " << siginfo->si_signo << endl + // << " si_code " << siginfo->si_code << endl + // << " si_pid " << siginfo->si_pid) ; if ( _Sleeping ) { _Sleeping = false ; - MESSAGE("SigIntHandler END sleeping.") ; + // MESSAGE("SigIntHandler END sleeping.") ; return ; } else { @@ -434,26 +866,148 @@ void SigIntHandler(int what , siginfo_t * siginfo , } else { _Sleeping = true ; - MESSAGE("SigIntHandler BEGIN sleeping.") ; + // MESSAGE("SigIntHandler BEGIN sleeping.") ; int count = 0 ; while( _Sleeping ) { sleep( 1 ) ; count += 1 ; } + // MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ; + } + return ; + } +} +#else // Case WNT +void SigIntHandler( int what ) { + MESSAGE( pthread_self() << "SigIntHandler what " << what << endl ); + if ( _Sleeping ) { + _Sleeping = false ; + MESSAGE("SigIntHandler END sleeping.") ; + return ; + } + else { + ActSigIntHandler() ; + if ( what == SIGUSR1 ) { + SetCpuUsed() ; + } + else { + _Sleeping = true ; + MESSAGE("SigIntHandler BEGIN sleeping.") ; + int count = 0 ; + while( _Sleeping ) { + Sleep( 1000 ) ; + count += 1 ; + } MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ; } return ; } } +#endif + +//============================================================================= +/*! + * 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* genericRegisterName, +// const char* componentName ) +// { +// _numInstanceMutex.lock() ; // lock on the instance number +// BEGIN_OF( "Container_i::instance " << componentName ) ; + +// string _genericRegisterName = genericRegisterName; +// string component_registerName = _containerName + "/" + _genericRegisterName; + +// 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); + +// 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); +// } -// Get the PID of the Container +//============================================================================= +/*! + * CORBA attribute: Machine Name (hostname without domain extensions) + */ +//============================================================================= -CORBA::Long Engines_Container_i::getPID() { - return (long)getpid(); -} +// char* Engines_Container_i::machineName() +// { +// string s = GetHostname(); +// MESSAGE("Engines_Container_i::machineName " << s); +// return CORBA::string_dup(s.c_str()) ; +// } -// Get the hostName of the Container -char* Engines_Container_i::getHostName() { - return((char*)(GetHostname().c_str())); -}