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 createRdExtVarFreeStyleTransac(in string varName, in ByteVec constValue, in string compareFuncContent) 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);
--- /dev/null
+// 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)
+
+#pragma once
+
+#include "Python.h"
+
+namespace SALOME
+{
+ class AutoPyRef
+ {
+ public:
+ AutoPyRef(PyObject *pyobj=nullptr):_pyobj(pyobj) { }
+ ~AutoPyRef() { release(); }
+ AutoPyRef(const AutoPyRef& other):_pyobj(other._pyobj) { if(_pyobj) Py_XINCREF(_pyobj); }
+ AutoPyRef(AutoPyRef&& other):_pyobj(other._pyobj) { other._pyobj=nullptr; }
+ AutoPyRef& operator=(const AutoPyRef& other) { if(_pyobj==other._pyobj) return *this; release(); _pyobj=other._pyobj; Py_XINCREF(_pyobj); return *this; }
+ AutoPyRef& operator=(AutoPyRef&& other) { if(_pyobj==other._pyobj) return *this; release(); _pyobj=other._pyobj; other._pyobj=nullptr; return *this; }
+ operator PyObject *() { return _pyobj; }
+ void set(PyObject *pyobj) { if(pyobj==_pyobj) return ; release(); _pyobj=pyobj; }
+ PyObject *get() { return _pyobj; }
+ bool isNull() const { return _pyobj==nullptr; }
+ PyObject *retn() { if(_pyobj) Py_XINCREF(_pyobj); return _pyobj; }
+ private:
+ void release() { if(_pyobj) Py_XDECREF(_pyobj); _pyobj=nullptr; }
+ private:
+ PyObject *_pyobj;
+ };
+}
+
_vars.push_back(p);
}
-void DataScopeServerTransaction::createRdExtVarFreeStyleInternal(const std::string& varName, const SALOME::ByteVec& constValue, std::vector<unsigned char>&& sha1)
+void DataScopeServerTransaction::createRdExtVarFreeStyleInternal(const std::string& varName, const SALOME::ByteVec& constValue, std::string&& compareFuncContent, SALOME::AutoPyRef&& compareFunc)
{
if(!isExistingVar(varName))
{
- PickelizedPyObjRdExtFreeStyleServer *tmp(new PickelizedPyObjRdExtFreeStyleServer(this,varName,constValue,std::move(sha1)));
+ PickelizedPyObjRdExtFreeStyleServer *tmp(new PickelizedPyObjRdExtFreeStyleServer(this,varName,constValue,std::move(compareFuncContent),std::move(compareFunc)));
CORBA::Object_var ret(tmp->activate());
std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
_vars.push_back(p);
if(!ds2)
{
std::ostringstream oss;
- oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : varname \"" << varName << "\" already exists with a non RdExtFreeStyle type !";
+ oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : varname \"" << varName << "\" already exists with a non Sha1Keeper type !";
throw Exception(oss.str());
}
- ds2->checkSha1(varName,sha1);
+ PickelizedPyObjServer *ds3(dynamic_cast<PickelizedPyObjServer *>(ds));
+ if(!ds3)
+ {
+ std::ostringstream oss;
+ oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : varname \"" << varName << "\" already exists with a non PickelizedPyObjServer type !";
+ throw Exception(oss.str());
+ }
+ std::vector<unsigned char> constValueAsCpp;
+ Transaction::FromByteSeqToVB(constValue,constValueAsCpp);
+ SALOME::AutoPyRef newObj(PickelizedPyObjServer::GetPyObjFromPickled(constValueAsCpp,this));
+ if(newObj.isNull())
+ {
+ std::ostringstream oss;
+ oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : varname \"" << varName << "\" already exists but input pickelized object is not loadable !";
+ throw Exception(oss.str());
+ }
+ ds2->checkSame(varName,compareFuncContent,ds3->getPyObj(),newObj);
}
}
return SALOME::Transaction::_narrow(obj);
}
-SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtVarFreeStyleTransac(const char *varName, const SALOME::ByteVec& constValue, const SALOME::ByteVec& sha1)
+SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtVarFreeStyleTransac(const char *varName, const SALOME::ByteVec& constValue, const char *compareFuncContent)
{// no check on varName done here. Will be done on perform
- TransactionRdExtVarFreeStyleCreate *ret(new TransactionRdExtVarFreeStyleCreate(this,varName,constValue,sha1));
+ TransactionRdExtVarFreeStyleCreate *ret(new TransactionRdExtVarFreeStyleCreate(this,varName,constValue,compareFuncContent));
CORBA::Object_var obj(ret->activate());
return SALOME::Transaction::_narrow(obj);
}
#include "SALOMESDS_RefCountServ.hxx"
#include "SALOMESDS_AutoRefCountPtr.hxx"
#include "SALOMESDS_BasicDataServer.hxx"
+#include "SALOMESDS_Auto.hxx"
#include "SALOMESDS_Defines.hxx"
#include <Python.h>
~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 createRdExtVarFreeStyleInternal(const std::string& varName, const SALOME::ByteVec& constValue, std::string&& compareFuncContent, SALOME::AutoPyRef&& compareFunc);
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; }
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 createRdExtVarFreeStyleTransac(const char *varName, const SALOME::ByteVec& constValue, const char *compareFuncContent);
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);
PickelizedPyObjRdExtServer *PickelizedPyObjRdExtInitFreeStyleServer::buildStdInstanceFrom(const std::string& varName)
{
PyObject *pyobj(this->getPyObj()); Py_XINCREF(pyobj);
- return new PickelizedPyObjRdExtFreeStyleServer(getFather(),varName,pyobj,std::move(_sha1));
+ return new PickelizedPyObjRdExtFreeStyleServer(getFather(),varName,pyobj,std::move(_cmp_func_content),std::move(_cmp_func));
}
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)) { }
+ PickelizedPyObjRdExtInitFreeStyleServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj, std::string&& compareFuncContent, SALOME::AutoPyRef&& compareFunc):PickelizedPyObjRdExtInitServer(father,varName,obj),Sha1Keeper(std::move(compareFuncContent),std::move(compareFunc)) { }
PickelizedPyObjRdExtServer *buildStdInstanceFrom(const std::string& varName) override;
};
}
PickelizedPyObjRdExtInitServer *PickelizedPyObjRdExtFreeStyleServer::buildInitInstanceFrom(const std::string& varName)
{
PyObject *pyobj(this->getPyObj()); Py_XINCREF(pyobj);
- return new PickelizedPyObjRdExtInitFreeStyleServer(getFather(),varName,pyobj,std::move(_sha1));
+ return new PickelizedPyObjRdExtInitFreeStyleServer(getFather(),varName,pyobj,std::move(_cmp_func_content),std::move(_cmp_func));
}
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)) { }
+ PickelizedPyObjRdExtFreeStyleServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value, std::string&& compareFuncContent, SALOME::AutoPyRef&& compareFunc):PickelizedPyObjRdExtServer(father,varName,value),Sha1Keeper(std::move(compareFuncContent),std::move(compareFunc)) { }
+ PickelizedPyObjRdExtFreeStyleServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj, std::string&& compareFuncContent, SALOME::AutoPyRef&& compareFunc):PickelizedPyObjRdExtServer(father,varName,obj),Sha1Keeper(std::move(compareFuncContent),std::move(compareFunc)) { }
PickelizedPyObjRdExtInitServer *buildInitInstanceFrom(const std::string& varName) override;
};
}
std::size_t sz(pickledData.size());
PyObject *pickledDataPy(PyBytes_FromStringAndSize(NULL,sz));// agy : do not use PyUnicode_FromString because std::string hides a vector of byte.
char *buf(PyBytes_AS_STRING(pickledDataPy));// this buf can be used thanks to python documentation.
- const unsigned char *inBuf(&pickledData[0]);
+ const unsigned char *inBuf(pickledData.data());
std::copy(inBuf,inBuf+sz,buf);
PyObject *selfMeth(PyObject_GetAttrString(dsb->getPickler(),"loads"));
PyObject *args(PyTuple_New(1)); PyTuple_SetItem(args,0,pickledDataPy);
#include <sstream>
-void SALOMESDS::Sha1Keeper::checkSha1(const std::string& varName, const std::vector<unsigned char>& sha1) const
+void SALOMESDS::Sha1Keeper::checkSame(const std::string& varName,const std::string& compareFuncContent, PyObject *oldObj, PyObject *newObj)
{
- if(sha1!=_sha1)
+ if(compareFuncContent!=_cmp_func_content)
{
- 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 !";
+ std::ostringstream oss; oss << "PickelizedPyObjRdExtFreeStyleServer::checkSame : content of compare func are not exactly the same ! It should !";
+ throw Exception(oss.str());
+ }
+ SALOME::AutoPyRef resu(PyObject_CallFunctionObjArgs(_cmp_func,oldObj,newObj,nullptr));
+ if(resu.isNull())
+ {
+ std::ostringstream oss; oss << "PickelizedPyObjRdExtFreeStyleServer::checkSame : evaluation of function failed !";
+ throw Exception(oss.str());
+ }
+ if(resu.get()!=Py_False && resu.get()!=Py_True)
+ {
+ std::ostringstream oss; oss << "PickelizedPyObjRdExtFreeStyleServer::checkSame : evaluation of function is OK but a boolean is expected !";
+ throw Exception(oss.str());
+ }
+ if(resu.get()==Py_False)
+ {
+ std::ostringstream oss; oss << "PickelizedPyObjRdExtFreeStyleServer::checkSame : comparison function returns False. 2 pybjects are considered different -> createRdExtVarFreeStyleTransac fails !";
throw Exception(oss.str());
}
}
#pragma once
+#include "SALOMESDS_Auto.hxx"
+
#include <vector>
#include <string>
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;
+ Sha1Keeper(std::string&& compareFuncContent, SALOME::AutoPyRef&& compareFunc):_cmp_func_content(std::move(compareFuncContent)),_cmp_func(std::move(compareFunc)) { }
+ void checkSame(const std::string& varName,const std::string& compareFuncContent, PyObject *oldObj, PyObject *newObj);
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;
+ std::string _cmp_func_content;
+ SALOME::AutoPyRef _cmp_func;
};
}
_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)
+TransactionRdExtVarFreeStyleCreate::TransactionRdExtVarFreeStyleCreate(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& constValue, const char *compareFuncContent):_cmp_func_content(compareFuncContent),_cmp_func(nullptr),TransactionRdExtVarCreate(dsct,varName,constValue)
{
- FromByteSeqToVB(sha1,_sha1);
+ constexpr char EXPECTED_COMPARE_FUNC_NAME[]="comptchev";
+ SALOME::AutoPyRef context(PyDict_New());
+ SALOME::AutoPyRef res(PyRun_String(compareFuncContent,Py_file_input,_dsct->getGlobals(),context));
+ if(res.isNull())
+ {
+ std::ostringstream oss; oss << "TransactionRdExtVarFreeStyleCreate ctor : Fail to parse and evaluate \"" << compareFuncContent << "\" as python function !";
+ throw Exception(oss.str());
+ }
+ PyObject *func(PyDict_GetItemString(context,EXPECTED_COMPARE_FUNC_NAME));//borrowed
+ if(!func)
+ {
+ std::ostringstream oss; oss << "TransactionRdExtVarFreeStyleCreate ctor : Parsing of func is OK but not func called \"" << EXPECTED_COMPARE_FUNC_NAME << "\" is the given parsed string !";
+ throw Exception(oss.str());
+ }
+ _cmp_func = func; Py_XINCREF(func);
+ if(PyDict_DelItemString(context,EXPECTED_COMPARE_FUNC_NAME)!=0)
+ {
+ std::ostringstream oss; oss << "TransactionRdExtVarFreeStyleCreate ctor : Internal error during suppression of \"" << EXPECTED_COMPARE_FUNC_NAME << "\" key that exepect to be present ! Smells bad !";
+ throw Exception(oss.str());
+ }
}
void TransactionRdExtVarFreeStyleCreate::prepareRollBackInCaseOfFailure()
{
SALOME::ByteVec data2;
FromVBToByteSeq(_data,data2);
- _dsct->createRdExtVarFreeStyleInternal(_var_name,data2,std::move(_sha1));
+ _dsct->createRdExtVarFreeStyleInternal(_var_name,data2,std::move(_cmp_func_content),std::move(_cmp_func));
}
void TransactionRdExtInitVarCreate::perform()
#include "SALOMESDS_Defines.hxx"
#include "SALOMESDS_Exception.hxx"
#include "SALOMESDS_DataServerManager.hxx"
+#include "SALOMESDS_Auto.hxx"
#include <string>
#include <vector>
class TransactionRdExtVarFreeStyleCreate : public TransactionRdExtVarCreate
{
public:
- TransactionRdExtVarFreeStyleCreate(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& constValue, const SALOME::ByteVec& sha1);
+ TransactionRdExtVarFreeStyleCreate(DataScopeServerTransaction *dsct, const std::string& varName, const SALOME::ByteVec& constValue, const char *compareFuncContent);
void prepareRollBackInCaseOfFailure();
void perform();
protected:
- std::vector<unsigned char> _sha1;
+ std::string _cmp_func_content;
+ SALOME::AutoPyRef _cmp_func;
};
class TransactionRdExtInitVarCreate : public TransactionVarCreate
pass
def testTransaction8(self):
- """ EDF 16833 """
+ """ EDF 16833 and EDF17719 """
+ funcContent="""def comptchev(a,b):
+ return "d" not in a
+"""
scopeName="ScopePP"
dsm=salome.naming_service.Resolve("/DataServerManager")
dsm.cleanScopesInNS()
value={"a":1,"b":2}
value2={'a':1,'c':3,'b':2}
+ value3={'a':1,'c':3,'b':2,'d':4}
varName="abc"
- t0=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),"sha1".encode()) # sha1 is the key used to compare the initial value
+ t0=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent) # 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".encode()) # key is the same as original one -> OK
+ t2=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent) # func says OK this is the same (even if it is not the case) as original one -> OK
dss.atomicApply([t2])
self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value2) # value2 remains untouched
- t3=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),"sha2".encode())
- self.assertRaises(SALOME.SALOME_Exception,dss.atomicApply,[t3]) # sha2 != sha1 -> rejected
+ t3=dss.addMultiKeyValueSession(varName)
+ t3.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("d"),obj2Str(4))
+ dss.atomicApply([t3])
+ self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value3)
+ t4=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent)
+ self.assertRaises(SALOME.SALOME_Exception,dss.atomicApply,[t4]) # d is in dict pointed by var. Func returns false -> rejected
+ self.assertRaises(SALOME.SALOME_Exception,dss.fetchSerializedContent,varName) # creation in the previous line fails -> the var has been removed
pass
def testTransaction9(self):
- """ EDF 16833 : use case 2. Trying to createRdExt during add key session"""
+ """ EDF 16833 and EDF17719 : use case 2. Trying to createRdExt during add key session"""
+ funcContent="""def comptchev(a,b):
+ return a==b
+"""
scopeName="ScopePP"
dsm=salome.naming_service.Resolve("/DataServerManager")
dsm.cleanScopesInNS()
value2={'a':1,'c':3,'b':2}
varName="abc"
- t0=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),"sha1".encode())
+ t0=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent)
dss.atomicApply([t0])
self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value)
t1=dss.addMultiKeyValueSession(varName)
- t2=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),"sha1".encode())
+ t2=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent)
dss.atomicApply([t2])
self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value)
t1.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("c"),obj2Str(3))