]> SALOME platform Git repositories - modules/kernel.git/commitdiff
Salome HOME
[EDF16833] : RdExt support multi fake creation.
authorAnthony Geay <anthony.geay@edf.fr>
Thu, 19 Apr 2018 07:32:30 +0000 (09:32 +0200)
committerAnthony Geay <anthony.geay@edf.fr>
Tue, 15 May 2018 11:37:12 +0000 (13:37 +0200)
13 files changed:
idl/SALOME_SDS.idl
src/SALOMESDS/CMakeLists.txt
src/SALOMESDS/SALOMESDS_DataScopeServer.cxx
src/SALOMESDS/SALOMESDS_DataScopeServer.hxx
src/SALOMESDS/SALOMESDS_PickelizedPyObjRdExtInitServer.cxx
src/SALOMESDS/SALOMESDS_PickelizedPyObjRdExtInitServer.hxx
src/SALOMESDS/SALOMESDS_PickelizedPyObjRdExtServer.cxx
src/SALOMESDS/SALOMESDS_PickelizedPyObjRdExtServer.hxx
src/SALOMESDS/SALOMESDS_Sha1Keeper.cxx [new file with mode: 0644]
src/SALOMESDS/SALOMESDS_Sha1Keeper.hxx [new file with mode: 0644]
src/SALOMESDS/SALOMESDS_Transaction.cxx
src/SALOMESDS/SALOMESDS_Transaction.hxx
src/SALOMESDS/TestSalomeSDS.py

index 1b28d56105cc49d2abef3bd74b8e38e1d1696e8c..09401cd0099c408af138466e42213cd2f91ba062 100644 (file)
@@ -140,6 +140,7 @@ module SALOME
     void fetchAndGetAccessOfVar(in string varName, out string access, out ByteVec data) 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 createRdExtVarFreeStyleTransac(in string varName, in ByteVec constValue, in ByteVec sha1) raises (SALOME::SALOME_Exception);
     Transaction createRdExtInitVarTransac(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);
index a56faba1e0fc5c61d98d1416e99efc348edd0b8d..8be06bad090dac1e2043be9dc96a1342ed758b12 100644 (file)
@@ -48,6 +48,7 @@ SET(SalomeSDS_SOURCES
   SALOMESDS_PickelizedPyObjRdWrServer.cxx
   SALOMESDS_Transaction.cxx
   SALOMESDS_KeyWaiter.cxx
+  SALOMESDS_Sha1Keeper.cxx
   )
 
 ADD_LIBRARY(SalomeSDS ${SalomeSDS_SOURCES})
index 969b720ef53bf6ed83b6e0768254b3c418c763c5..2010d89ef5aa0c12948fd3ac13b8f313758c4da1 100644 (file)
@@ -345,11 +345,16 @@ std::vector< std::string > DataScopeServerBase::getAllVarNames() const
   return ret;
 }
 
