From 7d6c556a77d4c54a2e3630280e42003790c34300 Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Fri, 10 Jul 2015 15:10:22 +0200 Subject: [PATCH] Implementation of producer/consumer mechanism and transaction mechanism for global vars. --- CTestTestfileInstall.cmake.in | 1 + idl/SALOME_SDS.idl | 44 +- src/SALOMESDS/CMakeLists.txt | 7 +- src/SALOMESDS/CTestTestfileInstall.cmake | 23 + src/SALOMESDS/SALOMESDS_AutoRefCountPtr.hxx | 49 ++ src/SALOMESDS/SALOMESDS_BasicDataServer.cxx | 17 +- src/SALOMESDS/SALOMESDS_BasicDataServer.hxx | 9 +- src/SALOMESDS/SALOMESDS_DataScopeServer.cxx | 506 +++++++++++++++--- src/SALOMESDS/SALOMESDS_DataScopeServer.hxx | 80 ++- src/SALOMESDS/SALOMESDS_DataServerManager.cxx | 151 ++++-- src/SALOMESDS/SALOMESDS_DataServerManager.hxx | 17 +- src/SALOMESDS/SALOMESDS_KeyWaiter.cxx | 137 +++++ src/SALOMESDS/SALOMESDS_KeyWaiter.hxx | 61 +++ .../SALOMESDS_PickelizedPyObjRdExtServer.cxx | 4 +- .../SALOMESDS_PickelizedPyObjRdExtServer.hxx | 4 +- .../SALOMESDS_PickelizedPyObjRdOnlyServer.cxx | 4 +- .../SALOMESDS_PickelizedPyObjRdOnlyServer.hxx | 4 +- .../SALOMESDS_PickelizedPyObjRdWrServer.cxx | 6 +- .../SALOMESDS_PickelizedPyObjRdWrServer.hxx | 6 +- .../SALOMESDS_PickelizedPyObjServer.cxx | 112 +++- .../SALOMESDS_PickelizedPyObjServer.hxx | 22 +- src/SALOMESDS/SALOMESDS_RefCountServ.cxx | 8 - src/SALOMESDS/SALOMESDS_RefCountServ.hxx | 6 +- src/SALOMESDS/SALOMESDS_Transaction.cxx | 181 +++++++ src/SALOMESDS/SALOMESDS_Transaction.hxx | 143 +++++ src/SALOMESDS/SALOME_DataScopeServer.cxx | 18 +- src/SALOMESDS/TestSalomeSDS.py | 205 +++++++ src/SALOMESDS/TestSalomeSDS1.py | 1 + src/SALOMESDS/TestSalomeSDS2.py | 83 --- src/SALOMESDS/TestSalomeSDSHelper0.py | 25 + 30 files changed, 1664 insertions(+), 270 deletions(-) create mode 100644 src/SALOMESDS/CTestTestfileInstall.cmake create mode 100644 src/SALOMESDS/SALOMESDS_KeyWaiter.cxx create mode 100644 src/SALOMESDS/SALOMESDS_KeyWaiter.hxx create mode 100644 src/SALOMESDS/SALOMESDS_Transaction.cxx create mode 100644 src/SALOMESDS/SALOMESDS_Transaction.hxx create mode 100644 src/SALOMESDS/TestSalomeSDS.py delete mode 100644 src/SALOMESDS/TestSalomeSDS2.py create mode 100644 src/SALOMESDS/TestSalomeSDSHelper0.py diff --git a/CTestTestfileInstall.cmake.in b/CTestTestfileInstall.cmake.in index b739c2e22..05f1720ca 100644 --- a/CTestTestfileInstall.cmake.in +++ b/CTestTestfileInstall.cmake.in @@ -36,6 +36,7 @@ SUBDIRS( Launcher KernelHelpers SALOMEDS SALOMEDSImpl + SALOMESDS Utils UnitTests connect diff --git a/idl/SALOME_SDS.idl b/idl/SALOME_SDS.idl index 333dee788..a7bb219bd 100644 --- a/idl/SALOME_SDS.idl +++ b/idl/SALOME_SDS.idl @@ -57,17 +57,48 @@ module SALOME interface DataServerManager; - interface DataScopeServer + interface DataScopeServerBase { void ping(); string getScopeName(); StringVec listVars(); - BasicDataServer retrieveVar(in string varName) raises (SALOME::SALOME_Exception); + boolean existVar(in string varName) raises (SALOME::SALOME_Exception); void deleteVar(in string varName) raises (SALOME::SALOME_Exception); + void shutdownIfNotHostedByDSM(); + }; + + interface DataScopeServer : DataScopeServerBase + { + BasicDataServer retrieveVar(in string varName) raises (SALOME::SALOME_Exception); PickelizedPyObjRdOnlyServer createRdOnlyVar(in string varName, in ByteVec constValue) raises (SALOME::SALOME_Exception); PickelizedPyObjRdExtServer createRdExtVar(in string varName, in ByteVec constValue) raises (SALOME::SALOME_Exception); //PickelizedPyObjRdWrServer createRdWrVar(in string typeName, in string varName) raises (SALOME::SALOME_Exception); - void shutdownIfNotHostedByDSM(); + }; + + interface Transaction + { + }; + + 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); + Transaction addKeyValueInVarHard(in string varName, in ByteVec keyValue, in ByteVec constValue) raises (SALOME::SALOME_Exception); + Transaction addKeyValueInVarErrorIfAlreadyExisting(in string varName, in ByteVec keyValue, in ByteVec constValue) raises (SALOME::SALOME_Exception); + Transaction removeKeyInVarErrorIfNotAlreadyExisting(in string varName, in ByteVec keyValue) raises (SALOME::SALOME_Exception); + KeyWaiter waitForKeyInVar(in string varName, in ByteVec keyVal) raises (SALOME::SALOME_Exception); + KeyWaiter waitForKeyInVarAndKillIt(in string varName, in ByteVec keyVal, out Transaction transac) raises (SALOME::SALOME_Exception); + void atomicApply(in ListOfTransaction transactions) raises (SALOME::SALOME_Exception); + ByteVec waitForMonoThrRev(in KeyWaiter kw) raises (SALOME::SALOME_Exception); }; interface DataServerManager @@ -76,9 +107,14 @@ module SALOME StringVec listAliveAndKickingScopes() raises (SALOME::SALOME_Exception); DataScopeServer getDefaultScope() raises (SALOME::SALOME_Exception); boolean isAliveAndKicking(in string scopeName) raises (SALOME::SALOME_Exception); + // DataScopeServer createDataScope(in string scopeName) raises (SALOME::SALOME_Exception); - DataScopeServer retriveDataScope(in string scopeName) raises (SALOME::SALOME_Exception); DataScopeServer giveADataScopeCalled(in string scopeName, out boolean isCreated); + // + DataScopeServerTransaction createDataScopeTransaction(in string scopeName) raises (SALOME::SALOME_Exception); + DataScopeServerTransaction giveADataScopeTransactionCalled(in string scopeName, out boolean isCreated); + // + DataScopeServerBase retriveDataScope(in string scopeName) raises (SALOME::SALOME_Exception); void removeDataScope(in string scopeName) raises (SALOME::SALOME_Exception); void cleanScopesInNS(); void shutdownScopes() raises (SALOME::SALOME_Exception); diff --git a/src/SALOMESDS/CMakeLists.txt b/src/SALOMESDS/CMakeLists.txt index f049fb543..79ca214dc 100644 --- a/src/SALOMESDS/CMakeLists.txt +++ b/src/SALOMESDS/CMakeLists.txt @@ -44,6 +44,8 @@ SET(SalomeSDS_SOURCES SALOMESDS_PickelizedPyObjRdOnlyServer.cxx SALOMESDS_PickelizedPyObjRdExtServer.cxx SALOMESDS_PickelizedPyObjRdWrServer.cxx + SALOMESDS_Transaction.cxx + SALOMESDS_KeyWaiter.cxx ) ADD_LIBRARY(SalomeSDS ${SalomeSDS_SOURCES}) @@ -54,6 +56,9 @@ ADD_EXECUTABLE(SALOME_DataScopeServer SALOME_DataScopeServer.cxx) TARGET_LINK_LIBRARIES(SALOME_DataScopeServer SalomeSDS) INSTALL(TARGETS SALOME_DataScopeServer DESTINATION ${SALOME_INSTALL_BINS}) INSTALL(FILES SalomeSDSClt.py DESTINATION ${SALOME_INSTALL_BINS}) - FILE(GLOB COMMON_HEADERS_HXX "${CMAKE_CURRENT_SOURCE_DIR}/*.hxx") INSTALL(FILES ${COMMON_HEADERS_HXX} DESTINATION ${SALOME_INSTALL_HEADERS}) +# tests part +SET(LOCAL_TEST_DIR ${KERNEL_TEST_DIR}/SALOMESDS) +INSTALL(FILES TestSalomeSDS.py TestSalomeSDSHelper0.py DESTINATION ${LOCAL_TEST_DIR}) +INSTALL(FILES CTestTestfileInstall.cmake DESTINATION ${LOCAL_TEST_DIR} RENAME CTestTestfile.cmake) diff --git a/src/SALOMESDS/CTestTestfileInstall.cmake b/src/SALOMESDS/CTestTestfileInstall.cmake new file mode 100644 index 000000000..bb8894679 --- /dev/null +++ b/src/SALOMESDS/CTestTestfileInstall.cmake @@ -0,0 +1,23 @@ +# Copyright (C) 2015 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, 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 +# + +IF(NOT WIN32) + ADD_TEST(TestSalomeSDS python ${SALOME_TEST_DRIVER} ${TIMEOUT} TestSalomeSDS.py) + SET_TESTS_PROPERTIES(TestSalomeSDS PROPERTIES LABELS "${COMPONENT_NAME}" ENVIRONMENT "PYTHONPATH=${KERNEL_TEST_LIB}:$ENV{PYTHONPATH}") +ENDIF(NOT WIN32) diff --git a/src/SALOMESDS/SALOMESDS_AutoRefCountPtr.hxx b/src/SALOMESDS/SALOMESDS_AutoRefCountPtr.hxx index ce199141f..dcbe86335 100644 --- a/src/SALOMESDS/SALOMESDS_AutoRefCountPtr.hxx +++ b/src/SALOMESDS/SALOMESDS_AutoRefCountPtr.hxx @@ -23,8 +23,31 @@ #include "SALOMESDS_Exception.hxx" +#include "omniORB4/CORBA.h" + namespace SALOMESDS { + class POAHolder : public virtual PortableServer::ServantBase + { + public: + virtual PortableServer::POA_var getPOA() const = 0; + CORBA::Object_var activate() + { + PortableServer::POA_var poa(getPOA()); + PortableServer::ObjectId_var id(poa->activate_object(this)); + CORBA::Object_var ret(poa->id_to_reference(id)); + return ret; + } + + void enforcedRelease() + { + PortableServer::POA_var poa(getPOA()); + PortableServer::ObjectId_var oid(poa->servant_to_id(this)); + poa->deactivate_object(oid); + _remove_ref(); + } + }; + template class AutoRefCountPtr { @@ -73,6 +96,32 @@ namespace SALOMESDS ptr->incrRef(); return ret; } + + template// T is expected to be a POAHolder subclass + class AutoServantPtr + { + public: + AutoServantPtr(T *ptr=0):_ptr(ptr) { } + ~AutoServantPtr() { destroyPtr(); } + bool operator==(const AutoServantPtr& other) const { return _ptr==other._ptr; } + bool operator==(const T *other) const { return _ptr==other; } + AutoServantPtr &operator=(T *ptr) { if(_ptr!=ptr) { destroyPtr(); _ptr=ptr; } return *this; } + T *operator->() { return _ptr ; } + const T *operator->() const { return _ptr; } + T& operator*() { return *_ptr; } + const T& operator*() const { return *_ptr; } + operator T *() { return _ptr; } + operator const T *() const { return _ptr; } + private: + void destroyPtr() + { + if(!_ptr) + return; + _ptr->enforcedRelease(); + } + private: + T *_ptr; + }; } #endif diff --git a/src/SALOMESDS/SALOMESDS_BasicDataServer.cxx b/src/SALOMESDS/SALOMESDS_BasicDataServer.cxx index f72154b1f..e89fd1653 100644 --- a/src/SALOMESDS/SALOMESDS_BasicDataServer.cxx +++ b/src/SALOMESDS/SALOMESDS_BasicDataServer.cxx @@ -26,13 +26,24 @@ using namespace SALOMESDS; -BasicDataServer::BasicDataServer(DataScopeServer *father, const std::string& varName):_father(father),_var_name(varName) +BasicDataServer::BasicDataServer(DataScopeServerBase *father, const std::string& varName):_father(father),_var_name(varName) { + /*PortableServer::POA_var poa(_father->getPOA()); + PortableServer::POAManager_var pman(poa->the_POAManager()); + CORBA::Object_var obj(_father->getORB()->resolve_initial_references("RootPOA")); + PortableServer::POA_var rootPOA(PortableServer::POA::_narrow(obj)); + CORBA::PolicyList policies; + policies.length(1); + PortableServer::ThreadPolicy_var threadPol(rootPOA->create_thread_policy(PortableServer::SINGLE_THREAD_MODEL)); + policies[0]=PortableServer::ThreadPolicy::_duplicate(threadPol); + std::ostringstream poaName; poaName << "POA_" << POA_CNT++ << "_" << _var_name; + _poa=rootPOA->create_POA(poaName.str().c_str(),pman,policies); + threadPol->destroy();*/ } SALOME::DataScopeServer_ptr BasicDataServer::getMyDataScopeServer() { - CORBA::Object_var obj(getPOA()->servant_to_reference(_father)); + CORBA::Object_var obj(_father->getPOA()->servant_to_reference(_father)); return SALOME::DataScopeServer::_narrow(obj); } @@ -64,7 +75,7 @@ void BasicDataServer::Destroy() enforcedRelease(); } -PortableServer::POA_var BasicDataServer::getPOA() +PortableServer::POA_var BasicDataServer::getPOA() const { return _father->getPOA(); } diff --git a/src/SALOMESDS/SALOMESDS_BasicDataServer.hxx b/src/SALOMESDS/SALOMESDS_BasicDataServer.hxx index 5ceec0ada..7a22300ef 100644 --- a/src/SALOMESDS/SALOMESDS_BasicDataServer.hxx +++ b/src/SALOMESDS/SALOMESDS_BasicDataServer.hxx @@ -30,12 +30,12 @@ namespace SALOMESDS { - class DataScopeServer; + class DataScopeServerBase; class BasicDataServer : public RefCountServ, public virtual POA_SALOME::BasicDataServer { public: - BasicDataServer(DataScopeServer *father, const std::string& varName); + BasicDataServer(DataScopeServerBase *father, const std::string& varName); SALOME::DataScopeServer_ptr getMyDataScopeServer(); char *getVarName(); char *getScopeName(); @@ -44,11 +44,12 @@ namespace SALOMESDS void UnRegister(); void Destroy(); public: + DataScopeServerBase *getFather() const { return _father; } std::string getVarNameCpp() const { return _var_name; } protected: - PortableServer::POA_var getPOA(); + PortableServer::POA_var getPOA() const; protected: - DataScopeServer *_father; + DataScopeServerBase *_father; private: std::string _var_name; }; diff --git a/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx b/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx index 6fdeb890f..ee1f9e07b 100644 --- a/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx +++ b/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx @@ -23,6 +23,8 @@ #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" @@ -40,17 +42,17 @@ using namespace SALOMESDS; -std::size_t DataScopeServer::COUNTER=0; +std::size_t DataScopeServerBase::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) +DataScopeServerBase::DataScopeServerBase(CORBA::ORB_ptr orb, const std::string& scopeName):_globals(0),_locals(0),_pickler(0),_orb(CORBA::ORB::_duplicate(orb)),_name(scopeName) { } -DataScopeServer::DataScopeServer(const DataScopeServer& other):_globals(0),_locals(0),_pickler(0),_name(other._name),_vars(other._vars) +DataScopeServerBase::DataScopeServerBase(const DataScopeServerBase& other):_globals(0),_locals(0),_pickler(0),_name(other._name),_vars(other._vars) { } -DataScopeServer::~DataScopeServer() +DataScopeServerBase::~DataScopeServerBase() { // _globals is borrowed ref -> do nothing Py_XDECREF(_locals); @@ -60,14 +62,14 @@ DataScopeServer::~DataScopeServer() /*! * Called remotely -> to protect against throw */ -void DataScopeServer::ping() +void DataScopeServerBase::ping() { } /*! * Called remotely -> to protect against throw */ -char *DataScopeServer::getScopeName() +char *DataScopeServerBase::getScopeName() { return CORBA::string_dup(_name.c_str()); } @@ -75,7 +77,7 @@ char *DataScopeServer::getScopeName() /*! * Called remotely -> to protect against throw */ -SALOME::StringVec *DataScopeServer::listVars() +SALOME::StringVec *DataScopeServerBase::listVars() { SALOME::StringVec *ret(new SALOME::StringVec); std::size_t sz(_vars.size()); @@ -90,31 +92,35 @@ SALOME::StringVec *DataScopeServer::listVars() return ret; } -SALOME::BasicDataServer_ptr DataScopeServer::retrieveVar(const char *varName) +CORBA::Boolean DataScopeServerBase::existVar(const char *varName) { - std::string varNameCpp(varName); - std::vector allNames(getAllVarNames()); - std::vector::iterator it(std::find(allNames.begin(),allNames.end(),varNameCpp)); - if(it==allNames.end()) - { - std::ostringstream oss; oss << "DataScopeServer::retrieveVar : name \"" << varNameCpp << "\" does not exists ! Possibilities are :"; - std::copy(allNames.begin(),allNames.end(),std::ostream_iterator(oss,", ")); - 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()); - for(std::size_t i=0;i >::const_iterator it(_vars.begin()); + for(;it!=_vars.end();it++) + if((*it).second->getVarNameCpp()==varName) + return true; + return false; +} + +SALOME::BasicDataServer_ptr DataScopeServerBase::retrieveVarInternal(const char *varName) +{ + std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(retrieveVarInternal3(varName)); return SALOME::BasicDataServer::_duplicate((*it0).first); } -void DataScopeServer::deleteVar(const char *varName) +BasicDataServer *DataScopeServerBase::retrieveVarInternal2(const std::string& varName) +{ + std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(retrieveVarInternal3(varName)); + return (*it0).second; +} + +void DataScopeServerBase::deleteVar(const char *varName) { std::string varNameCpp(varName); std::vector allNames(getAllVarNames()); std::vector::iterator it(std::find(allNames.begin(),allNames.end(),varNameCpp)); if(it==allNames.end()) { - std::ostringstream oss; oss << "DataScopeServer::deleteVar : name \"" << varNameCpp << "\" does not exists ! Possibilities are :"; + std::ostringstream oss; oss << "DataScopeServerBase::deleteVar : name \"" << varNameCpp << "\" does not exists ! Possibilities are :"; std::copy(allNames.begin(),allNames.end(),std::ostream_iterator(oss,", ")); throw Exception(oss.str()); } @@ -124,43 +130,7 @@ void DataScopeServer::deleteVar(const char *varName) _vars.erase(it0); } -SALOME::PickelizedPyObjRdOnlyServer_ptr DataScopeServer::createRdOnlyVar(const char *varName, const SALOME::ByteVec& constValue) -{ - std::string varNameCpp(varName); - checkNotAlreadyExistingVar(varNameCpp); - PickelizedPyObjRdOnlyServer *tmp(new PickelizedPyObjRdOnlyServer(this,varNameCpp,constValue)); - CORBA::Object_var ret(activateWithDedicatedPOA(tmp)); - std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp); - _vars.push_back(p); - return SALOME::PickelizedPyObjRdOnlyServer::_narrow(ret); -} - -SALOME::PickelizedPyObjRdExtServer_ptr DataScopeServer::createRdExtVar(const char *varName, const SALOME::ByteVec& constValue) -{ - std::string varNameCpp(varName); - checkNotAlreadyExistingVar(varNameCpp); - PickelizedPyObjRdExtServer *tmp(new PickelizedPyObjRdExtServer(this,varNameCpp,constValue)); - CORBA::Object_var ret(activateWithDedicatedPOA(tmp)); - std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp); - _vars.push_back(p); - return SALOME::PickelizedPyObjRdExtServer::_narrow(ret); -} - -/*! - * Called remotely -> to protect against throw - */ -SALOME::PickelizedPyObjRdWrServer_ptr DataScopeServer::createRdWrVar(const char *typeName, const char *varName) -{ - std::string varNameCpp(varName),typeNameCpp(typeName); - checkNotAlreadyExistingVar(varNameCpp); - PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,typeNameCpp,varNameCpp)); - CORBA::Object_var ret(activateWithDedicatedPOA(tmp)); - std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp); - _vars.push_back(p); - return SALOME::PickelizedPyObjRdWrServer::_narrow(ret); -} - -void DataScopeServer::shutdownIfNotHostedByDSM() +void DataScopeServerBase::shutdownIfNotHostedByDSM() { SALOME_NamingService ns(_orb); CORBA::Object_var obj(ns.Resolve(DataServerManager::NAME_IN_NS)); @@ -182,15 +152,14 @@ void DataScopeServer::shutdownIfNotHostedByDSM() _orb->shutdown(0); else { - PortableServer::ObjectId_var oid(_poa->servant_to_id(this)); - _poa->deactivate_object(oid); - ret->_remove_ref(); + enforcedRelease(); } } -void DataScopeServer::initializePython(int argc, char *argv[]) +void DataScopeServerBase::initializePython(int argc, char *argv[]) { Py_Initialize(); + PyEval_InitThreads(); PySys_SetArgv(argc,argv); PyObject *mainmod(PyImport_AddModule("__main__")); _globals=PyModule_GetDict(mainmod); @@ -206,7 +175,7 @@ void DataScopeServer::initializePython(int argc, char *argv[]) _pickler=PyImport_ImportModuleLevel(const_cast("cPickle"),_globals,_locals,tmp,-1); } -void DataScopeServer::registerToSalomePiDict() const +void DataScopeServerBase::registerToSalomePiDict() const { PyObject *mod(PyImport_ImportModule("addToKillList")); if(!mod) @@ -216,32 +185,33 @@ void DataScopeServer::registerToSalomePiDict() const { Py_XDECREF(mod); return ; } PyObject *args(PyTuple_New(2)); PyTuple_SetItem(args,0,PyInt_FromLong(getpid())); - PyTuple_SetItem(args,1,PyString_FromString("SALOME_DataScopeServer")); + PyTuple_SetItem(args,1,PyString_FromString("SALOME_DataScopeServerBase")); PyObject *res(PyObject_CallObject(meth,args)); Py_XDECREF(args); Py_XDECREF(res); Py_XDECREF(mod); } -/*! - * \a ptr has been activated by the POA \a poa. - */ -void DataScopeServer::setPOAAndRegister(PortableServer::POA_var poa, SALOME::DataScopeServer_ptr ptr) +void DataScopeServerBase::setPOA(PortableServer::POA_var poa) { _poa=poa; +} + +void DataScopeServerBase::registerInNS(SALOME::DataScopeServerBase_ptr ptr) +{ std::string fullScopeName(SALOMESDS::DataServerManager::CreateAbsNameInNSFromScopeName(_name)); SALOME_NamingService ns(_orb); ns.Register(ptr,fullScopeName.c_str()); } -std::string DataScopeServer::BuildTmpVarNameFrom(const std::string& varName) +std::string DataScopeServerBase::BuildTmpVarNameFrom(const std::string& varName) { std::ostringstream oss; oss << varName << "@" << COUNTER++; return oss.str(); } -std::vector< std::string > DataScopeServer::getAllVarNames() const +std::vector< std::string > DataScopeServerBase::getAllVarNames() const { std::size_t sz(_vars.size()); std::vector ret(sz); @@ -251,20 +221,402 @@ std::vector< std::string > DataScopeServer::getAllVarNames() const return ret; } -CORBA::Object_var DataScopeServer::activateWithDedicatedPOA(BasicDataServer *ds) +void DataScopeServerBase::checkNotAlreadyExistingVar(const std::string& varName) const { - PortableServer::ObjectId_var id(_poa->activate_object(ds)); - CORBA::Object_var ret(_poa->id_to_reference(id)); + std::vector allNames(getAllVarNames()); + std::vector::iterator it(std::find(allNames.begin(),allNames.end(),varName)); + if(it!=allNames.end()) + { + std::ostringstream oss; oss << "DataScopeServerBase::checkNotAlreadyExistingVar : name \"" << varName << "\" already exists !"; + throw Exception(oss.str()); + } +} + +void DataScopeServerBase::checkExistingVar(const std::string& varName) const +{ + std::vector allNames(getAllVarNames()); + std::vector::iterator it(std::find(allNames.begin(),allNames.end(),varName)); + if(it==allNames.end()) + { + std::ostringstream oss; oss << "DataScopeServerBase::checkExistingVar : name \"" << varName << "\" does not exist !"; + throw Exception(oss.str()); + } +} + +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; } -void DataScopeServer::checkNotAlreadyExistingVar(const std::string& varName) +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)); - if(it!=allNames.end()) + if(it==allNames.end()) { - std::ostringstream oss; oss << "DataScopeServer::checkNotAlreadyExistingVar : name \"" << varName << "\" already exists !"; + std::ostringstream oss; oss << "DataScopeServerBase::retrieveVarInternal : name \"" << varName << "\" does not exists ! Possibilities are :"; + std::copy(allNames.begin(),allNames.end(),std::ostream_iterator(oss,", ")); throw Exception(oss.str()); } + std::size_t pos(std::distance(allNames.begin(),it)); + std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(_vars.begin()); + for(std::size_t i=0;iactivate()); + std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp); + _vars.push_back(p); + return SALOME::PickelizedPyObjRdOnlyServer::_narrow(ret); +} + +SALOME::PickelizedPyObjRdExtServer_ptr DataScopeServer::createRdExtVar(const char *varName, const SALOME::ByteVec& constValue) +{ + std::string varNameCpp(varName); + checkNotAlreadyExistingVar(varNameCpp); + PickelizedPyObjRdExtServer *tmp(new PickelizedPyObjRdExtServer(this,varNameCpp,constValue)); + CORBA::Object_var ret(tmp->activate()); + std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp); + _vars.push_back(p); + return SALOME::PickelizedPyObjRdExtServer::_narrow(ret); } + +/*! + * Called remotely -> to protect against throw + */ +SALOME::PickelizedPyObjRdWrServer_ptr DataScopeServer::createRdWrVar(const char *typeName, const char *varName) +{ + std::string varNameCpp(varName),typeNameCpp(typeName); + checkNotAlreadyExistingVar(varNameCpp); + PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,typeNameCpp,varNameCpp)); + CORBA::Object_var ret(tmp->activate()); + std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp); + _vars.push_back(p); + return SALOME::PickelizedPyObjRdWrServer::_narrow(ret); +} + +DataScopeServer::~DataScopeServer() +{ +} + +//////// + +DataScopeServerTransaction::DataScopeServerTransaction(CORBA::ORB_ptr orb, const std::string& scopeName):DataScopeServerBase(orb,scopeName) +{ + CORBA::Object_var obj(_orb->resolve_initial_references("RootPOA")); + PortableServer::POA_var poa(PortableServer::POA::_narrow(obj)); + // + PortableServer::POAManager_var mgr(poa->the_POAManager()); + CORBA::PolicyList policies; + policies.length(1); + PortableServer::ThreadPolicy_var threadPol(poa->create_thread_policy(PortableServer::ORB_CTRL_MODEL)); + policies[0]=PortableServer::ThreadPolicy::_duplicate(threadPol); + PortableServer::POA_var poa2(poa->create_POA("POAForWaiters",mgr,policies)); + threadPol->destroy(); + // + _poa_for_key_waiter=poa2; +} + +DataScopeServerTransaction::DataScopeServerTransaction(const DataScopeServerTransaction& other):DataScopeServerBase(other),_poa_for_key_waiter(other.getPOA4KeyWaiter()) +{ +} + +void DataScopeServerTransaction::createRdOnlyVarInternal(const std::string& varName, const SALOME::ByteVec& constValue) +{ + checkNotAlreadyExistingVar(varName); + PickelizedPyObjRdOnlyServer *tmp(new PickelizedPyObjRdOnlyServer(this,varName,constValue)); + CORBA::Object_var ret(tmp->activate()); + std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp); + _vars.push_back(p); +} + +void DataScopeServerTransaction::createRdExtVarInternal(const std::string& varName, const SALOME::ByteVec& constValue) +{ + checkNotAlreadyExistingVar(varName); + PickelizedPyObjRdExtServer *tmp(new PickelizedPyObjRdExtServer(this,varName,constValue)); + CORBA::Object_var ret(tmp->activate()); + std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp); + _vars.push_back(p); +} + +void DataScopeServerTransaction::createRdWrVarInternal(const std::string& varName, const SALOME::ByteVec& constValue) +{ + checkNotAlreadyExistingVar(varName); + PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,varName,constValue)); + CORBA::Object_var ret(tmp->activate()); + std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp); + _vars.push_back(p); +} + +SALOME::ByteVec *DataScopeServerTransaction::fetchSerializedContent(const char *varName) +{ + BasicDataServer *var(retrieveVarInternal2(varName)); + PickelizedPyObjServer *varc(dynamic_cast(var)); + if(!varc) + { + std::ostringstream oss; oss << "DataScopeServerTransaction::fetchSerializedContent : var \"" << varName << "\"exists but it is not serialized !"; + throw Exception(oss.str()); + } + return varc->fetchSerializedContent(); +} + +SALOME::Transaction_ptr DataScopeServerTransaction::createRdOnlyVarTransac(const char *varName, const SALOME::ByteVec& constValue) +{ + checkNotAlreadyExistingVar(varName); + TransactionRdOnlyVarCreate *ret(new TransactionRdOnlyVarCreate(this,varName,constValue)); + 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)); + 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)); + CORBA::Object_var obj(ret->activate()); + return SALOME::Transaction::_narrow(obj); +} + +void DataScopeServerTransaction::addWaitKey(KeyWaiter *kw) +{ + if(!kw) + throw Exception("DataScopeServerTransaction::addWaitKey : NULL input object !"); + _waiting_keys.push_back(kw); +} + +void DataScopeServerTransaction::pingKey(PyObject *keyObj) +{ + PyObject *cmpObj(getPyCmpFunc()); + if(!keyObj) + throw Exception("ataScopeServerTransaction::pingKey : Key Object is NULL !"); + PyObject *args(PyTuple_New(2)); + PyTuple_SetItem(args,0,keyObj); Py_XINCREF(keyObj); + std::size_t ii(0); + // this part does nothing except to be sure that in notify key all will be OK. + for(std::list< KeyWaiter *>::iterator it=_waiting_keys.begin();it!=_waiting_keys.end();it++,ii++) + { + PyObject *waitKey((*it)->getKeyPyObj()); + PyTuple_SetItem(args,1,waitKey); Py_XINCREF(waitKey); + PyObject *res(PyObject_CallObject(cmpObj,args)); + if(res==NULL) + { + std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " error during cmp(k,wk[i]) !"; + throw Exception(oss.str()); + } + PyInt_AsLong(res); + if(PyErr_Occurred()) + { + std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " error during interpretation of cmp(k,wk[i]) !"; + throw Exception(oss.str()); + } + Py_XDECREF(res); + } +} + +void DataScopeServerTransaction::notifyKey(PyObject *keyObj, PyObject *valueObj) +{ + PyObject *cmpObj(getPyCmpFunc()); + if(!keyObj) + throw Exception("DataScopeServerTransaction::notifyKey : MAIN INTERNAL ERROR ! Key Object is NULL !"); + PyObject *args(PyTuple_New(2)); + PyTuple_SetItem(args,0,keyObj); Py_XINCREF(keyObj); + std::size_t ii(0); + std::list< KeyWaiter *> newList,listOfEltToWakeUp; + for(std::list< KeyWaiter *>::iterator it=_waiting_keys.begin();it!=_waiting_keys.end();it++,ii++) + { + PyObject *waitKey((*it)->getKeyPyObj()); + PyTuple_SetItem(args,1,waitKey); Py_XINCREF(waitKey); + PyObject *res(PyObject_CallObject(cmpObj,args)); + if(res==NULL) + { + std::ostringstream oss; oss << "DataScopeServerTransaction::notifyKey : MAIN INTERNAL ERROR ! for object id #" << ii << " error during cmp(k,wk[i]) !"; + throw Exception(oss.str()); + } + long resCpp(PyInt_AsLong(res)); + if(PyErr_Occurred()) + { + std::ostringstream oss; oss << "DataScopeServerTransaction::notifyKey : MAIN INTERNAL ERROR ! for object id #" << ii << " error during interpretation of cmp(k,wk[i]) !"; + throw Exception(oss.str()); + } + Py_XDECREF(res); + if(resCpp==0) + listOfEltToWakeUp.push_back(*it); + else + newList.push_back(*it); + } + for(std::list< KeyWaiter *>::iterator it=listOfEltToWakeUp.begin();it!=listOfEltToWakeUp.end();it++) + (*it)->valueJustCome(valueObj); + for(std::list< KeyWaiter *>::iterator it=listOfEltToWakeUp.begin();it!=listOfEltToWakeUp.end();it++) + (*it)->go(); + _waiting_keys=newList; +} + +SALOME::Transaction_ptr DataScopeServerTransaction::addKeyValueInVarHard(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value) +{ + checkVarExistingAndDict(varName); + TransactionAddKeyValueHard *ret(new TransactionAddKeyValueHard(this,varName,key,value)); + CORBA::Object_var obj(ret->activate()); + return SALOME::Transaction::_narrow(obj); +} + +SALOME::Transaction_ptr DataScopeServerTransaction::addKeyValueInVarErrorIfAlreadyExisting(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value) +{ + checkVarExistingAndDict(varName); + TransactionAddKeyValueErrorIfAlreadyExisting *ret(new TransactionAddKeyValueErrorIfAlreadyExisting(this,varName,key,value)); + CORBA::Object_var obj(ret->activate()); + return SALOME::Transaction::_narrow(obj); +} + +SALOME::Transaction_ptr DataScopeServerTransaction::removeKeyInVarErrorIfNotAlreadyExisting(const char *varName, const SALOME::ByteVec& key) +{ + checkVarExistingAndDict(varName); + TransactionRemoveKeyInVarErrorIfNotAlreadyExisting *ret(new TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(this,varName,key)); + CORBA::Object_var obj(ret->activate()); + return SALOME::Transaction::_narrow(obj); +} + +SALOME::KeyWaiter_ptr DataScopeServerTransaction::waitForKeyInVar(const char *varName, const SALOME::ByteVec& keyVal) +{ + PickelizedPyObjServer *pickelObj(checkVarExistingAndDict(varName)); + KeyWaiter *ret(new KeyWaiter(pickelObj,keyVal)); + CORBA::Object_var obj(ret->activate());//KeyWaiter instance activated inside a multithread POA contrary to all of objects in SALOMESDS in single thread ! + return SALOME::KeyWaiter::_narrow(obj); +} + +SALOME::KeyWaiter_ptr DataScopeServerTransaction::waitForKeyInVarAndKillIt(const char *varName, const SALOME::ByteVec& keyVal, SALOME::Transaction_out transac) +{ + PickelizedPyObjServer *pickelObj(checkVarExistingAndDict(varName)); + KeyWaiter *ret0(new KeyWaiter(pickelObj,keyVal)); + CORBA::Object_var obj(ret0->activate());//KeyWaiter instance activated inside a multithread POA contrary to all of objects in SALOMESDS in single thread ! + // + TransactionRemoveKeyInVarErrorIfNotAlreadyExisting *ret1(new TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(this,varName,keyVal)); + CORBA::Object_var obj2(ret1->activate()); + transac=SALOME::Transaction::_narrow(obj2); + // + return SALOME::KeyWaiter::_narrow(obj); +} + +SALOME::ByteVec *DataScopeServerTransaction::waitForMonoThrRev(SALOME::KeyWaiter_ptr kw) +{ + PortableServer::ServantBase *ret(0); + try + { + ret=_poa_for_key_waiter->reference_to_servant(kw); + } + catch(...) { ret=0; } + KeyWaiter *retc(dynamic_cast(ret)); + if(!retc) + throw Exception("DataScopeServerTransaction::invokeMonoThr : internal error 1 !"); + retc->_remove_ref(); + retc->waitForMonoThr(); +} + +class TrustTransaction +{ +public: + TrustTransaction():_must_rollback(0),_ptr(0) { } + void setTransaction(Transaction *t, bool *mustRollback) { if(!t || !mustRollback) throw Exception("TrustTransaction Error #1"); _ptr=t; _must_rollback=mustRollback; _ptr->prepareRollBackInCaseOfFailure(); } + void operate() { _ptr->perform(); } + ~TrustTransaction() { if(!_ptr) return ; if(*_must_rollback) _ptr->rollBack(); } +private: + bool *_must_rollback; + Transaction *_ptr; +}; + +void DataScopeServerTransaction::atomicApply(const SALOME::ListOfTransaction& transactions) +{ + std::size_t sz(transactions.length()); + if(sz==0) + return ; + std::vector< AutoServantPtr > transactionsCpp(sz); + for(std::size_t i=0;ireference_to_servant(transactions[i]); + elt=dynamic_cast(eltBase); + } + catch(...) + { + std::ostringstream oss; oss << "DataScopeServerTransaction::atomicApply : the elt #" << i << " is invalid !"; + throw Exception(oss.str()); + } + if(!elt) + { + std::ostringstream oss; oss << "DataScopeServerTransaction::atomicApply : the elt #" << i << " is null ?"; + throw Exception(oss.str()); + } + elt->_remove_ref(); + transactionsCpp[i]=elt; + } + {// important do not merge loops ! + std::vector transactions2(sz); + bool mustRollback(true); + for(std::size_t i=0;inotify(); +} + +/*! + * Returns borrowed reference. + */ +PyObject *DataScopeServerTransaction::getPyCmpFunc() +{ + PyObject *builtins(PyDict_GetItemString(_globals,"__builtins__"));//borrowed + if(builtins==NULL) + throw Exception("Fail to find reference to builtins !"); + PyObject *builtins2(PyModule_GetDict(builtins));//borrowed + if(builtins2==NULL) + throw Exception("Fail to invoke __dict__ on builtins !"); + PyObject *cmpObj(PyDict_GetItemString(builtins2,"cmp")); + if(cmpObj==NULL) + throw Exception("Fail to find cmp in __builtins__ !"); + return cmpObj; +} + +DataScopeServerTransaction::~DataScopeServerTransaction() +{ +} + diff --git a/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx b/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx index 7cf7f6d6d..db76fbf41 100644 --- a/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx +++ b/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx @@ -37,35 +37,43 @@ namespace SALOMESDS { - class SALOMESDS_EXPORT DataScopeServer : public virtual POA_SALOME::DataScopeServer + class KeyWaiter; + class PickelizedPyObjServer; + + class SALOMESDS_EXPORT DataScopeServerBase : public virtual POA_SALOME::DataScopeServerBase, public POAHolder { public: - DataScopeServer(CORBA::ORB_ptr orb, const std::string& scopeName); - DataScopeServer(const DataScopeServer& other); + DataScopeServerBase(CORBA::ORB_ptr orb, const std::string& scopeName); + DataScopeServerBase(const DataScopeServerBase& other); void ping(); char *getScopeName(); SALOME::StringVec *listVars(); - SALOME::BasicDataServer_ptr retrieveVar(const char *varName); + CORBA::Boolean existVar(const char *varName); + SALOME::BasicDataServer_ptr retrieveVarInternal(const char *varName); + BasicDataServer *retrieveVarInternal2(const std::string& varName); void deleteVar(const char *varName); - SALOME::PickelizedPyObjRdOnlyServer_ptr createRdOnlyVar(const char *varName, const SALOME::ByteVec& constValue); - SALOME::PickelizedPyObjRdExtServer_ptr createRdExtVar(const char *varName, const SALOME::ByteVec& constValue); - SALOME::PickelizedPyObjRdWrServer_ptr createRdWrVar(const char *typeName, const char *varName); void shutdownIfNotHostedByDSM(); - ~DataScopeServer(); + ~DataScopeServerBase(); public: void initializePython(int argc, char *argv[]); void registerToSalomePiDict() const; - void setPOAAndRegister(PortableServer::POA_var poa, SALOME::DataScopeServer_ptr ptr); + void setPOA(PortableServer::POA_var poa); + void registerInNS(SALOME::DataScopeServerBase_ptr ptr); PyObject *getGlobals() const { return _globals; } PyObject *getLocals() const { return _locals; } PyObject *getPickler() const { return _pickler; } - PortableServer::POA_var getPOA() { return _poa; } + PortableServer::POA_var getPOA() const { return _poa; } + CORBA::ORB_var getORB() { return _orb; } + std::string getScopeNameCpp() const { return _name; } static std::string BuildTmpVarNameFrom(const std::string& varName); - private: + public: std::vector< std::string> getAllVarNames() const; - CORBA::Object_var activateWithDedicatedPOA(BasicDataServer *ds); - void checkNotAlreadyExistingVar(const std::string& varName); - private: + 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 * > >::const_iterator retrieveVarInternal3(const std::string& varName) const; + protected: PyObject *_globals; PyObject *_locals; PyObject *_pickler; @@ -75,6 +83,50 @@ namespace SALOMESDS std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > > _vars; static std::size_t COUNTER; }; + + class SALOMESDS_EXPORT DataScopeServer : public DataScopeServerBase, public virtual POA_SALOME::DataScopeServer + { + public: + DataScopeServer(CORBA::ORB_ptr orb, const std::string& scopeName); + DataScopeServer(const DataScopeServer& other); + SALOME::BasicDataServer_ptr retrieveVar(const char *varName) { return retrieveVarInternal(varName); } + SALOME::PickelizedPyObjRdOnlyServer_ptr createRdOnlyVar(const char *varName, const SALOME::ByteVec& constValue); + SALOME::PickelizedPyObjRdExtServer_ptr createRdExtVar(const char *varName, const SALOME::ByteVec& constValue); + SALOME::PickelizedPyObjRdWrServer_ptr createRdWrVar(const char *typeName, const char *varName); + ~DataScopeServer(); + }; + + class SALOMESDS_EXPORT DataScopeServerTransaction : public DataScopeServerBase, public virtual POA_SALOME::DataScopeServerTransaction + { + public://not remotely callable + DataScopeServerTransaction(CORBA::ORB_ptr orb, const std::string& scopeName); + DataScopeServerTransaction(const DataScopeServerTransaction& other); + ~DataScopeServerTransaction(); + 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; } + void addWaitKey(KeyWaiter *kw); + void pingKey(PyObject *keyObj); + void notifyKey(PyObject *keyObj, PyObject *valueObj); + SALOME::ByteVec *waitForMonoThrRev(SALOME::KeyWaiter_ptr kw); + 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::Transaction_ptr addKeyValueInVarErrorIfAlreadyExisting(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value); + SALOME::Transaction_ptr removeKeyInVarErrorIfNotAlreadyExisting(const char *varName, const SALOME::ByteVec& key); + SALOME::KeyWaiter_ptr waitForKeyInVar(const char *varName, const SALOME::ByteVec& keyVal); + SALOME::KeyWaiter_ptr waitForKeyInVarAndKillIt(const char *varName, const SALOME::ByteVec& keyVal, SALOME::Transaction_out transac); + void atomicApply(const SALOME::ListOfTransaction& transactions); + private: + PyObject *getPyCmpFunc(); + private: + PortableServer::POA_var _poa_for_key_waiter; + std::list< KeyWaiter * > _waiting_keys; + }; } #endif diff --git a/src/SALOMESDS/SALOMESDS_DataServerManager.cxx b/src/SALOMESDS/SALOMESDS_DataServerManager.cxx index 08e4954b3..326adefe1 100644 --- a/src/SALOMESDS/SALOMESDS_DataServerManager.cxx +++ b/src/SALOMESDS/SALOMESDS_DataServerManager.cxx @@ -53,10 +53,10 @@ DataServerManager::DataServerManager(int argc, char *argv[], CORBA::ORB_ptr orb, SALOME_NamingService ns(orb); ns.Register(obj2,NAME_IN_NS); // the default DataScopeServer object is the only one hosted by the current process - id=_poa->activate_object(dftScope); - obj=_poa->id_to_reference(id); + dftScope->setPOA(_poa); + obj=dftScope->activate(); SALOME::DataScopeServer_var dftScopePtr(SALOME::DataScopeServer::_narrow(obj)); - dftScope->setPOAAndRegister(_poa,dftScopePtr);// agy : Very important ! invoke this method BEFORE activation ! Because this method initializes Python ! + dftScope->registerInNS(dftScopePtr);// agy : Very important ! invoke this method BEFORE activation ! Because this method initializes Python ! } SALOME::StringVec *DataServerManager::listScopes() @@ -91,87 +91,140 @@ SALOME::StringVec *DataServerManager::listAliveAndKickingScopes() SALOME::DataScopeServer_ptr DataServerManager::getDefaultScope() { - return retriveDataScope(DFT_SCOPE_NAME_IN_NS); + SALOME::DataScopeServerBase_var ret(retriveDataScope(DFT_SCOPE_NAME_IN_NS)); + if(CORBA::is_nil(ret)) + return SALOME::DataScopeServer::_narrow(ret); + SALOME::DataScopeServer_ptr ret2(SALOME::DataScopeServer::_narrow(ret)); + if(CORBA::is_nil(ret2)) + throw Exception("DataServerManager::getDefaultScope : exists but has not expected sub type !"); + return ret2; } CORBA::Boolean DataServerManager::isAliveAndKicking(const char *scopeName) { - SALOME::DataScopeServer_var scopePtr(getScopePtrGivenName(scopeName)); - CORBA::Boolean ret(true); - try - { - scopePtr->ping(); - } - catch(...) - { ret=false; } - return ret; + SALOME::DataScopeServerBase_var scopePtr(getScopePtrGivenName(scopeName)); + return IsAliveAndKicking(scopePtr); } -SALOME::DataScopeServer_ptr DataServerManager::createDataScope(const char *scopeName) +template +typename T::PtrType CreateDataScope(const std::string& scopeName, const std::vector& scopes, SALOME_NamingService& ns) { - std::string scopeNameCpp(scopeName); - std::vector scopes(listOfScopesCpp()); - if(std::find(scopes.begin(),scopes.end(),scopeNameCpp)!=scopes.end()) + int isTransactionInt(T::IsTransaction); + if(std::find(scopes.begin(),scopes.end(),scopeName)!=scopes.end()) { std::ostringstream oss; oss << "DataServerManager::createDataScope : scope name \"" << scopeName << "\" already exists !"; throw Exception(oss.str()); } // - SALOME_NamingService ns(_orb); - std::string fullScopeName(CreateAbsNameInNSFromScopeName(scopeName)); - std::ostringstream oss; oss << "SALOME_DataScopeServer" << " " << scopeName << " "; + std::string fullScopeName(DataServerManager::CreateAbsNameInNSFromScopeName(scopeName)); + std::ostringstream oss; oss << "SALOME_DataScopeServer" << " " << scopeName << " " << isTransactionInt << " "; SALOME_ContainerManager::AddOmninamesParams(oss,&ns); std::string command(oss.str()); SALOME_ContainerManager::MakeTheCommandToBeLaunchedASync(command); int status(SALOME_ContainerManager::SystemThreadSafe(command.c_str())); int count(SALOME_ContainerManager::GetTimeOutToLoaunchServer()); - SALOME::DataScopeServer_var ret(SALOME::DataScopeServer::_nil()); + typename T::VarType ret(T::nil()); while (CORBA::is_nil(ret) && count) { SALOME_ContainerManager::SleepInSecond(1); count--; CORBA::Object_var obj(ns.Resolve(fullScopeName.c_str())); - ret=SALOME::DataScopeServer::_narrow(obj); + ret=T::narrow(obj); } - return SALOME::DataScopeServer::_duplicate(ret); + return T::duplicate(ret); } -SALOME::DataScopeServer_ptr DataServerManager::giveADataScopeCalled(const char *scopeName, CORBA::Boolean& isCreated) +template +typename T::PtrType GiveADataScopeCalled(const std::string& scopeName, const std::vector& scopes, SALOME_NamingService& ns, CORBA::Boolean& isCreated) { - std::string scopeNameCpp(scopeName); - std::vector scopes(listOfScopesCpp()); - if(std::find(scopes.begin(),scopes.end(),scopeNameCpp)==scopes.end()) + if(std::find(scopes.begin(),scopes.end(),scopeName)==scopes.end()) { isCreated=true; - return createDataScope(scopeName); + return CreateDataScope(scopeName,scopes,ns); } else { - if(isAliveAndKicking(scopeName)) + SALOME::DataScopeServerBase_var ret(SALOMESDS::DataServerManager::GetScopePtrGivenName(scopeName,scopes,ns)); + if(SALOMESDS::DataServerManager::IsAliveAndKicking(ret)) { isCreated=false; - return retriveDataScope(scopeName); + typename T::PtrType ret2(T::narrow(ret)); + if(CORBA::is_nil(ret)) + return ret2; + if(CORBA::is_nil(ret2)) + { + std::ostringstream oss; oss << "DataServerManager::giveADataScopeCalled : scope \"" << scopeName << "\" exists but with invalid type !"; + throw Exception(oss.str()); + } + return ret2; } else { - SALOME_NamingService ns(_orb); - std::string fullScopeName(SALOMESDS::DataServerManager::CreateAbsNameInNSFromScopeName(scopeNameCpp)); + std::string fullScopeName(SALOMESDS::DataServerManager::CreateAbsNameInNSFromScopeName(scopeName)); ns.Destroy_Name(fullScopeName.c_str()); isCreated=true; - return createDataScope(scopeName); + return CreateDataScope(scopeName,scopes,ns); } } } -SALOME::DataScopeServer_ptr DataServerManager::retriveDataScope(const char *scopeName) +class NormalFunctor +{ +public: + typedef SALOME::DataScopeServer_ptr PtrType; + typedef SALOME::DataScopeServer_var VarType; + typedef SALOME::DataScopeServer TheType; + static const bool IsTransaction=false; + static PtrType nil() { return SALOME::DataScopeServer::_nil(); } + static PtrType narrow(CORBA::Object_ptr obj) { return SALOME::DataScopeServer::_narrow(obj); } + static PtrType duplicate(PtrType obj) { return SALOME::DataScopeServer::_duplicate(obj); } +}; + +class TransactionFunctor +{ +public: + typedef SALOME::DataScopeServerTransaction_ptr PtrType; + typedef SALOME::DataScopeServerTransaction_var VarType; + typedef SALOME::DataScopeServerTransaction TheType; + static const bool IsTransaction=true; + static PtrType nil() { return SALOME::DataScopeServerTransaction::_nil(); } + static PtrType narrow(CORBA::Object_ptr obj) { return SALOME::DataScopeServerTransaction::_narrow(obj); } + static PtrType duplicate(PtrType obj) { return SALOME::DataScopeServerTransaction::_duplicate(obj); } +}; + +SALOME::DataScopeServer_ptr DataServerManager::createDataScope(const char *scopeName) +{ + SALOME_NamingService ns(_orb); + return CreateDataScope(scopeName,listOfScopesCpp(),ns); +} + +SALOME::DataScopeServer_ptr DataServerManager::giveADataScopeCalled(const char *scopeName, CORBA::Boolean& isCreated) +{ + SALOME_NamingService ns(_orb); + return GiveADataScopeCalled(scopeName,listOfScopesCpp(),ns,isCreated); +} + +SALOME::DataScopeServerTransaction_ptr DataServerManager::createDataScopeTransaction(const char *scopeName) +{ + SALOME_NamingService ns(_orb); + return CreateDataScope(scopeName,listOfScopesCpp(),ns); +} + +SALOME::DataScopeServerTransaction_ptr DataServerManager::giveADataScopeTransactionCalled(const char *scopeName, CORBA::Boolean& isCreated) +{ + SALOME_NamingService ns(_orb); + return GiveADataScopeCalled(scopeName,listOfScopesCpp(),ns,isCreated); +} + +SALOME::DataScopeServerBase_ptr DataServerManager::retriveDataScope(const char *scopeName) { - SALOME::DataScopeServer_var ret(getScopePtrGivenName(scopeName)); - return SALOME::DataScopeServer::_duplicate(ret); + SALOME::DataScopeServerBase_var ret(getScopePtrGivenName(scopeName)); + return SALOME::DataScopeServerBase::_duplicate(ret); } void DataServerManager::removeDataScope(const char *scopeName) { - SALOME::DataScopeServer_var scs(getScopePtrGivenName(scopeName)); + SALOME::DataScopeServerBase_var scs(getScopePtrGivenName(scopeName)); scs->shutdownIfNotHostedByDSM(); } @@ -202,6 +255,18 @@ std::string DataServerManager::CreateAbsNameInNSFromScopeName(const std::string& return oss.str(); } +CORBA::Boolean DataServerManager::IsAliveAndKicking(SALOME::DataScopeServerBase_ptr scopePtr) +{ + CORBA::Boolean ret(true); + try + { + scopePtr->ping(); + } + catch(...) + { ret=false; } + return ret; +} + std::vector DataServerManager::listOfScopesCpp() { SALOME_NamingService ns(_orb); @@ -210,18 +275,22 @@ std::vector DataServerManager::listOfScopesCpp() return ret; } -SALOME::DataScopeServer_var DataServerManager::getScopePtrGivenName(const std::string& scopeName) +SALOME::DataScopeServerBase_var DataServerManager::GetScopePtrGivenName(const std::string& scopeName, const std::vector& scopes, SALOME_NamingService& ns) { - std::vector scopes(listOfScopesCpp()); std::size_t sz(scopes.size()); if(std::find(scopes.begin(),scopes.end(),scopeName)==scopes.end()) { std::ostringstream oss; oss << "DataServerManager::getScopePtrGivenName : scope name \"" << scopeName << "\" does not exist !"; throw Exception(oss.str()); } - SALOME_NamingService ns(_orb); std::string fullScopeName(CreateAbsNameInNSFromScopeName(scopeName)); CORBA::Object_var obj(ns.Resolve(fullScopeName.c_str())); - SALOME::DataScopeServer_var ret(SALOME::DataScopeServer::_narrow(obj)); + SALOME::DataScopeServerBase_var ret(SALOME::DataScopeServerBase::_narrow(obj)); return ret; } + +SALOME::DataScopeServerBase_var DataServerManager::getScopePtrGivenName(const std::string& scopeName) +{ + SALOME_NamingService ns(_orb); + return GetScopePtrGivenName(scopeName,listOfScopesCpp(),ns); +} diff --git a/src/SALOMESDS/SALOMESDS_DataServerManager.hxx b/src/SALOMESDS/SALOMESDS_DataServerManager.hxx index 944efc8c6..d9ad2caed 100644 --- a/src/SALOMESDS/SALOMESDS_DataServerManager.hxx +++ b/src/SALOMESDS/SALOMESDS_DataServerManager.hxx @@ -31,10 +31,12 @@ #include +class SALOME_NamingService; + namespace SALOMESDS { class DataScopeServer; - + class SALOMESDS_EXPORT DataServerManager : public virtual POA_SALOME::DataServerManager { public: @@ -43,19 +45,28 @@ namespace SALOMESDS SALOME::StringVec *listAliveAndKickingScopes(); SALOME::DataScopeServer_ptr getDefaultScope(); CORBA::Boolean isAliveAndKicking(const char *scopeName); + SALOME::DataScopeServerBase_ptr retriveDataScope(const char *scopeName); + // SALOME::DataScopeServer_ptr createDataScope(const char *scopeName); - SALOME::DataScopeServer_ptr retriveDataScope(const char *scopeName); SALOME::DataScopeServer_ptr giveADataScopeCalled(const char *scopeName, CORBA::Boolean& isCreated); + // + SALOME::DataScopeServerTransaction_ptr createDataScopeTransaction(const char *scopeName); + SALOME::DataScopeServerTransaction_ptr giveADataScopeTransactionCalled(const char *scopeName, CORBA::Boolean& isCreated); + // void removeDataScope(const char *scopeName); void cleanScopesInNS(); void shutdownScopes(); + public: + CORBA::ORB_var getORB() { return _orb; } static std::string CreateAbsNameInNSFromScopeName(const std::string& scopeName); + static CORBA::Boolean IsAliveAndKicking(SALOME::DataScopeServerBase_ptr scopePtr); + static SALOME::DataScopeServerBase_var GetScopePtrGivenName(const std::string& scopeName, const std::vector& scopes, SALOME_NamingService& ns); public: static const char NAME_IN_NS[]; static const char DFT_SCOPE_NAME_IN_NS[]; private: std::vector listOfScopesCpp(); - SALOME::DataScopeServer_var getScopePtrGivenName(const std::string& scopeName); + SALOME::DataScopeServerBase_var getScopePtrGivenName(const std::string& scopeName); private: CORBA::ORB_var _orb; //! single thread poa diff --git a/src/SALOMESDS/SALOMESDS_KeyWaiter.cxx b/src/SALOMESDS/SALOMESDS_KeyWaiter.cxx new file mode 100644 index 000000000..a35830bee --- /dev/null +++ b/src/SALOMESDS/SALOMESDS_KeyWaiter.cxx @@ -0,0 +1,137 @@ +// 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" + +#include + +using namespace SALOMESDS; + +KeyWaiter::KeyWaiter(PickelizedPyObjServer *var, const SALOME::ByteVec& keyVal):_var(var),_ze_key(0),_ze_value(0) +{ + if(sem_init(&_sem,0,0)!=0)// put value to 0 to lock by default + throw Exception("KeyWaiter constructor : Error on initialization of semaphore !"); + if(!var) + throw Exception("KeyWaiter constructor : Invalid glob var is NULL !"); + if(!dynamic_cast(var->getFather())) + throw Exception("KeyWaiter constructor : Invalid glob var ! Invalid DataScope hosting it ! DataScopeServerTransaction excpected !"); + std::string st; + PickelizedPyObjServer::FromByteSeqToCpp(keyVal,st); + _ze_key=PickelizedPyObjServer::GetPyObjFromPickled(st,getDSS()); + PyObject *selfMeth(PyObject_GetAttrString(_var->getPyObj(),"__contains__"));//new ref + 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__ !"); + if(retPy==Py_True) + { + PyObject *retPy2(PyDict_GetItem(_var->getPyObj(),_ze_key)); + if(retPy2==NULL) + throw Exception("KeyWaiter constructor : dict.getitem fails !"); + Py_XINCREF(retPy2); + _ze_value=retPy2; + go();//notify that value already arrives -> unlock + } + else + { + getDSS()->addWaitKey(this);// key not present let the DataScope managing it ! + } + Py_XDECREF(retPy); +} + +KeyWaiter::~KeyWaiter() +{ + Py_XDECREF(_ze_key); + if(_ze_value) + Py_XDECREF(_ze_value); +} + +PortableServer::POA_var KeyWaiter::getPOA() const +{ + return getDSS()->getPOA4KeyWaiter(); +} + +/*! + * WARNING : here it is the single method that can be invoked in non SINGLE_THREAD POA. + * So take care to do avoid collapses (especially in python). + */ +SALOME::ByteVec *KeyWaiter::waitFor() +{ + sem_wait(&_sem); + if(!_ze_value) + throw Exception("KeyWaiter::waitFor : internal error 1 !"); + SALOME::ByteVec *ret(0); + {// this section is to guarantee that no concurrent threads are doing python stuff at the same time + // Here a pickelization is needed so to guarantee to be alone doing python action the idea is to invoke using monothread POA. + DataScopeServerTransaction *dss(getDSS()); + PortableServer::POA_var poa(dss->getPOA()); + CORBA::Object_var dssPtr(poa->servant_to_reference(dss)); + SALOME::DataScopeServerTransaction_var dssPtr2(SALOME::DataScopeServerTransaction::_narrow(dssPtr)); + if(CORBA::is_nil(dssPtr2)) + throw Exception("KeyWaiter::waitFor : internal error 2 !"); + CORBA::Object_var thisPtr(getPOA()->servant_to_reference(this)); + SALOME::KeyWaiter_var thisPtr2(SALOME::KeyWaiter::_narrow(thisPtr)); + if(CORBA::is_nil(thisPtr2)) + throw Exception("KeyWaiter::waitFor : internal error 3 !"); + ret=dssPtr2->waitForMonoThrRev(thisPtr2);//<- this invokation through SINGLE_THREAD POA here will guarantee thread safety + } + enforcedRelease(); + return ret; +} + +/*! + * this method is supposed to be performed in alone. + */ +SALOME::ByteVec *KeyWaiter::waitForMonoThr() +{ + if(!_ze_value) + throw Exception("KeyWaiter::waitForMonoThr : no value ! invalid call of this method !"); + Py_XINCREF(_ze_value); + std::string st(PickelizedPyObjServer::Pickelize(_ze_value,_var->getFather())); + return PickelizedPyObjServer::FromCppToByteSeq(st); +} + +/*! + * WARNING call this method before calling go ! + */ +void KeyWaiter::valueJustCome(PyObject *val) +{ + if(_ze_value==val) + return ; + if(_ze_value) + Py_XDECREF(_ze_value); + _ze_value=val; + Py_XINCREF(_ze_value); +} + +void KeyWaiter::go() +{ + if(sem_post(&_sem)!=0) + { + std::ostringstream oss; oss << "KeyWaiter::go : error on post of semaphore ! "; + throw Exception(oss.str()); + } +} diff --git a/src/SALOMESDS/SALOMESDS_KeyWaiter.hxx b/src/SALOMESDS/SALOMESDS_KeyWaiter.hxx new file mode 100644 index 000000000..f16c72d7f --- /dev/null +++ b/src/SALOMESDS/SALOMESDS_KeyWaiter.hxx @@ -0,0 +1,61 @@ +// 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 "SALOMESDS_DataScopeServer.hxx" +#include "SALOMESDS_PickelizedPyObjServer.hxx" + +#include + +#include + +namespace SALOMESDS +{ + class DataScopeServerTransaction; + + class SALOMESDS_EXPORT KeyWaiter : public virtual POA_SALOME::KeyWaiter, public POAHolder + { + public: + KeyWaiter(PickelizedPyObjServer *var, const SALOME::ByteVec& keyVal); + PyObject *getKeyPyObj() const { return _ze_key; } + virtual ~KeyWaiter(); + PortableServer::POA_var getPOA() const; + SALOME::ByteVec *waitFor(); + void valueJustCome(PyObject *val); + void go(); + SALOME::ByteVec *waitForMonoThr(); + private: + DataScopeServerTransaction *getDSS() const { return static_cast(_var->getFather()); }//thanks to dynamic_cast in constructor + private: + PickelizedPyObjServer *_var; + PyObject *_ze_key; + PyObject *_ze_value; + sem_t _sem; + }; +} + +#endif diff --git a/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdExtServer.cxx b/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdExtServer.cxx index 50e2e05f6..0b1a196cc 100644 --- a/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdExtServer.cxx +++ b/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdExtServer.cxx @@ -27,12 +27,12 @@ using namespace SALOMESDS; -PickelizedPyObjRdExtServer::PickelizedPyObjRdExtServer(DataScopeServer *father, const std::string& varName, const SALOME::ByteVec& value):PickelizedPyObjServer(father,varName,value) +PickelizedPyObjRdExtServer::PickelizedPyObjRdExtServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value):PickelizedPyObjServer(father,varName,value) { } //! obj is consumed -PickelizedPyObjRdExtServer::PickelizedPyObjRdExtServer(DataScopeServer *father, const std::string& varName, PyObject *obj):PickelizedPyObjServer(father,varName,obj) +PickelizedPyObjRdExtServer::PickelizedPyObjRdExtServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj):PickelizedPyObjServer(father,varName,obj) { } diff --git a/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdExtServer.hxx b/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdExtServer.hxx index 72ab70895..d982c165b 100644 --- a/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdExtServer.hxx +++ b/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdExtServer.hxx @@ -33,8 +33,8 @@ namespace SALOMESDS class PickelizedPyObjRdExtServer : public PickelizedPyObjServer, public virtual POA_SALOME::PickelizedPyObjRdExtServer { public: - PickelizedPyObjRdExtServer(DataScopeServer *father, const std::string& varName, const SALOME::ByteVec& value); - PickelizedPyObjRdExtServer(DataScopeServer *father, const std::string& varName, PyObject *obj); + PickelizedPyObjRdExtServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value); + PickelizedPyObjRdExtServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj); ~PickelizedPyObjRdExtServer(); SALOME::PickelizedPyObjRdExtServer_ptr invokePythonMethodOn(const char *method, const SALOME::ByteVec& args); private: diff --git a/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdOnlyServer.cxx b/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdOnlyServer.cxx index da86efb92..e8bef2342 100644 --- a/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdOnlyServer.cxx +++ b/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdOnlyServer.cxx @@ -22,11 +22,11 @@ using namespace SALOMESDS; -PickelizedPyObjRdOnlyServer::PickelizedPyObjRdOnlyServer(DataScopeServer *father, const std::string& varName, const SALOME::ByteVec& value):PickelizedPyObjServer(father,varName,value) +PickelizedPyObjRdOnlyServer::PickelizedPyObjRdOnlyServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value):PickelizedPyObjServer(father,varName,value) { } -PickelizedPyObjRdOnlyServer::PickelizedPyObjRdOnlyServer(DataScopeServer *father, const std::string& varName, PyObject *obj):PickelizedPyObjServer(father,varName,obj) +PickelizedPyObjRdOnlyServer::PickelizedPyObjRdOnlyServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj):PickelizedPyObjServer(father,varName,obj) { } diff --git a/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdOnlyServer.hxx b/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdOnlyServer.hxx index 9ae3bb221..a5047fdaa 100644 --- a/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdOnlyServer.hxx +++ b/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdOnlyServer.hxx @@ -33,8 +33,8 @@ namespace SALOMESDS class PickelizedPyObjRdOnlyServer : public PickelizedPyObjServer, public virtual POA_SALOME::PickelizedPyObjRdOnlyServer { public: - PickelizedPyObjRdOnlyServer(DataScopeServer *father, const std::string& varName, const SALOME::ByteVec& value); - PickelizedPyObjRdOnlyServer(DataScopeServer *father, const std::string& varName, PyObject *obj); + PickelizedPyObjRdOnlyServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value); + PickelizedPyObjRdOnlyServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj); ~PickelizedPyObjRdOnlyServer(); }; } diff --git a/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdWrServer.cxx b/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdWrServer.cxx index 5e982de50..cdb0d6922 100644 --- a/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdWrServer.cxx +++ b/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdWrServer.cxx @@ -27,16 +27,16 @@ using namespace SALOMESDS; -PickelizedPyObjRdWrServer::PickelizedPyObjRdWrServer(DataScopeServer *father, const std::string& typeName, const std::string& varName):PickelizedPyObjServer(father,varName,CreateDftObjFromType(father->getGlobals(),typeName)) +PickelizedPyObjRdWrServer::PickelizedPyObjRdWrServer(DataScopeServerBase *father, const std::string& typeName, const std::string& varName):PickelizedPyObjServer(father,varName,CreateDftObjFromType(father->getGlobals(),typeName)) { } -PickelizedPyObjRdWrServer::PickelizedPyObjRdWrServer(DataScopeServer *father, const std::string& varName, const SALOME::ByteVec& value):PickelizedPyObjServer(father,varName,value) +PickelizedPyObjRdWrServer::PickelizedPyObjRdWrServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value):PickelizedPyObjServer(father,varName,value) { } //! obj is consumed -PickelizedPyObjRdWrServer::PickelizedPyObjRdWrServer(DataScopeServer *father, const std::string& varName, PyObject *obj):PickelizedPyObjServer(father,varName,obj) +PickelizedPyObjRdWrServer::PickelizedPyObjRdWrServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj):PickelizedPyObjServer(father,varName,obj) { } diff --git a/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdWrServer.hxx b/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdWrServer.hxx index 858ca771d..b6fba2f21 100644 --- a/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdWrServer.hxx +++ b/src/SALOMESDS/SALOMESDS_PickelizedPyObjRdWrServer.hxx @@ -33,9 +33,9 @@ namespace SALOMESDS class PickelizedPyObjRdWrServer : public PickelizedPyObjServer, public virtual POA_SALOME::PickelizedPyObjRdWrServer { public: - PickelizedPyObjRdWrServer(DataScopeServer *father, const std::string& typeName, const std::string& varName); - PickelizedPyObjRdWrServer(DataScopeServer *father, const std::string& varName, const SALOME::ByteVec& value); - PickelizedPyObjRdWrServer(DataScopeServer *father, const std::string& varName, PyObject *obj); + PickelizedPyObjRdWrServer(DataScopeServerBase *father, const std::string& typeName, const std::string& varName); + PickelizedPyObjRdWrServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value); + PickelizedPyObjRdWrServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj); ~PickelizedPyObjRdWrServer(); void setSerializedContent(const SALOME::ByteVec& newValue); SALOME::PickelizedPyObjRdWrServer_ptr invokePythonMethodOn(const char *method, const SALOME::ByteVec& args); diff --git a/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.cxx b/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.cxx index 149425051..2989150d4 100644 --- a/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.cxx +++ b/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.cxx @@ -27,13 +27,13 @@ using namespace SALOMESDS; -PickelizedPyObjServer::PickelizedPyObjServer(DataScopeServer *father, const std::string& varName, const SALOME::ByteVec& value):BasicDataServer(father,varName),_self(0) +PickelizedPyObjServer::PickelizedPyObjServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value):BasicDataServer(father,varName),_self(0) { setSerializedContentInternal(value); } //! obj is consumed -PickelizedPyObjServer::PickelizedPyObjServer(DataScopeServer *father, const std::string& varName, PyObject *obj):BasicDataServer(father,varName),_self(0) +PickelizedPyObjServer::PickelizedPyObjServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj):BasicDataServer(father,varName),_self(0) { setNewPyObj(obj); } @@ -52,6 +52,46 @@ SALOME::ByteVec *PickelizedPyObjServer::fetchSerializedContent() return FromCppToByteSeq(pickelize(_self)); } +bool PickelizedPyObjServer::isDict() +{ + if(PyDict_Check(_self)) + return true; + else + return false; +} + +void PickelizedPyObjServer::checkKeyNotAlreadyPresent(PyObject *key) +{ + checkKeyPresence(key,false); +} + +void PickelizedPyObjServer::checkKeyPresent(PyObject *key) +{ + checkKeyPresence(key,true); +} + +void PickelizedPyObjServer::addKeyValueHard(PyObject *key, PyObject *value) +{ + bool isOK(PyDict_SetItem(_self,key,value)==0); + if(!isOK) + throw Exception("PickelizedPyObjServer::addKeyValueHard : error when trying to add key,value to dict !"); +} + +void PickelizedPyObjServer::addKeyValueErrorIfAlreadyExisting(PyObject *key, PyObject *value) +{ + checkKeyNotAlreadyPresent(key); + bool isOK(PyDict_SetItem(_self,key,value)==0); + if(!isOK) + throw Exception("PickelizedPyObjServer::addKeyValueErrorIfAlreadyExisting : error when trying to add key,value to dict !"); +} + +void PickelizedPyObjServer::removeKeyInVarErrorIfNotAlreadyExisting(PyObject *key) +{ + checkKeyPresent(key); + if(PyDict_DelItem(_self,key)!=0) + throw Exception("PickelizedPyObjServer::removeKeyInVarErrorIfNotAlreadyExisting : error during deletion of key in dict !"); +} + void PickelizedPyObjServer::FromByteSeqToCpp(const SALOME::ByteVec& bsToBeConv, std::string& ret) { std::size_t sz(bsToBeConv.length()); @@ -73,14 +113,36 @@ 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); + Py_XDECREF(selfMeth); + return ret; +} + +//! New reference returned +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(dsb->getPickler(),"loads")); PyObject *args(PyTuple_New(1)); PyTuple_SetItem(args,0,pickledDataPy); PyObject *ret(PyObject_CallObject(selfMeth,args)); Py_XDECREF(args); @@ -88,13 +150,19 @@ PyObject *PickelizedPyObjServer::getPyObjFromPickled(const std::string& pickledD return ret; } +//! New reference returned +PyObject *PickelizedPyObjServer::getPyObjFromPickled(const std::vector& pickledData) +{ + return GetPyObjFromPickled(pickledData,_father); +} + //! obj is consumed by this method. -std::string PickelizedPyObjServer::pickelize(PyObject *obj) +std::string PickelizedPyObjServer::Pickelize(PyObject *obj, DataScopeServerBase *dsb) { PyObject *args(PyTuple_New(2)); PyTuple_SetItem(args,0,obj); PyTuple_SetItem(args,1,PyInt_FromLong(2));// because "assert(cPickle.HIGHEST_PROTOCOL is 2)" - PyObject *selfMeth(PyObject_GetAttrString(_father->getPickler(),"dumps")); + PyObject *selfMeth(PyObject_GetAttrString(dsb->getPickler(),"dumps")); PyObject *retPy(PyObject_CallObject(selfMeth,args)); Py_XDECREF(selfMeth); Py_XDECREF(args); @@ -108,6 +176,12 @@ std::string PickelizedPyObjServer::pickelize(PyObject *obj) return ret; } +//! obj is consumed by this method. +std::string PickelizedPyObjServer::pickelize(PyObject *obj) +{ + return Pickelize(obj,_father); +} + //! obj is consumed by this method. void PickelizedPyObjServer::setNewPyObj(PyObject *obj) { @@ -159,3 +233,29 @@ PyObject *PickelizedPyObjServer::CreateDftObjFromType(PyObject *globals, const s Py_XDECREF(args); return ret; } + +void PickelizedPyObjServer::checkKeyPresence(PyObject *key, bool presence) +{ + if(!isDict()) + throw Exception("PickelizedPyObjServer::checkKeyPresence : not a dict !"); + PyObject *selfMeth(PyObject_GetAttrString(_self,"__contains__"));//new ref + PyObject *args(PyTuple_New(1)); + PyTuple_SetItem(args,0,key); Py_XINCREF(key);// 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("PickelizedPyObjServer::checkKeyPresence : unexpected return of dict.__contains__ !"); + if(!presence) + { + if(retPy==Py_True) + throw Exception("PickelizedPyObjServer::checkKeyPresence : key is already present and it should not !"); + } + else + { + if(retPy==Py_False) + throw Exception("PickelizedPyObjServer::checkKeyPresence : key is not present and it should !"); + } + Py_XDECREF(retPy); +} diff --git a/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.hxx b/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.hxx index 2d94ca1d6..a52e27eea 100644 --- a/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.hxx +++ b/src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.hxx @@ -28,24 +28,40 @@ #include "SALOMESDS_BasicDataServer.hxx" +#include + namespace SALOMESDS { class PickelizedPyObjServer : public BasicDataServer, public virtual POA_SALOME::PickelizedPyObjServer { public: - PickelizedPyObjServer(DataScopeServer *father, const std::string& varName, const SALOME::ByteVec& value); - PickelizedPyObjServer(DataScopeServer *father, const std::string& varName, PyObject *obj); + PickelizedPyObjServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value); + PickelizedPyObjServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj); ~PickelizedPyObjServer(); void setSerializedContent(const SALOME::ByteVec& newValue); SALOME::ByteVec *fetchSerializedContent(); - protected: + public: + bool isDict(); + void checkKeyNotAlreadyPresent(PyObject *key); + void checkKeyPresent(PyObject *key); + void addKeyValueHard(PyObject *key, PyObject *value); + void addKeyValueErrorIfAlreadyExisting(PyObject *key, PyObject *value); + void removeKeyInVarErrorIfNotAlreadyExisting(PyObject *key); + PyObject *getPyObj() const { return _self; } + 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); + static std::string Pickelize(PyObject *obj, DataScopeServerBase *dsb); PyObject *getPyObjFromPickled(const std::string& pickledData); + PyObject *getPyObjFromPickled(const std::vector& pickledData); std::string pickelize(PyObject *obj); void setNewPyObj(PyObject *obj); void setSerializedContentInternal(const SALOME::ByteVec& newValue); static PyObject *CreateDftObjFromType(PyObject *globals, const std::string& typeName); + private: + void checkKeyPresence(PyObject *key, bool presence); protected: static const char FAKE_VAR_NAME_FOR_WORK[]; PyObject *_self; diff --git a/src/SALOMESDS/SALOMESDS_RefCountServ.cxx b/src/SALOMESDS/SALOMESDS_RefCountServ.cxx index 1e03c16f0..3eaebfcbb 100644 --- a/src/SALOMESDS/SALOMESDS_RefCountServ.cxx +++ b/src/SALOMESDS/SALOMESDS_RefCountServ.cxx @@ -38,14 +38,6 @@ bool RefCountServ::decrRef() const 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 bcc7f3568..2fee70216 100644 --- a/src/SALOMESDS/SALOMESDS_RefCountServ.hxx +++ b/src/SALOMESDS/SALOMESDS_RefCountServ.hxx @@ -21,18 +21,16 @@ #ifndef __SALOMESDS_REFCOUNTSERV_HXX__ #define __SALOMESDS_REFCOUNTSERV_HXX__ -#include +#include "SALOMESDS_AutoRefCountPtr.hxx" namespace SALOMESDS { - class RefCountServ : public virtual PortableServer::ServantBase + class RefCountServ : public virtual PortableServer::ServantBase, public POAHolder { 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_Transaction.cxx b/src/SALOMESDS/SALOMESDS_Transaction.cxx new file mode 100644 index 000000000..ca9bc32ee --- /dev/null +++ b/src/SALOMESDS/SALOMESDS_Transaction.cxx @@ -0,0 +1,181 @@ +// 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_Transaction.hxx" +#include "SALOMESDS_Exception.hxx" +#include "SALOMESDS_PickelizedPyObjServer.hxx" + +#include + +using namespace SALOMESDS; + +void Transaction::FromByteSeqToVB(const SALOME::ByteVec& bsToBeConv, std::vector& ret) +{ + std::size_t sz(bsToBeConv.length()); + ret.resize(sz); + unsigned char *buf(const_cast(&ret[0])); + for(std::size_t i=0;i& bsToBeConv, SALOME::ByteVec& ret) +{ + std::size_t sz(bsToBeConv.size()); + ret.length(sz); + for(std::size_t i=0;iexistVar(_var_name.c_str())) + _dsct->deleteVar(_var_name.c_str()); +} + +/*! + TODO : To be implemented. + */ +void TransactionVarCreate::notify() +{ +} + +void TransactionRdOnlyVarCreate::perform() +{ + SALOME::ByteVec data2; + FromVBToByteSeq(_data,data2); + _dsct->createRdOnlyVarInternal(_var_name,data2); +} + +void TransactionRdExtVarCreate::perform() +{ + SALOME::ByteVec data2; + FromVBToByteSeq(_data,data2); + _dsct->createRdExtVarInternal(_var_name,data2); +} + +void TransactionRdWrVarCreate::perform() +{ + SALOME::ByteVec data2; + FromVBToByteSeq(_data,data2); + _dsct->createRdWrVarInternal(_var_name,data2); +} + +TransactionDictModify::TransactionDictModify(DataScopeServerTransaction *dsct, const std::string& varName):Transaction(dsct,varName),_varc(0) +{ + _varc=checkVarExistingAndDict(); +} + +void TransactionDictModify::prepareRollBackInCaseOfFailure() +{ + _zeDataBefore.clear(); + PyObject *zeDictPy(_varc->getPyObj()); + Py_XINCREF(zeDictPy); + _zeDataBefore=_varc->pickelize(zeDictPy); +} + +void TransactionDictModify::rollBack() +{ + PyObject *obj(_varc->getPyObjFromPickled(_zeDataBefore)); + _varc->setNewPyObj(obj); + _zeDataBefore.clear(); +} + +TransactionAddKeyValue::TransactionAddKeyValue(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value):TransactionDictModify(dsct,varName) +{ + std::vector key2,value2; + FromByteSeqToVB(key,key2); + FromByteSeqToVB(value,value2); + _key=PickelizedPyObjServer::GetPyObjFromPickled(key2,_dsct); + _value=PickelizedPyObjServer::GetPyObjFromPickled(value2,_dsct); +} + +void TransactionAddKeyValue::prepareRollBackInCaseOfFailure() +{ + TransactionDictModify::prepareRollBackInCaseOfFailure(); + _dsct->pingKey(_key);// check that key is OK with all waiting keys +} + +void TransactionAddKeyValue::notify() +{ + _dsct->notifyKey(_key,_value); +} + +TransactionAddKeyValue::~TransactionAddKeyValue() +{ + Py_XDECREF(_key); + Py_XDECREF(_value); +} + +TransactionAddKeyValueHard::TransactionAddKeyValueHard(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value):TransactionAddKeyValue(dsct,varName,key,value) +{ +} + +void TransactionAddKeyValueHard::perform() +{ + _varc->addKeyValueHard(_key,_value); +} + +TransactionAddKeyValueErrorIfAlreadyExisting::TransactionAddKeyValueErrorIfAlreadyExisting(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value):TransactionAddKeyValue(dsct,varName,key,value) +{ + _varc->checkKeyNotAlreadyPresent(_key); +} + +void TransactionAddKeyValueErrorIfAlreadyExisting::perform() +{ + _varc->addKeyValueErrorIfAlreadyExisting(_key,_value); +} + +TransactionRemoveKeyInVarErrorIfNotAlreadyExisting::TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& key):TransactionDictModify(dsct,varName),_key(0) +{ + std::vector key2; + FromByteSeqToVB(key,key2); + _key=PickelizedPyObjServer::GetPyObjFromPickled(key2,_dsct); +} + +void TransactionRemoveKeyInVarErrorIfNotAlreadyExisting::perform() +{ + _varc->removeKeyInVarErrorIfNotAlreadyExisting(_key); +} + +/*! + * not implementation it is not a bug ! + */ +void TransactionRemoveKeyInVarErrorIfNotAlreadyExisting::notify() +{ +} + +TransactionRemoveKeyInVarErrorIfNotAlreadyExisting::~TransactionRemoveKeyInVarErrorIfNotAlreadyExisting() +{ + Py_XDECREF(_key); +} diff --git a/src/SALOMESDS/SALOMESDS_Transaction.hxx b/src/SALOMESDS/SALOMESDS_Transaction.hxx new file mode 100644 index 000000000..2bed22478 --- /dev/null +++ b/src/SALOMESDS/SALOMESDS_Transaction.hxx @@ -0,0 +1,143 @@ +// 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_TRANSACTION_HXX__ +#define __SALOMESDS_TRANSACTION_HXX__ + +#include "SALOMEconfig.h" +#include CORBA_SERVER_HEADER(SALOME_SDS) + +#include "SALOMESDS_Defines.hxx" +#include "SALOMESDS_Exception.hxx" +#include "SALOMESDS_DataServerManager.hxx" + +#include +#include + +namespace SALOMESDS +{ + class PickelizedPyObjServer; + + class SALOMESDS_EXPORT Transaction : public virtual POA_SALOME::Transaction, public POAHolder + { + public: + Transaction(DataScopeServerTransaction *dsct, const std::string& varName):_dsct(dsct),_var_name(varName) { if(!_dsct) throw Exception("Transaction constructor error !"); } + std::string getVarName() const { return _var_name; } + void checkVarExisting() { _dsct->checkExistingVar(_var_name); } + void checkNotAlreadyExisting() { _dsct->checkNotAlreadyExistingVar(_var_name); } + PortableServer::POA_var getPOA() const { return _dsct->getPOA(); } + virtual void prepareRollBackInCaseOfFailure() = 0; + virtual void perform() = 0; + virtual void rollBack() = 0; + virtual void notify() = 0; + virtual ~Transaction(); + public: + static void FromByteSeqToVB(const SALOME::ByteVec& bsToBeConv, std::vector& ret); + static void FromVBToByteSeq(const std::vector& bsToBeConv, SALOME::ByteVec& ret); + protected: + DataScopeServerTransaction *_dsct; + std::string _var_name; + }; + + class TransactionVarCreate : public Transaction + { + public: + TransactionVarCreate(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& constValue); + void prepareRollBackInCaseOfFailure(); + void rollBack(); + void notify(); + protected: + std::vector _data; + }; + + class TransactionRdOnlyVarCreate : public TransactionVarCreate + { + public: + TransactionRdOnlyVarCreate(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& constValue):TransactionVarCreate(dsct,varName,constValue) { } + void perform(); + }; + + class TransactionRdExtVarCreate : public TransactionVarCreate + { + public: + TransactionRdExtVarCreate(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& constValue):TransactionVarCreate(dsct,varName,constValue) { } + void perform(); + }; + + class TransactionRdWrVarCreate : public TransactionVarCreate + { + public: + TransactionRdWrVarCreate(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& constValue):TransactionVarCreate(dsct,varName,constValue) { } + void perform(); + }; + + class PickelizedPyObjServer; + + class TransactionDictModify : public Transaction + { + public: + TransactionDictModify(DataScopeServerTransaction *dsct, const std::string& varName); + PickelizedPyObjServer *checkVarExistingAndDict() { return _dsct->checkVarExistingAndDict(_var_name); } + void prepareRollBackInCaseOfFailure(); + void rollBack(); + protected: + std::string _zeDataBefore; + PickelizedPyObjServer *_varc; + }; + + class TransactionAddKeyValue : public TransactionDictModify + { + public: + TransactionAddKeyValue(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value); + void prepareRollBackInCaseOfFailure(); + void notify(); + ~TransactionAddKeyValue(); + protected: + PyObject *_key; + PyObject *_value; + }; + + class TransactionAddKeyValueHard : public TransactionAddKeyValue + { + public: + TransactionAddKeyValueHard(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value); + void perform(); + }; + + class TransactionAddKeyValueErrorIfAlreadyExisting : public TransactionAddKeyValue + { + public: + TransactionAddKeyValueErrorIfAlreadyExisting(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value); + void perform(); + }; + + class TransactionRemoveKeyInVarErrorIfNotAlreadyExisting : public TransactionDictModify + { + public: + TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& key); + void perform(); + void notify(); + ~TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(); + private: + PyObject *_key; + }; +} + +#endif diff --git a/src/SALOMESDS/SALOME_DataScopeServer.cxx b/src/SALOMESDS/SALOME_DataScopeServer.cxx index d45f84102..de6790b1f 100644 --- a/src/SALOMESDS/SALOME_DataScopeServer.cxx +++ b/src/SALOMESDS/SALOME_DataScopeServer.cxx @@ -33,12 +33,19 @@ int main(int argc, char *argv[]) if(argc<=1) throw SALOMESDS::Exception("In the main of SALOME_DataScopeServer.cxx !"); scopeName=argv[1]; + std::istringstream isTransacSS(argv[2]); + int isTransac(0); + isTransacSS >> isTransac; CORBA::ORB_var orb(CORBA::ORB_init(argc,argv)); CORBA::Object_var obj(orb->resolve_initial_references("RootPOA")); PortableServer::POA_var poa(PortableServer::POA::_narrow(obj)); PortableServer::POAManager_var mgr(poa->the_POAManager()); mgr->activate(); - SALOMESDS::DataScopeServer *server(new SALOMESDS::DataScopeServer(orb,scopeName)); + SALOMESDS::DataScopeServerBase *server(0); + if(!isTransac) + server=new SALOMESDS::DataScopeServer(orb,scopeName); + else + server=new SALOMESDS::DataScopeServerTransaction(orb,scopeName); // CORBA::PolicyList policies; policies.length(1); @@ -48,10 +55,11 @@ int main(int argc, char *argv[]) threadPol->destroy(); server->initializePython(argc,argv);// agy : Very important ! invoke this method BEFORE activation ! server->registerToSalomePiDict(); - PortableServer::ObjectId_var id(poa2->activate_object(server)); - obj=poa2->id_to_reference(id); - SALOME::DataScopeServer_var serverPtr(SALOME::DataScopeServer::_narrow(obj)); - server->setPOAAndRegister(poa2,serverPtr); + // + server->setPOA(poa2); + obj=server->activate(); + SALOME::DataScopeServerBase_var serverPtr(SALOME::DataScopeServerBase::_narrow(obj)); + server->registerInNS(serverPtr); // orb->run(); server->_remove_ref(); diff --git a/src/SALOMESDS/TestSalomeSDS.py b/src/SALOMESDS/TestSalomeSDS.py new file mode 100644 index 000000000..9a5fd83e0 --- /dev/null +++ b/src/SALOMESDS/TestSalomeSDS.py @@ -0,0 +1,205 @@ +# -*- coding: utf-8 -*- +# 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 + +import SalomeSDSClt +import SALOME +import salome +import unittest +import cPickle +import gc +import time +import multiprocessing as mp + +def obj2Str(obj): + return cPickle.dumps(obj,cPickle.HIGHEST_PROTOCOL) +def str2Obj(strr): + return cPickle.loads(strr) +def generateKey(varName,scopeName): + dsm=salome.naming_service.Resolve("/DataServerManager") + dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName) + assert(not isCreated) + t=dss.addKeyValueInVarHard(varName,obj2Str("ef"),obj2Str([11,14,100])) + time.sleep(3) + dss.atomicApply([t]) +def work(t): + i,varName,scopeName=t + if i==0: + generateKey(varName,scopeName) + return 0 + else: + import TestSalomeSDSHelper0 + import os,subprocess + fname=os.path.splitext(TestSalomeSDSHelper0.__file__)[0]+".py" + proc=subprocess.Popen(["python",fname],stdout=subprocess.PIPE,stderr=subprocess.PIPE) + out,err=proc.communicate() + if proc.returncode!=0: + print out + print err + return proc.returncode + +class SalomeSDSTest(unittest.TestCase): + + def testList1(self): + a=SalomeSDSClt.CreateRdExtGlobalVar([],"a","Scope0") + self.assertEqual(a.local_copy(),[]) + a.append(5) + self.assertEqual(a.local_copy(),[5]) + self.assertRaises(SALOME.SALOME_Exception,a.__delitem__,0) + a.append(["rt"]) + self.assertEqual(a.local_copy(),[5,["rt"]]) + a[1].append(8) + self.assertEqual(a.local_copy(),[5,["rt",8]]) + a.extend(a) + self.assertEqual(a.local_copy(),[5,["rt",8],5,["rt",8]]) + a.extend(a[3:]) + self.assertEqual(a.local_copy(),[5,["rt",8],5,["rt",8],["rt",8]]) + a[4].append(7) + self.assertEqual(a.local_copy(),[5,["rt",8],5,["rt",8],["rt",8,7]]) + a.ptr().getMyDataScopeServer().deleteVar("a") + pass + + def testDict1(self): + a=SalomeSDSClt.CreateRdExtGlobalVar({},"a","Scope0") + a["ab"]=4 + self.assertEqual(a.local_copy(),{"ab":4}) + a["cd"]=[5] + self.assertEqual(a.local_copy(),{"ab":4,"cd":[5]}) + a["cd"].append(77) + self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77]}) + a.__setitem__("ef",["a","bb"]) + self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb"]}) + self.assertRaises(SALOME.SALOME_Exception,a.__setitem__,"ef",["a","bb"]) + self.assertRaises(SALOME.SALOME_Exception,a.__setitem__,"ef",["a","bb","ccc"]) + a["ef"].append("ccc") + self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"]}) + a["gh"]=a + self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"],"gh":{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"]}}) + a["gh"]["cd"].append(99) ; a["cd"].append(88) + self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77,88],"ef":["a","bb","ccc"],"gh":{"ab":4,"cd":[5,77,99],"ef":["a","bb","ccc"]}}) + a.ptr().getMyDataScopeServer().deleteVar("a") + pass + + def testReadOnly1(self): + a=SalomeSDSClt.CreateRdOnlyGlobalVar({"ab":4,"cd":[5,77]},"a","Scope0") + self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77]}) + self.assertRaises(Exception,a.__getitem__,"ab") + a.ptr().getMyDataScopeServer().deleteVar("a") + + def testTransaction1(self): + scopeName="Scope1" + varName="a" + dsm=salome.naming_service.Resolve("/DataServerManager") + dsm.cleanScopesInNS() + if scopeName in dsm.listScopes(): + dsm.removeDataScope(scopeName) + dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName) + self.assertTrue(isCreated) + # + t0=dss.createRdExtVarTransac(varName,obj2Str({"ab":[4,5,6]})) + dss.atomicApply([t0]) + # + t1=dss.addKeyValueInVarHard(varName,obj2Str("cd"),obj2Str([7,8,9,10])) + dss.atomicApply([t1]) + # + self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]}) + wk=dss.waitForKeyInVar(varName,obj2Str("cd")) + self.assertEqual(str2Obj(wk.waitFor()),[7,8,9,10]) + # + nbProc=8 + pool=mp.Pool(processes=nbProc) + asyncResult=pool.map_async(work,[(i,varName,scopeName) for i in xrange(nbProc)]) + self.assertEqual(asyncResult.get(),nbProc*[0]) # <- the big test is here ! + dsm.removeDataScope(scopeName) + + def testTransaction2(self): + scopeName="Scope1" + varName="a" + dsm=salome.naming_service.Resolve("/DataServerManager") + dsm.cleanScopesInNS() + if scopeName in dsm.listScopes(): + dsm.removeDataScope(scopeName) + dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName) + self.assertTrue(isCreated) + # + t0=dss.createRdExtVarTransac(varName,obj2Str({"ab":[4,5,6]})) + dss.atomicApply([t0]) + # + self.assertRaises(SALOME.SALOME_Exception,dss.addKeyValueInVarErrorIfAlreadyExisting,varName,obj2Str("ab"),obj2Str([7,8,9,10]))#raises because ab is already a key ! + t1=dss.addKeyValueInVarErrorIfAlreadyExisting(varName,obj2Str("cd"),obj2Str([7,8,9,10])) + dss.atomicApply([t1]) + # + self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]}) + wk=dss.waitForKeyInVar(varName,obj2Str("cd")) + self.assertEqual(str2Obj(wk.waitFor()),[7,8,9,10]) + + def testTransaction3(self): + scopeName="Scope1" + varName="a" + dsm=salome.naming_service.Resolve("/DataServerManager") + dsm.cleanScopesInNS() + if scopeName in dsm.listScopes(): + dsm.removeDataScope(scopeName) + dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName) + self.assertTrue(isCreated) + # + t0=dss.createRdExtVarTransac(varName,obj2Str({"ab":[4,5,6]})) + dss.atomicApply([t0]) + # + t1=dss.addKeyValueInVarErrorIfAlreadyExisting(varName,obj2Str("cd"),obj2Str([7,8,9,10])) + dss.atomicApply([t1]) + # + self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]}) + # + t2=dss.removeKeyInVarErrorIfNotAlreadyExisting(varName,obj2Str("ab")) + dss.atomicApply([t2]) + self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'cd':[7,8,9,10]}) + + def testTransaction4(self): + scopeName="Scope1" + varName="a" + dsm=salome.naming_service.Resolve("/DataServerManager") + dsm.cleanScopesInNS() + if scopeName in dsm.listScopes(): + dsm.removeDataScope(scopeName) + dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName) + self.assertTrue(isCreated) + # + t0=dss.createRdExtVarTransac(varName,obj2Str({"ab":[4,5,6]})) + dss.atomicApply([t0]) + # + t1=dss.addKeyValueInVarHard(varName,obj2Str("cd"),obj2Str([7,8,9,10])) + dss.atomicApply([t1]) + # + self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]}) + wk,t2=dss.waitForKeyInVarAndKillIt(varName,obj2Str("cd")) + self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]}) + self.assertEqual(str2Obj(wk.waitFor()),[7,8,9,10]) + dss.atomicApply([t2]) + self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6]}) + + def setUp(self): + salome.salome_init() + pass + + pass + +unittest.main() + diff --git a/src/SALOMESDS/TestSalomeSDS1.py b/src/SALOMESDS/TestSalomeSDS1.py index f33d3a896..bb5aa6b59 100644 --- a/src/SALOMESDS/TestSalomeSDS1.py +++ b/src/SALOMESDS/TestSalomeSDS1.py @@ -25,6 +25,7 @@ import cPickle import gc import SalomeSDSClt +salome.salome_init() st="jjj" dsm=salome.naming_service.Resolve("/DataServerManager") assert(dsm.isAliveAndKicking("Default")) diff --git a/src/SALOMESDS/TestSalomeSDS2.py b/src/SALOMESDS/TestSalomeSDS2.py deleted file mode 100644 index eb1c1ce59..000000000 --- a/src/SALOMESDS/TestSalomeSDS2.py +++ /dev/null @@ -1,83 +0,0 @@ -# -*- coding: utf-8 -*- -# 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 - -import SalomeSDSClt -import SALOME -import salome -import unittest -import gc - -class SalomeSDS2Test(unittest.TestCase): - - def testList1(self): - a=SalomeSDSClt.CreateRdExtGlobalVar([],"a","Scope0") - self.assertEqual(a.local_copy(),[]) - a.append(5) - self.assertEqual(a.local_copy(),[5]) - self.assertRaises(SALOME.SALOME_Exception,a.__delitem__,0) - a.append(["rt"]) - self.assertEqual(a.local_copy(),[5,["rt"]]) - a[1].append(8) - self.assertEqual(a.local_copy(),[5,["rt",8]]) - a.extend(a) - self.assertEqual(a.local_copy(),[5,["rt",8],5,["rt",8]]) - a.extend(a[3:]) - self.assertEqual(a.local_copy(),[5,["rt",8],5,["rt",8],["rt",8]]) - a[4].append(7) - self.assertEqual(a.local_copy(),[5,["rt",8],5,["rt",8],["rt",8,7]]) - a.ptr().getMyDataScopeServer().deleteVar("a") - pass - - def testDict1(self): - a=SalomeSDSClt.CreateRdExtGlobalVar({},"a","Scope0") - a["ab"]=4 - self.assertEqual(a.local_copy(),{"ab":4}) - a["cd"]=[5] - self.assertEqual(a.local_copy(),{"ab":4,"cd":[5]}) - a["cd"].append(77) - self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77]}) - a.__setitem__("ef",["a","bb"]) - self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb"]}) - self.assertRaises(SALOME.SALOME_Exception,a.__setitem__,"ef",["a","bb"]) - self.assertRaises(SALOME.SALOME_Exception,a.__setitem__,"ef",["a","bb","ccc"]) - a["ef"].append("ccc") - self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"]}) - a["gh"]=a - self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"],"gh":{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"]}}) - a["gh"]["cd"].append(99) ; a["cd"].append(88) - self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77,88],"ef":["a","bb","ccc"],"gh":{"ab":4,"cd":[5,77,99],"ef":["a","bb","ccc"]}}) - a.ptr().getMyDataScopeServer().deleteVar("a") - pass - - def testReadOnly1(self): - a=SalomeSDSClt.CreateRdOnlyGlobalVar({"ab":4,"cd":[5,77]},"a","Scope0") - self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77]}) - self.assertRaises(Exception,a.__getitem__,"ab") - a.ptr().getMyDataScopeServer().deleteVar("a") - - def setUp(self): - salome.salome_init() - pass - - pass - -unittest.main() - diff --git a/src/SALOMESDS/TestSalomeSDSHelper0.py b/src/SALOMESDS/TestSalomeSDSHelper0.py new file mode 100644 index 000000000..fc3fd0f3d --- /dev/null +++ b/src/SALOMESDS/TestSalomeSDSHelper0.py @@ -0,0 +1,25 @@ +import SALOME +import cPickle +import salome +import sys + +salome.salome_init() + +scopeName="Scope1" +varName="a" + +def obj2Str(obj): + return cPickle.dumps(obj,cPickle.HIGHEST_PROTOCOL) + +def str2Obj(strr): + return cPickle.loads(strr) + +def waitKey(): + dsm=salome.naming_service.Resolve("/DataServerManager") + dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName) + assert(not isCreated) + wk=dss.waitForKeyInVar(varName,obj2Str("ef")) + return str2Obj(wk.waitFor())==[11,14,100] + +if __name__=="__main__": + sys.exit(not int(waitKey())) -- 2.39.2