]> SALOME platform Git repositories - modules/kernel.git/commitdiff
Salome HOME
Implementation of producer/consumer mechanism and transaction mechanism for global...
authorAnthony Geay <anthony.geay@edf.fr>
Fri, 10 Jul 2015 13:10:22 +0000 (15:10 +0200)
committerAnthony Geay <anthony.geay@edf.fr>
Wed, 22 Jul 2015 15:47:03 +0000 (17:47 +0200)
30 files changed:
CTestTestfileInstall.cmake.in
idl/SALOME_SDS.idl
src/SALOMESDS/CMakeLists.txt
src/SALOMESDS/CTestTestfileInstall.cmake [new file with mode: 0644]
src/SALOMESDS/SALOMESDS_AutoRefCountPtr.hxx
src/SALOMESDS/SALOMESDS_BasicDataServer.cxx
src/SALOMESDS/SALOMESDS_BasicDataServer.hxx
src/SALOMESDS/SALOMESDS_DataScopeServer.cxx
src/SALOMESDS/SALOMESDS_DataScopeServer.hxx
src/SALOMESDS/SALOMESDS_DataServerManager.cxx
src/SALOMESDS/SALOMESDS_DataServerManager.hxx
src/SALOMESDS/SALOMESDS_KeyWaiter.cxx [new file with mode: 0644]
src/SALOMESDS/SALOMESDS_KeyWaiter.hxx [new file with mode: 0644]
src/SALOMESDS/SALOMESDS_PickelizedPyObjRdExtServer.cxx
src/SALOMESDS/SALOMESDS_PickelizedPyObjRdExtServer.hxx
src/SALOMESDS/SALOMESDS_PickelizedPyObjRdOnlyServer.cxx
src/SALOMESDS/SALOMESDS_PickelizedPyObjRdOnlyServer.hxx
src/SALOMESDS/SALOMESDS_PickelizedPyObjRdWrServer.cxx
src/SALOMESDS/SALOMESDS_PickelizedPyObjRdWrServer.hxx
src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.cxx
src/SALOMESDS/SALOMESDS_PickelizedPyObjServer.hxx
src/SALOMESDS/SALOMESDS_RefCountServ.cxx
src/SALOMESDS/SALOMESDS_RefCountServ.hxx
src/SALOMESDS/SALOMESDS_Transaction.cxx [new file with mode: 0644]
src/SALOMESDS/SALOMESDS_Transaction.hxx [new file with mode: 0644]
src/SALOMESDS/SALOME_DataScopeServer.cxx
src/SALOMESDS/TestSalomeSDS.py [new file with mode: 0644]
src/SALOMESDS/TestSalomeSDS1.py
src/SALOMESDS/TestSalomeSDS2.py [deleted file]
src/SALOMESDS/TestSalomeSDSHelper0.py [new file with mode: 0644]

index b739c2e22bbb7f4a9f43e50b285c01c6ebc0369a..05f1720ca10c9b1917a35f927cc735b155f361ad 100644 (file)
@@ -36,6 +36,7 @@ SUBDIRS( Launcher
          KernelHelpers
          SALOMEDS
          SALOMEDSImpl
+        SALOMESDS
          Utils
          UnitTests
          connect
index 333dee788d9e7145194f3b3853e3d8521633df91..a7bb219bdbe39d93c971fb2011a3c3cf6209d973 100644 (file)
@@ -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<Transaction> 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);
index f049fb5439b0b738c9013c6a268cda06ef5742da..79ca214dc22f9757becd244ef8800cf1ca108827 100644 (file)
@@ -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 (file)
index 0000000..bb88946
--- /dev/null
@@ -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)
index ce199141f359fc392202acfed6fb4c626bd22d36..dcbe863351b0947be9ecb19a2c79dd535f6f9075 100644 (file)
 
 #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 T>
   class AutoRefCountPtr
   {
@@ -73,6 +96,32 @@ namespace SALOMESDS
       ptr->incrRef();
     return ret;
   }
+
+  template<class T>// 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
index f72154b1fda089c91db5f62e92c73527826787ea..e89fd16535226ed340ec55c5d8ae0b1e3b9a9bca 100644 (file)
 
 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();
 }
index 5ceec0ada9096ac106a88d9c532c7df58cd32857..7a22300efb9e2cfe4b4722706ddc194476b3c9e9 100644 (file)
 
 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;
   };
index 6fdeb890f8901720fc481bb05cf2d31f3aec46e1..ee1f9e07b41c2b22ef9d4767fc7a9663f2a49618 100644 (file)
@@ -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"
 
 
 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<std::string> allNames(getAllVarNames());