-void DataScopeServerBase::checkNotAlreadyExistingVar(const std::string& varName) const
+bool DataScopeServerBase::isExistingVar(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())
+  return it!=allNames.end();
+}
+
+void DataScopeServerBase::checkNotAlreadyExistingVar(const std::string& varName) const
+{
+  if(isExistingVar(varName))
     {
       std::ostringstream oss; oss << "DataScopeServerBase::checkNotAlreadyExistingVar : name \"" << varName << "\" already exists !";
       throw Exception(oss.str());
@@ -425,8 +430,7 @@ void DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExtInit(const s
     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExtInit : var is neither RdExt nor RdExtInit !");
   if(varc0)
     {
-      PyObject *pyobj(varc0->getPyObj()); Py_XINCREF(pyobj);
-      PickelizedPyObjRdExtInitServer *newVar(new PickelizedPyObjRdExtInitServer(this,varName,pyobj));
+      PickelizedPyObjRdExtInitServer *newVar(varc0->buildInitInstanceFrom(varName));
       newVar->incrNbClients();
       CORBA::Object_var obj(newVar->activate());
       SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
@@ -449,8 +453,7 @@ void DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExt(const std::
     {
       if(varc0->decrNbClients())
         {
-          PyObject *pyobj(varc0->getPyObj()); Py_XINCREF(pyobj);
-          PickelizedPyObjRdExtServer *newVar(new PickelizedPyObjRdExtServer(this,varName,pyobj));
+          PickelizedPyObjRdExtServer *newVar(varc0->buildStdInstanceFrom(varName));
           CORBA::Object_var obj(newVar->activate());
           SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
           p.first=obj2; p.second=newVar;
@@ -601,6 +604,35 @@ void DataScopeServerTransaction::createRdExtVarInternal(const std::string& varNa
   _vars.push_back(p);
 }
 
+void DataScopeServerTransaction::createRdExtVarFreeStyleInternal(const std::string& varName, const SALOME::ByteVec& constValue, std::vector<unsigned char>&& sha1)
+{
+  if(!isExistingVar(varName))
+    {
+      PickelizedPyObjRdExtFreeStyleServer *tmp(new PickelizedPyObjRdExtFreeStyleServer(this,varName,constValue,std::move(sha1)));
+      CORBA::Object_var ret(tmp->activate());
+      std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
+      _vars.push_back(p);
+    }
+  else
+    {
+      BasicDataServer *ds(retrieveVarInternal2(varName));
+      if(!ds)
+        {
+          std::ostringstream oss;
+          oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : internal error 1 for varname \"" << varName << "\"!";
+          throw Exception(oss.str());
+        }
+      Sha1Keeper *ds2(dynamic_cast<Sha1Keeper *>(ds));
+      if(!ds2)
+        {
+          std::ostringstream oss;
+          oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : varname \"" << varName << "\" already exists with a non RdExtFreeStyle type !";
+          throw Exception(oss.str());
+        }
+      ds2->checkSha1(varName,sha1);
+    }
+}
+
 void DataScopeServerTransaction::createRdExtInitVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
 {
   checkNotAlreadyExistingVar(varName);
@@ -635,6 +667,13 @@ SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtVarTransac(const
   return SALOME::Transaction::_narrow(obj);
 }
 
+SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtVarFreeStyleTransac(const char *varName, const SALOME::ByteVec& constValue, const SALOME::ByteVec& sha1)
+{// no check on varName done here. Will be done on perform
+  TransactionRdExtVarFreeStyleCreate *ret(new TransactionRdExtVarFreeStyleCreate(this,varName,constValue,sha1));
+  CORBA::Object_var obj(ret->activate());
+  return SALOME::Transaction::_narrow(obj);
+}
+
 SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtInitVarTransac(const char *varName, const SALOME::ByteVec& constValue)
 {
   checkNotAlreadyExistingVar(varName);
index fed46259265c0983f14143c090e71f8ace199328..58b16e57e04011a7f8174398934f22a7a70c37b5 100644 (file)
@@ -100,6 +100,7 @@ namespace SALOMESDS
     static std::string BuildTmpVarNameFrom(const std::string& varName);
   public:
     std::vector< std::string> getAllVarNames() const;
+    bool isExistingVar(const std::string& varName) const;
     void checkNotAlreadyExistingVar(const std::string& varName) const;
     void checkExistingVar(const std::string& varName) const;
     PickelizedPyObjServer *checkVarExistingAndDict(const std::string& varName);
@@ -143,6 +144,7 @@ namespace SALOMESDS
     ~DataScopeServerTransaction();
     void createRdOnlyVarInternal(const std::string& varName, const SALOME::ByteVec& constValue);
     void createRdExtVarInternal(const std::string& varName, const SALOME::ByteVec& constValue);
+    void createRdExtVarFreeStyleInternal(const std::string& varName, const SALOME::ByteVec& constValue, std::vector<unsigned char>&& sha1);
     void createRdExtInitVarInternal(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; }
@@ -156,6 +158,7 @@ namespace SALOMESDS
     void fetchAndGetAccessOfVar(const char *varName, CORBA::String_out access, SALOME::ByteVec_out data);
     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 createRdExtVarFreeStyleTransac(const char *varName, const SALOME::ByteVec& constValue, const SALOME::ByteVec& sha1);
     SALOME::Transaction_ptr createRdExtInitVarTransac(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);
index b091ceab6b1610a22d5f22a3e7188240eadd7267..1d0afd7cf275f843a7a8940255af9852e512a95f 100644 (file)
@@ -19,6 +19,7 @@
 // Author : Anthony GEAY (EDF R&D)
 
 #include "SALOMESDS_PickelizedPyObjRdExtInitServer.hxx"
+#include "SALOMESDS_PickelizedPyObjRdExtServer.hxx"
 #include "SALOMESDS_DataScopeServer.hxx"
 #include "SALOMESDS_Exception.hxx"
 
@@ -45,6 +46,12 @@ PickelizedPyObjRdExtInitServer::~PickelizedPyObjRdExtInitServer()
   Py_XDECREF(_self_deep_copy);
 }
 
+PickelizedPyObjRdExtServer *PickelizedPyObjRdExtInitServer::buildStdInstanceFrom(const std::string& varName)
+{
+  PyObject *pyobj(this->getPyObj()); Py_XINCREF(pyobj);
+  return new PickelizedPyObjRdExtServer(getFather(),varName,pyobj);
+}
+
 std::string PickelizedPyObjRdExtInitServer::getAccessStr() const
 {
   return std::string(ACCESS_REPR);
@@ -68,3 +75,9 @@ PyObject *PickelizedPyObjRdExtInitServer::DeepCopyPyObj(PyObject *pyobj)
   Py_XDECREF(mod);
   return ret;
 }
+
+PickelizedPyObjRdExtServer *PickelizedPyObjRdExtInitFreeStyleServer::buildStdInstanceFrom(const std::string& varName)
+{
+  PyObject *pyobj(this->getPyObj()); Py_XINCREF(pyobj);
+  return new PickelizedPyObjRdExtFreeStyleServer(getFather(),varName,pyobj,std::move(_sha1));
+}
index 5845c7aca1a99400116cc88170e743cd768deba8..d9e4213e269c6ac4b3674c364678838b8e2f1610 100644 (file)
 #include <Python.h>
 
 #include "SALOMESDS_PickelizedPyObjServer.hxx"
+#include "SALOMESDS_Sha1Keeper.hxx"
 
 namespace SALOMESDS
 {
+  class PickelizedPyObjRdExtServer;
+  
   /*!
    * State during the producer/consumer phase. Activated by TransactionMultiKeyAddSession transaction returned by dss.addMultiKeyValueSession.
    */
@@ -39,6 +42,7 @@ namespace SALOMESDS
     PickelizedPyObjRdExtInitServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value);
     PickelizedPyObjRdExtInitServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj);
     ~PickelizedPyObjRdExtInitServer();
+    virtual PickelizedPyObjRdExtServer *buildStdInstanceFrom(const std::string& varName);
   public:
     std::string getAccessStr() const;
     SALOME::ByteVec *fetchSerializedContent();
@@ -54,6 +58,13 @@ namespace SALOMESDS
   public:
     static const char ACCESS_REPR[];
   };
+
+  class PickelizedPyObjRdExtInitFreeStyleServer : public PickelizedPyObjRdExtInitServer, public Sha1Keeper
+  {
+  public:
+    PickelizedPyObjRdExtInitFreeStyleServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj, std::vector<unsigned char>&& sha1):PickelizedPyObjRdExtInitServer(father,varName,obj),Sha1Keeper(std::move(sha1)) { }
+    PickelizedPyObjRdExtServer *buildStdInstanceFrom(const std::string& varName) override;
+  };
 }
 
 #endif
index 11b1ea9ff48551fe3239c0edc04531339d8ab9fd..674efef0f5956eabbc692f3e1e40f82fc34395c9 100644 (file)
@@ -19,6 +19,7 @@
 // Author : Anthony GEAY (EDF R&D)
 
 #include "SALOMESDS_PickelizedPyObjRdExtServer.hxx"
+#include "SALOMESDS_PickelizedPyObjRdExtInitServer.hxx"
 #include "SALOMESDS_DataScopeServer.hxx"
 #include "SALOMESDS_Exception.hxx"
 
@@ -75,6 +76,12 @@ SALOME::PickelizedPyObjRdExtServer_ptr PickelizedPyObjRdExtServer::invokePythonM
   return SALOME::PickelizedPyObjRdExtServer::_narrow(obj);
 }
 
+PickelizedPyObjRdExtInitServer *PickelizedPyObjRdExtServer::buildInitInstanceFrom(const std::string& varName)
+{
+  PyObject *pyobj(this->getPyObj()); Py_XINCREF(pyobj);
+  return new PickelizedPyObjRdExtInitServer(getFather(),varName,pyobj);
+}
+
 void PickelizedPyObjRdExtServer::checkRdExtnessOf(const std::string& methodName, PyObject *argsPy)
 {
   if(!_self)
@@ -142,3 +149,10 @@ std::string PickelizedPyObjRdExtServer::getAccessStr() const
 {
   return std::string(ACCESS_REPR);
 }
+
+
+PickelizedPyObjRdExtInitServer *PickelizedPyObjRdExtFreeStyleServer::buildInitInstanceFrom(const std::string& varName)
+{
+  PyObject *pyobj(this->getPyObj()); Py_XINCREF(pyobj);
+  return new PickelizedPyObjRdExtInitFreeStyleServer(getFather(),varName,pyobj,std::move(_sha1));
+}
index 9f941ba845cec3d162af057da9c0ca06da30aa88..c4fbf3a9add8abd9df7069066ac4f7688866f90c 100644 (file)
 #include <Python.h>
 
 #include "SALOMESDS_PickelizedPyObjServer.hxx"
+#include "SALOMESDS_Sha1Keeper.hxx"
 
 namespace SALOMESDS
 {
+  class PickelizedPyObjRdExtInitServer;
+  
   class PickelizedPyObjRdExtServer : public PickelizedPyObjServerModifiable, public virtual POA_SALOME::PickelizedPyObjRdExtServer
   {
   public:
     PickelizedPyObjRdExtServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value);
     PickelizedPyObjRdExtServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj);
-    ~PickelizedPyObjRdExtServer();
+    virtual ~PickelizedPyObjRdExtServer();
     SALOME::PickelizedPyObjRdExtServer_ptr invokePythonMethodOn(const char *method, const SALOME::ByteVec& args);
+    virtual PickelizedPyObjRdExtInitServer *buildInitInstanceFrom(const std::string& varName);
   public:
     std::string getAccessStr() const;
   private:
@@ -47,6 +51,14 @@ namespace SALOMESDS
   public:
     static const char ACCESS_REPR[];
   };
+
+  class PickelizedPyObjRdExtFreeStyleServer : public PickelizedPyObjRdExtServer, public Sha1Keeper
+  {
+  public:
+    PickelizedPyObjRdExtFreeStyleServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value, std::vector<unsigned char>&& sha1):PickelizedPyObjRdExtServer(father,varName,value),Sha1Keeper(std::move(sha1)) { }
+    PickelizedPyObjRdExtFreeStyleServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj, std::vector<unsigned char>&& sha1):PickelizedPyObjRdExtServer(father,varName,obj),Sha1Keeper(std::move(sha1)) { }
+    PickelizedPyObjRdExtInitServer *buildInitInstanceFrom(const std::string& varName) override;
+  };
 }
 
 #endif
