From: Anthony Geay Date: Fri, 31 Oct 2014 10:18:45 +0000 (+0100) Subject: String -> PyObject + support of invocation of methods recursively. X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=8a3b2e43c5d895bc99112f1f4ba4784ac22eff7f;p=modules%2Fkernel.git String -> PyObject + support of invocation of methods recursively. --- diff --git a/idl/SALOME_SDS.idl b/idl/SALOME_SDS.idl index d77538f73..381d9947c 100644 --- a/idl/SALOME_SDS.idl +++ b/idl/SALOME_SDS.idl @@ -18,27 +18,26 @@ // // Author : Anthony GEAY (EDF R&D) +#include "SALOME_GenericObj.idl" + module SALOME { typedef sequence StringVec; typedef sequence ByteVec; - interface BasicDataServer + interface BasicDataServer : GenericObj { string getVarName(); + string getScopeName(); void setReadOnlyStatus(); void setRWStatus(); }; - /*interface PythonDataServer : BasicDataServer - { - };*/ - interface StringDataServer : BasicDataServer { void setSerializedContent(in ByteVec newValue); ByteVec fetchSerializedContent(); - ByteVec invokePythonMethodOn(in string method, in ByteVec args); + StringDataServer invokePythonMethodOn(in string method, in ByteVec args); }; interface DataServerManager; @@ -50,6 +49,7 @@ module SALOME StringVec listVars(); BasicDataServer retrieveVar(in string varName); StringDataServer createGlobalStringVar(in string varName); + StringDataServer createGlobalTmpVar(in ByteVec newValue); void shutdownIfNotHostedByDSM(); }; diff --git a/src/SALOMESDS/SALOMEGlobalVarHelper.py b/src/SALOMESDS/SALOMEGlobalVarHelper.py index 3de94933c..8ceaf4522 100644 --- a/src/SALOMESDS/SALOMEGlobalVarHelper.py +++ b/src/SALOMESDS/SALOMEGlobalVarHelper.py @@ -22,23 +22,17 @@ import SALOME import cPickle -class SALOMEGlobalVarMethodHelper: - def __init__(self,varPtr,meth): +class SALOMEGlobalVarHelper: + def __init__(self,varPtr,isTemporaryVar=False): assert(isinstance(varPtr,SALOME._objref_StringDataServer)) self._var_ptr=varPtr - self._meth=meth + if not isTemporaryVar: + self._var_ptr.Register() + self._is_temp=isTemporaryVar pass - def __call__(self,*args): - #print "__call__ %s : %s"%(self._meth,str(args)) - ret=self._var_ptr.invokePythonMethodOn(self._meth,cPickle.dumps(args,cPickle.HIGHEST_PROTOCOL)) - return cPickle.loads(ret) - pass - -class SALOMEGlobalVarHelper: - def __init__(self,varPtr): - assert(isinstance(varPtr,SALOME._objref_StringDataServer)) - self._var_ptr=varPtr + def __del__(self): + self._var_ptr.UnRegister() pass def assign(self,elt): @@ -46,9 +40,9 @@ class SALOMEGlobalVarHelper: self._var_ptr.setSerializedContent(st) pass - def __getattr__(self,*args): - #print "__getattr__,%s"%(str(args)) - return SALOMEGlobalVarMethodHelper(self._var_ptr,args[0]) + def __getattr__(self,meth): + #print "__getattr__,%s"%(meth) + return SALOMEGlobalVarMethodHelper(self._var_ptr,meth) def __str__(self): return self.local_copy().__str__() @@ -59,3 +53,25 @@ class SALOMEGlobalVarHelper: def local_copy(self): return cPickle.loads(self._var_ptr.fetchSerializedContent()) pass + +class SALOMEGlobalVarMethodHelper: + def __init__(self,varPtr,meth): + assert(isinstance(varPtr,SALOME._objref_StringDataServer)) + self._var_ptr=varPtr + self._var_ptr.Register() + self._meth=meth + pass + + def __call__(self,*args): + #print "__call__ %s : %s"%(self._meth,str(args)) + ret=self._var_ptr.invokePythonMethodOn(self._meth,cPickle.dumps(args,cPickle.HIGHEST_PROTOCOL)) + ret=SALOMEGlobalVarHelper(ret,True) + if self._meth not in ["__len__","__coerce__"]: + return ret + else: + return ret.local_copy() + + def __del__(self): + self._var_ptr.UnRegister() + pass + pass diff --git a/src/SALOMESDS/SALOMESDS_BasicDataServer.cxx b/src/SALOMESDS/SALOMESDS_BasicDataServer.cxx index b376b8772..d002d2fb9 100644 --- a/src/SALOMESDS/SALOMESDS_BasicDataServer.cxx +++ b/src/SALOMESDS/SALOMESDS_BasicDataServer.cxx @@ -19,6 +19,7 @@ // Author : Anthony GEAY (EDF R&D) #include "SALOMESDS_BasicDataServer.hxx" +#include "SALOMESDS_DataScopeServer.hxx" #include "SALOMESDS_Exception.hxx" #include @@ -37,6 +38,11 @@ char *BasicDataServer::getVarName() return CORBA::string_dup(_var_name.c_str()); } +char *BasicDataServer::getScopeName() +{ + return _father->getScopeName(); +} + /*! * Called remotely -> to protect against throw */ @@ -53,6 +59,21 @@ void BasicDataServer::setRWStatus() _is_read_only=false; } +void BasicDataServer::Register() +{ + incrRef(); +} + +void BasicDataServer::UnRegister() +{ + decrRef(); +} + +void BasicDataServer::Destroy() +{ + enforcedRelease(); +} + void BasicDataServer::checkReadOnlyStatusRegardingConstness(const char *sender) const { if(isReadOnly()) diff --git a/src/SALOMESDS/SALOMESDS_BasicDataServer.hxx b/src/SALOMESDS/SALOMESDS_BasicDataServer.hxx index 5edd934c5..d6139aabc 100644 --- a/src/SALOMESDS/SALOMESDS_BasicDataServer.hxx +++ b/src/SALOMESDS/SALOMESDS_BasicDataServer.hxx @@ -37,8 +37,14 @@ namespace SALOMESDS public: BasicDataServer(DataScopeServer *father, const std::string& varName); char *getVarName(); + char *getScopeName(); void setReadOnlyStatus(); void setRWStatus(); + public: + void Register(); + void UnRegister(); + void Destroy(); + public: std::string getVarNameCpp() const { return _var_name; } protected: void checkReadOnlyStatusRegardingConstness(const char *sender) const; diff --git a/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx b/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx index 0d7673505..7b529a59f 100644 --- a/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx +++ b/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx @@ -30,6 +30,8 @@ using namespace SALOMESDS; +std::size_t DataScopeServer::COUNTER=0; + DataScopeServer::DataScopeServer(CORBA::ORB_ptr orb, const std::string& scopeName):_globals(0),_locals(0),_pickler(0),_orb(CORBA::ORB::_duplicate(orb)),_name(scopeName) { } @@ -118,6 +120,22 @@ SALOME::StringDataServer_ptr DataScopeServer::createGlobalStringVar(const char * return SALOME::StringDataServer::_narrow(ret); } +/*! + * Called remotely -> to protect against throw + */ +SALOME::StringDataServer_ptr DataScopeServer::createGlobalTmpVar(const SALOME::ByteVec& newValue) +{ + static const char TMP_VAR_NAME[]="TmP"; + std::string vn(BuildTmpVarNameFrom(TMP_VAR_NAME)); + StringDataServer *retCpp(new StringDataServer(this,vn)); + retCpp->setPOA(_poa); + retCpp->setSerializedContent(newValue); + // + PortableServer::ObjectId_var id(_poa->activate_object(retCpp)); + CORBA::Object_var ret(_poa->id_to_reference(id)); + return SALOME::StringDataServer::_narrow(ret); +} + void DataScopeServer::shutdownIfNotHostedByDSM() { SALOME_NamingService ns(_orb); @@ -162,10 +180,6 @@ void DataScopeServer::initializePython(int argc, char *argv[]) _locals=PyDict_New(); PyObject *tmp(PyList_New(0)); _pickler=PyImport_ImportModuleLevel(const_cast("cPickle"),_globals,_locals,tmp,-1); - //Py_XDECREF(tmp); - //if(PyRun_String("import cPickle\n",Py_single_input,_globals,_locals)!=0) - // throw Exception("DataScopeServer::setPOAAndRegister : cPickle is not available !"); - /*_pickler=PyDict_GetItemString(_globals,"cPickle");*/ } /*! @@ -179,6 +193,13 @@ void DataScopeServer::setPOAAndRegister(PortableServer::POA_var poa, SALOME::Dat ns.Register(ptr,fullScopeName.c_str()); } +std::string DataScopeServer::BuildTmpVarNameFrom(const std::string& varName) +{ + std::ostringstream oss; + oss << varName << "@" << COUNTER++; + return oss.str(); +} + std::vector< std::string > DataScopeServer::getAllVarNames() const { std::size_t sz(_vars.size()); diff --git a/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx b/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx index 8c71a524f..ca4976d1a 100644 --- a/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx +++ b/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx @@ -46,6 +46,7 @@ namespace SALOMESDS SALOME::StringVec *listVars(); SALOME::BasicDataServer_ptr retrieveVar(const char *varName); SALOME::StringDataServer_ptr createGlobalStringVar(const char *varName); + SALOME::StringDataServer_ptr createGlobalTmpVar(const SALOME::ByteVec& newValue); void shutdownIfNotHostedByDSM(); ~DataScopeServer(); public: @@ -54,6 +55,8 @@ namespace SALOMESDS PyObject *getGlobals() const { return _globals; } PyObject *getLocals() const { return _locals; } PyObject *getPickler() const { return _pickler; } + PortableServer::POA_var getPOA() { return _poa; } + static std::string BuildTmpVarNameFrom(const std::string& varName); private: std::vector< std::string> getAllVarNames() const; CORBA::Object_var activateWithDedicatedPOA(BasicDataServer *ds); @@ -65,6 +68,7 @@ namespace SALOMESDS CORBA::ORB_var _orb; std::string _name; std::list< std::pair< SALOME::BasicDataServer_var, AutoRefCountPtr > > _vars; + static std::size_t COUNTER; }; } diff --git a/src/SALOMESDS/SALOMESDS_RefCountServ.cxx b/src/SALOMESDS/SALOMESDS_RefCountServ.cxx index ca572817f..b21d5a9dc 100644 --- a/src/SALOMESDS/SALOMESDS_RefCountServ.cxx +++ b/src/SALOMESDS/SALOMESDS_RefCountServ.cxx @@ -32,13 +32,20 @@ bool RefCountServ::decrRef() const bool ret((--_cnt)==0); if(ret) { - PortableServer::ObjectId_var oid = (const_cast(this))->_default_POA()->servant_to_id(const_cast(this)); - (const_cast(this))->_default_POA()->deactivate_object(oid); - (const_cast(this))->_remove_ref(); + RefCountServ *thisNC(const_cast(this)); + thisNC->enforcedRelease(); } return ret; } +void RefCountServ::enforcedRelease() +{ + PortableServer::POA_var poa(getPOA()); + PortableServer::ObjectId_var oid(poa->servant_to_id(this)); + poa->deactivate_object(oid); + _remove_ref(); +} + RefCountServ::RefCountServ():_cnt(1) { } diff --git a/src/SALOMESDS/SALOMESDS_RefCountServ.hxx b/src/SALOMESDS/SALOMESDS_RefCountServ.hxx index 56582e3ad..0ec2d95ab 100644 --- a/src/SALOMESDS/SALOMESDS_RefCountServ.hxx +++ b/src/SALOMESDS/SALOMESDS_RefCountServ.hxx @@ -30,7 +30,9 @@ namespace SALOMESDS public: void incrRef() const; bool decrRef() const; + virtual PortableServer::POA_var getPOA() = 0; protected: + void enforcedRelease(); RefCountServ(); RefCountServ(const RefCountServ& other); virtual ~RefCountServ(); diff --git a/src/SALOMESDS/SALOMESDS_StringDataServer.cxx b/src/SALOMESDS/SALOMESDS_StringDataServer.cxx index 1bbc0236a..77e5796e1 100644 --- a/src/SALOMESDS/SALOMESDS_StringDataServer.cxx +++ b/src/SALOMESDS/SALOMESDS_StringDataServer.cxx @@ -22,16 +22,25 @@ #include "SALOMESDS_DataScopeServer.hxx" #include "SALOMESDS_Exception.hxx" +#include #include using namespace SALOMESDS; -StringDataServer::StringDataServer(DataScopeServer *father, const std::string& varName):BasicDataServer(father,varName) +StringDataServer::StringDataServer(DataScopeServer *father, const std::string& varName):BasicDataServer(father,varName),_self(Py_None) +{ + Py_XINCREF(Py_None); +} + +//! obj is consumed +StringDataServer::StringDataServer(DataScopeServer *father, const std::string& varName, PyObject *obj):BasicDataServer(father,varName),_self(obj) { } StringDataServer::~StringDataServer() { + std::cerr << "~~~~~~~~~~ StringDataServer : " << getVarNameCpp() << std::endl; + Py_XDECREF(_self); } /*! @@ -40,7 +49,9 @@ StringDataServer::~StringDataServer() void StringDataServer::setSerializedContent(const SALOME::ByteVec& newValue) { checkReadOnlyStatusRegardingConstness("StringDataServer::setSerializedContent : read only var !"); - FromByteSeqToCpp(newValue,_data); + std::string data; + FromByteSeqToCpp(newValue,data); + setNewPyObj(getPyObjFromPickled(data)); } /*! @@ -48,38 +59,46 @@ void StringDataServer::setSerializedContent(const SALOME::ByteVec& newValue) */ SALOME::ByteVec *StringDataServer::fetchSerializedContent() { - return FromCppToByteSeq(_data); + Py_XINCREF(_self);//because pickelize consume _self + return FromCppToByteSeq(pickelize(_self)); } /*! * Called remotely -> to protect against throw */ -SALOME::ByteVec *StringDataServer::invokePythonMethodOn(const char *method, const SALOME::ByteVec& args) +SALOME::StringDataServer_ptr StringDataServer::invokePythonMethodOn(const char *method, const SALOME::ByteVec& args) { - PyObject *self(getPyObjFromPickled(_data)); + if(!_self) + throw Exception("StringDataServer::invokePythonMethodOn : self is NULL !"); std::string argsCpp; FromByteSeqToCpp(args,argsCpp); PyObject *argsPy(getPyObjFromPickled(argsCpp)); // - PyObject *selfMeth(PyObject_GetAttrString(self,method)); + PyObject *selfMeth(PyObject_GetAttrString(_self,method)); if(!selfMeth) { std::ostringstream oss; oss << "StringDataServer::invokePythonMethodOn : Method \"" << method << "\" is not available !"; throw Exception(oss.str()); } - PyObject *res(PyObject_CallObject(selfMeth,argsPy)); + PyObject *res(PyObject_CallObject(selfMeth,argsPy));// self can have been modified by this call ! + Py_XDECREF(selfMeth); + Py_XDECREF(argsPy); if(!res) { std::ostringstream oss; oss << "StringDataServer::invokePythonMethodOn : Problem during invokation serverside of Method \"" << method << "\" !"; throw Exception(oss.str()); } - _data=pickelize(self);// if it is a non const method ! - std::string retCpp(pickelize(res)); - // to test : res and self - Py_XDECREF(selfMeth); - // - Py_XDECREF(argsPy); - return FromCppToByteSeq(retCpp); + StringDataServer *ret(new StringDataServer(_father,DataScopeServer::BuildTmpVarNameFrom(getVarNameCpp()),res)); + PortableServer::POA_var poa(_father->getPOA()); + ret->setPOA(poa); + PortableServer::ObjectId_var id(poa->activate_object(ret)); + CORBA::Object_var obj(poa->id_to_reference(id)); + return SALOME::StringDataServer::_narrow(obj); +} + +PortableServer::POA_var StringDataServer::getPOA() +{ + return _poa; } void StringDataServer::FromByteSeqToCpp(const SALOME::ByteVec& bsToBeConv, std::string& ret) @@ -137,3 +156,14 @@ std::string StringDataServer::pickelize(PyObject *obj) Py_XDECREF(retPy); return ret; } + +//! obj is consumed by this method. +void StringDataServer::setNewPyObj(PyObject *obj) +{ + if(!obj) + throw Exception("StringDataServer::setNewPyObj : trying to assign a NULL pyobject in this !"); + if(obj==_self) + return ; + Py_XDECREF(_self); + _self=obj; +} diff --git a/src/SALOMESDS/SALOMESDS_StringDataServer.hxx b/src/SALOMESDS/SALOMESDS_StringDataServer.hxx index 94be7af61..bb266a058 100644 --- a/src/SALOMESDS/SALOMESDS_StringDataServer.hxx +++ b/src/SALOMESDS/SALOMESDS_StringDataServer.hxx @@ -34,18 +34,24 @@ namespace SALOMESDS { public: StringDataServer(DataScopeServer *father, const std::string& varName); + StringDataServer(DataScopeServer *father, const std::string& varName, PyObject *obj); ~StringDataServer(); void setSerializedContent(const SALOME::ByteVec& newValue); SALOME::ByteVec *fetchSerializedContent(); - SALOME::ByteVec *invokePythonMethodOn(const char *method, const SALOME::ByteVec& args); + SALOME::StringDataServer_ptr invokePythonMethodOn(const char *method, const SALOME::ByteVec& args); + public: + void setPOA(PortableServer::POA_var poa) { _poa=poa; } private: + PortableServer::POA_var getPOA(); static void FromByteSeqToCpp(const SALOME::ByteVec& bsToBeConv, std::string& ret); static SALOME::ByteVec *FromCppToByteSeq(const std::string& strToBeConv); PyObject *getPyObjFromPickled(const std::string& pickledData); std::string pickelize(PyObject *obj); + void setNewPyObj(PyObject *obj); private: static const char FAKE_VAR_NAME_FOR_WORK[]; - std::string _data; + PyObject *_self; + PortableServer::POA_var _poa; }; }