X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2FPythonNode.cxx;h=3dea3eefdf0734bd119aba7591235fa0c38a06e3;hb=3702c4124b9f5a5580ce105d8b7f5103d69fc356;hp=e4d7c596f9d043eadae388c2050ee37c46069aee;hpb=f4c10bf1781a76534bb1fa293aef541aef56148b;p=modules%2Fyacs.git diff --git a/src/runtime/PythonNode.cxx b/src/runtime/PythonNode.cxx index e4d7c596f..3dea3eefd 100644 --- a/src/runtime/PythonNode.cxx +++ b/src/runtime/PythonNode.cxx @@ -1,28 +1,43 @@ -// Copyright (C) 2006-2008 CEA/DEN, EDF R&D +// Copyright (C) 2006-2013 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 -// License as published by the Free Software Foundation; either -// version 2.1 of the License. +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. // -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // + #include "RuntimeSALOME.hxx" #include "PythonNode.hxx" #include "PythonPorts.hxx" +#include "TypeCode.hxx" +#include "Container.hxx" +#include "SalomeContainer.hxx" +#include "ConversionException.hxx" #include "PyStdout.hxx" #include #include +#include + +#ifdef WIN32 +#include +#define getpid _getpid +#endif + +#if PY_VERSION_HEX < 0x02050000 +typedef int Py_ssize_t; +#endif //#define _DEVDEBUG_ #include "YacsTrace.hxx" @@ -38,6 +53,14 @@ PythonNode::PythonNode(const PythonNode& other, ComposedNode *father):InlineNode _implementation=IMPL_NAME; PyGILState_STATE gstate=PyGILState_Ensure(); _context=PyDict_New(); + if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() )) + { + stringstream msg; + msg << "Impossible to set builtins" << __FILE__ << ":" << __LINE__; + PyGILState_Release(gstate); + _errorDetails=msg.str(); + throw Exception(msg.str()); + } PyGILState_Release(gstate); } @@ -46,6 +69,14 @@ PythonNode::PythonNode(const std::string& name):InlineNode(name) _implementation=IMPL_NAME; PyGILState_STATE gstate = PyGILState_Ensure(); _context=PyDict_New(); + if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() )) + { + stringstream msg; + msg << "Impossible to set builtins" << __FILE__ << ":" << __LINE__; + PyGILState_Release(gstate); + _errorDetails=msg.str(); + throw Exception(msg.str()); + } PyGILState_Release(gstate); } @@ -57,22 +88,301 @@ PythonNode::~PythonNode() PyGILState_Release(gstate); } +void PythonNode::checkBasicConsistency() const throw(YACS::Exception) +{ + DEBTRACE("checkBasicConsistency"); + InlineNode::checkBasicConsistency(); + + PyGILState_STATE gstate = PyGILState_Ensure(); + PyObject* res; + res=Py_CompileString(_script.c_str(),getName().c_str(),Py_file_input); + if(res == NULL) + { + std::string error=""; + PyObject* new_stderr = newPyStdOut(error); + PySys_SetObject((char*)"stderr", new_stderr); + PyErr_Print(); + PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__")); + Py_DECREF(new_stderr); + PyGILState_Release(gstate); + throw Exception(error); + } + else + Py_XDECREF(res); + PyGILState_Release(gstate); +} + void PythonNode::load() { + DEBTRACE( "---------------PyNode::load function---------------" ); + if(_mode=="remote") + loadRemote(); + else + loadLocal(); +} + +void PythonNode::loadLocal() +{ + DEBTRACE( "---------------PyNode::loadLocal function---------------" ); + // do nothing +} + +void PythonNode::loadRemote() +{ + DEBTRACE( "---------------PyNode::loadRemote function---------------" ); + if(_container) + { + if(!_container->isAlreadyStarted(0)) + { + try + { + _container->start(0); + } + catch(Exception& e) + { + _errorDetails=e.what(); + throw e; + } + } + } + else + { + std::string what("PyNode::loadRemote : a load operation requested on \""); + what+=_name; what+="\" with no container specified."; + _errorDetails=what; + throw Exception(what); + } + + Engines::Container_var objContainer=((SalomeContainer*)_container)->getContainerPtr(0); + + try + { + _pynode = objContainer->createPyScriptNode(getName().c_str(),getScript().c_str()); + } + catch( const SALOME::SALOME_Exception& ex ) + { + std::string msg="Exception on remote python node creation "; + msg += '\n'; + msg += ex.details.text.in(); + _errorDetails=msg; + throw Exception(msg); + } + + PyGILState_STATE gstate = PyGILState_Ensure(); + const char picklizeScript[]="import cPickle\n" + "def pickleForDistPyth2009(kws):\n" + " return cPickle.dumps(((),kws),-1)\n" + "\n" + "def unPickleForDistPyth2009(st):\n" + " args=cPickle.loads(st)\n" + " return args\n"; + PyObject *res=PyRun_String(picklizeScript,Py_file_input,_context,_context); + if(res == 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); + + PyGILState_Release(gstate); + throw Exception("Error during load"); + } + Py_DECREF(res); + + _pyfuncSer=PyDict_GetItemString(_context,"pickleForDistPyth2009"); + _pyfuncUnser=PyDict_GetItemString(_context,"unPickleForDistPyth2009"); + if(_pyfuncSer == 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); + + PyGILState_Release(gstate); + throw Exception("Error during load"); + } + if(_pyfuncUnser == 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); + + PyGILState_Release(gstate); + throw Exception("Error during load"); + } + DEBTRACE( "---------------End PyNode::loadRemote function---------------" ); + PyGILState_Release(gstate); + } void PythonNode::execute() { - DEBTRACE( "++++++++++++++ PyNode::execute: " << getName() << " ++++++++++++++++++++" ); + if(_mode=="remote") + executeRemote(); + else + executeLocal(); +} + +void PythonNode::executeRemote() +{ + DEBTRACE( "++++++++++++++ PyNode::executeRemote: " << getName() << " ++++++++++++++++++++" ); + if(!_pyfuncSer) + throw Exception("DistributedPythonNode badly loaded"); PyGILState_STATE gstate = PyGILState_Ensure(); - if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() )) + + //=========================================================================== + // Get inputs in input ports, build a Python dict and pickle it + //=========================================================================== + PyObject* ob; + PyObject* args = PyDict_New(); + std::list::iterator iter2; + int pos=0; + for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); ++iter2) + { + InputPyPort *p=(InputPyPort *)*iter2; + ob=p->getPyObj(); + PyDict_SetItemString(args,p->getName().c_str(),ob); + pos++; + } +#ifdef _DEVDEBUG_ + PyObject_Print(args,stderr,Py_PRINT_RAW); + std::cerr << endl; +#endif + PyObject *serializationInput=PyObject_CallFunctionObjArgs(_pyfuncSer,args,NULL); + //The pickled string may contain NULL characters so use PyString_AsStringAndSize + char* serializationInputC; + Py_ssize_t len; + if (PyString_AsStringAndSize(serializationInput, &serializationInputC, &len)) { - stringstream msg; - msg << "Impossible to set builtins" << __FILE__ << ":" << __LINE__; PyGILState_Release(gstate); - _errorDetails=msg.str(); - throw Exception(msg.str()); + throw Exception("DistributedPythonNode problem in python pickle"); } + PyGILState_Release(gstate); + + Engines::pickledArgs_var serializationInputCorba=new Engines::pickledArgs; + serializationInputCorba->length(len); + for(int i=0; i < len ; i++) + serializationInputCorba[i]=serializationInputC[i]; + + //get the list of output argument names + std::list::iterator iter; + Engines::listofstring myseq; + myseq.length(getNumberOfOutputPorts()); + pos=0; + for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); ++iter) + { + OutputPyPort *p=(OutputPyPort *)*iter; + myseq[pos]=p->getName().c_str(); + DEBTRACE( "port name: " << p->getName() ); + DEBTRACE( "port kind: " << p->edGetType()->kind() ); + DEBTRACE( "port pos : " << pos ); + pos++; + } + //=========================================================================== + // Execute in remote Python node + //=========================================================================== + DEBTRACE( "-----------------starting remote python invocation-----------------" ); + Engines::pickledArgs_var resultCorba; + try + { + //pass outargsname and dict serialized + resultCorba=_pynode->execute(myseq,serializationInputCorba); + } + 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); + } + 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]; + + gstate = PyGILState_Ensure(); + + PyObject* resultPython=PyString_FromStringAndSize(resultCorbaC,resultCorba->length()); + delete [] resultCorbaC; + args = PyTuple_New(1); + PyTuple_SetItem(args,0,resultPython); + PyObject *finalResult=PyObject_CallObject(_pyfuncUnser,args); + Py_DECREF(args); + + if (finalResult == NULL) + { + std::stringstream msg; + msg << "Conversion with pickle of output ports failed !"; + msg << " : " << __FILE__ << ":" << __LINE__; + PyGILState_Release(gstate); + _errorDetails=msg.str(); + throw YACS::ENGINE::ConversionException(msg.str()); + } + + DEBTRACE( "-----------------PythonNode::outputs-----------------" ); + int nres=1; + if(finalResult == Py_None) + nres=0; + else if(PyTuple_Check(finalResult)) + nres=PyTuple_Size(finalResult); + + if(getNumberOfOutputPorts() != nres) + { + std::string msg="Number of output arguments : Mismatch between definition and execution"; + Py_DECREF(finalResult); + PyGILState_Release(gstate); + _errorDetails=msg; + throw Exception(msg); + } + + pos=0; + try + { + for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); ++iter) + { + OutputPyPort *p=(OutputPyPort *)*iter; + DEBTRACE( "port name: " << p->getName() ); + DEBTRACE( "port kind: " << p->edGetType()->kind() ); + DEBTRACE( "port pos : " << pos ); + if(PyTuple_Check(finalResult)) + ob=PyTuple_GetItem(finalResult,pos) ; + else + ob=finalResult; + DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); + p->put(ob); + pos++; + } + Py_DECREF(finalResult); + } + catch(ConversionException& ex) + { + Py_DECREF(finalResult); + PyGILState_Release(gstate); + _errorDetails=ex.what(); + throw; + } + + PyGILState_Release(gstate); + + DEBTRACE( "++++++++++++++ ENDOF PyNode::executeRemote: " << getName() << " ++++++++++++++++++++" ); +} + +void PythonNode::executeLocal() +{ + DEBTRACE( "++++++++++++++ PyNode::executeLocal: " << getName() << " ++++++++++++++++++++" ); + PyGILState_STATE gstate = PyGILState_Ensure(); DEBTRACE( "---------------PyNode::inputs---------------" ); list::iterator iter2; @@ -97,7 +407,25 @@ void PythonNode::execute() DEBTRACE( "----------------PyNode::calculation---------------" ); DEBTRACE( _script ); DEBTRACE( "_context refcnt: " << _context->ob_refcnt ); - PyObject *res=PyRun_String(_script.c_str(),Py_file_input,_context,_context); + + std::ostringstream stream; + stream << "/tmp/PythonNode_"; + stream << getpid(); + + 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); + PyGILState_Release(gstate); + throw Exception("Error during execution"); + } + PyObject *res = PyEval_EvalCode((PyCodeObject *)code, _context, _context); + Py_DECREF(code); DEBTRACE( "_context refcnt: " << _context->ob_refcnt ); fflush(stdout); fflush(stderr); @@ -105,9 +433,15 @@ void PythonNode::execute() { _errorDetails=""; PyObject* new_stderr = newPyStdOut(_errorDetails); - PySys_SetObject("stderr", new_stderr); + PySys_SetObject((char*)"stderr", new_stderr); + ofstream errorfile(stream.str().c_str()); + if (errorfile.is_open()) + { + errorfile << _script; + errorfile.close(); + } PyErr_Print(); - PySys_SetObject("stderr", PySys_GetObject("__stderr__")); + PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__")); Py_DECREF(new_stderr); PyGILState_Release(gstate); @@ -152,6 +486,39 @@ void PythonNode::execute() DEBTRACE( "++++++++++++++ End PyNode::execute: " << getName() << " ++++++++++++++++++++" ); } +std::string PythonNode::getContainerLog() +{ + if(_mode=="local")return ""; + + std::string msg; + try + { + Engines::Container_var objContainer=((SalomeContainer*)_container)->getContainerPtr(0); + CORBA::String_var logname = objContainer->logfilename(); + DEBTRACE(logname); + msg=logname; + std::string::size_type pos = msg.find(":"); + msg=msg.substr(pos+1); + } + catch(...) + { + msg = "Container no longer reachable"; + } + return msg; +} + +void PythonNode::shutdown(int level) +{ + DEBTRACE("PythonNode::shutdown " << level); + if(_mode=="local")return; + if(_container) + { + if(!CORBA::is_nil(_pynode)) _pynode->UnRegister(); + _pynode=Engines::PyScriptNode::_nil(); + _container->shutdown(level); + } +} + Node *PythonNode::simpleClone(ComposedNode *father, bool editionOnly) const { return new PythonNode(*this,father); @@ -225,12 +592,143 @@ PyFuncNode::~PyFuncNode() if(_pyfunc)DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt ); Py_DECREF(_context); PyGILState_Release(gstate); + if(!CORBA::is_nil(_pynode)) + { + _pynode->UnRegister(); + } +} + +void PyFuncNode::checkBasicConsistency() const throw(YACS::Exception) +{ + DEBTRACE("checkBasicConsistency"); + InlineFuncNode::checkBasicConsistency(); + + PyGILState_STATE gstate = PyGILState_Ensure(); + PyObject* res; + res=Py_CompileString(_script.c_str(),getName().c_str(),Py_file_input); + if(res == NULL) + { + std::string error=""; + PyObject* new_stderr = newPyStdOut(error); + PySys_SetObject((char*)"stderr", new_stderr); + PyErr_Print(); + PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__")); + Py_DECREF(new_stderr); + PyGILState_Release(gstate); + throw Exception(error); + } + else + Py_XDECREF(res); + PyGILState_Release(gstate); } void PyFuncNode::load() +{ + DEBTRACE( "---------------PyfuncNode::load function---------------" ); + if(_mode=="remote") + loadRemote(); + else + loadLocal(); +} + +void PyFuncNode::loadRemote() +{ + DEBTRACE( "---------------PyfuncNode::loadRemote function---------------" ); + if(_container) + { + if(!_container->isAlreadyStarted(0)) + { + try + { + _container->start(0); + } + catch(Exception& e) + { + _errorDetails=e.what(); + throw e; + } + } + } + else + { + std::string what("PyFuncNode::loadRemote : a load operation requested on \""); + what+=_name; what+="\" with no container specified."; + _errorDetails=what; + throw Exception(what); + } + + Engines::Container_var objContainer=((SalomeContainer*)_container)->getContainerPtr(0); + try + { + _pynode = objContainer->createPyNode(getName().c_str(),getScript().c_str()); + } + catch( const SALOME::SALOME_Exception& ex ) + { + std::string msg="Exception on remote python node creation "; + msg += '\n'; + msg += ex.details.text.in(); + _errorDetails=msg; + throw Exception(msg); + } + + PyGILState_STATE gstate = PyGILState_Ensure(); + const char picklizeScript[]="import cPickle\n" + "def pickleForDistPyth2009(*args,**kws):\n" + " return cPickle.dumps((args,kws),-1)\n" + "\n" + "def unPickleForDistPyth2009(st):\n" + " args=cPickle.loads(st)\n" + " return args\n"; + PyObject *res=PyRun_String(picklizeScript,Py_file_input,_context,_context); + if(res == 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); + + PyGILState_Release(gstate); + throw Exception("Error during load"); + } + Py_DECREF(res); + + _pyfuncSer=PyDict_GetItemString(_context,"pickleForDistPyth2009"); + _pyfuncUnser=PyDict_GetItemString(_context,"unPickleForDistPyth2009"); + if(_pyfuncSer == 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); + + PyGILState_Release(gstate); + throw Exception("Error during load"); + } + if(_pyfuncUnser == 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); + + PyGILState_Release(gstate); + throw Exception("Error during load"); + } + DEBTRACE( "---------------End PyfuncNode::loadRemote function---------------" ); + PyGILState_Release(gstate); +} + +void PyFuncNode::loadLocal() { DEBTRACE( "---------------PyFuncNode::load function " << getName() << " ---------------" ); DEBTRACE( _script ); + #ifdef _DEVDEBUG_ list::iterator iter; for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++) @@ -240,17 +738,43 @@ void PyFuncNode::load() DEBTRACE( "port kind: " << p->edGetType()->kind() ); } #endif + PyGILState_STATE gstate = PyGILState_Ensure(); DEBTRACE( "_context refcnt: " << _context->ob_refcnt ); - PyObject *res=PyRun_String(_script.c_str(),Py_file_input,_context,_context); + + std::ostringstream stream; + stream << "/tmp/PythonNode_"; + stream << getpid(); + + 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); + PyGILState_Release(gstate); + throw Exception("Error during execution"); + } + PyObject *res = PyEval_EvalCode((PyCodeObject *)code, _context, _context); + Py_DECREF(code); + DEBTRACE( "_context refcnt: " << _context->ob_refcnt ); if(res == NULL) { _errorDetails=""; PyObject* new_stderr = newPyStdOut(_errorDetails); - PySys_SetObject("stderr", new_stderr); + PySys_SetObject((char*)"stderr", new_stderr); + ofstream errorfile(stream.str().c_str()); + if (errorfile.is_open()) + { + errorfile << _script; + errorfile.close(); + } PyErr_Print(); - PySys_SetObject("stderr", PySys_GetObject("__stderr__")); + PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__")); Py_DECREF(new_stderr); PyGILState_Release(gstate); @@ -264,9 +788,9 @@ void PyFuncNode::load() { _errorDetails=""; PyObject* new_stderr = newPyStdOut(_errorDetails); - PySys_SetObject("stderr", new_stderr); + PySys_SetObject((char*)"stderr", new_stderr); PyErr_Print(); - PySys_SetObject("stderr", PySys_GetObject("__stderr__")); + PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__")); Py_DECREF(new_stderr); PyGILState_Release(gstate); @@ -277,8 +801,143 @@ void PyFuncNode::load() } void PyFuncNode::execute() +{ + if(_mode=="remote") + executeRemote(); + else + executeLocal(); +} + +void PyFuncNode::executeRemote() +{ + DEBTRACE( "++++++++++++++ PyFuncNode::executeRemote: " << getName() << " ++++++++++++++++++++" ); + if(!_pyfuncSer) + throw Exception("DistributedPythonNode badly loaded"); + PyGILState_STATE gstate = PyGILState_Ensure(); + + //=========================================================================== + // Get inputs in input ports, build a Python tuple and pickle it + //=========================================================================== + PyObject* ob; + PyObject* args = PyTuple_New(getNumberOfInputPorts()); + std::list::iterator iter2; + int pos=0; + for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); ++iter2) + { + InputPyPort *p=(InputPyPort *)*iter2; + ob=p->getPyObj(); + Py_INCREF(ob); + PyTuple_SetItem(args,pos,ob); + pos++; + } +#ifdef _DEVDEBUG_ + PyObject_Print(args,stderr,Py_PRINT_RAW); + std::cerr << endl; +#endif + PyObject *serializationInput=PyObject_CallObject(_pyfuncSer,args); + //The pickled string may contain NULL characters so use PyString_AsStringAndSize + char* serializationInputC; + Py_ssize_t len; + if (PyString_AsStringAndSize(serializationInput, &serializationInputC, &len)) + { + PyGILState_Release(gstate); + throw Exception("DistributedPythonNode problem in python pickle"); + } + PyGILState_Release(gstate); + + Engines::pickledArgs_var serializationInputCorba=new Engines::pickledArgs; + serializationInputCorba->length(len); + for(int i=0; i < len ; i++) + serializationInputCorba[i]=serializationInputC[i]; + + //=========================================================================== + // Execute in remote Python node + //=========================================================================== + DEBTRACE( "-----------------starting remote python invocation-----------------" ); + Engines::pickledArgs_var resultCorba; + try + { + resultCorba=_pynode->execute(getFname().c_str(),serializationInputCorba); + } + 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); + } + 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]; + + gstate = PyGILState_Ensure(); + + PyObject* resultPython=PyString_FromStringAndSize(resultCorbaC,resultCorba->length()); + delete [] resultCorbaC; + args = PyTuple_New(1); + PyTuple_SetItem(args,0,resultPython); + PyObject *finalResult=PyObject_CallObject(_pyfuncUnser,args); + Py_DECREF(args); + + DEBTRACE( "-----------------PythonNode::outputs-----------------" ); + int nres=1; + if(finalResult == Py_None) + nres=0; + else if(PyTuple_Check(finalResult)) + nres=PyTuple_Size(finalResult); + + if(getNumberOfOutputPorts() != nres) + { + std::string msg="Number of output arguments : Mismatch between definition and execution"; + Py_DECREF(finalResult); + PyGILState_Release(gstate); + _errorDetails=msg; + throw Exception(msg); + } + + pos=0; + std::list::iterator iter; + try + { + for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); ++iter) + { + OutputPyPort *p=(OutputPyPort *)*iter; + DEBTRACE( "port name: " << p->getName() ); + DEBTRACE( "port kind: " << p->edGetType()->kind() ); + DEBTRACE( "port pos : " << pos ); + if(PyTuple_Check(finalResult)) + ob=PyTuple_GetItem(finalResult,pos) ; + else + ob=finalResult; + DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); + p->put(ob); + pos++; + } + Py_DECREF(finalResult); + } + catch(ConversionException& ex) + { + Py_DECREF(finalResult); + PyGILState_Release(gstate); + _errorDetails=ex.what(); + throw; + } + + PyGILState_Release(gstate); + + DEBTRACE( "++++++++++++++ ENDOF PyFuncNode::executeRemote: " << getName() << " ++++++++++++++++++++" ); +} + +void PyFuncNode::executeLocal() { DEBTRACE( "++++++++++++++ PyFuncNode::execute: " << getName() << " ++++++++++++++++++++" ); + int pos=0; PyObject* ob; if(!_pyfunc)throw Exception("PyFuncNode badly loaded"); @@ -322,9 +981,18 @@ void PyFuncNode::execute() { _errorDetails=""; PyObject* new_stderr = newPyStdOut(_errorDetails); - PySys_SetObject("stderr", new_stderr); + PySys_SetObject((char*)"stderr", new_stderr); + std::ostringstream stream; + stream << "/tmp/PythonNode_"; + stream << getpid(); + ofstream errorfile(stream.str().c_str()); + if (errorfile.is_open()) + { + errorfile << _script; + errorfile.close(); + } PyErr_Print(); - PySys_SetObject("stderr", PySys_GetObject("__stderr__")); + PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__")); Py_DECREF(new_stderr); PyGILState_Release(gstate); @@ -412,3 +1080,37 @@ PyFuncNode* PyFuncNode::cloneNode(const std::string& name) } return n; } + +std::string PyFuncNode::getContainerLog() +{ + if(_mode=="local")return ""; + + std::string msg; + try + { + Engines::Container_var objContainer=((SalomeContainer*)_container)->getContainerPtr(0); + CORBA::String_var logname = objContainer->logfilename(); + DEBTRACE(logname); + msg=logname; + std::string::size_type pos = msg.find(":"); + msg=msg.substr(pos+1); + } + catch(...) + { + msg = "Container no longer reachable"; + } + return msg; +} + +void PyFuncNode::shutdown(int level) +{ + DEBTRACE("PyFuncNode::shutdown " << level); + if(_mode=="local")return; + if(_container) + { + if(!CORBA::is_nil(_pynode)) _pynode->UnRegister(); + _pynode=Engines::PyNode::_nil(); + _container->shutdown(level); + } +} +