diff --git a/src/SALOMESDS/SALOMESDS_Sha1Keeper.cxx b/src/SALOMESDS/SALOMESDS_Sha1Keeper.cxx
new file mode 100644 (file)
index 0000000..10a4153
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright (C) 2018  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_Sha1Keeper.hxx"
+#include "SALOMESDS_Exception.hxx"
+
+#include <sstream>
+
+void SALOMESDS::Sha1Keeper::checkSha1(const std::string& varName, const std::vector<unsigned char>& sha1) const
+{
+  if(sha1!=_sha1)
+    {
+      std::ostringstream oss; oss << "PickelizedPyObjRdExtFreeStyleServer::checkSha1 : SHA1 check fails ! Attempt of corruption of rdext data ! It means that var \"" << varName << "\" has been created but with an initial value different from the new value !";
+      throw Exception(oss.str());
+    }
+}
diff --git a/src/SALOMESDS/SALOMESDS_Sha1Keeper.hxx b/src/SALOMESDS/SALOMESDS_Sha1Keeper.hxx
new file mode 100644 (file)
index 0000000..497e206
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (C) 2007-2016  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)
+
+#pragma once
+
+#include <vector>
+#include <string>
+
+namespace SALOMESDS
+{
+  class Sha1Keeper
+  {
+  public:
+    Sha1Keeper(std::vector<unsigned char>&& sha1):_sha1(std::move(sha1)) { }
+    void checkSha1(const std::string& varName, const std::vector<unsigned char>& sha1) const;
+    virtual ~Sha1Keeper() { }
+  protected:
+    //! This sha1 is a discriminant key that allows RdExt "FreeStyle" methods to ensure that a "creation" over an already present var is legal or illegal.
+    std::vector<unsigned char> _sha1;
+  };
+}
+
index 26fd9affe464d43cb3b4f57c349c4df61cc192cf..29d9a3ed88a22bbfc99ef98ff0178ac6b2662831 100644 (file)
@@ -56,7 +56,7 @@ TransactionVarCreate::TransactionVarCreate(DataScopeServerTransaction *dsct, con
 }
 
 void TransactionVarCreate::prepareRollBackInCaseOfFailure()