-  std::vector<std::string>::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<std::string>(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<pos;i++,it0++);
+  std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::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<std::string> allNames(getAllVarNames());
   std::vector<std::string>::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<std::string>(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<char *>("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<std::string> 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<std::string> allNames(getAllVarNames());
+  std::vector<std::string>::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<std::string> allNames(getAllVarNames());
+  std::vector<std::string>::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<PickelizedPyObjServer *>(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<std::string> allNames(getAllVarNames());
   std::vector<std::string>::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<std::string>(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;i<pos;i++,it0++);
+  return it0;
+}
+
+///////
+
+DataScopeServer::DataScopeServer(CORBA::ORB_ptr orb, const std::string& scopeName):DataScopeServerBase(orb,scopeName)
+{
+}
+
+DataScopeServer::DataScopeServer(const DataScopeServer& other):DataScopeServerBase(other)
+{
+}
+
+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(tmp->activate());
+  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<PickelizedPyObjServer *>(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<KeyWaiter *>(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<Transaction> > transactionsCpp(sz);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      PortableServer::ServantBase *eltBase(0);
+      Transaction *elt(0);
+      try
+        {
+          eltBase=_poa->reference_to_servant(transactions[i]);
+          elt=dynamic_cast<Transaction *>(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<TrustTransaction> transactions2(sz);
+    bool mustRollback(true);
+    for(std::size_t i=0;i<sz;i++)
+      transactions2[i].setTransaction(transactionsCpp[i],&mustRollback);
+    for(std::size_t i=0;i<sz;i++)
+      transactions2[i].operate();
+    mustRollback=false;
+  }
+  for(std::size_t i=0;i<sz;i++)
+    transactionsCpp[i]->notify();
+}
+
+/*!
+ * 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()
+{
+}
+
index 7cf7f6d6db445e4d45a1d09674a9398407f5dbbd..db76fbf413baade45e029d71112c35a09af5aea0 100644 (file)
 
 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
index 08e4954b3d4ba26506129496ae19bc0788472394..326adefe19bcd194955b9f28a1cc7b9c0732dc3c 100644 (file)
@@ -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<class T>
+typename T::PtrType CreateDataScope(const std::string& scopeName, const std::vector<std::string>& scopes, SALOME_NamingService& ns)
 {
-  std::string scopeNameCpp(scopeName);
-  std::vector<std::string> 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<class T>
+typename T::PtrType GiveADataScopeCalled(const std::string& scopeName, const std::vector<std::string>& scopes, SALOME_NamingService& ns, CORBA::Boolean& isCreated)
 {
-  std::string scopeNameCpp(scopeName);
-  std::vector<std::string> 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<T>(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<T>(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<NormalFunctor>(scopeName,listOfScopesCpp(),ns);
+}
+
+SALOME::DataScopeServer_ptr DataServerManager::giveADataScopeCalled(const char *scopeName, CORBA::Boolean& isCreated)
+{
+  SALOME_NamingService ns(_orb);
+  return GiveADataScopeCalled<NormalFunctor>(scopeName,listOfScopesCpp(),ns,isCreated);
+}
+
+SALOME::DataScopeServerTransaction_ptr DataServerManager::createDataScopeTransaction(const char *scopeName)
+{
+  SALOME_NamingService ns(_orb);
+  return CreateDataScope<TransactionFunctor>(scopeName,listOfScopesCpp(),ns);
+}
+
+SALOME::DataScopeServerTransaction_ptr DataServerManager::giveADataScopeTransactionCalled(const char *scopeName, CORBA::Boolean& isCreated)
+{
+  SALOME_NamingService ns(_orb);
+  return GiveADataScopeCalled<TransactionFunctor>(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<std::string> DataServerManager::listOfScopesCpp()
 {
   SALOME_NamingService ns(_orb);
@@ -210,18 +275,22 @@ std::vector<std::string> 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<std::string>& scopes, SALOME_NamingService& ns)
 {
-  std::vector<std::string> 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);
+}
index 944efc8c61c3ebf0e343c3ec80bedb8708f75a46..d9ad2caed5748389bb5344dfda0da69ca3599c91 100644 (file)
 
 #include <string>
 
+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<std::string>& scopes, SALOME_NamingService& ns);
   public:
     static const char NAME_IN_NS[];
     static const char DFT_SCOPE_NAME_IN_NS[];
   private:
     std::vector<std::string> 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 (file)
index 0000000..a35830b
--- /dev/null
@@ -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 <sstream>
+
+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<DataScopeServerTransaction *>(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 (file)
index 0000000..f16c72d
--- /dev/null
@@ -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 <Python.h>
+
+#include <semaphore.h>
+
+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<DataScopeServerTransaction *>(_var->getFather()); }//thanks to dynamic_cast in constructor
+  private:
+    PickelizedPyObjServer *_var;
+    PyObject *_ze_key;
+    PyObject *_ze_value;
+    sem_t _sem;
+  };
+}
+
+#endif
index 50e2e05f6415ae762843fdf6983bdece9d82a319..0b1a196cc9461ad24aed793ea78c92f866890aec 100644 (file)
 
 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)
 {
 }
 
index 72ab708958fdceb92a8c3e38a9748c282e87b6fc..d982c165b4162b5ee036c39e6dea9ef872844153 100644 (file)
@@ -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:
index da86efb921beae9e1ecb1f98ecb2e11ad1614a4a..e8bef2342b637dfe431171ee69759e68aab9fd14 100644 (file)
 
 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)
 {
 }
 
index 9ae3bb221152af0e24f2e1c427c7ee9940f41bb2..a5047fdaa81369b27a412ccba00ba0e10ae93c57 100644 (file)
@@ -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();
   };
 }
index 5e982de50a62c774473d2c6a16eab8cc56a031ed..cdb0d69222b6c7b879d0a3b566acd8038af10317 100644 (file)
 
 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)
 {
 }
 
index 858ca771d3fc392669aac1acf3077a47103bea6f..b6fba2f21502175c481145ea04e125dfd071826d 100644 (file)
@@ -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);
index 1494250515953606714e9f4e8ae4429225eff380..2989150d486b79632d2f8171f22ca44c1e0f2e32 100644 (file)
 
 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<unsigned char>& 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<unsigned char>& 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);
+}
index 2d94ca1d6a564c381575cc81c2f905a8bd32bbf4..a52e27eea0ad8e579ac68df91dc913ac88f23890 100644 (file)
 
 #include "SALOMESDS_BasicDataServer.hxx"
 
+#include <vector>
+
 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<unsigned char>& pickledData, DataScopeServerBase *dsb);
+    static std::string Pickelize(PyObject *obj, DataScopeServerBase *dsb);
     PyObject *getPyObjFromPickled(const std::string& pickledData);
+    PyObject *getPyObjFromPickled(const std::vector<unsigned char>& 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;
index 1e03c16f070836c858a9912e310e823e5fc7e7ae..3eaebfcbb9ea95d85643fc36111f6e65b2734c34 100644 (file)
@@ -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)
 {
 }
index bcc7f35688748b6daafb8f6c7d7786c2e2aee4c0..2fee70216c89f69ed62b10bcfeab67c2ef25d6d4 100644 (file)
 #ifndef __SALOMESDS_REFCOUNTSERV_HXX__
 #define __SALOMESDS_REFCOUNTSERV_HXX__
 
-#include <omniORB4/CORBA.h>
+#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 (file)
index 0000000..ca9bc32
--- /dev/null
@@ -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 <sstream>
+
+using namespace SALOMESDS;
+
+void Transaction::FromByteSeqToVB(const SALOME::ByteVec& bsToBeConv, std::vector<unsigned char>& ret)
+{
+  std::size_t sz(bsToBeConv.length());
+  ret.resize(sz);
+  unsigned char *buf(const_cast<unsigned char *>(&ret[0]));
+  for(std::size_t i=0;i<sz;i++)
+    buf[i]=bsToBeConv[i];
+}
+
+void Transaction::FromVBToByteSeq(const std::vector<unsigned char>& bsToBeConv, SALOME::ByteVec& ret)
+{
+  std::size_t sz(bsToBeConv.size());
+  ret.length(sz);
+  for(std::size_t i=0;i<sz;i++)
+    ret[i]=bsToBeConv[i];
+}
+
+Transaction::~Transaction()
+{
+}
+
+TransactionVarCreate::TransactionVarCreate(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& constValue):Transaction(dsct,varName)
+{
+  FromByteSeqToVB(constValue,_data);
+}
+
+void TransactionVarCreate::prepareRollBackInCaseOfFailure()
+{//nothing it is not a bug
+  checkNotAlreadyExisting();
+}
+
+void TransactionVarCreate::rollBack()
+{
+  if(_dsct->existVar(_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<unsigned char> 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<unsigned char> 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 (file)
index 0000000..2bed224
--- /dev/null
@@ -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 <string>
+#include <vector>
+
+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<unsigned char>& ret);
+    static void FromVBToByteSeq(const std::vector<unsigned char>& 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<unsigned char> _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
index d45f84102044526b88cfc04a9a4906739b56611c..de6790b1f8f07f82072156720ff0d13aec566e91 100644 (file)
@@ -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 (file)
index 0000000..9a5fd83
--- /dev/null
@@ -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()
+
index f33d3a896d12daa4443886e612d30df42388066d..bb5aa6b5946db2ff9e96902df94e3de221e11177 100644 (file)
@@ -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 (file)
index eb1c1ce..0000000
+++ /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 (file)
index 0000000..fc3fd0f
--- /dev/null
@@ -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()))