-// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
+#include <memory>
#ifndef WIN32
#include <sys/time.h>
#include <dlfcn.h>
#include <unistd.h>
#include <sys/wait.h>
+#include <errno.h>
+#include <stdlib.h>
#else
#include <signal.h>
#include <process.h>
#include CORBA_SERVER_HEADER(SALOME_Component)
#include CORBA_SERVER_HEADER(SALOME_Exception)
#include <pthread.h> // must be before Python.h !
+#include "OpUtil.hxx"
#include "SALOME_Container_i.hxx"
#include "SALOME_Component_i.hxx"
#include "SALOME_FileRef_i.hxx"
#include "SALOME_FileTransfer_i.hxx"
#include "Salome_file_i.hxx"
#include "SALOME_NamingService.hxx"
+#include "SALOME_Fake_NamingService.hxx"
+#include "SALOME_Embedded_NamingService_Client.hxx"
+#include "SALOME_Embedded_NamingService.hxx"
#include "Basics_Utils.hxx"
+#include "PythonCppUtils.hxx"
#ifdef _XOPEN_SOURCE
#undef _XOPEN_SOURCE
#endif
#include <Python.h>
+#include <structmember.h>
#include "Container_init_python.hxx"
+#ifdef BOS26455_WITH_BOOST_PYTHON
+#include <boost/python.hpp>
+#endif
bool _Sleeping = false ;
#define SLASH '/'
#endif
-std::map<std::string, int> Engines_Container_i::_cntInstances_map;
-std::map<std::string, void *> Engines_Container_i::_library_map;
-std::map<std::string, void *> Engines_Container_i::_toRemove_map;
-omni_mutex Engines_Container_i::_numInstanceMutex ;
+std::map<std::string, int> Abstract_Engines_Container_i::_cntInstances_map;
+std::map<std::string, void *> Abstract_Engines_Container_i::_library_map;
+std::map<std::string, void *> Abstract_Engines_Container_i::_toRemove_map;
+omni_mutex Abstract_Engines_Container_i::_numInstanceMutex ;
static PyObject* _pyCont;
*/
//=============================================================================
-Engines_Container_i::Engines_Container_i () :
-_numInstance(0),_id(0),_NS(0)
+Abstract_Engines_Container_i::Abstract_Engines_Container_i () :
+ _NS(nullptr),_id(nullptr),_numInstance(0)
{
}
//=============================================================================
/*!
-* Construtor to use
+* Constructor to use
*/
//=============================================================================
-Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb,
- PortableServer::POA_ptr poa,
- char *containerName ,
- int argc , char* argv[],
- bool activAndRegist,
- bool isServantAloneInProcess
- ) :
- _numInstance(0),_isServantAloneInProcess(isServantAloneInProcess),_id(0),_NS(0)
+Abstract_Engines_Container_i::Abstract_Engines_Container_i (CORBA::ORB_ptr orb,
+ PortableServer::POA_ptr poa,
+ char *containerName ,
+ int argc , char* argv[],
+ SALOME_NamingService_Container_Abstract *ns,
+ bool isServantAloneInProcess
+ ) :
+ _NS(nullptr),_id(0),_numInstance(0),_isServantAloneInProcess(isServantAloneInProcess)
{
_pid = (long)getpid();
- if(activAndRegist)
+ if(ns)
ActSigIntHandler() ;
_argc = argc ;
// Pour les containers paralleles: il ne faut pas enregistrer et activer
// le container generique, mais le container specialise
- if(activAndRegist)
{
_id = _poa->activate_object(this);
- _NS = new SALOME_NamingService();
+ // key point : if ns is nullptr : this servant is alone in its process
+ // if ns is not null : this servant embedded into single process.
+ _NS = ns==nullptr ? new SALOME_NamingService : ns->clone();
_NS->init_orb( _orb ) ;
CORBA::Object_var obj=_poa->id_to_reference(*_id);
- Engines::Container_var pCont
- = Engines::Container::_narrow(obj);
+ Engines::Container_var pCont = Engines::Container::_narrow(obj);
_remove_ref();
- _containerName = _NS->BuildContainerNameForNS(containerName,
- hostname.c_str());
+ _containerName = SALOME_NamingService_Abstract::BuildContainerNameForNS(containerName, hostname.c_str());
SCRUTE(_containerName);
_NS->Register(pCont, _containerName.c_str());
- MESSAGE("Engines_Container_i::Engines_Container_i : Container name "
- << _containerName);
+ MESSAGE("Engines_Container_i::Engines_Container_i : Container name " << _containerName);
// Python:
// import SALOME_Container
//approach leads to the deadlock of the main thread of the application on Windows platform
//in case if cppContainer runs in the standalone mode. The problem with the PyThreadState
//described by ABN seems not reproduced, to be checked carefully later...
- PyGILState_STATE gstate = PyGILState_Ensure();
-
- //// [ABN]: using the PyGILState* API here is unstable. omniORB logic is invoked
- //// by the Python code executed below, and in some (random) cases, the Python code
- //// execution ends with a PyThreadState which was not the one we have here.
- //// (TODO: understand why ...)
- //// To be on the safe side we get and load the thread state ourselves:
- //PyEval_AcquireLock(); // get GIL
- //PyThreadState * mainThreadState = PyThreadState_Get();
- //PyThreadState_Swap(mainThreadState);
+ {
+ AutoGIL gstate;
+ //// [ABN]: using the PyGILState* API here is unstable. omniORB logic is invoked
+ //// by the Python code executed below, and in some (random) cases, the Python code
+ //// execution ends with a PyThreadState which was not the one we have here.
+ //// (TODO: understand why ...)
+ //// To be on the safe side we get and load the thread state ourselves:
+ //PyEval_AcquireLock(); // get GIL
+ //PyThreadState * mainThreadState = PyThreadState_Get();
+ //PyThreadState_Swap(mainThreadState);
#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");
-
- //PyThreadState_Swap(NULL);
- //PyEval_ReleaseLock();
- PyGILState_Release(gstate);
+ 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");
+ //PyThreadState_Swap(NULL);
+ //PyEval_ReleaseLock();
+ }
fileTransfer_i* aFileTransfer = new fileTransfer_i();
CORBA::Object_var obref=aFileTransfer->_this();
*/
//=============================================================================
-Engines_Container_i::~Engines_Container_i()
+Abstract_Engines_Container_i::~Abstract_Engines_Container_i()
{
- MESSAGE("Container_i::~Container_i()");
+ MESSAGE("Abstract_Container_i::~Abstract_Container_i()");
if(_id)
delete _id;
if(_NS)
delete _NS;
- for(std::map<std::string,Engines::PyNode_var>::iterator it=_dftPyNode.begin();it!=_dftPyNode.end();it++)
- {
- Engines::PyNode_var tmpVar((*it).second);
- if(!CORBA::is_nil(tmpVar))
- tmpVar->UnRegister();
- }
- for(std::map<std::string,Engines::PyScriptNode_var>::iterator it=_dftPyScriptNode.begin();it!=_dftPyScriptNode.end();it++)
- {
- Engines::PyScriptNode_var tmpVar((*it).second);
- if(!CORBA::is_nil(tmpVar))
- tmpVar->UnRegister();
- }
+ cleanAllPyScripts();
}
//=============================================================================
*/
//=============================================================================
-char* Engines_Container_i::name()
+char* Abstract_Engines_Container_i::name()
{
return CORBA::string_dup(_containerName.c_str()) ;
}
*/
//=============================================================================
-char* Engines_Container_i::workingdir()
+char* Abstract_Engines_Container_i::workingdir()
{
char wd[256];
getcwd (wd,256);
*/
//=============================================================================
-char* Engines_Container_i::logfilename()
+char* Abstract_Engines_Container_i::logfilename()
{
return CORBA::string_dup(_logfilename.c_str()) ;
}
//! Set container log file name
-void Engines_Container_i::logfilename(const char* name)
+void Abstract_Engines_Container_i::logfilename(const char* name)
{
_logfilename=name;
}
*/
//=============================================================================
-char* Engines_Container_i::getHostName()
+char* Abstract_Engines_Container_i::getHostName()
{
std::string s = Kernel_Utils::GetHostname();
// MESSAGE("Engines_Container_i::getHostName " << s);
*/
//=============================================================================
-CORBA::Long Engines_Container_i::getPID()
+CORBA::Long Abstract_Engines_Container_i::getPID()
{
return (CORBA::Long)getpid();
}
* CORBA method: check if servant is still alive
*/
//=============================================================================
-void Engines_Container_i::ping()
+void Abstract_Engines_Container_i::ping()
{
MESSAGE("Engines_Container_i::ping() pid "<< getpid());
}
+//=============================================================================
+//! Get number of CPU cores in the calculation node
+/*!
+* CORBA method: get number of CPU cores
+*/
+//=============================================================================
+
+CORBA::Long Abstract_Engines_Container_i::getNumberOfCPUCores()
+{
+ AutoGIL gstate;
+ PyObject *module = PyImport_ImportModuleNoBlock((char*)"salome_psutil");
+ PyObject *result = PyObject_CallMethod(module,
+ (char*)"getNumberOfCPUCores", NULL);
+ int n = PyLong_AsLong(result);
+ Py_DECREF(result);
+
+ return (CORBA::Long)n;
+}
+
+//=============================================================================
+//! Get a load of each CPU core in the calculation node
+/*!
+* CORBA method: get a load of each CPU core
+*/
+//=============================================================================
+namespace {
+ typedef struct
+ {
+ PyObject_HEAD
+ int softspace;
+ std::string *out;
+ } PyStdOut;
+
+ static void
+ PyStdOut_dealloc(PyStdOut *self)
+ {
+ PyObject_Del(self);
+ }
+
+ static PyObject*
+ PyStdOut_write(PyStdOut* self, PyObject* args)
+ {
+ char *c;
+ if (!PyArg_ParseTuple(args, "s", &c))
+ return NULL;
+
+ *(self->out) = *(self->out) + c;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ static PyMethodDef PyStdOut_methods[] =
+ {
+ {"write", (PyCFunction)PyStdOut_write, METH_VARARGS,
+ PyDoc_STR("write(string) -> None")},
+ {0, 0, 0, 0} /* sentinel */
+ };
+
+ static PyMemberDef PyStdOut_memberlist[] =
+ {
+ {(char*)"softspace", T_INT, offsetof(PyStdOut, softspace), 0,
+ (char*)"flag indicating that a space needs to be printed; used by print"},
+ {0, 0, 0, 0, 0} /* sentinel */
+ };
+
+ static PyTypeObject PyStdOut_Type =
+ {
+ /* The ob_type field must be initialized in the module init function
+ * to be portable to Windows without using C++. */
+ PyVarObject_HEAD_INIT(NULL, 0)
+ /* 0, */ /*ob_size*/
+ "PyOut", /*tp_name*/
+ sizeof(PyStdOut), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)PyStdOut_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ PyObject_GenericGetAttr, /*tp_getattro*/
+ /* softspace is writable: we must supply tp_setattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ 0, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ PyStdOut_methods, /*tp_methods*/
+ PyStdOut_memberlist, /*tp_members*/
+ 0, /*tp_getset*/
+ 0, /*tp_base*/
+ 0, /*tp_dict*/
+ 0, /*tp_descr_get*/
+ 0, /*tp_descr_set*/
+ 0, /*tp_dictoffset*/
+ 0, /*tp_init*/
+ 0, /*tp_alloc*/
+ 0, /*tp_new*/
+ 0, /*tp_free*/
+ 0, /*tp_is_gc*/
+ 0, /*tp_bases*/
+ 0, /*tp_mro*/
+ 0, /*tp_cache*/
+ 0, /*tp_subclasses*/
+ 0, /*tp_weaklist*/
+ 0, /*tp_del*/
+ 0, /*tp_version_tag*/
+ 0, /*tp_finalize*/
+ };
+
+ PyObject* newPyStdOut(std::string& out)
+ {
+ PyStdOut* self = PyObject_New(PyStdOut, &PyStdOut_Type);
+ if (self) {
+ self->softspace = 0;
+ self->out=&out;
+ }
+ return (PyObject*)self;
+ }
+
+ std::string parseException()
+ {
+ std::string error;
+ if (PyErr_Occurred())
+ {
+#ifdef BOS26455_WITH_BOOST_PYTHON
+ PyObject *ptype = nullptr;
+ PyObject *pvalue = nullptr;
+ PyObject *ptraceback = nullptr;
+ PyErr_Fetch(&ptype, &pvalue, &ptraceback);
+ if (ptype == nullptr)
+ return std::string("Null exception type");
+ PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
+ if (ptraceback != nullptr)
+ PyException_SetTraceback(pvalue, ptraceback);
+ boost::python::handle<> htype(ptype);
+ boost::python::handle<> hvalue(boost::python::allow_null(pvalue));
+ boost::python::handle<> htraceback(boost::python::allow_null(ptraceback));
+ boost::python::object traceback = boost::python::import("traceback");
+ boost::python::object format_exc = traceback.attr("format_exception");
+ boost::python::object formatted = format_exc(htype, hvalue, htraceback);
+ error = boost::python::extract<std::string>(boost::python::str("\n").join(formatted));
+#else
+ PyObject* new_stderr = newPyStdOut(error);
+ PyObject* old_stderr = PySys_GetObject((char*)"stderr");
+ Py_INCREF(old_stderr);
+ PySys_SetObject((char*)"stderr", new_stderr);
+ PyErr_Print();
+ PySys_SetObject((char*)"stderr", old_stderr);
+ Py_DECREF(new_stderr);
+#endif
+ }
+ return error;
+ }
+}
+
+Engines::vectorOfDouble* Abstract_Engines_Container_i::loadOfCPUCores()
+{
+ AutoGIL gstate;
+ PyObject *module = PyImport_ImportModuleNoBlock((char*)"salome_psutil");
+ PyObject *result = PyObject_CallMethod(module,
+ (char*)"loadOfCPUCores", "s",
+ _load_script.c_str());
+ if (PyErr_Occurred())
+ {
+ std::string error = parseException();
+ PyErr_Print();
+ SALOME::ExceptionStruct es;
+ es.type = SALOME::INTERNAL_ERROR;
+ es.text = CORBA::string_dup(error.c_str());
+ throw SALOME::SALOME_Exception(es);
+ }
+
+ int n = this->getNumberOfCPUCores();
+ if (!PyList_Check(result) || PyList_Size(result) != n) {
+ // bad number of cores
+ Py_DECREF(result);
+ SALOME::ExceptionStruct es;
+ es.type = SALOME::INTERNAL_ERROR;
+ es.text = "wrong number of cores";
+ throw SALOME::SALOME_Exception(es);
+ }
+
+ Engines::vectorOfDouble_var loads = new Engines::vectorOfDouble;
+ loads->length(n);
+ for (Py_ssize_t i = 0; i < PyList_Size(result); ++i) {
+ PyObject* item = PyList_GetItem(result, i);
+ double foo = PyFloat_AsDouble(item);
+ if (foo < 0.0 || foo > 1.0)
+ {
+ // value not in [0, 1] range
+ Py_DECREF(result);
+ SALOME::ExceptionStruct es;
+ es.type = SALOME::INTERNAL_ERROR;
+ es.text = "load not in [0, 1] range";
+ throw SALOME::SALOME_Exception(es);
+ }
+ loads[i] = foo;
+ }
+
+ Py_DECREF(result);
+
+ return loads._retn();
+}
+
+//=============================================================================
+//! Set custom script to calculate a load of each CPU core
+/*!
+* CORBA method: Set custom script to calculate CPU load
+* \param script Python script to execute
+*/
+//=============================================================================
+
+void Abstract_Engines_Container_i::setPyScriptForCPULoad(const char *script)
+{
+ _load_script = script;
+}
+
+//=============================================================================
+//! Nullify custom script to calculate each CPU core's load
+/*!
+* CORBA method: reset script for load calculation to default implementation
+*/
+//=============================================================================
+
+void Abstract_Engines_Container_i::resetScriptForCPULoad()
+{
+ _load_script = "";
+}
+
+//=============================================================================
+//! Get total physical memory of calculation node, in megabytes
+/*!
+* CORBA method: get total physical memory of calculation node
+*/
+//=============================================================================
+
+CORBA::Long Abstract_Engines_Container_i::getTotalPhysicalMemory()
+{
+ AutoGIL gstate;
+ PyObject *module = PyImport_ImportModuleNoBlock((char*)"salome_psutil");
+ PyObject *result = PyObject_CallMethod(module,
+ (char*)"getTotalPhysicalMemory", NULL);
+ int n = PyLong_AsLong(result);
+ Py_DECREF(result);
+
+ return (CORBA::Long)n;
+}
+
+//=============================================================================
+//! Get used physical memory of calculation node, in megabytes
+/*!
+* CORBA method: get used physical memory of calculation node
+*/
+//=============================================================================
+
+CORBA::Long Abstract_Engines_Container_i::getTotalPhysicalMemoryInUse()
+{
+ AutoGIL gstate;
+ PyObject *module = PyImport_ImportModuleNoBlock((char*)"salome_psutil");
+ PyObject *result = PyObject_CallMethod(module,
+ (char*)"getTotalPhysicalMemoryInUse", NULL);
+ int n = PyLong_AsLong(result);
+ Py_DECREF(result);
+
+ return (CORBA::Long)n;
+}
+
+//=============================================================================
+//! Obtain physical memory, used by the current process, in megabytes.
+/*!
+* CORBA method: get physical memory, used by the current process
+*/
+//=============================================================================
+
+CORBA::Long Abstract_Engines_Container_i::getTotalPhysicalMemoryInUseByMe()
+{
+ AutoGIL gstate;
+ PyObject *module = PyImport_ImportModuleNoBlock((char*)"salome_psutil");
+ PyObject *result = PyObject_CallMethod(module,
+ (char*)"getTotalPhysicalMemoryInUseByMe", NULL);
+ int n = PyLong_AsLong(result);
+ Py_DECREF(result);
+
+ return (CORBA::Long)n;
+}
+
//=============================================================================
//! Shutdown the container
/*!
* - orb shutdown if no other servants in the process
*/
//=============================================================================
-void Engines_Container_i::Shutdown()
+void Abstract_Engines_Container_i::Shutdown()
{
MESSAGE("Engines_Container_i::Shutdown()");
{
itm->second->destroy();
}
- catch(const CORBA::Exception& e)
+ catch(const CORBA::Exception&)
{
// ignore this entry and continue
}
}
_listInstances_map.clear();
- _NS->Destroy_FullDirectory(_containerName.c_str());
- _NS->Destroy_Name(_containerName.c_str());
+ // NS unregistering may throw in SSL mode if master process hosting SALOME_Embedded_NamingService servant has vanished
+ // In this case it's skip it and still continue.
+ try
+ {
+ _NS->Destroy_FullDirectory(_containerName.c_str());
+ _NS->Destroy_Name(_containerName.c_str());
+ }
+ catch(...)
+ {
+ }
+ //
+ this->cleanAllPyScripts();
+ //
if(_isServantAloneInProcess)
{
MESSAGE("Effective Shutdown of container Begins...");
* CORBA method
* \param componentName component name
* \param reason explains error when load fails
-* \return true if dlopen successfull or already done, false otherwise
+* \return true if dlopen successful or already done, false otherwise
*/
//=============================================================================
bool
-Engines_Container_i::load_component_Library(const char* componentName, CORBA::String_out reason)
+Abstract_Engines_Container_i::load_component_Library(const char* componentName, CORBA::String_out reason)
{
//=================================================================
* 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
+* \return true if loading is successful or already done, false otherwise
*/
//=============================================================================
bool
-Engines_Container_i::load_component_CppImplementation(const char* componentName, std::string& reason)
+Abstract_Engines_Container_i::load_component_CppImplementation(const char* componentName, std::string& reason)
{
std::string aCompName(componentName);
std::string impl_name = std::string(LIB) + aCompName + ENGINESO;
}
#else
HINSTANCE handle;
- handle = LoadLibrary( impl_name.c_str() );
+#ifdef UNICODE
+ std::wstring libToLoad = Kernel_Utils::utf8_decode_s( impl_name );
+#else
+ std::string libToLoad = impl_name;
+#endif
+ handle = LoadLibrary(libToLoad.c_str() );
if ( !handle )
{
reason="ImplementationNotFound";
* C++ method:
* \param componentName name of the component
* \param reason explains error when load fails
-* \return true if loading is successfull or already done, false otherwise
+* \return true if loading is successful or already done, false otherwise
*/
//=============================================================================
bool
-Engines_Container_i::load_component_PythonImplementation(const char* componentName, std::string& reason)
+Abstract_Engines_Container_i::load_component_PythonImplementation(const char* componentName, std::string& reason)
{
std::string aCompName(componentName);
}
_numInstanceMutex.unlock() ;
- PyGILState_STATE gstate = PyGILState_Ensure();
- PyObject *result = PyObject_CallMethod(_pyCont,
- (char*)"import_component",
- (char*)"s",componentName);
+ {
+ AutoGIL gstate;
+ PyObject *result = PyObject_CallMethod(_pyCont,
+ (char*)"import_component",
+ (char*)"s",componentName);
- reason=PyUnicode_AsUTF8(result);
- Py_XDECREF(result);
- SCRUTE(reason);
- PyGILState_Release(gstate);
+ reason=PyUnicode_AsUTF8(result);
+ Py_XDECREF(result);
+ SCRUTE(reason);
+ }
if (reason=="")
{
* C++ method:
* \param componentName name of the component
* \param reason explains error when load fails
-* \return true if loading is successfull or already done, false otherwise
+* \return true if loading is successful or already done, false otherwise
*/
//=============================================================================
bool
-Engines_Container_i::load_component_ExecutableImplementation(const char* componentName, std::string& reason)
+Abstract_Engines_Container_i::load_component_ExecutableImplementation(const char* componentName, std::string& reason)
{
std::string aCompName(componentName);
std::string executable=aCompName+".exe";
//! Create a new component instance
/*!
* CORBA method: Creates a new servant instance of a component.
-* The servant registers itself to naming service and Registry.
+* The servant registers itself to naming service and Registry.tdlib
* \param genericRegisterName Name of the component instance to register
* in Registry & Name Service (without _inst_n suffix)
* \return a loaded component
*/
//=============================================================================
Engines::EngineComponent_ptr
-Engines_Container_i::create_component_instance(const char*genericRegisterName)
+Abstract_Engines_Container_i::create_component_instance(const char*genericRegisterName)
{
Engines::FieldsDict_var env = new Engines::FieldsDict;
char* reason;
return compo;
}
+void EffectiveOverrideEnvironment( const Engines::FieldsDict& env )
+{
+ MESSAGE("Positionning environment on container ");
+ for (CORBA::ULong i=0; i < env.length(); i++)
+ {
+ if (env[i].value.type()->kind() == CORBA::tk_string)
+ {
+ const char* value;
+ env[i].value >>= value;
+ MESSAGE( env[i].key << " = " << value);
+#ifndef WIN32
+ if( setenv(env[i].key,value,1) != 0 )
+ {
+ int errsv = errno;
+ std::string sErr( strerror( errsv) );
+ MESSAGE(sErr);
+ }
+#endif
+ }
+ }
+}
+
+std::vector< std::pair<std::string,std::string> > GetOSEnvironment()
+{
+ std::vector< std::pair<std::string,std::string> > ret;
+#ifndef WIN32
+ char **envPt( environ );
+ for(;*envPt != nullptr; ++envPt)
+ {
+ std::string s( *envPt );
+ auto pos = s.find_first_of('=');
+ std::string k( s.substr(0,pos) ),v( s.substr(pos+1) );
+ ret.emplace_back( std::pair<std::string,std::string>(k,v) );
+ }
+#endif
+ return ret;
+}
+
+void Abstract_Engines_Container_i::override_environment( const Engines::FieldsDict& env )
+{
+ EffectiveOverrideEnvironment(env);
+}
+
+Engines::FieldsDict *Abstract_Engines_Container_i::get_os_environment()
+{
+ std::unique_ptr<Engines::FieldsDict> ret( new Engines::FieldsDict );
+ std::vector< std::pair<std::string,std::string> > retCpp( GetOSEnvironment() );
+ auto sz = retCpp.size();
+ ret->length( sz );
+ for(auto i = 0 ; i < sz ; ++i)
+ {
+ (*ret)[i].key = CORBA::string_dup( retCpp[i].first.c_str() );
+ (*ret)[i].value <<= CORBA::string_dup( retCpp[i].second.c_str() );
+ }
+ return ret.release();
+}
+
//=============================================================================
//! Create a new component instance with environment variables specified
/*!
*/
//=============================================================================
Engines::EngineComponent_ptr
-Engines_Container_i::create_component_instance_env(const char*genericRegisterName,
+Abstract_Engines_Container_i::create_component_instance_env(const char*genericRegisterName,
const Engines::FieldsDict& env,
CORBA::String_out reason)
{
*/
//=============================================================================
Engines::EngineComponent_ptr
-Engines_Container_i::createExecutableInstance(std::string CompName,
- const Engines::FieldsDict& env,
- std::string& reason)
+Abstract_Engines_Container_i::createExecutableInstance(std::string CompName,
+ const Engines::FieldsDict& env,
+ std::string& reason)
{
Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil() ;
pid_t pid = fork();
if(pid == 0) // child
{
- for (CORBA::ULong i=0; i < env.length(); i++)
- {
- if (env[i].value.type()->kind() == CORBA::tk_string)
- {
- const char* value;
- env[i].value >>= value;
- std::string s(env[i].key);
- s+='=';
- s+=value;
- putenv(strdup(s.c_str()));
- }
- }
+ EffectiveOverrideEnvironment(env);
execl("/bin/sh", "sh", "-c", command.c_str() , (char *)0);
status=-1;
*/
//=============================================================================
Engines::EngineComponent_ptr
-Engines_Container_i::createPythonInstance(std::string CompName,
+Abstract_Engines_Container_i::createPythonInstance(std::string CompName,
std::string& reason)
{
Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil() ;
sprintf( aNumI , "%d" , numInstance ) ;
std::string instanceName = CompName + "_inst_" + aNumI ;
std::string component_registerName = _containerName + "/" + instanceName;
-
- PyGILState_STATE gstate = PyGILState_Ensure();
- PyObject *result = PyObject_CallMethod(_pyCont,
- (char*)"create_component_instance",
- (char*)"ss",
- CompName.c_str(),
- instanceName.c_str());
- const char *ior;
- const char *error;
- PyArg_ParseTuple(result,"ss", &ior, &error);
- std::string iors = ior;
- reason=error;
- Py_DECREF(result);
- PyGILState_Release(gstate);
+ std::string iors;
+ {
+ AutoGIL gstate;
+ PyObject *result = PyObject_CallMethod(_pyCont,
+ (char*)"create_component_instance",
+ (char*)"ss",
+ CompName.c_str(),
+ instanceName.c_str());
+ const char *ior;
+ const char *error;
+ PyArg_ParseTuple(result,"ss", &ior, &error);
+ iors = ior;
+ reason=error;
+ Py_DECREF(result);
+ }
if( iors!="" )
{
}
char *
-Engines_Container_i::create_python_service_instance(const char * CompName,
+Abstract_Engines_Container_i::create_python_service_instance(const char * CompName,
CORBA::String_out reason)
{
CORBA::Object_var object = CORBA::Object::_nil();
std::string instanceName = std::string(CompName) + "_inst_" + aNumI ;
std::string component_registerName = _containerName + "/" + instanceName;
- PyGILState_STATE gstate = PyGILState_Ensure();
- PyObject *result = PyObject_CallMethod(_pyCont,
- (char*)"create_component_instance",
- (char*)"ss",
- CompName,
- instanceName.c_str());
- const char *ior;
- const char *error;
- PyArg_ParseTuple(result,"ss", &ior, &error);
- reason = CORBA::string_dup(error);
- char * _ior = CORBA::string_dup(ior);
- Py_DECREF(result);
- PyGILState_Release(gstate);
-
+ char * _ior = nullptr;
+ {
+ AutoGIL gstate;
+ PyObject *result = PyObject_CallMethod(_pyCont,
+ (char*)"create_component_instance",
+ (char*)"ss",
+ CompName,
+ instanceName.c_str());
+ const char *ior;
+ const char *error;
+ PyArg_ParseTuple(result,"ss", &ior, &error);
+ reason = CORBA::string_dup(error);
+ _ior = CORBA::string_dup(ior);
+ Py_DECREF(result);
+ }
return _ior;
}
*/
//=============================================================================
Engines::EngineComponent_ptr
-Engines_Container_i::createInstance(std::string genericRegisterName,
+Abstract_Engines_Container_i::createInstance(std::string genericRegisterName,
void *handle,
std::string& reason)
{
std::string component_registerName =
_containerName + "/" + instanceName;
- // --- Instanciate required CORBA object
+ // --- Instantiate required CORBA object
PortableServer::ObjectId *id ; //not owner, do not delete (nore use var)
id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str(),
}
catch (...)
{
- reason="Container_i::createInstance exception catched";
+ reason="Container_i::createInstance exception caught";
INFOS(reason) ;
}
return iobject._retn();
*/
//=============================================================================
Engines::EngineComponent_ptr
-Engines_Container_i::find_component_instance( const char* registeredName)
+Abstract_Engines_Container_i::find_component_instance( const char* registeredName)
{
Engines::EngineComponent_var anEngine = Engines::EngineComponent::_nil();
std::map<std::string,Engines::EngineComponent_var>::iterator itm =_listInstances_map.begin();
*/
//=============================================================================
-void Engines_Container_i::remove_impl(Engines::EngineComponent_ptr component_i)
+void Abstract_Engines_Container_i::remove_impl(Engines::EngineComponent_ptr component_i)
{
ASSERT(! CORBA::is_nil(component_i));
std::string instanceName = component_i->instanceName() ;
* CORBA method: Discharges unused libraries from the container.
*/
//=============================================================================
-void Engines_Container_i::finalize_removal()
+void Abstract_Engines_Container_i::finalize_removal()
{
MESSAGE("finalize unload : dlclose");
_numInstanceMutex.lock(); // lock to be alone
*
*/
//=============================================================================
-void Engines_Container_i::decInstanceCnt(std::string genericRegisterName)
+void Abstract_Engines_Container_i::decInstanceCnt(std::string genericRegisterName)
{
if(_cntInstances_map.count(genericRegisterName)==0)
return;
//=============================================================================
Engines::EngineComponent_ptr
-Engines_Container_i::load_impl( const char* genericRegisterName,
- const char* componentName )
+Abstract_Engines_Container_i::load_impl( const char* genericRegisterName,
+ const char* /*componentName*/ )
{
char* reason;
std::string impl_name = std::string(LIB) + genericRegisterName + ENGINESO;
return iobject._retn();
}
+Engines::EmbeddedNamingService_ptr Abstract_Engines_Container_i::get_embedded_NS_if_ssl()
+{
+ SALOME_Embedded_NamingService_Client *nsc(dynamic_cast<SALOME_Embedded_NamingService_Client *>(this->_NS));
+ if(nsc)
+ {
+ Engines::EmbeddedNamingService_var obj = nsc->GetObject();
+ return Engines::EmbeddedNamingService::_duplicate(obj);
+ }
+ else
+ {
+ SALOME_Fake_NamingService *fns(dynamic_cast<SALOME_Fake_NamingService *>(this->_NS));
+ if(fns)
+ {
+ Engines::EmbeddedNamingService_var ret = GetEmbeddedNamingService();
+ return ret._retn();
+ }
+ else
+ return Engines::EmbeddedNamingService::_nil();
+ }
+}
+
//=============================================================================
//! Finds an already existing component instance or create a new instance
/*!
//=============================================================================
Engines::EngineComponent_ptr
-Engines_Container_i::find_or_create_instance(std::string genericRegisterName,
- std::string componentLibraryName)
+Abstract_Engines_Container_i::find_or_create_instance(std::string genericRegisterName,
+ std::string componentLibraryName)
{
std::string aGenRegisterName = genericRegisterName;
std::string impl_name = componentLibraryName;
}
catch (...)
{
- INFOS( "Container_i::load_impl catched" ) ;
+ INFOS( "Container_i::load_impl caught" ) ;
}
return iobject._retn();
}
* Retrieves only with container naming convention if it is a python container
*/
//=============================================================================
-bool Engines_Container_i::isPythonContainer(const char* ContainerName)
+bool Abstract_Engines_Container_i::isPythonContainer(const char* ContainerName)
{
bool ret=false;
- int len=strlen(ContainerName);
+ size_t len=strlen(ContainerName);
if(len>=2)
if(strcmp(ContainerName+len-2,"Py")==0)
ret=true;
* To remove : never returns !
*/
//=============================================================================
-bool Engines_Container_i::Kill_impl()
+bool Abstract_Engines_Container_i::Kill_impl()
{
MESSAGE("Engines_Container_i::Kill() pid "<< getpid() << " containerName "
<< _containerName.c_str() << " machineName "
void CallCancelThread() ;
#ifndef WIN32
-void SigIntHandler(int what ,
+void SigIntHandler(int /*what*/ ,
siginfo_t * siginfo ,
- void * toto )
+ void * /*toto*/ )
{
//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 :
*/
//=============================================================================
Engines::fileRef_ptr
-Engines_Container_i::createFileRef(const char* origFileName)
+Abstract_Engines_Container_i::createFileRef(const char* origFileName)
{
std::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 '/'");
+ INFOS("path of file to copy must be an absolute path beginning with '/'");
return Engines::fileRef::_nil();
}
*/
//=============================================================================
Engines::fileTransfer_ptr
-Engines_Container_i::getFileTransfer()
+Abstract_Engines_Container_i::getFileTransfer()
{
Engines::fileTransfer_var aFileTransfer
= Engines::fileTransfer::_duplicate(_fileTransfer);
//! Create a Salome file
//=============================================================================
Engines::Salome_file_ptr
-Engines_Container_i::createSalome_file(const char* origFileName)
+Abstract_Engines_Container_i::createSalome_file(const char* origFileName)
{
std::string origName(origFileName);
if (CORBA::is_nil(_Salome_file_map[origName]))
aSalome_file->setLocalFile(origFileName);
aSalome_file->recvFiles();
}
- catch (const SALOME::SALOME_Exception& e)
+ catch (const SALOME::SALOME_Exception& /*e*/) //!< TODO: unused variable
{
return Engines::Salome_file::_nil();
}
* \param localFile the local file
*/
//=============================================================================
-void Engines_Container_i::copyFile(Engines::Container_ptr container, const char* remoteFile, const char* localFile)
+void Abstract_Engines_Container_i::copyFile(Engines::Container_ptr container, const char* remoteFile, const char* localFile)
{
Engines::fileTransfer_var fileTransfer = container->getFileTransfer();
* \return the PyNode
*/
//=============================================================================
-Engines::PyNode_ptr Engines_Container_i::createPyNode(const char* nodeName, const char* code)
+Engines::PyNode_ptr Abstract_Engines_Container_i::createPyNode(const char* nodeName, const char* code)
{
Engines::PyNode_var node= Engines::PyNode::_nil();
-
- PyGILState_STATE gstate = PyGILState_Ensure();
- PyObject *res = PyObject_CallMethod(_pyCont,
- (char*)"create_pynode",
- (char*)"ss",
- nodeName,
- code);
- if(res==NULL)
- {
- //internal error
- PyErr_Print();
- PyGILState_Release(gstate);
- SALOME::ExceptionStruct es;
- es.type = SALOME::INTERNAL_ERROR;
- es.text = "can not create a python node";
- throw SALOME::SALOME_Exception(es);
+ long ierr(-1);
+ std::string astr;
+ {
+ AutoGIL gstate;
+ PyObject *res = PyObject_CallMethod(_pyCont,
+ (char*)"create_pynode",
+ (char*)"ss",
+ nodeName,
+ code);
+ if(res==NULL)
+ {
+ //internal error
+ PyErr_Print();
+ SALOME::ExceptionStruct es;
+ es.type = SALOME::INTERNAL_ERROR;
+ es.text = "can not create a python node";
+ throw SALOME::SALOME_Exception(es);
+ }
+ ierr=PyLong_AsLong(PyTuple_GetItem(res,0));
+ PyObject* result=PyTuple_GetItem(res,1);
+ astr = PyUnicode_AsUTF8(result);
+ Py_DECREF(res);
}
- long ierr=PyLong_AsLong(PyTuple_GetItem(res,0));
- PyObject* result=PyTuple_GetItem(res,1);
- std::string astr=PyUnicode_AsUTF8(result);
- Py_DECREF(res);
- PyGILState_Release(gstate);
if(ierr==0)
{
Utils_Locker lck(&_mutexForDftPy);
*
*/
//=============================================================================
-Engines::PyNode_ptr Engines_Container_i::getDefaultPyNode(const char *nodeName)
+Engines::PyNode_ptr Abstract_Engines_Container_i::getDefaultPyNode(const char *nodeName)
{
Utils_Locker lck(&_mutexForDftPy);
std::map<std::string,Engines::PyNode_var>::iterator it(_dftPyNode.find(nodeName));
* \return the PyScriptNode
*/
//=============================================================================
-Engines::PyScriptNode_ptr Engines_Container_i::createPyScriptNode(const char* nodeName, const char* code)
+Engines::PyScriptNode_ptr Abstract_Engines_Container_i::createPyScriptNode(const char* nodeName, const char* code)
{
Engines::PyScriptNode_var node= Engines::PyScriptNode::_nil();
-
- PyGILState_STATE gstate = PyGILState_Ensure();
- PyObject *res = PyObject_CallMethod(_pyCont,
- (char*)"create_pyscriptnode",
- (char*)"ss",
- nodeName,
- code);
- if(res==NULL)
- {
- //internal error
- PyErr_Print();
- PyGILState_Release(gstate);
- SALOME::ExceptionStruct es;
- es.type = SALOME::INTERNAL_ERROR;
- es.text = "can not create a python node";
- throw SALOME::SALOME_Exception(es);
+ long ierr(-1);
+ std::string astr;
+ {
+ AutoGIL gstate;
+ PyObject *res = PyObject_CallMethod(_pyCont,
+ (char*)"create_pyscriptnode",
+ (char*)"ss",
+ nodeName,
+ code);
+ if(res==NULL)
+ {
+ //internal error
+ PyErr_Print();
+ SALOME::ExceptionStruct es;
+ es.type = SALOME::INTERNAL_ERROR;
+ es.text = "can not create a python node";
+ throw SALOME::SALOME_Exception(es);
+ }
+ ierr=PyLong_AsLong(PyTuple_GetItem(res,0));
+ PyObject* result=PyTuple_GetItem(res,1);
+ astr = PyUnicode_AsUTF8(result);
+ Py_DECREF(res);
}
- long ierr=PyLong_AsLong(PyTuple_GetItem(res,0));
- PyObject* result=PyTuple_GetItem(res,1);
- std::string astr=PyUnicode_AsUTF8(result);
- Py_DECREF(res);
- PyGILState_Release(gstate);
if(ierr==0)
{
oldNode->UnRegister();
(*it).second=node;
}
- if(!CORBA::is_nil(node))
- node->Register();
return node._retn();
}
else
}
}
+void Abstract_Engines_Container_i::removePyScriptNode(const char *nodeName)
+{
+ std::map<std::string,Engines::PyScriptNode_var>::iterator it(_dftPyScriptNode.find(nodeName));
+ if(it==_dftPyScriptNode.end())
+ {
+ std::ostringstream oss; oss << "Engines_Container_i::removePyScriptNode : node \"" << nodeName << "\" is not map !";
+ SALOME::ExceptionStruct es;
+ es.type = SALOME::INTERNAL_ERROR;
+ es.text = oss.str().c_str();
+ throw SALOME::SALOME_Exception(es);
+ }
+ (*it).second->UnRegister();
+ _dftPyScriptNode.erase(it);
+}
+
+void Abstract_Engines_Container_i::cleanAllPyScripts()
+{
+ for(std::map<std::string,Engines::PyNode_var>::iterator it=_dftPyNode.begin();it!=_dftPyNode.end();it++)
+ {
+ Engines::PyNode_var tmpVar((*it).second);
+ if(!CORBA::is_nil(tmpVar))
+ tmpVar->UnRegister();
+ }
+ _dftPyNode.clear();
+ for(std::map<std::string,Engines::PyScriptNode_var>::iterator it=_dftPyScriptNode.begin();it!=_dftPyScriptNode.end();it++)
+ {
+ Engines::PyScriptNode_var tmpVar((*it).second);
+ if(!CORBA::is_nil(tmpVar))
+ tmpVar->UnRegister();
+ }
+ _dftPyScriptNode.clear();
+}
+
//=============================================================================
/*! \brief Retrieves the last created PyScriptNode instance with createPyScriptNode.
*
*/
//=============================================================================
-Engines::PyScriptNode_ptr Engines_Container_i::getDefaultPyScriptNode(const char *nodeName)
+Engines::PyScriptNode_ptr Abstract_Engines_Container_i::getDefaultPyScriptNode(const char *nodeName)
{
Utils_Locker lck(&_mutexForDftPy);
std::map<std::string,Engines::PyScriptNode_var>::iterator it(_dftPyScriptNode.find(nodeName));
return found;
}
-void Engines_Container_i::registerTemporaryFile( const std::string& fileName )
+void Abstract_Engines_Container_i::registerTemporaryFile( const std::string& fileName )
{
_tmp_files.remove( fileName );
_tmp_files.push_back( fileName );
}
-void Engines_Container_i::unregisterTemporaryFile( const std::string& fileName )
+void Abstract_Engines_Container_i::unregisterTemporaryFile( const std::string& fileName )
{
_tmp_files.remove( fileName );
}
-void Engines_Container_i::clearTemporaryFiles()
+void Abstract_Engines_Container_i::clearTemporaryFiles()
{
std::list<std::string>::const_iterator it;
for ( it = _tmp_files.begin(); it != _tmp_files.end(); ++it ) {
-#ifdef WIN32
- std::string command = "del /F /P";
+#if defined(WIN32) && defined(UNICODE)
+ std::wstring aFile = Kernel_Utils::utf8_decode_s(*it);
+ std::wstring command = (GetFileAttributes(aFile.c_str()) == FILE_ATTRIBUTE_DIRECTORY) ? L"rd /Q \"" : L"del /F /Q \"";
+ command += aFile;
+ command += L"\" 2>NUL";
+ _wsystem(command.c_str());
#else
- std::string command = "rm -rf ";
+#if defined(WIN32)
+ std::string aFile = *it;
+ std::string command = (GetFileAttributes(aFile.c_str()) == FILE_ATTRIBUTE_DIRECTORY) ? "rd /Q \"" : "del /F /Q \"";
+ command += aFile;
+ command += "\" 2>NUL";
+#else
+ std::string command = "rm -rf ";
+ command += *it;
+#endif
+ system(command.c_str());
#endif
- command += *it;
- system( command.c_str() );
}
_tmp_files.clear();
}
-/*
-std::string Engines_Container_i::AnotherMethodeToReplace_PyString_AsString(PyObject * result)
+static Engines_Container_SSL_i *_container_singleton_ssl = nullptr;
+
+static Engines::Container_var _container_ref_singleton_ssl;
+
+Engines_Container_SSL_i *KERNEL::getContainerSA()
{
- std::string my_result = "";
- if (PyUnicode_Check(result)) {
- // Convert string to bytes.
- // strdup() bytes into my_result.
- PyObject * temp_bytes = PyUnicode_AsEncodedString(result, "ASCII", "strict"); // Owned reference
- if (temp_bytes != NULL) {
- my_result = PyBytes_AS_STRING(temp_bytes); // Borrowed pointer
- my_result = strdup(my_result);
- Py_DECREF(temp_bytes);
- } else {
- // TODO PY3: Handle encoding error.
- Py_DECREF(temp_bytes);
- }
+ if(!_container_singleton_ssl)
+ {
+ CORBA::ORB_var orb = KERNEL::GetRefToORB();
+ CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
+ PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);
+ PortableServer::POAManager_var pman = poa->the_POAManager();
+ CORBA::PolicyList policies;
+ policies.length(0);
+ //
+ char *argv[4] = {"Container","FactoryServer","toto",nullptr};
+ SALOME_Fake_NamingService ns;
+ _container_singleton_ssl = new Engines_Container_SSL_i(orb,poa,"FactoryServer",2,argv,&ns,false);
+ PortableServer::ObjectId * cont_id = _container_singleton_ssl->getCORBAId();
+ //
+ CORBA::Object_var zeRef = poa->id_to_reference(*cont_id);
+ _container_ref_singleton_ssl = Engines::Container::_narrow(zeRef);
+ }
+ return _container_singleton_ssl;
+}
- } else if (PyBytes_Check(result)) {
- // strdup() bytes into my_result.
- my_result = PyBytes_AS_STRING(result); // Borrowed pointer
- my_result = strdup(my_result);
- } else {
- // Convert into your favorite string representation.
- // Convert string to bytes if it is not already.
- // strdup() bytes into my_result.
- // TODO PY3: Check if only bytes is ok.
- PyObject * temp_bytes = PyObject_Bytes(result); // Owned reference
- if (temp_bytes != NULL) {
- my_result = PyBytes_AS_STRING(temp_bytes); // Borrowed pointer
- my_result = strdup(my_result);
- Py_DECREF(temp_bytes);
- } else {
- // TODO PY3: Handle error.
- Py_DECREF(temp_bytes);
- }
- }
- return my_result;
+Engines::Container_var KERNEL::getContainerRefSA()
+{
+ getContainerSA();
+ return _container_ref_singleton_ssl;
}
-*/