-{//nothing it is not a bug
+{
   checkNotAlreadyExisting();
 }
 
@@ -87,6 +87,22 @@ void TransactionRdExtVarCreate::perform()
   _dsct->createRdExtVarInternal(_var_name,data2);
 }
 
+TransactionRdExtVarFreeStyleCreate::TransactionRdExtVarFreeStyleCreate(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& constValue, const SALOME::ByteVec& sha1):TransactionRdExtVarCreate(dsct,varName,constValue)
+{
+  FromByteSeqToVB(sha1,_sha1);
+}
+
+void TransactionRdExtVarFreeStyleCreate::prepareRollBackInCaseOfFailure()
+{//nothing it is not a bug
+}
+
+void TransactionRdExtVarFreeStyleCreate::perform()
+{
+  SALOME::ByteVec data2;
+  FromVBToByteSeq(_data,data2);
+  _dsct->createRdExtVarFreeStyleInternal(_var_name,data2,std::move(_sha1));
+}
+
 void TransactionRdExtInitVarCreate::perform()
 {
   SALOME::ByteVec data2;
index c7fced70e0acedb42b34165b688d7742904156f4..4152bebd45739fdb7edc75efd082f0a63c5163bd 100644 (file)
@@ -83,6 +83,16 @@ namespace SALOMESDS
     void perform();
   };
 
