X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2FPythonNode.cxx;h=57a13a016448a21fbd9322d87bd9550823187f5d;hb=d4af5aa95ba95d6e4b301323050ccd0d843d67a8;hp=59f5a3a73e51f224a5fcc52003d18c3c05f9030e;hpb=8994efe52d503a115cda1559ad67f20c3847f2ab;p=modules%2Fyacs.git diff --git a/src/runtime/PythonNode.cxx b/src/runtime/PythonNode.cxx index 59f5a3a73..57a13a016 100644 --- a/src/runtime/PythonNode.cxx +++ b/src/runtime/PythonNode.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2006-2022 CEA/DEN, EDF R&D +// Copyright (C) 2006-2023 CEA, EDF // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -56,6 +56,8 @@ const char PythonEntry::SCRIPT_FOR_SIMPLE_SERIALIZATION[]="import pickle\n" " return pickle.dumps(val,-1)\n" "\n"; +PyObject *PythonEntry::_pyClsBigObject = nullptr; + const char PythonNode::IMPL_NAME[]="Python"; const char PythonNode::KIND[]="Python"; @@ -80,7 +82,7 @@ const char PyFuncNode::SCRIPT_FOR_SERIALIZATION[]="import pickle\n" " return args\n"; static char SCRIPT_FOR_BIGOBJECT[]="import SALOME_PyNode\n" - "BigObjectOnDisk = SALOME_PyNode.BigObjectOnDisk\n"; + "BigObjectOnDiskBase = SALOME_PyNode.BigObjectOnDiskBase\n"; // pickle.load concurrency issue : see https://bugs.python.org/issue12680 #if PY_VERSION_HEX < 0x03070000 @@ -219,7 +221,11 @@ void PythonEntry::loadRemoteContext(InlineNode *reqNode, Engines::Container_ptr _pyfuncSer=PyDict_GetItemString(_context,"pickleForDistPyth2009"); _pyfuncUnser=PyDict_GetItemString(_context,"unPickleForDistPyth2009"); _pyfuncSimpleSer=PyDict_GetItemString(_context,"pickleForVarSimplePyth2009"); - _pyClsBigObject=PyDict_GetItemString(_context,"BigObjectOnDisk"); + if(! _pyClsBigObject ) + { + _pyClsBigObject=PyDict_GetItemString(_context,"BigObjectOnDiskBase"); + Py_INCREF(_pyClsBigObject); + } if(_pyfuncSer == NULL) { std::string errorDetails; @@ -322,7 +328,95 @@ bool PythonEntry::hasImposedResource()const return !_imposedResource.empty() && !_imposedContainer.empty(); } -PythonNode::PythonNode(const PythonNode& other, ComposedNode *father):InlineNode(other,father),_autoSqueeze(other._autoSqueeze) +bool PythonEntry::IsProxy( PyObject *ob ) +{ + if(!_pyClsBigObject) + return false; + if( PyObject_IsInstance( ob, _pyClsBigObject) == 1 ) + { + return true; + } + else + { + if( PyList_Check( ob ) ) + { + auto sz = PyList_Size( ob ); + for( auto i = 0 ; i < sz ; ++i ) + { + PyObject *elt = PyList_GetItem( ob, i ); + if( PythonEntry::IsProxy(elt) ) + return true; + } + } + } + return false; +} + +bool PythonEntry::GetDestroyStatus( PyObject *ob ) +{ + if(!_pyClsBigObject) + return false; + if( PyObject_IsInstance( ob, _pyClsBigObject) == 1 ) + { + AutoPyRef unlinkOnDestructor = PyObject_GetAttrString(ob,"getDestroyStatus"); + AutoPyRef tmp = PyObject_CallFunctionObjArgs(unlinkOnDestructor,nullptr); + if( PyBool_Check(tmp.get()) ) + { + return tmp.get() == Py_True; + } + return false; + } + else + { + if( PyList_Check( ob ) ) + { + auto sz = PyList_Size( ob ); + for( auto i = 0 ; i < sz ; ++i ) + { + PyObject *elt = PyList_GetItem( ob, i ); + if( PythonEntry::GetDestroyStatus(elt) ) + return true; + } + } + } + return false; +} + +void PythonEntry::IfProxyDoSomething( PyObject *ob, const char *meth ) +{ + if(!_pyClsBigObject) + return ; + if( PyObject_IsInstance( ob, _pyClsBigObject) == 1 ) + { + AutoPyRef unlinkOnDestructor = PyObject_GetAttrString(ob,meth); + AutoPyRef tmp = PyObject_CallFunctionObjArgs(unlinkOnDestructor,nullptr); + } + else + { + if( PyList_Check( ob ) ) + { + auto sz = PyList_Size( ob ); + for( auto i = 0 ; i < sz ; ++i ) + { + PyObject *elt = PyList_GetItem( ob, i ); + PythonEntry::IfProxyDoSomething( elt, meth ); + } + } + } +} + +void PythonEntry::DoNotTouchFileIfProxy( PyObject *ob ) +{ + IfProxyDoSomething(ob,"doNotTouchFile"); +} + +void PythonEntry::UnlinkOnDestructorIfProxy( PyObject *ob ) +{ + IfProxyDoSomething(ob,"unlinkOnDestructor"); +} + +PythonNode::PythonNode(const PythonNode& other, ComposedNode *father): +InlineNode(other,father),_autoSqueeze(other._autoSqueeze),_nonSqueezableOutputNodes(other._nonSqueezableOutputNodes) { _pynode = Engines::PyScriptNode::_nil(); _implementation=IMPL_NAME; @@ -603,12 +697,7 @@ void PythonNode::executeRemote() _errorDetails=msg.str(); throw YACS::ENGINE::ConversionException(msg.str()); } - - if( PyObject_IsInstance( ob, _pyClsBigObject) == 1 ) - { - AutoPyRef unlinkOnDestructor = PyObject_GetAttrString(ob,"unlinkOnDestructor"); - AutoPyRef tmp = PyObject_CallFunctionObjArgs(unlinkOnDestructor,nullptr); - } + UnlinkOnDestructorIfProxy(ob); p->put( ob ); } pos++; @@ -633,12 +722,57 @@ void PythonNode::executeRemote() DEBTRACE( "++++++++++++++ ENDOF PyNode::executeRemote: " << getName() << " ++++++++++++++++++++" ); } +void PythonNode::ExecuteLocalInternal(const std::string& codeStr, PyObject *context, std::string& errorDetails) +{ + DEBTRACE( code ); + DEBTRACE( "context refcnt: " << context->ob_refcnt ); + std::ostringstream stream; + stream << "/tmp/PythonNode_"; + stream << getpid(); + AutoPyRef code=Py_CompileString(codeStr.c_str(), stream.str().c_str(), Py_file_input); + if(code == NULL) + { + errorDetails=""; + AutoPyRef new_stderr = newPyStdOut(errorDetails); + PySys_SetObject((char*)"stderr", new_stderr); + PyErr_Print(); + PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__")); + throw YACS::Exception("Error during execution"); + } + { + AutoPyRef res = PyEval_EvalCode( code, context, context); + } + DEBTRACE( "context refcnt: " << context->ob_refcnt ); + fflush(stdout); + fflush(stderr); + if(PyErr_Occurred ()) + { + errorDetails=""; + AutoPyRef new_stderr = newPyStdOut(errorDetails); + PySys_SetObject((char*)"stderr", new_stderr); + ofstream errorfile(stream.str().c_str()); + if (errorfile.is_open()) + { + errorfile << codeStr; + errorfile.close(); + } + PyErr_Print(); + PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__")); + throw YACS::Exception("Error during execution"); + } +} + +void PythonNode::executeLocalInternal(const std::string& codeStr) +{ + ExecuteLocalInternal(codeStr,_context,_errorDetails); +} + void PythonNode::executeLocal() { DEBTRACE( "++++++++++++++ PyNode::executeLocal: " << getName() << " ++++++++++++++++++++" ); { AutoGIL agil; - + std::ostringstream unpxy; unpxy << "from SALOME_PyNode import UnProxyObjectSimpleLocal" << std::endl; DEBTRACE( "---------------PyNode::inputs---------------" ); list::iterator iter2; for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++) @@ -647,7 +781,8 @@ void PythonNode::executeLocal() DEBTRACE( "port name: " << p->getName() ); DEBTRACE( "port kind: " << p->edGetType()->kind() ); PyObject* ob=p->getPyObj(); - DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); + DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); + unpxy << p->getName() << " = UnProxyObjectSimpleLocal( " << p->getName() << " )" << std::endl; #ifdef _DEVDEBUG_ PyObject_Print(ob,stderr,Py_PRINT_RAW); cerr << endl; @@ -660,47 +795,11 @@ void PythonNode::executeLocal() //calculation DEBTRACE( "----------------PyNode::calculation---------------" ); - DEBTRACE( _script ); - DEBTRACE( "_context refcnt: " << _context->ob_refcnt ); - - std::ostringstream stream; - stream << "/tmp/PythonNode_"; - stream << getpid(); + + if( ! getSqueezeStatus() ) + executeLocalInternal( unpxy.str() ); - PyObject* code=Py_CompileString(_script.c_str(), stream.str().c_str(), Py_file_input); - if(code == NULL) - { - _errorDetails=""; - PyObject* new_stderr = newPyStdOut(_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 execution"); - } - PyObject *res = PyEval_EvalCode( code, _context, _context); - - Py_DECREF(code); - Py_XDECREF(res); - DEBTRACE( "_context refcnt: " << _context->ob_refcnt ); - fflush(stdout); - fflush(stderr); - if(PyErr_Occurred ()) - { - _errorDetails=""; - PyObject* new_stderr = newPyStdOut(_errorDetails); - PySys_SetObject((char*)"stderr", new_stderr); - ofstream errorfile(stream.str().c_str()); - if (errorfile.is_open()) - { - errorfile << _script; - errorfile.close(); - } - PyErr_Print(); - PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__")); - Py_DECREF(new_stderr); - throw Exception("Error during execution"); - } + executeLocalInternal( _script ); DEBTRACE( "-----------------PyNode::outputs-----------------" ); list::iterator iter; @@ -725,6 +824,8 @@ void PythonNode::executeLocal() cerr << endl; #endif p->put(ob); + if(!isUsingPythonCache()) + PyDict_DelItemString(_context,p->getName().c_str()); } } catch(ConversionException& ex) @@ -735,10 +836,29 @@ void PythonNode::executeLocal() if(_autoSqueeze) squeezeMemory(); DEBTRACE( "-----------------End PyNode::outputs-----------------" ); + if(!isUsingPythonCache()) + { + for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++) + { + AutoPyRef pStr = PyUnicode_FromString( (*iter2)->getName().c_str() ); + if( PyDict_Contains(_context,pStr) == 1 ) + { PyDict_DelItem(_context,pStr); } + } + } } DEBTRACE( "++++++++++++++ End PyNode::execute: " << getName() << " ++++++++++++++++++++" ); } +/*! + * [EDF28562] + * \param in squeezeExceptions list on output port name excluded from the squeeze mecanism + */ +void PythonNode::setSqueezeStatusWithExceptions(bool sqStatus, const std::vector& squeezeExceptions) +{ + this->setSqueezeStatus(sqStatus); + this->_nonSqueezableOutputNodes = std::set(squeezeExceptions.begin(), squeezeExceptions.end()); +} + void PythonNode::squeezeMemorySafe() { AutoGIL agil; @@ -759,6 +879,8 @@ void PythonNode::squeezeMemory() } for(auto p : _setOfOutputPort) { + if (!this->_nonSqueezableOutputNodes.empty() && this->_nonSqueezableOutputNodes.find(p->getName()) != this->_nonSqueezableOutputNodes.end()) + continue; PyDict_DelItemString(_context,p->getName().c_str()); OutputPyPort *p2(static_cast(p)); p2->putWithoutForward(Py_None); @@ -775,6 +897,8 @@ void PythonNode::squeezeMemoryRemote() } for(auto p : _setOfOutputPort) { + if (!this->_nonSqueezableOutputNodes.empty() && this->_nonSqueezableOutputNodes.find(p->getName()) != this->_nonSqueezableOutputNodes.end()) + continue; OutputPyPort *p2(static_cast(p)); p2->putWithoutForward(Py_None); }