X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2FPythonNode.cxx;h=66c7aae24dfb4ceaad737d3e8a0aebc1756049fe;hb=13ca785a6bf36d005ee74eba2bc28d0cf4f8dca7;hp=e8cbc26248a5a640f154355bd4dfc214cc51af0e;hpb=ceb46f3f5e81cec00a1a833c42765f3300dcabb0;p=modules%2Fyacs.git diff --git a/src/runtime/PythonNode.cxx b/src/runtime/PythonNode.cxx index e8cbc2624..66c7aae24 100644 --- a/src/runtime/PythonNode.cxx +++ b/src/runtime/PythonNode.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2006-2014 CEA/DEN, EDF R&D +// Copyright (C) 2006-2021 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,7 @@ #include "PythonNode.hxx" #include "PythonPorts.hxx" #include "TypeCode.hxx" -#include "AutoGIL.hxx" +#include "PythonCppUtils.hxx" #include "Container.hxx" #include "SalomeContainer.hxx" #include "SalomeHPContainer.hxx" @@ -30,6 +30,7 @@ #include "PyStdout.hxx" #include +#include #include #include @@ -48,26 +49,41 @@ typedef int Py_ssize_t; using namespace YACS::ENGINE; using namespace std; +const char PythonEntry::SCRIPT_FOR_SIMPLE_SERIALIZATION[]="import pickle\n" + "def pickleForVarSimplePyth2009(val):\n" + " return pickle.dumps(val,-1)\n" + "\n"; + const char PythonNode::IMPL_NAME[]="Python"; const char PythonNode::KIND[]="Python"; -const char PythonNode::SCRIPT_FOR_SERIALIZATION[]="import cPickle\n" +const char PythonNode::SCRIPT_FOR_SERIALIZATION[]="import pickle\n" "def pickleForDistPyth2009(kws):\n" - " return cPickle.dumps(((),kws),-1)\n" + " return pickle.dumps(((),kws),-1)\n" "\n" "def unPickleForDistPyth2009(st):\n" - " args=cPickle.loads(st)\n" + " args=pickle.loads(st)\n" " return args\n"; -const char PyFuncNode::SCRIPT_FOR_SERIALIZATION[]="import cPickle\n" +const char PythonNode::REMOTE_NAME[]="remote"; + +const char PythonNode::DPL_INFO_NAME[]="my_dpl_localization"; + +const char PyFuncNode::SCRIPT_FOR_SERIALIZATION[]="import pickle\n" "def pickleForDistPyth2009(*args,**kws):\n" - " return cPickle.dumps((args,kws),-1)\n" + " return pickle.dumps((args,kws),-1)\n" "\n" "def unPickleForDistPyth2009(st):\n" - " args=cPickle.loads(st)\n" + " args=pickle.loads(st)\n" " return args\n"; -PythonEntry::PythonEntry():_context(0),_pyfuncSer(0),_pyfuncUnser(0) +// pickle.load concurrency issue : see https://bugs.python.org/issue12680 +#if PY_VERSION_HEX < 0x03070000 +#include +static std::mutex data_mutex; +#endif + +PythonEntry::PythonEntry():_context(0),_pyfuncSer(0),_pyfuncUnser(0),_pyfuncSimpleSer(0) { } @@ -80,26 +96,29 @@ PythonEntry::~PythonEntry() Py_XDECREF(_context); } -void PythonEntry::commonRemoteLoadPart1(InlineNode *reqNode) +void PythonEntry::loadRemoteContainer(InlineNode *reqNode) { DEBTRACE( "---------------PythonEntry::CommonRemoteLoad function---------------" ); Container *container(reqNode->getContainer()); bool isContAlreadyStarted(false); if(container) { - isContAlreadyStarted=container->isAlreadyStarted(reqNode); - if(!isContAlreadyStarted) + try + { + if(hasImposedResource()) + container->start(reqNode, _imposedResource, _imposedContainer); + else { - try - { - container->start(reqNode); - } - catch(Exception& e) - { - reqNode->setErrorDetails(e.what()); - throw e; - } + isContAlreadyStarted=container->isAlreadyStarted(reqNode); + if(!isContAlreadyStarted) + container->start(reqNode); } + } + catch(Exception& e) + { + reqNode->setErrorDetails(e.what()); + throw e; + } } else { @@ -110,43 +129,47 @@ void PythonEntry::commonRemoteLoadPart1(InlineNode *reqNode) } } -Engines::Container_var PythonEntry::commonRemoteLoadPart2(InlineNode *reqNode, bool& isInitializeRequested) +Engines::Container_var GetContainerObj(InlineNode *reqNode, bool& isStandardCont) { + isStandardCont = false; Container *container(reqNode->getContainer()); - Engines::Container_var objContainer=Engines::Container::_nil(); + Engines::Container_var objContainer(Engines::Container::_nil()); if(!container) - throw Exception("No container specified !"); + throw YACS::Exception("No container specified !"); SalomeContainer *containerCast0(dynamic_cast(container)); SalomeHPContainer *containerCast1(dynamic_cast(container)); if(containerCast0) - objContainer=containerCast0->getContainerPtr(reqNode); + { + isStandardCont = true; + objContainer=containerCast0->getContainerPtr(reqNode); + } else if(containerCast1) { YACS::BASES::AutoCppPtr tmpCont(SalomeContainerTmpForHP::BuildFrom(containerCast1,reqNode)); objContainer=tmpCont->getContainerPtr(reqNode); } else - throw Exception("Unrecognized type of container ! Salome one is expected for PythonNode/PyFuncNode !"); + throw YACS::Exception("Unrecognized type of container ! Salome one is expected for PythonNode/PyFuncNode !"); if(CORBA::is_nil(objContainer)) - throw Exception("Container corba pointer is NULL for PythonNode !"); + throw YACS::Exception("Container corba pointer is NULL for PythonNode !"); + return objContainer; +} + +Engines::Container_var PythonEntry::loadPythonAdapter(InlineNode *reqNode, bool& isInitializeRequested) +{ + bool isStandardCont(true); + Engines::Container_var objContainer(GetContainerObj(reqNode,isStandardCont)); isInitializeRequested=false; try { - if(containerCast0) - { - createRemoteAdaptedPyInterpretor(objContainer); - } - else - { - Engines::PyNodeBase_var dftPyScript(retrieveDftRemotePyInterpretorIfAny(objContainer)); - if(CORBA::is_nil(dftPyScript)) - { - isInitializeRequested=true; - createRemoteAdaptedPyInterpretor(objContainer); - } - else - assignRemotePyInterpretor(dftPyScript); - } + Engines::PyNodeBase_var dftPyScript(retrieveDftRemotePyInterpretorIfAny(objContainer)); + if(CORBA::is_nil(dftPyScript)) + { + isInitializeRequested=!isStandardCont; + createRemoteAdaptedPyInterpretor(objContainer); + } + else + assignRemotePyInterpretor(dftPyScript); } catch( const SALOME::SALOME_Exception& ex ) { @@ -162,16 +185,20 @@ Engines::Container_var PythonEntry::commonRemoteLoadPart2(InlineNode *reqNode, b return objContainer; } -void PythonEntry::commonRemoteLoadPart3(InlineNode *reqNode, Engines::Container_ptr objContainer, bool isInitializeRequested) +void PythonEntry::loadRemoteContext(InlineNode *reqNode, Engines::Container_ptr objContainer, bool isInitializeRequested) { Container *container(reqNode->getContainer()); Engines::PyNodeBase_var pynode(getRemoteInterpreterHandle()); /// { +#if PY_VERSION_HEX < 0x03070000 + std::unique_lock lock(data_mutex); +#endif AutoGIL agil; const char *picklizeScript(getSerializationScript()); PyObject *res=PyRun_String(picklizeScript,Py_file_input,_context,_context); - if(res == NULL) + PyObject *res2(PyRun_String(SCRIPT_FOR_SIMPLE_SERIALIZATION,Py_file_input,_context,_context)); + if(res == NULL || res2==NULL) { std::string errorDetails; PyObject* new_stderr = newPyStdOut(errorDetails); @@ -182,9 +209,10 @@ void PythonEntry::commonRemoteLoadPart3(InlineNode *reqNode, Engines::Container_ Py_DECREF(new_stderr); throw Exception("Error during load"); } - Py_DECREF(res); + Py_DECREF(res); Py_DECREF(res2); _pyfuncSer=PyDict_GetItemString(_context,"pickleForDistPyth2009"); _pyfuncUnser=PyDict_GetItemString(_context,"unPickleForDistPyth2009"); + _pyfuncSimpleSer=PyDict_GetItemString(_context,"pickleForVarSimplePyth2009"); if(_pyfuncSer == NULL) { std::string errorDetails; @@ -207,6 +235,17 @@ void PythonEntry::commonRemoteLoadPart3(InlineNode *reqNode, Engines::Container_ Py_DECREF(new_stderr); throw Exception("Error during load"); } + if(_pyfuncSimpleSer == NULL) + { + std::string errorDetails; + PyObject *new_stderr(newPyStdOut(errorDetails)); + reqNode->setErrorDetails(errorDetails); + PySys_SetObject((char*)"stderr", new_stderr); + PyErr_Print(); + PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__")); + Py_DECREF(new_stderr); + throw Exception("Error during load"); + } } if(isInitializeRequested) {//This one is called only once at initialization in the container if an init-script is specified. @@ -265,14 +304,20 @@ std::string PythonEntry::GetContainerLog(const std::string& mode, Container *con void PythonEntry::commonRemoteLoad(InlineNode *reqNode) { - commonRemoteLoadPart1(reqNode); + loadRemoteContainer(reqNode); bool isInitializeRequested; - Engines::Container_var objContainer(commonRemoteLoadPart2(reqNode,isInitializeRequested)); - commonRemoteLoadPart3(reqNode,objContainer,isInitializeRequested); + Engines::Container_var objContainer(loadPythonAdapter(reqNode,isInitializeRequested)); + loadRemoteContext(reqNode,objContainer,isInitializeRequested); +} + +bool PythonEntry::hasImposedResource()const +{ + return !_imposedResource.empty() && !_imposedContainer.empty(); } -PythonNode::PythonNode(const PythonNode& other, ComposedNode *father):InlineNode(other,father) +PythonNode::PythonNode(const PythonNode& other, ComposedNode *father):InlineNode(other,father),_autoSqueeze(other._autoSqueeze) { + _pynode = Engines::PyScriptNode::_nil(); _implementation=IMPL_NAME; { AutoGIL agil; @@ -289,6 +334,7 @@ PythonNode::PythonNode(const PythonNode& other, ComposedNode *father):InlineNode PythonNode::PythonNode(const std::string& name):InlineNode(name) { + _pynode = Engines::PyScriptNode::_nil(); _implementation=IMPL_NAME; { AutoGIL agil; @@ -305,13 +351,10 @@ PythonNode::PythonNode(const std::string& name):InlineNode(name) PythonNode::~PythonNode() { - if(!CORBA::is_nil(_pynode)) - { - _pynode->UnRegister(); - } + freeKernelPynode(); } -void PythonNode::checkBasicConsistency() const throw(YACS::Exception) +void PythonNode::checkBasicConsistency() const { DEBTRACE("checkBasicConsistency"); InlineNode::checkBasicConsistency(); @@ -337,7 +380,7 @@ void PythonNode::checkBasicConsistency() const throw(YACS::Exception) void PythonNode::load() { DEBTRACE( "---------------PyNode::load function---------------" ); - if(_mode=="remote") + if(_mode==PythonNode::REMOTE_NAME) loadRemote(); else loadLocal(); @@ -356,7 +399,7 @@ void PythonNode::loadRemote() void PythonNode::execute() { - if(_mode=="remote") + if(_mode==PythonNode::REMOTE_NAME) executeRemote(); else executeLocal(); @@ -366,17 +409,21 @@ void PythonNode::executeRemote() { DEBTRACE( "++++++++++++++ PyNode::executeRemote: " << getName() << " ++++++++++++++++++++" ); if(!_pyfuncSer) - throw Exception("DistributedPythonNode badly loaded"); + throw Exception("PythonNode badly loaded"); // if(dynamic_cast(getContainer())) { bool dummy; - commonRemoteLoadPart2(this,dummy); + loadPythonAdapter(this,dummy); _pynode->assignNewCompiledCode(getScript().c_str()); } // - Engines::pickledArgs_var serializationInputCorba(new Engines::pickledArgs); + std::unique_ptr serializationInputCorba(new Engines::pickledArgs); + AutoPyRef serializationInput; { +#if PY_VERSION_HEX < 0x03070000 + std::unique_lock lock(data_mutex); +#endif AutoGIL agil; PyObject *args(0),*ob(0); //=========================================================================== @@ -396,17 +443,15 @@ void PythonNode::executeRemote() PyObject_Print(args,stderr,Py_PRINT_RAW); std::cerr << endl; #endif - PyObject *serializationInput(PyObject_CallFunctionObjArgs(_pyfuncSer,args,NULL)); + serializationInput.set(PyObject_CallFunctionObjArgs(_pyfuncSer,args,nullptr)); Py_DECREF(args); //The pickled string may contain NULL characters so use PyString_AsStringAndSize char *serializationInputC(0); Py_ssize_t len; - if (PyString_AsStringAndSize(serializationInput, &serializationInputC, &len)) + if (PyBytes_AsStringAndSize(serializationInput, &serializationInputC, &len)) throw Exception("DistributedPythonNode problem in python pickle"); - serializationInputCorba->length(len); - for(int i=0; i < len ; i++) - serializationInputCorba[i]=serializationInputC[i]; - Py_DECREF(serializationInput); + // no copy here. The C byte array of Python is taken as this into CORBA sequence to avoid copy + serializationInputCorba.reset(new Engines::pickledArgs(len,len,reinterpret_cast(serializationInputC),0)); } //get the list of output argument names @@ -427,37 +472,57 @@ void PythonNode::executeRemote() // Execute in remote Python node //=========================================================================== DEBTRACE( "-----------------starting remote python invocation-----------------" ); - Engines::pickledArgs_var resultCorba; + std::unique_ptr resultCorba; try { //pass outargsname and dict serialized - resultCorba=_pynode->execute(myseq,serializationInputCorba); + _pynode->executeFirst(*(serializationInputCorba.get())); + //serializationInput and serializationInputCorba are no more needed for server. Release it. + serializationInputCorba.reset(nullptr); serializationInput.set(nullptr); + resultCorba.reset(_pynode->executeSecond(myseq)); } catch( const SALOME::SALOME_Exception& ex ) { - std::string msg="Exception on remote python invocation"; - msg += '\n'; - msg += ex.details.text.in(); - _errorDetails=msg; - throw Exception(msg); + std::ostringstream msg; msg << "Exception on remote python invocation" << std::endl << ex.details.text.in() << std::endl; + msg << "PyScriptNode CORBA ref : "; + { + CORBA::ORB_ptr orb(getSALOMERuntime()->getOrb()); + if(!CORBA::is_nil(orb)) + { + CORBA::String_var IOR(orb->object_to_string(_pynode)); + msg << IOR; + } + } + msg << std::endl; + _errorDetails=msg.str(); + throw Exception(msg.str()); } +// if(!CORBA::is_nil(_pynode)) +// { +// _pynode->UnRegister(); +// } +// _pynode = Engines::PyScriptNode::_nil(); +// // +// bool dummy; +// Engines::Container_var cont(GetContainerObj(this,dummy)); +// cont->removePyScriptNode(getName().c_str()); DEBTRACE( "-----------------end of remote python invocation-----------------" ); //=========================================================================== // Get results, unpickle and put them in output ports //=========================================================================== - char *resultCorbaC=new char[resultCorba->length()+1]; - resultCorbaC[resultCorba->length()]='\0'; - for(int i=0;ilength();i++) - resultCorbaC[i]=resultCorba[i]; - + auto length(resultCorba->length()); + char *resultCorbaC(reinterpret_cast(resultCorba->get_buffer())); { +#if PY_VERSION_HEX < 0x03070000 + std::unique_lock lock(data_mutex); +#endif AutoGIL agil; PyObject *args(0),*ob(0); - PyObject* resultPython=PyString_FromStringAndSize(resultCorbaC,resultCorba->length()); - delete [] resultCorbaC; + PyObject* resultPython=PyMemoryView_FromMemory(resultCorbaC,length,PyBUF_READ); args = PyTuple_New(1); PyTuple_SetItem(args,0,resultPython); PyObject *finalResult=PyObject_CallObject(_pyfuncUnser,args); + resultCorba.reset(nullptr); Py_DECREF(args); if (finalResult == NULL) @@ -509,6 +574,16 @@ void PythonNode::executeRemote() _errorDetails=ex.what(); throw; } + if(_autoSqueeze) + squeezeMemoryRemote(); + } + // + if(!isUsingPythonCache()) + { + freeKernelPynode(); + bool dummy; + Engines::Container_var cont(GetContainerObj(this,dummy)); + cont->removePyScriptNode(getName().c_str()); } DEBTRACE( "++++++++++++++ ENDOF PyNode::executeRemote: " << getName() << " ++++++++++++++++++++" ); } @@ -550,7 +625,7 @@ void PythonNode::executeLocal() PyObject* code=Py_CompileString(_script.c_str(), stream.str().c_str(), Py_file_input); if(code == NULL) { - _errorDetails=""; + _errorDetails=""; PyObject* new_stderr = newPyStdOut(_errorDetails); PySys_SetObject((char*)"stderr", new_stderr); PyErr_Print(); @@ -558,7 +633,7 @@ void PythonNode::executeLocal() Py_DECREF(new_stderr); throw Exception("Error during execution"); } - PyObject *res = PyEval_EvalCode((PyCodeObject *)code, _context, _context); + PyObject *res = PyEval_EvalCode( code, _context, _context); Py_DECREF(code); Py_XDECREF(res); @@ -612,12 +687,54 @@ void PythonNode::executeLocal() _errorDetails=ex.what(); throw; } - + if(_autoSqueeze) + squeezeMemory(); DEBTRACE( "-----------------End PyNode::outputs-----------------" ); } DEBTRACE( "++++++++++++++ End PyNode::execute: " << getName() << " ++++++++++++++++++++" ); } +void PythonNode::squeezeMemorySafe() +{ + AutoGIL agil; + if(_mode==PythonNode::REMOTE_NAME) + this->squeezeMemoryRemote(); + else + this->squeezeMemory(); +} + +void PythonNode::squeezeMemory() +{ + for(auto p : _setOfInputPort) + { + PyDict_DelItemString(_context,p->getName().c_str()); + InputPyPort *p2(static_cast(p)); + if(p2->canSafelySqueezeMemory()) + p2->put(Py_None); + } + for(auto p : _setOfOutputPort) + { + PyDict_DelItemString(_context,p->getName().c_str()); + OutputPyPort *p2(static_cast(p)); + p2->putWithoutForward(Py_None); + } +} + +void PythonNode::squeezeMemoryRemote() +{ + for(auto p : _setOfInputPort) + { + InputPyPort *p2(static_cast(p)); + if(p2->canSafelySqueezeMemory()) + p2->put(Py_None); + } + for(auto p : _setOfOutputPort) + { + OutputPyPort *p2(static_cast(p)); + p2->putWithoutForward(Py_None); + } +} + std::string PythonNode::getContainerLog() { return PythonEntry::GetContainerLog(_mode,_container,this); @@ -629,12 +746,63 @@ void PythonNode::shutdown(int level) if(_mode=="local")return; if(_container) { - if(!CORBA::is_nil(_pynode)) _pynode->UnRegister(); - _pynode=Engines::PyScriptNode::_nil(); + freeKernelPynode(); _container->shutdown(level); } } +void PythonNode::imposeResource(const std::string& resource_name, + const std::string& container_name) +{ + if(!resource_name.empty() && !container_name.empty()) + { + _imposedResource = resource_name; + _imposedContainer = container_name; + } +} + +bool PythonNode::canAcceptImposedResource() +{ + return _container != nullptr && _container->canAcceptImposedResource(); +} + +bool PythonNode::hasImposedResource()const +{ + return PythonEntry::hasImposedResource(); +} + +std::string PythonNode::pythonEntryName()const +{ + if(isUsingPythonCache()) + return "DEFAULT_NAME_FOR_UNIQUE_PYTHON_NODE_ENTRY"; + else + return getName(); +} + +bool PythonNode::isUsingPythonCache()const +{ + bool found = false; + if(_container) + found = _container->isUsingPythonCache(); + return found; +} + +void PythonNode::freeKernelPynode() +{ + if(!CORBA::is_nil(_pynode)) + { + try + { + _pynode->UnRegister(); + } + catch(...) + { + DEBTRACE("Trouble when pynode->UnRegister!") + } + _pynode = Engines::PyScriptNode::_nil(); + } +} + Node *PythonNode::simpleClone(ComposedNode *father, bool editionOnly) const { return new PythonNode(*this,father); @@ -642,14 +810,14 @@ Node *PythonNode::simpleClone(ComposedNode *father, bool editionOnly) const void PythonNode::createRemoteAdaptedPyInterpretor(Engines::Container_ptr objContainer) { - if(!CORBA::is_nil(_pynode)) - _pynode->UnRegister(); - _pynode=objContainer->createPyScriptNode(getName().c_str(),getScript().c_str()); + freeKernelPynode(); + _pynode=objContainer->createPyScriptNode(pythonEntryName().c_str(),getScript().c_str()); + _pynode->Register(); } Engines::PyNodeBase_var PythonNode::retrieveDftRemotePyInterpretorIfAny(Engines::Container_ptr objContainer) const { - Engines::PyScriptNode_var ret(objContainer->getDefaultPyScriptNode()); + Engines::PyScriptNode_var ret(objContainer->getDefaultPyScriptNode(pythonEntryName().c_str())); if(!CORBA::is_nil(ret)) { ret->Register(); @@ -659,15 +827,18 @@ Engines::PyNodeBase_var PythonNode::retrieveDftRemotePyInterpretorIfAny(Engines: void PythonNode::assignRemotePyInterpretor(Engines::PyNodeBase_var remoteInterp) { - if(!CORBA::is_nil(_pynode)) + if(CORBA::is_nil(_pynode)) + _pynode=Engines::PyScriptNode::_narrow(remoteInterp); + else + { + Engines::PyScriptNode_var tmpp(Engines::PyScriptNode::_narrow(remoteInterp)); + if(!_pynode->_is_equivalent(tmpp)) { - Engines::PyScriptNode_var tmpp(Engines::PyScriptNode::_narrow(remoteInterp)); - if(_pynode->_is_equivalent(tmpp)) - return ; + freeKernelPynode(); + _pynode=Engines::PyScriptNode::_narrow(remoteInterp); } - if(!CORBA::is_nil(_pynode)) - _pynode->UnRegister(); - _pynode=Engines::PyScriptNode::_narrow(remoteInterp); + } + _pynode->assignNewCompiledCode(getScript().c_str()); } Engines::PyNodeBase_var PythonNode::getRemoteInterpreterHandle() @@ -699,6 +870,52 @@ PythonNode* PythonNode::cloneNode(const std::string& name) return n; } +void PythonNode::applyDPLScope(ComposedNode *gfn) +{ + std::vector< std::pair > ret(getDPLScopeInfo(gfn)); + if(ret.empty()) + return ; + // + PyObject *ob(0); + { + AutoGIL agil; + std::size_t sz(ret.size()); + ob=PyList_New(sz); + for(std::size_t i=0;i& p(ret[i]); + PyObject *elt(PyTuple_New(2)); + PyTuple_SetItem(elt,0,PyUnicode_FromString(p.first.c_str())); + PyTuple_SetItem(elt,1,PyLong_FromLong(p.second)); + PyList_SetItem(ob,i,elt); + } + } + if(_mode==REMOTE_NAME) + { + Engines::pickledArgs_var serializationInputCorba(new Engines::pickledArgs); + { + AutoGIL agil; + PyObject *serializationInput(PyObject_CallFunctionObjArgs(_pyfuncSimpleSer,ob,NULL)); + Py_XDECREF(ob); + char *serializationInputC(0); + Py_ssize_t len; + if (PyBytes_AsStringAndSize(serializationInput, &serializationInputC, &len)) + throw Exception("DistributedPythonNode problem in python pickle"); + serializationInputCorba->length(len); + for(int i=0; i < len ; i++) + serializationInputCorba[i]=serializationInputC[i]; + Py_XDECREF(serializationInput); + } + _pynode->defineNewCustomVar(DPL_INFO_NAME,serializationInputCorba); + } + else + { + AutoGIL agil; + PyDict_SetItemString(_context,DPL_INFO_NAME,ob); + Py_XDECREF(ob); + } +} + PyFuncNode::PyFuncNode(const PyFuncNode& other, ComposedNode *father):InlineFuncNode(other,father),_pyfunc(0) { _implementation = PythonNode::IMPL_NAME; @@ -743,7 +960,21 @@ PyFuncNode::~PyFuncNode() } } -void PyFuncNode::checkBasicConsistency() const throw(YACS::Exception) +void PyFuncNode::init(bool start) +{ + initCommonPartWithoutStateManagement(start); + if(_state == YACS::DISABLED) + { + exDisabledState(); // to refresh propagation of DISABLED state + return ; + } + if(start) //complete initialization + setState(YACS::READY); + else if(_state > YACS::LOADED)// WARNING FuncNode has internal vars (CEA usecase) ! Partial initialization (inside a loop). Exclusivity of funcNode. + setState(YACS::TORECONNECT); +} + +void PyFuncNode::checkBasicConsistency() const { DEBTRACE("checkBasicConsistency"); InlineFuncNode::checkBasicConsistency(); @@ -769,7 +1000,7 @@ void PyFuncNode::checkBasicConsistency() const throw(YACS::Exception) void PyFuncNode::load() { DEBTRACE( "---------------PyfuncNode::load function---------------" ); - if(_mode=="remote") + if(_mode==PythonNode::REMOTE_NAME) loadRemote(); else loadLocal(); @@ -814,7 +1045,7 @@ void PyFuncNode::loadLocal() Py_DECREF(new_stderr); throw Exception("Error during execution"); } - PyObject *res = PyEval_EvalCode((PyCodeObject *)code, _context, _context); + PyObject *res = PyEval_EvalCode( code, _context, _context); Py_DECREF(code); Py_XDECREF(res); @@ -854,7 +1085,7 @@ void PyFuncNode::loadLocal() void PyFuncNode::execute() { - if(_mode=="remote") + if(_mode==PythonNode::REMOTE_NAME) executeRemote(); else executeLocal(); @@ -869,12 +1100,15 @@ void PyFuncNode::executeRemote() if(dynamic_cast(getContainer())) { bool dummy; - commonRemoteLoadPart2(this,dummy); + loadPythonAdapter(this,dummy); _pynode->executeAnotherPieceOfCode(getScript().c_str()); } // Engines::pickledArgs_var serializationInputCorba(new Engines::pickledArgs);; { +#if PY_VERSION_HEX < 0x03070000 + std::unique_lock lock(data_mutex); +#endif AutoGIL agil; PyObject *ob(0); //=========================================================================== @@ -898,7 +1132,7 @@ void PyFuncNode::executeRemote() //The pickled string may contain NULL characters so use PyString_AsStringAndSize char *serializationInputC(0); Py_ssize_t len; - if (PyString_AsStringAndSize(serializationInput, &serializationInputC, &len)) + if (PyBytes_AsStringAndSize(serializationInput, &serializationInputC, &len)) throw Exception("DistributedPythonNode problem in python pickle"); serializationInputCorba->length(len); @@ -934,9 +1168,12 @@ void PyFuncNode::executeRemote() resultCorbaC[i]=resultCorba[i]; { +#if PY_VERSION_HEX < 0x03070000 + std::unique_lock lock(data_mutex); +#endif AutoGIL agil; - PyObject *resultPython(PyString_FromStringAndSize(resultCorbaC,resultCorba->length())); + PyObject *resultPython(PyBytes_FromStringAndSize(resultCorbaC,resultCorba->length())); delete [] resultCorbaC; PyObject *args(PyTuple_New(1)),*ob(0); PyTuple_SetItem(args,0,resultPython); @@ -1117,7 +1354,7 @@ void PyFuncNode::createRemoteAdaptedPyInterpretor(Engines::Container_ptr objCont Engines::PyNodeBase_var PyFuncNode::retrieveDftRemotePyInterpretorIfAny(Engines::Container_ptr objContainer) const { - Engines::PyNode_var ret(objContainer->getDefaultPyNode()); + Engines::PyNode_var ret(objContainer->getDefaultPyNode(getName().c_str())); if(!CORBA::is_nil(ret)) { ret->Register(); @@ -1181,3 +1418,23 @@ void PyFuncNode::shutdown(int level) } } +void PyFuncNode::imposeResource(const std::string& resource_name, + const std::string& container_name) +{ + if(!resource_name.empty() && !container_name.empty()) + { + _imposedResource = resource_name; + _imposedContainer = container_name; + } +} + +bool PyFuncNode::canAcceptImposedResource() +{ + return _container != nullptr && _container->canAcceptImposedResource(); +} + +bool PyFuncNode::hasImposedResource()const +{ + return PythonEntry::hasImposedResource(); +} +