From f7c5bb0c6eb808a2fe0fe66029e09600366edab1 Mon Sep 17 00:00:00 2001 From: caremoli Date: Fri, 9 Apr 2010 16:27:12 +0000 Subject: [PATCH] CCAR: improvement to the component loading mechanism of SALOME (issue 20675) Main modifications are: - add an out string argument to container methods (load_component_Library and create_component_instance_env) to report reason when load or create fails (INTERFACE CHANGE) - try to detect if the implementation is C++, python or executable based on intermediate errors (dlopen, dlsym, import, ...) - some refactoring to put specific parts in separate methods - minimal update of MPIContainer and ParallelContainer - keep LifeCycle unchanged --- idl/SALOME_Component.idl | 7 +- src/Container/Container_i.cxx | 1338 +++++++++-------- src/Container/SALOME_Container.cxx | 32 +- src/Container/SALOME_Container.py | 26 +- src/Container/SALOME_ContainerPy.py | 5 +- src/Container/SALOME_Container_i.hxx | 18 +- src/LifeCycleCORBA/SALOME_LifeCycleCORBA.cxx | 43 +- src/MPIContainer/MPIContainer_i.cxx | 18 +- src/MPIContainer/MPIContainer_i.hxx | 5 +- .../SALOME_ParallelContainerProxy_i.cxx | 21 +- .../SALOME_ParallelContainerProxy_i.hxx | 5 +- .../SALOME_ParallelContainer_i.cxx | 22 +- .../SALOME_ParallelContainer_i.hxx | 7 +- src/TestContainer/TestContainer.cxx | 12 +- 14 files changed, 887 insertions(+), 672 deletions(-) diff --git a/idl/SALOME_Component.idl b/idl/SALOME_Component.idl index 6253ecb8f..22b310948 100644 --- a/idl/SALOME_Component.idl +++ b/idl/SALOME_Component.idl @@ -79,9 +79,10 @@ module Engines \param componentName like COMPONENT, (Python or C++ implementation) try to make a Python import of COMPONENT, then a lib open of libCOMPONENTEngine.so + \param reason in case of error (return false) a string explaining the error \return true if load successfull or already done, false otherwise */ - boolean load_component_Library(in string componentName); + boolean load_component_Library(in string componentName, out string reason); //! Create a new servant instance of a component. /*! @@ -105,10 +106,12 @@ module Engines \param studyId 0 if instance is not associated to a study, >0 otherwise (== study id) \param env a dict of env variables + \param reason in case of error (return nil) a string explaining the error \return a loaded component */ Engines::Component create_component_instance_env(in string componentName, - in long studyId, in FieldsDict env); + in long studyId, in FieldsDict env, + out string reason); //! Find a servant instance of a component /*! \param registeredName Name of the component in Registry or Name Service, diff --git a/src/Container/Container_i.cxx b/src/Container/Container_i.cxx index 4197e70eb..99e4a4284 100644 --- a/src/Container/Container_i.cxx +++ b/src/Container/Container_i.cxx @@ -73,12 +73,21 @@ extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; } extern "C" {void SigIntHandler( int ) ; } #endif -#ifdef WIN32 -# define separator '\\' +#ifndef WIN32 +#define LIB "lib" +#define ENGINESO "Engine.so" #else -# define separator '/' +#define LIB "" +#define ENGINESO "Engine.dll" #endif +#ifdef WIN32 +#define SEP ';' +#define SLASH '\\' +#else +#define SEP ':' +#define SLASH '/' +#endif map Engines_Container_i::_cntInstances_map; map Engines_Container_i::_library_map; @@ -88,7 +97,7 @@ omni_mutex Engines_Container_i::_numInstanceMutex ; static PyObject* _pyCont; int checkifexecutable(const std::string&); -int findpathof(std::string&, const std::string&); +int findpathof(const std::string& path, std::string&, const std::string&); /*! \class Engines_Container_i * \brief C++ implementation of Engines::Container interface @@ -154,13 +163,6 @@ Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb, } SCRUTE(argv[1]); _isSupervContainer = false; - if (strcmp(argv[1],"SuperVisionContainer") == 0) _isSupervContainer = true; - - if (_isSupervContainer) - { - _ArgC = argc ; - _ArgV = argv ; - } _orb = CORBA::ORB::_duplicate(orb) ; _poa = PortableServer::POA::_duplicate(poa) ; @@ -196,26 +198,23 @@ Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb, myCommand += "')\n"; SCRUTE(myCommand); - if (!_isSupervContainer) - { - PyGILState_STATE gstate = PyGILState_Ensure(); + PyGILState_STATE gstate = PyGILState_Ensure(); #ifdef WIN32 - // mpv: this is temporary solution: there is a unregular crash if not - //Sleep(2000); - // - // first element is the path to Registry.dll, but it's wrong - PyRun_SimpleString("import sys\n"); - PyRun_SimpleString("sys.path = sys.path[1:]\n"); + // mpv: this is temporary solution: there is a unregular crash if not + //Sleep(2000); + // + // first element is the path to Registry.dll, but it's wrong + PyRun_SimpleString("import sys\n"); + PyRun_SimpleString("sys.path = sys.path[1:]\n"); #endif - PyRun_SimpleString("import SALOME_Container\n"); - PyRun_SimpleString((char*)myCommand.c_str()); - PyObject *mainmod = PyImport_AddModule("__main__"); - PyObject *globals = PyModule_GetDict(mainmod); - _pyCont = PyDict_GetItemString(globals, "pyCont"); + PyRun_SimpleString("import SALOME_Container\n"); + PyRun_SimpleString((char*)myCommand.c_str()); + PyObject *mainmod = PyImport_AddModule("__main__"); + PyObject *globals = PyModule_GetDict(mainmod); + _pyCont = PyDict_GetItemString(globals, "pyCont"); - PyGILState_Release(gstate); - } + PyGILState_Release(gstate); fileTransfer_i* aFileTransfer = new fileTransfer_i(); CORBA::Object_var obref=aFileTransfer->_this(); @@ -315,7 +314,6 @@ CORBA::Long Engines_Container_i::getPID() * CORBA method: check if servant is still alive */ //============================================================================= - void Engines_Container_i::ping() { MESSAGE("Engines_Container_i::ping() pid "<< getpid()); @@ -330,7 +328,6 @@ void Engines_Container_i::ping() * - orb shutdown if no other servants in the process */ //============================================================================= - void Engines_Container_i::Shutdown() { MESSAGE("Engines_Container_i::Shutdown()"); @@ -366,226 +363,269 @@ void Engines_Container_i::Shutdown() } } -/* int checkifexecutable(const char *filename) -* -* Return non-zero if the name is an executable file, and -* zero if it is not executable, or if it does not exist. +//============================================================================= +//! load a component implementation +/*! +* CORBA method +* \param componentName component name +* \param reason explains error when load fails +* \return true if dlopen successfull or already done, false otherwise */ - -int checkifexecutable(const string& filename) +//============================================================================= +bool +Engines_Container_i::load_component_Library(const char* componentName, CORBA::String_out reason) { - int result; - struct stat statinfo; - - result = stat(filename.c_str(), &statinfo); - if (result < 0) return 0; - if (!S_ISREG(statinfo.st_mode)) return 0; - -#ifdef WIN32 - return 1; -#else - if (statinfo.st_uid == geteuid()) return statinfo.st_mode & S_IXUSR; - if (statinfo.st_gid == getegid()) return statinfo.st_mode & S_IXGRP; - return statinfo.st_mode & S_IXOTH; -#endif -} + //================================================================= + // --- C++ implementation section + //================================================================= + std::string retso; + if(load_component_CppImplementation(componentName,retso)) + { + reason=CORBA::string_dup(""); + return true; + } + else if(retso != "ImplementationNotFound") + { + reason=CORBA::string_dup(retso.c_str()); + return false; + } -/* int findpathof(char *pth, const char *exe) -* -* Find executable by searching the PATH environment variable. -* -* const char *exe - executable name to search for. -* char *pth - the path found is stored here, space -* needs to be available. -* -* If a path is found, returns non-zero, and the path is stored -* in pth. If exe is not found returns 0, with pth undefined. -*/ - -int findpathof(string& pth, const string& exe) -{ - string path( getenv("PATH") ); - if ( path.size() == 0 ) - return 0; - - char path_spr = -#ifdef WIN32 - ';'; -#else - ':'; -#endif - - char dir_spr = -#ifdef WIN32 - '\\'; -#else - '/'; -#endif - - int offset = 0; - int stop = 0; - int found = 0; - while(!stop && !found) - { - int pos = path.find( path_spr, offset ); - if (pos == string::npos) - stop = 1; + retso="Component "; + retso+=componentName; + retso+=": Can't find C++ implementation "; + retso+=string(LIB) + componentName + ENGINESO; - pth = path.substr( offset, pos - offset ); - if ( pth.size() > 0 ) + //================================================================= + // --- Python implementation section + //================================================================= + std::string retpy; + if(load_component_PythonImplementation(componentName,retpy)) + { + reason=CORBA::string_dup(""); + return true; + } + else if(retpy != "ImplementationNotFound") { - if( pth[pth.size()-1] != dir_spr ) - pth += dir_spr; - pth += exe; - found = checkifexecutable(pth.c_str()); + reason=CORBA::string_dup(retpy.c_str()); + return false; + } + + retpy="Component "; + retpy+=componentName; + retpy+=": Can't find python implementation "; + retpy+=componentName; + retpy+="(.py)"; + + //================================================================= + // -- Executable implementation section + //================================================================= + std::string retex; + if(load_component_ExecutableImplementation(componentName,retex)) + { + reason=CORBA::string_dup(""); + return true; + } + else if(retex != "ImplementationNotFound") + { + reason=CORBA::string_dup(retex.c_str()); + return false; } - offset = pos+1; - } + retex="Component "; + retex+=componentName; + retex+=": Can't find executable implementation "; + retex+=componentName; + retex+=".exe"; -/* char *searchpath; - char *beg, *end; - int stop, found; - int len; + std::string ret="Component implementation not found: "; + ret += componentName ; + ret += '\n' ; + ret += retso+ '\n' ; + ret += retpy+ '\n' ; + ret += retex+ '\n' ; - if (strchr(exe, separator) != NULL) { -#ifndef WIN32 - if (realpath(exe, pth) == NULL) return 0; -#endif - return checkifexecutable(pth); - } + std::cerr << ret << std::endl; + reason=CORBA::string_dup(ret.c_str()); - searchpath = getenv("PATH"); - if (searchpath == NULL) return 0; - if (strlen(searchpath) <= 0) return 0; - - string env_path(searchpath); - - beg = searchpath; - stop = 0; found = 0; - do { - end = strchr(beg, ':'); - if (end == NULL) { - stop = 1; - strncpy(pth, beg, PATH_MAX); - len = strlen(pth); - } else { - strncpy(pth, beg, end - beg); - pth[end - beg] = '\0'; - len = end - beg; - } - if (pth[len - 1] != '/') strncat(pth, "/", 1); - strncat(pth, exe, PATH_MAX - len); - found = checkifexecutable(pth); - if (!stop) beg = end + 1; - } while (!stop && !found); -*/ - return found; + return false; } - - //============================================================================= -//! load a new component class +//! try to load a C++ component implementation /*! -* 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 +* C++ method: +* \param componentName the name of the component (COMPONENT, for example) +* \param reason explains error when load fails +* \return true if loading is successfull or already done, false otherwise */ //============================================================================= - bool -Engines_Container_i::load_component_Library(const char* componentName) +Engines_Container_i::load_component_CppImplementation(const char* componentName, std::string& reason) { - - string aCompName = componentName; - - // --- try dlopen C++ component - -#ifndef WIN32 - string impl_name = string ("lib") + aCompName + string("Engine.so"); -#else - string impl_name = aCompName + string("Engine.dll"); -#endif + std::string aCompName(componentName); + string impl_name = string(LIB) + aCompName + ENGINESO; SCRUTE(impl_name); - _numInstanceMutex.lock(); // lock to be alone + _numInstanceMutex.lock(); // lock to be alone // (see decInstanceCnt, finalize_removal)) if (_toRemove_map.count(impl_name) != 0) _toRemove_map.erase(impl_name); if (_library_map.count(impl_name) != 0) - { - MESSAGE("Library " << impl_name << " already loaded"); - _numInstanceMutex.unlock(); - return true; - } + { + MESSAGE("Library " << impl_name << " already loaded"); + _numInstanceMutex.unlock(); + reason=""; + return true; + } + _numInstanceMutex.unlock(); - std::string retso=""; #ifndef WIN32 void* handle; - handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ; - if ( !handle )retso=dlerror(); + handle = dlopen( impl_name.c_str() , RTLD_NOW ) ; + if ( !handle ) + { + //not loadable. Try to find the lib file in LD_LIBRARY_PATH + std::string path; + char* p=getenv("LD_LIBRARY_PATH"); + if(p)path=p; + path=path+SEP+"/usr/lib"+SEP+"/lib"; + + std::string pth; + if(findpathof(path, pth, impl_name)) + { + //found but not loadable + reason="Component "; + reason+=aCompName; + reason+=": C++ implementation found "; + reason+=pth; + reason+=" but it is not loadable. Error:\n"; + reason+=dlerror(); + std::cerr << reason << std::endl; + return false; + } + else + { + //not found + //continue with other implementation + reason="ImplementationNotFound"; + return false; + } + } #else HINSTANCE handle; handle = LoadLibrary( impl_name.c_str() ); #endif if ( handle ) - { - _library_map[impl_name] = handle; - _numInstanceMutex.unlock(); - return true; - } - _numInstanceMutex.unlock(); + { + _numInstanceMutex.lock(); + _library_map[impl_name] = handle; + _numInstanceMutex.unlock(); + reason=""; + return true; + } - // --- try import Python component + return false; - INFOS("try import Python component "<0) otherwise -* \param env dict of env variables +* \param env dict of env variables +* \param reason explains error when create_component_instance_env fails * \return a loaded component */ //============================================================================= - Engines::Component_ptr Engines_Container_i::create_component_instance_env(const char*genericRegisterName, - CORBA::Long studyId,const Engines::FieldsDict& env) + CORBA::Long studyId, + const Engines::FieldsDict& env, + CORBA::String_out reason) { if (studyId < 0) - { - INFOS("studyId must be > 0 for mono study instance, =0 for multiStudy"); - return Engines::Component::_nil() ; - } - - Engines::Component_var iobject = Engines::Component::_nil() ; - - string aCompName = genericRegisterName; - if (_library_map.count(aCompName) != 0) // Python component - { - if (_isSupervContainer) { - INFOS("Supervision Container does not support Python Component Engines"); - return Engines::Component::_nil(); + INFOS("studyId must be > 0 for mono study instance, =0 for multiStudy"); + reason=CORBA::string_dup("studyId must be > 0 for mono study instance, =0 for multiStudy"); + 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; - PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject *result = PyObject_CallMethod(_pyCont, - (char*)"create_component_instance", - (char*)"ssl", - aCompName.c_str(), - instanceName.c_str(), - studyId); - string iors = PyString_AsString(result); - Py_DECREF(result); - SCRUTE(iors); - PyGILState_Release(gstate); + std::string error; + if (_library_map.count(genericRegisterName) != 0) + { + // It's a Python component + Engines::Component_ptr compo = createPythonInstance(genericRegisterName, studyId, error); + reason=CORBA::string_dup(error.c_str()); + return compo; + } - if( iors!="" ) + string impl_name = string(LIB) + genericRegisterName + ENGINESO; + if (_library_map.count(impl_name) != 0) { - CORBA::Object_var obj = _orb->string_to_object(iors.c_str()); - iobject = Engines::Component::_narrow( obj ) ; - _listInstances_map[instanceName] = iobject; + // It's a C++ component + void* handle = _library_map[impl_name]; + Engines::Component_ptr compo = createInstance(genericRegisterName, handle, studyId, error); + reason=CORBA::string_dup(error.c_str()); + return compo; } - return iobject._retn(); - } - //--- try C++ + impl_name = string(genericRegisterName) + ".exe"; + if (_library_map.count(impl_name) != 0) + { + //It's an executable component + Engines::Component_ptr compo = createExecutableInstance(genericRegisterName, studyId, env, error); + reason=CORBA::string_dup(error.c_str()); + return compo; + } -#ifndef WIN32 - string impl_name = string ("lib") + genericRegisterName +string("Engine.so"); -#else - string impl_name = genericRegisterName +string("Engine.dll"); -#endif - if (_library_map.count(impl_name) != 0) // C++ component - { - void* handle = _library_map[impl_name]; - iobject = createInstance(genericRegisterName, - handle, - studyId); - return iobject._retn(); - } + error="load_component_Library has probably not been called for component: "; + error += genericRegisterName; + INFOS(error); + reason=CORBA::string_dup(error.c_str()); + return Engines::Component::_nil() ; +} - // If it's not a Python or a C++ component try to launch a standalone component - // in a sub directory - // This component is implemented in an executable with name genericRegisterName.exe - // It must register itself in Naming Service. The container waits some time (10 s max) - // it's registration. +//============================================================================= +//! Create a new component instance (Executable implementation) +/*! +* \param CompName Name of the component instance +* \param studyId 0 for multiStudy instance, +* study Id (>0) otherwise +* \param env dict of env variables +* \param reason explains error when creation fails +* \return a loaded component +* +* This component is implemented in an executable with name genericRegisterName.exe +* It must register itself in Naming Service. The container waits some time (10 s max) +* it's registration. +*/ +//============================================================================= +Engines::Component_ptr +Engines_Container_i::createExecutableInstance(std::string CompName, int studyId, + const Engines::FieldsDict& env, + std::string& reason) +{ + Engines::Component_var iobject = Engines::Component::_nil() ; _numInstanceMutex.lock() ; // lock on the instance number _numInstance++ ; @@ -705,7 +743,7 @@ Engines_Container_i::create_component_instance_env(const char*genericRegisterNam char aNumI[12]; sprintf( aNumI , "%d" , numInstance ) ; - string instanceName = aCompName + "_inst_" + aNumI ; + string instanceName = CompName + "_inst_" + aNumI ; string component_registerName = _containerName + "/" + instanceName; //check if an entry exist in naming service @@ -730,7 +768,7 @@ Engines_Container_i::create_component_instance_env(const char*genericRegisterNam command+=";cd "; command+=instanceName; command+=";"; - command+=genericRegisterName ; + command+=CompName ; command+=".exe"; command+=" "; command+= sior; // container ior string @@ -782,13 +820,15 @@ Engines_Container_i::create_component_instance_env(const char*genericRegisterNam if (status == -1) { - MESSAGE("SALOME_Container::create_component_instance system failed " << "(system command status -1)"); + reason="SALOME_Container::create_component_instance system failed (system command status -1)"; + MESSAGE(reason); return Engines::Component::_nil(); } #ifndef WIN32 else if (WEXITSTATUS(status) == 217) { - MESSAGE("SALOME_Container::create_component_instance system failed " << "(system command status 217)"); + reason="SALOME_Container::create_component_instance system failed (system command status 217)"; + MESSAGE(reason); return Engines::Component::_nil(); } #endif @@ -804,13 +844,14 @@ Engines_Container_i::create_component_instance_env(const char*genericRegisterNam Sleep(1000); #endif count-- ; - MESSAGE( count << ". Waiting for component " << genericRegisterName); + MESSAGE( count << ". Waiting for component " << CompName); obj = _NS->Resolve(component_registerName.c_str()); } if(CORBA::is_nil(obj)) { - MESSAGE("SALOME_Container::create_component_instance failed"); + reason="SALOME_Container::create_component_instance failed"; + MESSAGE(reason); return Engines::Component::_nil(); } else @@ -823,314 +864,59 @@ Engines_Container_i::create_component_instance_env(const char*genericRegisterNam } } + //============================================================================= -//! Find an existing (in the container) component instance +//! Create a new component instance (Python implementation) /*! -* 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 +* \param CompName Name of the component instance +* \param studyId 0 for multiStudy instance, +* study Id (>0) otherwise +* \param reason explains error when creation fails +* \return a loaded component */ //============================================================================= - Engines::Component_ptr -Engines_Container_i::find_component_instance( const char* registeredName, - CORBA::Long studyId) +Engines_Container_i::createPythonInstance(std::string CompName, int studyId, + std::string& reason) { - 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) + Engines::Component_var iobject = 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 = CompName + "_inst_" + aNumI ; + string component_registerName = _containerName + "/" + instanceName; + + PyGILState_STATE gstate = PyGILState_Ensure(); + PyObject *result = PyObject_CallMethod(_pyCont, + (char*)"create_component_instance", + (char*)"ssl", + CompName.c_str(), + instanceName.c_str(), + studyId); + const char *ior; + const char *error; + PyArg_ParseTuple(result,"ss", &ior, &error); + string iors = ior; + reason=error; + Py_DECREF(result); + PyGILState_Release(gstate); + + if( iors!="" ) { - anEngine = (*itm).second; - if (studyId == anEngine->getStudyId()) - { - return anEngine._retn(); - } + CORBA::Object_var obj = _orb->string_to_object(iors.c_str()); + iobject = Engines::Component::_narrow( obj ) ; + _listInstances_map[instanceName] = iobject; } - itm++; - } - return anEngine._retn(); + return iobject._retn(); } //============================================================================= -//! Find or create a new component instance -/*! -* 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(); -} - - -//============================================================================= -//! Remove the component instance from container -/*! -* 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); - _numInstanceMutex.lock() ; // lock to be alone (stl container write) - _listInstances_map.erase(instanceName); - _numInstanceMutex.unlock() ; - component_i->destroy() ; - _NS->Destroy_Name(instanceName.c_str()); -} - -//============================================================================= -//! Unload component libraries from the container -/*! -* 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(); -} - -//============================================================================= -//! Kill the container -/*! -* 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 " - << Kernel_Utils::GetHostname().c_str()); - INFOS("==============================================================="); - INFOS("= REMOVE calls to Kill_impl in C++ container ="); - INFOS("==============================================================="); - //exit( 0 ) ; - ASSERT(0); - return false; -} - -//============================================================================= -//! Get or create a file reference object associated to a local file (to transfer it) -/*! -* CORBA method: get or create a fileRef object associated to a local file -* (a file on the computer on which runs the container server), which stores -* a list of (machine, localFileName) corresponding to copies already done. -* -* \param origFileName absolute path for a local file to copy on other -* computers -* \return a fileRef object associated to the file. -*/ -//============================================================================= - -Engines::fileRef_ptr -Engines_Container_i::createFileRef(const char* origFileName) -{ - string origName(origFileName); - Engines::fileRef_var theFileRef = Engines::fileRef::_nil(); - - if (origName[0] != '/') - { - INFOS("path of file to copy must be an absolute path begining with '/'"); - return Engines::fileRef::_nil(); - } - - if (CORBA::is_nil(_fileRef_map[origName])) - { - CORBA::Object_var obj=_poa->id_to_reference(*_id); - Engines::Container_var pCont = Engines::Container::_narrow(obj); - fileRef_i* aFileRef = new fileRef_i(pCont, origFileName); - theFileRef = Engines::fileRef::_narrow(aFileRef->_this()); - _numInstanceMutex.lock() ; // lock to be alone (stl container write) - _fileRef_map[origName] = theFileRef; - _numInstanceMutex.unlock() ; - } - - theFileRef = Engines::fileRef::_duplicate(_fileRef_map[origName]); - ASSERT(! CORBA::is_nil(theFileRef)); - return theFileRef._retn(); -} - -//============================================================================= -//! Get a fileTransfer reference -/*! -* CORBA method: -* \return a reference to the fileTransfer object -*/ -//============================================================================= - -Engines::fileTransfer_ptr -Engines_Container_i::getFileTransfer() -{ - Engines::fileTransfer_var aFileTransfer - = Engines::fileTransfer::_duplicate(_fileTransfer); - return aFileTransfer._retn(); -} - - -//! Create a Salome file -Engines::Salome_file_ptr -Engines_Container_i::createSalome_file(const char* origFileName) -{ - string origName(origFileName); - if (CORBA::is_nil(_Salome_file_map[origName])) - { - Salome_file_i* aSalome_file = new Salome_file_i(); - aSalome_file->setContainer(Engines::Container::_duplicate(this->_this())); - try - { - aSalome_file->setLocalFile(origFileName); - aSalome_file->recvFiles(); - } - catch (const SALOME::SALOME_Exception& e) - { - return Engines::Salome_file::_nil(); - } - - Engines::Salome_file_var theSalome_file = Engines::Salome_file::_nil(); - theSalome_file = Engines::Salome_file::_narrow(aSalome_file->_this()); - _numInstanceMutex.lock() ; // lock to be alone (stl container write) - _Salome_file_map[origName] = theSalome_file; - _numInstanceMutex.unlock() ; - } - - Engines::Salome_file_ptr theSalome_file = - Engines::Salome_file::_duplicate(_Salome_file_map[origName]); - ASSERT(!CORBA::is_nil(theSalome_file)); - return theSalome_file; -} -//============================================================================= -//! Finds an already existing component instance or create a new instance -/*! -* 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(std::string genericRegisterName, - std::string componentLibraryName) -{ - string aGenRegisterName = genericRegisterName; - string impl_name = componentLibraryName; - if (_library_map.count(impl_name) == 0) - { - INFOS("shared library " << impl_name <<" must be loaded before creating instance"); - return Engines::Component::_nil() ; - } - else - { - // --- find a registered instance in naming service, or create - - void* handle = _library_map[impl_name]; - 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(); - } -} - -//============================================================================= -//! Create a new component instance +//! Create a new component instance (C++ implementation) /*! * C++ method: create a servant instance of a component. * \param genericRegisterName Name of the component instance to register @@ -1139,6 +925,7 @@ Engines_Container_i::find_or_create_instance(std::string genericRegisterName, * \param handle loaded library handle * \param studyId 0 for multiStudy instance, * study Id (>0) otherwise +* \param reason explains error when creation fails * \return a loaded component * * example with names: @@ -1150,11 +937,11 @@ Engines_Container_i::find_or_create_instance(std::string genericRegisterName, * - component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1 */ //============================================================================= - Engines::Component_ptr Engines_Container_i::createInstance(std::string genericRegisterName, void *handle, - int studyId) + int studyId, + std::string& reason) { // --- find the factory @@ -1162,12 +949,11 @@ Engines_Container_i::createInstance(std::string 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 *) ; + typedef PortableServer::ObjectId* (*FACTORY_FUNCTION) (CORBA::ORB_ptr, + PortableServer::POA_ptr, + PortableServer::ObjectId *, + const char *, + const char *) ; #ifndef WIN32 FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION)dlsym( handle, factory_name.c_str() ); @@ -1179,7 +965,8 @@ Engines_Container_i::createInstance(std::string genericRegisterName, { INFOS( "Can't resolve symbol: " + factory_name ); #ifndef WIN32 - SCRUTE( dlerror() ); + reason=dlerror(); + INFOS(reason); #endif return Engines::Component::_nil() ; } @@ -1205,9 +992,13 @@ Engines_Container_i::createInstance(std::string genericRegisterName, PortableServer::ObjectId *id ; //not owner, do not delete (nore use var) id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str(), - aGenRegisterName.c_str() ) ; + aGenRegisterName.c_str() ) ; if (id == NULL) - return iobject._retn(); + { + reason="Can't get ObjectId from factory"; + INFOS(reason); + return iobject._retn(); + } // --- get reference & servant from id @@ -1236,25 +1027,107 @@ Engines_Container_i::createInstance(std::string genericRegisterName, } catch (...) { - INFOS( "Container_i::createInstance exception catched" ) ; + reason="Container_i::createInstance exception catched"; + INFOS(reason) ; } return iobject._retn(); } +//============================================================================= +//! Find an existing (in the container) component instance +/*! +* 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(); +} + +//============================================================================= +//! Remove the component instance from container +/*! +* 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); + _numInstanceMutex.lock() ; // lock to be alone (stl container write) + _listInstances_map.erase(instanceName); + _numInstanceMutex.unlock() ; + component_i->destroy() ; + _NS->Destroy_Name(instanceName.c_str()); +} + +//============================================================================= +//! Unload component libraries from the container +/*! +* 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(); +} + //============================================================================= //! Decrement component instance reference count -/*! +/*! * */ //============================================================================= - void Engines_Container_i::decInstanceCnt(std::string genericRegisterName) { if(_cntInstances_map.count(genericRegisterName)==0) return; string aGenRegisterName =genericRegisterName; MESSAGE("Engines_Container_i::decInstanceCnt " << aGenRegisterName); - ASSERT(_cntInstances_map[aGenRegisterName] > 0); + ASSERT(_cntInstances_map[aGenRegisterName] > 0); _numInstanceMutex.lock(); // lock to be alone // (see finalize_removal, load_component_Library) _cntInstances_map[aGenRegisterName] -= 1; @@ -1271,13 +1144,127 @@ void Engines_Container_i::decInstanceCnt(std::string genericRegisterName) _numInstanceMutex.unlock(); } +//============================================================================= +//! Find or create a new component instance +/*! +* 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 ) +{ + char* reason; + string impl_name = string(LIB) + genericRegisterName + ENGINESO; + Engines::Component_var iobject = Engines::Component::_nil() ; + if (load_component_Library(genericRegisterName,reason)) + iobject = find_or_create_instance(genericRegisterName, impl_name); + CORBA::string_free(reason); + return iobject._retn(); +} + +//============================================================================= +//! Finds an already existing component instance or create a new instance +/*! +* 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(std::string genericRegisterName, + std::string componentLibraryName) +{ + string aGenRegisterName = genericRegisterName; + string impl_name = componentLibraryName; + if (_library_map.count(impl_name) == 0) + { + INFOS("shared library " << impl_name <<" must be loaded before creating instance"); + return Engines::Component::_nil() ; + } + else + { + // --- find a registered instance in naming service, or create + + void* handle = _library_map[impl_name]; + string component_registerBase = + _containerName + "/" + aGenRegisterName; + Engines::Component_var iobject = Engines::Component::_nil() ; + std::string reason; + try + { + CORBA::Object_var obj = + _NS->ResolveFirst( component_registerBase.c_str()); + if ( CORBA::is_nil( obj ) ) + { + iobject = createInstance(genericRegisterName, + handle, + 0, + reason); // 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(); + } +} + //============================================================================= //! Indicate if container is a python one /*! * Retrieves only with container naming convention if it is a python container */ //============================================================================= - bool Engines_Container_i::isPythonContainer(const char* ContainerName) { bool ret=false; @@ -1288,12 +1275,31 @@ bool Engines_Container_i::isPythonContainer(const char* ContainerName) return ret; } +//============================================================================= +//! Kill the container +/*! +* 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 " + << Kernel_Utils::GetHostname().c_str()); + INFOS("==============================================================="); + INFOS("= REMOVE calls to Kill_impl in C++ container ="); + INFOS("==============================================================="); + //_exit( 0 ) ; + ASSERT(0); + return false; +} + //============================================================================= /*! * */ //============================================================================= - void ActSigIntHandler() { #ifndef WIN32 @@ -1429,11 +1435,102 @@ void SigIntHandler( int what ) } #endif +//============================================================================= +//! Get or create a file reference object associated to a local file (to transfer it) +/*! +* CORBA method: get or create a fileRef object associated to a local file +* (a file on the computer on which runs the container server), which stores +* a list of (machine, localFileName) corresponding to copies already done. +* +* \param origFileName absolute path for a local file to copy on other +* computers +* \return a fileRef object associated to the file. +*/ +//============================================================================= +Engines::fileRef_ptr +Engines_Container_i::createFileRef(const char* origFileName) +{ + string origName(origFileName); + Engines::fileRef_var theFileRef = Engines::fileRef::_nil(); + + if (origName[0] != '/') + { + INFOS("path of file to copy must be an absolute path begining with '/'"); + return Engines::fileRef::_nil(); + } + + if (CORBA::is_nil(_fileRef_map[origName])) + { + CORBA::Object_var obj=_poa->id_to_reference(*_id); + Engines::Container_var pCont = Engines::Container::_narrow(obj); + fileRef_i* aFileRef = new fileRef_i(pCont, origFileName); + theFileRef = Engines::fileRef::_narrow(aFileRef->_this()); + _numInstanceMutex.lock() ; // lock to be alone (stl container write) + _fileRef_map[origName] = theFileRef; + _numInstanceMutex.unlock() ; + } + + theFileRef = Engines::fileRef::_duplicate(_fileRef_map[origName]); + ASSERT(! CORBA::is_nil(theFileRef)); + return theFileRef._retn(); +} + +//============================================================================= +//! Get a fileTransfer reference +/*! +* CORBA method: +* \return a reference to the fileTransfer object +*/ +//============================================================================= +Engines::fileTransfer_ptr +Engines_Container_i::getFileTransfer() +{ + Engines::fileTransfer_var aFileTransfer + = Engines::fileTransfer::_duplicate(_fileTransfer); + return aFileTransfer._retn(); +} + +//============================================================================= +//! Create a Salome file +//============================================================================= +Engines::Salome_file_ptr +Engines_Container_i::createSalome_file(const char* origFileName) +{ + string origName(origFileName); + if (CORBA::is_nil(_Salome_file_map[origName])) + { + Salome_file_i* aSalome_file = new Salome_file_i(); + aSalome_file->setContainer(Engines::Container::_duplicate(this->_this())); + try + { + aSalome_file->setLocalFile(origFileName); + aSalome_file->recvFiles(); + } + catch (const SALOME::SALOME_Exception& e) + { + return Engines::Salome_file::_nil(); + } + + Engines::Salome_file_var theSalome_file = Engines::Salome_file::_nil(); + theSalome_file = Engines::Salome_file::_narrow(aSalome_file->_this()); + _numInstanceMutex.lock() ; // lock to be alone (stl container write) + _Salome_file_map[origName] = theSalome_file; + _numInstanceMutex.unlock() ; + } + + Engines::Salome_file_ptr theSalome_file = + Engines::Salome_file::_duplicate(_Salome_file_map[origName]); + ASSERT(!CORBA::is_nil(theSalome_file)); + return theSalome_file; +} + +//============================================================================= /*! \brief copy a file from a remote host (container) to the local host * \param container the remote container * \param remoteFile the file to copy locally from the remote host into localFile * \param localFile the local file */ +//============================================================================= void Engines_Container_i::copyFile(Engines::Container_ptr container, const char* remoteFile, const char* localFile) { Engines::fileTransfer_var fileTransfer = container->getFileTransfer(); @@ -1472,11 +1569,13 @@ void Engines_Container_i::copyFile(Engines::Container_ptr container, const char* } } +//============================================================================= /*! \brief create a PyNode object to execute remote python code * \param nodeName the name of the node * \param code the python code to load * \return the PyNode */ +//============================================================================= Engines::PyNode_ptr Engines_Container_i::createPyNode(const char* nodeName, const char* code) { Engines::PyNode_var node= Engines::PyNode::_nil(); @@ -1518,3 +1617,64 @@ Engines::PyNode_ptr Engines_Container_i::createPyNode(const char* nodeName, cons } } + +//============================================================================= +/* int checkifexecutable(const char *filename) +* +* Return non-zero if the name is an executable file, and +* zero if it is not executable, or if it does not exist. +*/ +//============================================================================= +int checkifexecutable(const string& filename) +{ + int result; + struct stat statinfo; + + result = stat(filename.c_str(), &statinfo); + if (result < 0) return 0; + if (!S_ISREG(statinfo.st_mode)) return 0; + +#ifdef WIN32 + return 1; +#else + if (statinfo.st_uid == geteuid()) return statinfo.st_mode & S_IXUSR; + if (statinfo.st_gid == getegid()) return statinfo.st_mode & S_IXGRP; + return statinfo.st_mode & S_IXOTH; +#endif +} + + +//============================================================================= +/*! \brief Find a file by searching in a path + * \param filename file name to search + * \param path path to search in + * \param pth the complete file path if found + * \return 1 if found 0 if not +*/ +//============================================================================= +int findpathof(const std::string& path, std::string& pth, const std::string& filename) +{ + if ( path.size() == 0 ) return 0; + + std::string::size_type offset = 0; + std::string::size_type pos = 0; + int found = 0; + struct stat statinfo; + + while(!found) + { + pos = path.find( SEP, offset ); + pth = path.substr( offset, pos - offset ); + if ( pth.size() > 0 ) + { + if( pth[pth.size()-1] != SLASH ) pth += SLASH; + pth += filename; + int result=stat(pth.c_str(), &statinfo); + if(result == 0) found=1; + } + if (pos == string::npos) break; + offset = pos+1; + } + return found; +} + diff --git a/src/Container/SALOME_Container.cxx b/src/Container/SALOME_Container.cxx index 9c59fe28b..5ec639d12 100644 --- a/src/Container/SALOME_Container.cxx +++ b/src/Container/SALOME_Container.cxx @@ -110,7 +110,7 @@ void Handler(int theSigId) std::cerr << "SIGSEGV: " << std::endl; AttachDebugger(); //to exit or not to exit - exit(1); + _exit(1); } void terminateHandler(void) @@ -155,20 +155,8 @@ int main(int argc, char* argv[]) ASSERT(argc > 1); SCRUTE(argv[1]); - bool isSupervContainer = false; - if (strcmp(argv[1],"SuperVisionContainer") == 0) isSupervContainer = true; - if (!isSupervContainer) - { - // int _argc = 1; - // char* _argv[] = {""}; - KERNEL_PYTHON::init_python(argc,argv); - } - else - { - Py_Initialize() ; - PySys_SetArgv( argc , argv ) ; - } + KERNEL_PYTHON::init_python(argc,argv); char *containerName = (char *)""; if(argc > 1) @@ -204,19 +192,15 @@ int main(int argc, char* argv[]) HandleServerSideSignals(orb); - if (!isSupervContainer) - { +//#define MEMORYLEAKS +#ifdef MEMORYLEAKS PyGILState_Ensure(); //Destroy orb from python (for chasing memory leaks) - //PyRun_SimpleString("from omniORB import CORBA"); - //PyRun_SimpleString("orb=CORBA.ORB_init([''], CORBA.ORB_ID)"); - //PyRun_SimpleString("orb.destroy()"); + PyRun_SimpleString("from omniORB import CORBA"); + PyRun_SimpleString("orb=CORBA.ORB_init([''], CORBA.ORB_ID)"); + PyRun_SimpleString("orb.destroy()"); Py_Finalize(); - } - else - { - orb->destroy(); - } +#endif } catch(CORBA::SystemException&) { diff --git a/src/Container/SALOME_Container.py b/src/Container/SALOME_Container.py index df05365d5..6bff65a61 100644 --- a/src/Container/SALOME_Container.py +++ b/src/Container/SALOME_Container.py @@ -36,8 +36,9 @@ import os import sys import string import traceback +import imp from omniORB import CORBA, PortableServer -import SALOMEDS +import SALOMEDS import Engines, Engines__POA from SALOME_NamingServicePy import * from SALOME_ComponentPy import * @@ -77,9 +78,23 @@ class SALOME_Container_i: if verbose(): print "try import ",componentName __import__(componentName) if verbose(): print "import ",componentName," successful" + except ImportError,e: + #can't import python module componentName + #try to find it in python path + try: + fp, pathname, description = imp.find_module(componentName) + if fp:fp.close() + #module file found in path + ret="Component "+componentName+": Python implementation found but it can't be loaded\n" + ret=ret+traceback.format_exc(10) + except ImportError,ee: + ret="ImplementationNotFound" + except: + if verbose():print "error when calling find_module" + ret="ImplementationNotFound" except: - import traceback - ret=traceback.format_exc(10) + ret="Component "+componentName+": Python implementation found but it can't be loaded\n" + ret=ret+traceback.format_exc(10) if verbose(): traceback.print_exc() print "import ",componentName," not possible" @@ -90,6 +105,7 @@ class SALOME_Container_i: def create_component_instance(self, componentName, instanceName, studyId): MESSAGE( "SALOME_Container_i::create_component_instance" ) comp_iors="" + ret="" try: component=__import__(componentName) factory=getattr(component,componentName) @@ -104,10 +120,10 @@ class SALOME_Container_i: comp_o = comp_i._this() comp_iors = self._orb.object_to_string(comp_o) except: - import traceback + ret=traceback.format_exc(10) traceback.print_exc() MESSAGE( "SALOME_Container_i::create_component_instance : NOT OK") - return comp_iors + return comp_iors, ret def create_pynode(self,nodeName,code): diff --git a/src/Container/SALOME_ContainerPy.py b/src/Container/SALOME_ContainerPy.py index d9a09cd49..d7de959ea 100755 --- a/src/Container/SALOME_ContainerPy.py +++ b/src/Container/SALOME_ContainerPy.py @@ -186,10 +186,13 @@ class SALOME_ContainerPy_i (Engines__POA.Container): ret = 0 instanceName = componentName + "_inst_" + `self._numInstance` interfaceName = componentName - return self.import_component(componentName) + return self.import_component(componentName), "" #------------------------------------------------------------------------- + def create_component_instance_env(self, componentName, studyId, env): + return self.create_component_instance(componentName, studyId), "" + def create_component_instance(self, componentName, studyId): MESSAGE( "SALOME_ContainerPy_i::create_component_instance ==> " + str(componentName) + ' ' + str(studyId) ) if studyId < 0: diff --git a/src/Container/SALOME_Container_i.hxx b/src/Container/SALOME_Container_i.hxx index c0a189193..1e5e714dd 100644 --- a/src/Container/SALOME_Container_i.hxx +++ b/src/Container/SALOME_Container_i.hxx @@ -63,7 +63,7 @@ public: // --- CORBA methods - virtual bool load_component_Library(const char* componentName); + virtual bool load_component_Library(const char* componentName, CORBA::String_out reason); virtual Engines::Component_ptr create_component_instance( const char* componentName, @@ -71,8 +71,9 @@ public: virtual Engines::Component_ptr create_component_instance_env( const char* componentName, - CORBA::Long studyId, // 0 for multiStudy - const Engines::FieldsDict& env); + CORBA::Long studyId, // 0 for multiStudy + const Engines::FieldsDict& env, + CORBA::String_out reason); Engines::Component_ptr find_component_instance( const char* registeredName, CORBA::Long studyId); // 0 for multiStudy @@ -109,10 +110,13 @@ public: find_or_create_instance( std::string genericRegisterName, std::string componentLibraryName); - Engines::Component_ptr - createInstance(std::string genericRegisterName, - void *handle, - int studyId); + bool load_component_CppImplementation(const char* componentName,std::string& reason); + bool load_component_PythonImplementation(const char* componentName,std::string& reason); + bool load_component_ExecutableImplementation(const char* componentName,std::string& reason); + + Engines::Component_ptr createPythonInstance(std::string CompName, int studyId, std::string& error); + Engines::Component_ptr createExecutableInstance(std::string CompName, int studyId, const Engines::FieldsDict& env, std::string& error); + Engines::Component_ptr createInstance(std::string genericRegisterName, void *handle, int studyId, std::string& error); static bool isPythonContainer(const char* ContainerName); static void decInstanceCnt(std::string genericRegisterName); diff --git a/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.cxx b/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.cxx index a9612b4b5..65a743859 100644 --- a/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.cxx +++ b/src/LifeCycleCORBA/SALOME_LifeCycleCORBA.cxx @@ -589,37 +589,37 @@ void SALOME_LifeCycleCORBA::shutdownServers() nanosleep(&ts_req,0); #endif - // 4) Registry + // 4) SalomeLauncher try { - CORBA::Object_var objR = _NS->Resolve("/Registry"); - Registry::Components_var registry = Registry::Components::_narrow(objR); - if ( !CORBA::is_nil(registry) && ( pid != registry->getPID() ) ) - registry->Shutdown(); + CORBA::Object_var objSL = _NS->Resolve("/SalomeLauncher"); + Engines::SalomeLauncher_var launcher = Engines::SalomeLauncher::_narrow(objSL); + if (!CORBA::is_nil(launcher) && (pid != launcher->getPID())) + launcher->Shutdown(); } catch(const CORBA::Exception& e) { // ignore and continue } - -//Wait some time so that registry be completely shutdown + +//Wait some time so that launcher be completely shutdown #ifndef WIN32 nanosleep(&ts_req,0); #endif - // 5) SalomeLauncher + // 5) Registry try { - CORBA::Object_var objSL = _NS->Resolve("/SalomeLauncher"); - Engines::SalomeLauncher_var launcher = Engines::SalomeLauncher::_narrow(objSL); - if (!CORBA::is_nil(launcher) && (pid != launcher->getPID())) - launcher->Shutdown(); + CORBA::Object_var objR = _NS->Resolve("/Registry"); + Registry::Components_var registry = Registry::Components::_narrow(objR); + if ( !CORBA::is_nil(registry) && ( pid != registry->getPID() ) ) + registry->Shutdown(); } catch(const CORBA::Exception& e) { // ignore and continue } - + // 6) Logger int argc = 0; char *xargv = (char*)""; @@ -778,8 +778,15 @@ _LoadComponent(const Engines::ContainerParameters& params, Engines::Container_var cont = _ContManager->GiveContainer(local_params); if (CORBA::is_nil(cont)) return Engines::Component::_nil(); - bool isLoadable = cont->load_component_Library(componentName); - if (!isLoadable) return Engines::Component::_nil(); + char* reason; + bool isLoadable = cont->load_component_Library(componentName,reason); + if (!isLoadable) + { + //std::cerr << reason << std::endl; + CORBA::string_free(reason); + return Engines::Component::_nil(); + } + CORBA::string_free(reason); Engines::Component_var myInstance = cont->create_component_instance(componentName, studyId); @@ -820,11 +827,15 @@ SALOME_LifeCycleCORBA::Load_ParallelComponent(const Engines::ContainerParameters } MESSAGE("Loading component library"); - bool isLoadable = cont->load_component_Library(componentName); + char* reason; + bool isLoadable = cont->load_component_Library(componentName,reason); if (!isLoadable) { INFOS(componentName <<" library is not loadable !"); + //std::cerr << reason << std::endl; + CORBA::string_free(reason); return Engines::Component::_nil(); } + CORBA::string_free(reason); MESSAGE("Creating component instance"); // @PARALLEL@ permits to identify that the component requested diff --git a/src/MPIContainer/MPIContainer_i.cxx b/src/MPIContainer/MPIContainer_i.cxx index b03da70ed..a6e0d7125 100644 --- a/src/MPIContainer/MPIContainer_i.cxx +++ b/src/MPIContainer/MPIContainer_i.cxx @@ -114,8 +114,10 @@ void Engines_MPIContainer_i::Shutdown() } // Load a component library -bool Engines_MPIContainer_i::load_component_Library(const char* componentName) +bool Engines_MPIContainer_i::load_component_Library(const char* componentName, CORBA::String_out reason) { + reason=CORBA::string_dup(""); + pthread_t *th; if(_numproc == 0){ th = new pthread_t[_nbproc]; @@ -211,8 +213,11 @@ bool Engines_MPIContainer_i::Lload_component_Library(const char* componentName) Engines::Component_ptr Engines_MPIContainer_i::create_component_instance_env( const char* componentName, CORBA::Long studyId, - const Engines::FieldsDict& env) + const Engines::FieldsDict& env, + CORBA::String_out reason) { + reason=CORBA::string_dup(""); + pthread_t *th; if(_numproc == 0){ th = new pthread_t[_nbproc]; @@ -275,7 +280,10 @@ Engines_MPIContainer_i::Lcreate_component_instance( const char* genericRegisterN aCompName.c_str(), instanceName.c_str(), studyId); - string iors = PyString_AsString(result); + const char *ior; + const char *error; + PyArg_ParseTuple(result,"ss", &ior, &error); + string iors = ior; SCRUTE(iors); Py_RELEASE_NEW_THREAD; @@ -588,7 +596,9 @@ void Engines_MPIContainer_i::finalize_removal() void *th_loadcomponentlibrary(void *s) { thread_st *st = (thread_st*)s; - (Engines::MPIContainer::_narrow((*(st->tior))[st->ip]))->load_component_Library(st->compoName.c_str()); + char* reason; + (Engines::MPIContainer::_narrow((*(st->tior))[st->ip]))->load_component_Library(st->compoName.c_str(),reason); + CORBA::string_free(reason); return NULL; } diff --git a/src/MPIContainer/MPIContainer_i.hxx b/src/MPIContainer/MPIContainer_i.hxx index 899c068cc..0318a659c 100644 --- a/src/MPIContainer/MPIContainer_i.hxx +++ b/src/MPIContainer/MPIContainer_i.hxx @@ -67,14 +67,15 @@ class Engines_MPIContainer_i : public POA_Engines::MPIContainer, // Load a component library // synchronous version for process 0 - bool load_component_Library(const char* componentName); + bool load_component_Library(const char* componentName, CORBA::String_out reason); // Create an instance of component // synchronous version for process 0 virtual Engines::Component_ptr create_component_instance_env( const char* componentName, CORBA::Long studyId, // 0 for multiStudy - const Engines::FieldsDict& env); + const Engines::FieldsDict& env, + CORBA::String_out reason); // Load a component in current MPI container // synchronous version for process 0 diff --git a/src/ParallelContainer/SALOME_ParallelContainerProxy_i.cxx b/src/ParallelContainer/SALOME_ParallelContainerProxy_i.cxx index a37c15edc..7db94fe0b 100644 --- a/src/ParallelContainer/SALOME_ParallelContainerProxy_i.cxx +++ b/src/ParallelContainer/SALOME_ParallelContainerProxy_i.cxx @@ -136,9 +136,11 @@ Container_proxy_impl_final::Shutdown() // déterminer si on doit créer une instance sequentielle // ou parallèle d'un composant dans la méthode create_component_instance CORBA::Boolean -Container_proxy_impl_final::load_component_Library(const char* componentName) +Container_proxy_impl_final::load_component_Library(const char* componentName, CORBA::String_out reason) { - MESSAGE("Begin of load_component_Library on proxy : " << componentName) + MESSAGE("Begin of load_component_Library on proxy : " << componentName); + reason=CORBA::string_dup(""); + std::string aCompName = componentName; CORBA::Boolean ret = true; @@ -236,14 +238,17 @@ Container_proxy_impl_final::load_component_Library(const char* componentName) Engines::Container_var node = Engines::Container::_narrow(object); if (!CORBA::is_nil(node)) { + char* reason; try { - node->load_component_Library(componentName); + node->load_component_Library(componentName,reason); MESSAGE("Call load_component_Library done node : " << i); + CORBA::string_free(reason); } catch (...) { INFOS("Exception catch during load_component_Library of node : " << i); + CORBA::string_free(reason); ret = false; } } @@ -268,7 +273,10 @@ Engines::Component_ptr Container_proxy_impl_final::create_component_instance(const char* componentName, ::CORBA::Long studyId) { Engines::FieldsDict_var env = new Engines::FieldsDict; - return create_component_instance_env(componentName, studyId, env); + char* reason; + Engines::Component_ptr compo = create_component_instance_env(componentName, studyId, env, reason); + CORBA::string_free(reason); + return compo; } // Il y a deux cas : @@ -276,8 +284,11 @@ Container_proxy_impl_final::create_component_instance(const char* componentName, // Composant parallèle -> création du proxy ici puis appel de la création de chaque objet participant // au composant parallèle Engines::Component_ptr -Container_proxy_impl_final::create_component_instance_env(const char* componentName, ::CORBA::Long studyId, const Engines::FieldsDict& env) +Container_proxy_impl_final::create_component_instance_env(const char* componentName, ::CORBA::Long studyId, + const Engines::FieldsDict& env, CORBA::String_out reason) { + reason=CORBA::string_dup(""); + std::string aCompName = componentName; if (_libtype_map.count(aCompName) == 0) { diff --git a/src/ParallelContainer/SALOME_ParallelContainerProxy_i.hxx b/src/ParallelContainer/SALOME_ParallelContainerProxy_i.hxx index 900712494..ec9972cab 100644 --- a/src/ParallelContainer/SALOME_ParallelContainerProxy_i.hxx +++ b/src/ParallelContainer/SALOME_ParallelContainerProxy_i.hxx @@ -54,11 +54,12 @@ class Container_proxy_impl_final : virtual void Shutdown(); - virtual ::CORBA::Boolean load_component_Library(const char* componentName); + virtual ::CORBA::Boolean load_component_Library(const char* componentName,CORBA::String_out reason); virtual Engines::Component_ptr create_component_instance(const char* componentName, ::CORBA::Long studyId); virtual Engines::Component_ptr create_component_instance_env( const char* componentName, CORBA::Long studyId, // 0 for multiStudy - const Engines::FieldsDict& env); + const Engines::FieldsDict& env, + CORBA::String_out reason); private: std::map _libtype_map; // libname -> libtype (seq ou par) diff --git a/src/ParallelContainer/SALOME_ParallelContainer_i.cxx b/src/ParallelContainer/SALOME_ParallelContainer_i.cxx index 33d9be7b3..c22ff906d 100644 --- a/src/ParallelContainer/SALOME_ParallelContainer_i.cxx +++ b/src/ParallelContainer/SALOME_ParallelContainer_i.cxx @@ -289,8 +289,10 @@ void Engines_Parallel_Container_i::Shutdown() //============================================================================= bool -Engines_Parallel_Container_i::load_component_Library(const char* componentName) +Engines_Parallel_Container_i::load_component_Library(const char* componentName, CORBA::String_out reason) { + reason=CORBA::string_dup(""); + MESSAGE("Begin of load_component_Library : " << componentName) bool ret = false; std::string aCompName = componentName; @@ -386,7 +388,10 @@ Engines_Parallel_Container_i::create_component_instance(const char*genericRegist CORBA::Long studyId) { Engines::FieldsDict_var env = new Engines::FieldsDict; - return create_component_instance_env(genericRegisterName,studyId,env); + char* reason; + Engines::Component_ptr compo = create_component_instance_env(genericRegisterName,studyId,env, reason); + CORBA::string_free(reason); + return compo; } //============================================================================= @@ -406,9 +411,11 @@ Engines_Parallel_Container_i::create_component_instance(const char*genericRegist Engines::Component_ptr Engines_Parallel_Container_i::create_component_instance_env(const char*genericRegisterName, CORBA::Long studyId, - const Engines::FieldsDict& env) + const Engines::FieldsDict& env, + CORBA::String_out reason) { MESSAGE("Begin of create_component_instance in node : " << getMyRank()); + reason=CORBA::string_dup(""); if (studyId < 0) { @@ -504,8 +511,10 @@ Engines::Component_ptr Engines_Parallel_Container_i::load_impl( const char* gene const char* componentName ) { Engines::Component_var iobject = Engines::Component::_nil(); - if (load_component_Library(genericRegisterName)) + char* reason; + if (load_component_Library(genericRegisterName,reason)) iobject = find_or_create_instance(genericRegisterName); + CORBA::string_free(reason); return iobject._retn(); } @@ -782,7 +791,10 @@ Engines_Parallel_Container_i::createPythonInstance(string genericRegisterName, i genericRegisterName.c_str(), instanceName.c_str(), studyId); - std::string iors = PyString_AsString(result); + const char *ior; + const char *error; + PyArg_ParseTuple(result,"ss", &ior, &error); + string iors = ior; Py_DECREF(result); Py_RELEASE_NEW_THREAD; diff --git a/src/ParallelContainer/SALOME_ParallelContainer_i.hxx b/src/ParallelContainer/SALOME_ParallelContainer_i.hxx index 55bbf8802..8e9102660 100644 --- a/src/ParallelContainer/SALOME_ParallelContainer_i.hxx +++ b/src/ParallelContainer/SALOME_ParallelContainer_i.hxx @@ -71,7 +71,7 @@ public: // --- CORBA methods - virtual bool load_component_Library(const char* componentName); + virtual bool load_component_Library(const char* componentName, CORBA::String_out reason); virtual Engines::Component_ptr create_component_instance( const char* componentName, @@ -79,8 +79,9 @@ public: virtual Engines::Component_ptr create_component_instance_env( const char* componentName, - CORBA::Long studyId, // 0 for multiStudy - const Engines::FieldsDict& env); + CORBA::Long studyId, // 0 for multiStudy + const Engines::FieldsDict& env, + CORBA::String_out reason); Engines::Component_ptr find_component_instance( const char* registeredName, diff --git a/src/TestContainer/TestContainer.cxx b/src/TestContainer/TestContainer.cxx index be2c6ebc2..eb847807d 100644 --- a/src/TestContainer/TestContainer.cxx +++ b/src/TestContainer/TestContainer.cxx @@ -62,18 +62,16 @@ static std::ostream& operator<<(std::ostream& os, const CORBA::Exception& e) Engines::TestComponent_ptr create_instance(Engines::Container_ptr iGenFact, std::string componenttName) { + char* reason; #if defined(_DEBUG_) || defined(_DEBUG) bool isLib = - iGenFact->load_component_Library(componenttName.c_str()); - // iGenFact->load_component_Library("SalomeTestComponent"); + iGenFact->load_component_Library(componenttName.c_str(),reason); ASSERT(isLib); #else - iGenFact->load_component_Library(componenttName.c_str()); + iGenFact->load_component_Library(componenttName.c_str(),reason); #endif - CORBA::Object_var obj = - // iGenFact->create_component_instance("SalomeTestComponent", - iGenFact->create_component_instance(componenttName.c_str(), - 0); + CORBA::string_free(reason); + CORBA::Object_var obj = iGenFact->create_component_instance(componenttName.c_str(), 0); Engines::TestComponent_var anInstance = Engines::TestComponent::_narrow(obj); MESSAGE("create anInstance"); SCRUTE(anInstance->instanceName()); -- 2.39.2