From 51fe9f1896f7392815d81f2cf86f64c25feef49e Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Wed, 15 Jul 2015 18:07:39 +0200 Subject: [PATCH] First draft of wait mechanism. --- idl/SALOME_SDS.idl | 6 ++ src/SALOMESDS/CMakeLists.txt | 1 + src/SALOMESDS/SALOMESDS_DataScopeServer.cxx | 52 ++++++++++++---- src/SALOMESDS/SALOMESDS_DataScopeServer.hxx | 13 +++- src/SALOMESDS/SALOMESDS_KeyWaiter.cxx | 60 +++++++++++++++++++ src/SALOMESDS/SALOMESDS_KeyWaiter.hxx | 50 ++++++++++++++++ .../SALOMESDS_PickelizedPyObjServer.cxx | 20 +++++-- .../SALOMESDS_PickelizedPyObjServer.hxx | 2 + src/SALOMESDS/SALOMESDS_Transaction.cxx | 15 +---- src/SALOMESDS/SALOMESDS_Transaction.hxx | 3 + 10 files changed, 190 insertions(+), 32 deletions(-) create mode 100644 src/SALOMESDS/SALOMESDS_KeyWaiter.cxx create mode 100644 src/SALOMESDS/SALOMESDS_KeyWaiter.hxx diff --git a/idl/SALOME_SDS.idl b/idl/SALOME_SDS.idl index d5c5d4d15..d26c2ad58 100644 --- a/idl/SALOME_SDS.idl +++ b/idl/SALOME_SDS.idl @@ -81,12 +81,18 @@ module SALOME typedef sequence ListOfTransaction; + interface KeyWaiter + { + ByteVec waitFor() raises (SALOME::SALOME_Exception); + }; + interface DataScopeServerTransaction : DataScopeServerBase { ByteVec fetchSerializedContent(in string varName) raises (SALOME::SALOME_Exception); Transaction createRdOnlyVarTransac(in string varName, in ByteVec constValue) raises (SALOME::SALOME_Exception); Transaction createRdExtVarTransac(in string varName, in ByteVec constValue) raises (SALOME::SALOME_Exception); Transaction createRdWrVarTransac(in string varName, in ByteVec constValue) raises (SALOME::SALOME_Exception); + KeyWaiter waitForKeyInVar(in string varName, in ByteVec keyVal) raises (SALOME::SALOME_Exception); void atomicApply(in ListOfTransaction transactions) raises (SALOME::SALOME_Exception); }; diff --git a/src/SALOMESDS/CMakeLists.txt b/src/SALOMESDS/CMakeLists.txt index e76e4b664..8a9a4c145 100644 --- a/src/SALOMESDS/CMakeLists.txt +++ b/src/SALOMESDS/CMakeLists.txt @@ -45,6 +45,7 @@ SET(SalomeSDS_SOURCES SALOMESDS_PickelizedPyObjRdExtServer.cxx SALOMESDS_PickelizedPyObjRdWrServer.cxx SALOMESDS_Transaction.cxx + SALOMESDS_KeyWaiter.cxx ) ADD_LIBRARY(SalomeSDS ${SalomeSDS_SOURCES}) diff --git a/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx b/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx index 3e82e2f5b..38b923393 100644 --- a/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx +++ b/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx @@ -23,6 +23,7 @@ #include "SALOMESDS_PickelizedPyObjRdOnlyServer.hxx" #include "SALOMESDS_PickelizedPyObjRdExtServer.hxx" #include "SALOMESDS_PickelizedPyObjRdWrServer.hxx" +#include "SALOMESDS_KeyWaiter.hxx" #include "SALOMESDS_Transaction.hxx" #include "SALOME_NamingService.hxx" #include "SALOMESDS_Exception.hxx" @@ -102,13 +103,13 @@ CORBA::Boolean DataScopeServerBase::existVar(const char *varName) SALOME::BasicDataServer_ptr DataScopeServerBase::retrieveVarInternal(const char *varName) { - std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it0(retrieveVarInternal3(varName)); + std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(retrieveVarInternal3(varName)); return SALOME::BasicDataServer::_duplicate((*it0).first); } BasicDataServer *DataScopeServerBase::retrieveVarInternal2(const std::string& varName) { - std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it0(retrieveVarInternal3(varName)); + std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(retrieveVarInternal3(varName)); return (*it0).second; } @@ -218,7 +219,7 @@ std::vector< std::string > DataScopeServerBase::getAllVarNames() const return ret; } -void DataScopeServerBase::checkNotAlreadyExistingVar(const std::string& varName) +void DataScopeServerBase::checkNotAlreadyExistingVar(const std::string& varName) const { std::vector allNames(getAllVarNames()); std::vector::iterator it(std::find(allNames.begin(),allNames.end(),varName)); @@ -229,7 +230,7 @@ void DataScopeServerBase::checkNotAlreadyExistingVar(const std::string& varName) } } -void DataScopeServerBase::checkExistingVar(const std::string& varName) +void DataScopeServerBase::checkExistingVar(const std::string& varName) const { std::vector allNames(getAllVarNames()); std::vector::iterator it(std::find(allNames.begin(),allNames.end(),varName)); @@ -240,7 +241,25 @@ void DataScopeServerBase::checkExistingVar(const std::string& varName) } } -std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator DataScopeServerBase::retrieveVarInternal3(const std::string& varName) +PickelizedPyObjServer *DataScopeServerBase::checkVarExistingAndDict(const std::string& varName) +{ + checkExistingVar(varName); + BasicDataServer *var(retrieveVarInternal2(varName.c_str())); + PickelizedPyObjServer *ret(dynamic_cast(var)); + if(!ret) + { + std::ostringstream oss; oss << "TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure : var \"" << varName << "\"exists but it is not serialized !"; + throw Exception(oss.str()); + } + if(!ret->isDict()) + { + std::ostringstream oss; oss << "TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure : var \"" << varName << "\"exists but it is not a Dict !"; + throw Exception(oss.str()); + } + return ret; +} + +std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator DataScopeServerBase::retrieveVarInternal3(const std::string& varName) const { std::vector allNames(getAllVarNames()); std::vector::iterator it(std::find(allNames.begin(),allNames.end(),varName)); @@ -251,7 +270,7 @@ std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterat throw Exception(oss.str()); } std::size_t pos(std::distance(allNames.begin(),it)); - std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it0(_vars.begin()); + std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(_vars.begin()); for(std::size_t i=0;iresolve_initial_references("RootPOA")); + PortableServer::POA_var poa(PortableServer::POA::_narrow(obj)); + _poa_for_key_waiter=poa; } -DataScopeServerTransaction::DataScopeServerTransaction(const DataScopeServerTransaction& other):DataScopeServerBase(other) +DataScopeServerTransaction::DataScopeServerTransaction(const DataScopeServerTransaction& other):DataScopeServerBase(other),_poa_for_key_waiter(other.getPOA4KeyWaiter()) { } @@ -357,36 +379,44 @@ SALOME::ByteVec *DataScopeServerTransaction::fetchSerializedContent(const char * SALOME::Transaction_ptr DataScopeServerTransaction::createRdOnlyVarTransac(const char *varName, const SALOME::ByteVec& constValue) { + checkNotAlreadyExistingVar(varName); TransactionRdOnlyVarCreate *ret(new TransactionRdOnlyVarCreate(this,varName,constValue)); - ret->checkNotAlreadyExisting(); CORBA::Object_var obj(ret->activate()); return SALOME::Transaction::_narrow(obj); } SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtVarTransac(const char *varName, const SALOME::ByteVec& constValue) { + checkNotAlreadyExistingVar(varName); TransactionRdExtVarCreate *ret(new TransactionRdExtVarCreate(this,varName,constValue)); - ret->checkNotAlreadyExisting(); CORBA::Object_var obj(ret->activate()); return SALOME::Transaction::_narrow(obj); } SALOME::Transaction_ptr DataScopeServerTransaction::createRdWrVarTransac(const char *varName, const SALOME::ByteVec& constValue) { + checkNotAlreadyExistingVar(varName); TransactionRdWrVarCreate *ret(new TransactionRdWrVarCreate(this,varName,constValue)); - ret->checkNotAlreadyExisting(); CORBA::Object_var obj(ret->activate()); return SALOME::Transaction::_narrow(obj); } SALOME::Transaction_ptr DataScopeServerTransaction::addKeyValueInVarHard(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value) { + checkNotAlreadyExistingVar(varName); TransactionAddKeyValueHard *ret(new TransactionAddKeyValueHard(this,varName,key,value)); - ret->checkNotAlreadyExisting(); CORBA::Object_var obj(ret->activate()); return SALOME::Transaction::_narrow(obj); } +SALOME::KeyWaiter_ptr DataScopeServerTransaction::waitForKeyInVar(const char *varName, const SALOME::ByteVec& keyVal) +{ + checkVarExistingAndDict(varName); + KeyWaiter *ret(new KeyWaiter(this,keyVal)); + CORBA::Object_var obj(ret->activate()); + return SALOME::KeyWaiter::_narrow(obj); +} + class TrustTransaction { public: diff --git a/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx b/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx index 63af1c333..749fcae9f 100644 --- a/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx +++ b/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx @@ -37,6 +37,8 @@ namespace SALOMESDS { + class PickelizedPyObjServer; + class SALOMESDS_EXPORT DataScopeServerBase : public virtual POA_SALOME::DataScopeServerBase, public POAHolder { public: @@ -64,10 +66,11 @@ namespace SALOMESDS static std::string BuildTmpVarNameFrom(const std::string& varName); public: std::vector< std::string> getAllVarNames() const; - void checkNotAlreadyExistingVar(const std::string& varName); - void checkExistingVar(const std::string& varName); + void checkNotAlreadyExistingVar(const std::string& varName) const; + void checkExistingVar(const std::string& varName) const; + PickelizedPyObjServer *checkVarExistingAndDict(const std::string& varName); protected: - std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator retrieveVarInternal3(const std::string& varName); + std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator retrieveVarInternal3(const std::string& varName) const; protected: PyObject *_globals; PyObject *_locals; @@ -100,13 +103,17 @@ namespace SALOMESDS void createRdOnlyVarInternal(const std::string& varName, const SALOME::ByteVec& constValue); void createRdExtVarInternal(const std::string& varName, const SALOME::ByteVec& constValue); void createRdWrVarInternal(const std::string& varName, const SALOME::ByteVec& constValue); + PortableServer::POA_var getPOA4KeyWaiter() const { return _poa_for_key_waiter; } public://remotely callable SALOME::ByteVec *fetchSerializedContent(const char *varName); SALOME::Transaction_ptr createRdOnlyVarTransac(const char *varName, const SALOME::ByteVec& constValue); SALOME::Transaction_ptr createRdExtVarTransac(const char *varName, const SALOME::ByteVec& constValue); SALOME::Transaction_ptr createRdWrVarTransac(const char *varName, const SALOME::ByteVec& constValue); SALOME::Transaction_ptr addKeyValueInVarHard(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value); + SALOME::KeyWaiter_ptr waitForKeyInVar(const char *varName, const SALOME::ByteVec& keyVal); void atomicApply(const SALOME::ListOfTransaction& transactions); + private: + PortableServer::POA_var _poa_for_key_waiter; }; /* diff --git a/src/SALOMESDS/SALOMESDS_KeyWaiter.cxx b/src/SALOMESDS/SALOMESDS_KeyWaiter.cxx new file mode 100644 index 000000000..aead15337 --- /dev/null +++ b/src/SALOMESDS/SALOMESDS_KeyWaiter.cxx @@ -0,0 +1,60 @@ +// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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, or (at your option) any later version. +// +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// Author : Anthony GEAY (EDF R&D) + +#include "SALOMESDS_KeyWaiter.hxx" +#include "SALOMESDS_DataScopeServer.hxx" +#include "SALOMESDS_PickelizedPyObjServer.hxx" + +using namespace SALOMESDS; + +KeyWaiter::KeyWaiter(DataScopeServerTransaction *dst, const SALOME::ByteVec& keyVal):_dst(dst),_ze_key(0),_ze_value(0) +{ + std::string st; + PickelizedPyObjServer::FromByteSeqToCpp(keyVal,st); + _ze_key=PickelizedPyObjServer::GetPyObjFromPickled(st,_dst); + PyObject *selfMeth(PyObject_GetAttrString(_dst->getPickler(),"__contains__")); + PyObject *args(PyTuple_New(1)); + PyTuple_SetItem(args,0,_ze_key); Py_XINCREF(_ze_key); // _ze_key is stolen by PyTuple_SetItem + PyObject *retPy(PyObject_CallObject(selfMeth,args)); + Py_XDECREF(args); + Py_XDECREF(selfMeth); + // + if(retPy!=Py_False && retPy!=Py_True) + throw Exception("KeyWaiter constructor : unexpected return of dict.__contains__ !"); + + Py_XDECREF(retPy); +} + +KeyWaiter::~KeyWaiter() +{ + Py_XDECREF(_ze_key); + if(_ze_value) + Py_XDECREF(_ze_value); +} + +PortableServer::POA_var KeyWaiter::getPOA() const +{ + return _dst->getPOA4KeyWaiter(); +} + +SALOME::ByteVec *KeyWaiter::waitFor() +{ + return 0; +} diff --git a/src/SALOMESDS/SALOMESDS_KeyWaiter.hxx b/src/SALOMESDS/SALOMESDS_KeyWaiter.hxx new file mode 100644 index 000000000..f1a6f4685 --- /dev/null +++ b/src/SALOMESDS/SALOMESDS_KeyWaiter.hxx @@ -0,0 +1,50 @@ +// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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, or (at your option) any later version. +// +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// Author : Anthony GEAY (EDF R&D) + +#ifndef __SALOMESDS_KEYWAITER_HXX__ +#define __SALOMESDS_KEYWAITER_HXX__ + +#include "SALOMEconfig.h" +#include CORBA_SERVER_HEADER(SALOME_SDS) + +#include "SALOMESDS_Defines.hxx" +#include "SALOMESDS_AutoRefCountPtr.hxx" + +#include + +namespace SALOMESDS +{ + class DataScopeServerTransaction; + + class SALOMESDS_EXPORT KeyWaiter : public virtual POA_SALOME::KeyWaiter, public POAHolder + { + public: + KeyWaiter(DataScopeServerTransaction *dst, const SALOME::ByteVec& keyVal); + virtual ~KeyWaiter(); + PortableServer::POA_var getPOA() const; + SALOME::ByteVec *waitFor(); + private: + DataScopeServerTransaction *_dst; + PyObject *_ze_key; + PyObject *_ze_value; + }; +} + +#endif diff --git a/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.cxx b/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.cxx index 0dd9701e3..d0ef1e96f 100644 --- a/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.cxx +++ b/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.cxx @@ -94,14 +94,14 @@ SALOME::ByteVec *PickelizedPyObjServer::FromCppToByteSeq(const std::string& strT } //! New reference returned -PyObject *PickelizedPyObjServer::getPyObjFromPickled(const std::string& pickledData) +PyObject *PickelizedPyObjServer::GetPyObjFromPickled(const std::string& pickledData, DataScopeServerBase *dsb) { std::size_t sz(pickledData.size()); PyObject *pickledDataPy(PyString_FromStringAndSize(NULL,sz));// agy : do not use PyString_FromString because std::string hides a vector of byte. char *buf(PyString_AsString(pickledDataPy));// this buf can be used thanks to python documentation. const char *inBuf(pickledData.c_str()); std::copy(inBuf,inBuf+sz,buf); - PyObject *selfMeth(PyObject_GetAttrString(_father->getPickler(),"loads")); + PyObject *selfMeth(PyObject_GetAttrString(dsb->getPickler(),"loads")); PyObject *args(PyTuple_New(1)); PyTuple_SetItem(args,0,pickledDataPy); PyObject *ret(PyObject_CallObject(selfMeth,args)); Py_XDECREF(args); @@ -110,14 +110,20 @@ PyObject *PickelizedPyObjServer::getPyObjFromPickled(const std::string& pickledD } //! New reference returned -PyObject *PickelizedPyObjServer::getPyObjFromPickled(const std::vector& pickledData) +PyObject *PickelizedPyObjServer::getPyObjFromPickled(const std::string& pickledData) +{ + return GetPyObjFromPickled(pickledData,_father); +} + +//! New reference returned +PyObject *PickelizedPyObjServer::GetPyObjFromPickled(const std::vector& pickledData, DataScopeServerBase *dsb) { std::size_t sz(pickledData.size()); PyObject *pickledDataPy(PyString_FromStringAndSize(NULL,sz));// agy : do not use PyString_FromString because std::string hides a vector of byte. char *buf(PyString_AsString(pickledDataPy));// this buf can be used thanks to python documentation. const unsigned char *inBuf(&pickledData[0]); std::copy(inBuf,inBuf+sz,buf); - PyObject *selfMeth(PyObject_GetAttrString(_father->getPickler(),"loads")); + PyObject *selfMeth(PyObject_GetAttrString(dsb->getPickler(),"loads")); PyObject *args(PyTuple_New(1)); PyTuple_SetItem(args,0,pickledDataPy); PyObject *ret(PyObject_CallObject(selfMeth,args)); Py_XDECREF(args); @@ -125,6 +131,12 @@ PyObject *PickelizedPyObjServer::getPyObjFromPickled(const std::vector& pickledData) +{ + return GetPyObjFromPickled(pickledData,_father); +} + //! obj is consumed by this method. std::string PickelizedPyObjServer::pickelize(PyObject *obj) { diff --git a/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.hxx b/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.hxx index e8f3edb5f..968339b8c 100644 --- a/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.hxx +++ b/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.hxx @@ -46,6 +46,8 @@ namespace SALOMESDS public: static void FromByteSeqToCpp(const SALOME::ByteVec& bsToBeConv, std::string& ret); static SALOME::ByteVec *FromCppToByteSeq(const std::string& strToBeConv); + static PyObject *GetPyObjFromPickled(const std::string& pickledData, DataScopeServerBase *dsb); + static PyObject *GetPyObjFromPickled(const std::vector& pickledData, DataScopeServerBase *dsb); PyObject *getPyObjFromPickled(const std::string& pickledData); PyObject *getPyObjFromPickled(const std::vector& pickledData); std::string pickelize(PyObject *obj); diff --git a/src/SALOMESDS/SALOMESDS_Transaction.cxx b/src/SALOMESDS/SALOMESDS_Transaction.cxx index e46a6dafb..7809157b0 100644 --- a/src/SALOMESDS/SALOMESDS_Transaction.cxx +++ b/src/SALOMESDS/SALOMESDS_Transaction.cxx @@ -99,20 +99,7 @@ TransactionAddKeyValueHard::TransactionAddKeyValueHard(DataScopeServerTransactio void TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure() { - checkNotAlreadyExisting(); - // - BasicDataServer *var(_dsct->retrieveVarInternal2(_var_name.c_str())); - _varc=dynamic_cast(var); - if(!_varc) - { - std::ostringstream oss; oss << "TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure : var \"" << _var_name << "\"exists but it is not serialized !"; - throw Exception(oss.str()); - } - if(!_varc->isDict()) - { - std::ostringstream oss; oss << "TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure : var \"" << _var_name << "\"exists but it is not a Dict !"; - throw Exception(oss.str()); - } + _varc=checkVarExistingAndDict(); // _zeDataBefore.clear(); SALOME::ByteVec *zeDataBefore(_varc->fetchSerializedContent()); diff --git a/src/SALOMESDS/SALOMESDS_Transaction.hxx b/src/SALOMESDS/SALOMESDS_Transaction.hxx index 55531c224..37e37f2bc 100644 --- a/src/SALOMESDS/SALOMESDS_Transaction.hxx +++ b/src/SALOMESDS/SALOMESDS_Transaction.hxx @@ -33,6 +33,8 @@ namespace SALOMESDS { + class PickelizedPyObjServer; + class SALOMESDS_EXPORT Transaction : public virtual POA_SALOME::Transaction, public POAHolder { public: @@ -40,6 +42,7 @@ namespace SALOMESDS std::string getVarName() const { return _var_name; } void checkNotAlreadyExisting() { _dsct->checkNotAlreadyExistingVar(_var_name); } void checkVarExisting() { _dsct->checkExistingVar(_var_name); } + PickelizedPyObjServer *checkVarExistingAndDict() { return _dsct->checkVarExistingAndDict(_var_name); } PortableServer::POA_var getPOA() const { return _dsct->getPOA(); } virtual void prepareRollBackInCaseOfFailure() = 0; virtual void perform() = 0; -- 2.39.2