+  class TransactionRdExtVarFreeStyleCreate : public TransactionRdExtVarCreate
+  {
+  public:
+    TransactionRdExtVarFreeStyleCreate(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& constValue, const SALOME::ByteVec& sha1);
+    void prepareRollBackInCaseOfFailure();
+    void perform();
+  protected:
+    std::vector<unsigned char> _sha1;
+  };
+
   class TransactionRdExtInitVarCreate : public TransactionVarCreate
   {
   public:
index 155085b4772fc565d220972f6ae63512ced3f3e5..63a237ef7f6b6e69b0580e77d8f62037fc5fde0b 100644 (file)
@@ -348,6 +348,61 @@ class SalomeSDSTest(unittest.TestCase):
     self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
     pass
 
+  def testTransaction8(self):
+    """ EDF 16833 """
+    scopeName="ScopePP"
+    dsm=salome.naming_service.Resolve("/DataServerManager")
+    dsm.cleanScopesInNS()
+    if scopeName in dsm.listScopes():
+        dsm.removeDataScope(scopeName)
+    dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
+    self.assertTrue(isCreated)
+
+    value={"a":1,"b":2}
+    value2={'a':1,'c':3,'b':2}
+
+    varName="abc"
+    t0=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),"sha1") # sha1 is the key used to compare the initial value
+    dss.atomicApply([t0])
+    self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value)
+    t1=dss.addMultiKeyValueSession(varName)
+    t1.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("c"),obj2Str(3))
+    dss.atomicApply([t1])
+    self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value2)
+    t2=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),"sha1") # key is the same as original one -> OK
+    dss.atomicApply([t2])
+    self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value2) # value2 remains untouched
+    t3=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),"sha2")
+    self.assertRaises(SALOME.SALOME_Exception,dss.atomicApply,[t3]) # sha2 != sha1 -> rejected
+    pass
+  
+  def testTransaction9(self):
+    """ EDF 16833 : use case 2. Trying to createRdExt during add key session"""
+    scopeName="ScopePP"
+    dsm=salome.naming_service.Resolve("/DataServerManager")
+    dsm.cleanScopesInNS()
+    if scopeName in dsm.listScopes():
+        dsm.removeDataScope(scopeName)
+    dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
+    self.assertTrue(isCreated)
+
+    value={"a":1,"b":2}
+    value2={'a':1,'c':3,'b':2}
+
+    varName="abc"
+    t0=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),"sha1")
+    dss.atomicApply([t0])
+    self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value)
+    t1=dss.addMultiKeyValueSession(varName)
+    t2=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),"sha1")
+    dss.atomicApply([t2])
+    self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value)
+    t1.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("c"),obj2Str(3))
+    dss.atomicApply([t1])
+    self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value2)
+    pass
+
+    
   def testLockToDump(self):
     """ Test to check that holdRequests method. This method wait for clean server status and hold it until activeRequests is called.
     Warning this method expects a not overloaded machine to be run because test is based on ellapse time.