Salome HOME
[EDF17719] : Comparison between 2 objects is now a user defined function called ...
[modules/kernel.git] / src / SALOMESDS / SALOMESDS_DataScopeServer.cxx
index 62d45fb0deaf4a643d52cdc4fece2abcb2ecd983..d8b70ef3a8f620bfddf96e5da172a5b57236d654 100644 (file)
@@ -46,38 +46,42 @@ using namespace SALOMESDS;
 
 std::size_t DataScopeServerBase::COUNTER=0;
 
+#if PY_VERSION_HEX < 0x03050000
+static char*
+Py_EncodeLocale(const wchar_t *arg, size_t *size)
+{
+       return _Py_wchar2char(arg, size);
+}
+static wchar_t*
+Py_DecodeLocale(const char *arg, size_t *size)
+{
+       return _Py_char2wchar(arg, size);
+}
+#endif
+
 void DataScopeKiller::shutdown()
 {
   Py_Finalize();
   _orb->shutdown(0);
 }
 
-RequestSwitcher::RequestSwitcher(CORBA::ORB_ptr orb)
+RequestSwitcher::RequestSwitcher(CORBA::ORB_ptr orb, DataScopeServerTransaction *ds):RequestSwitcherBase(orb),_ds(ds)
 {
-  CORBA::Object_var obj(orb->resolve_initial_references("RootPOA"));
-  PortableServer::POA_var poa(PortableServer::POA::_narrow(obj));
-  _poa_manager_under_control=poa->the_POAManager();
-  //
-  CORBA::PolicyList policies;
-  policies.length(1);
-  PortableServer::ThreadPolicy_var threadPol(poa->create_thread_policy(PortableServer::SINGLE_THREAD_MODEL));
-  policies[0]=PortableServer::ThreadPolicy::_duplicate(threadPol);
-  // all is in PortableServer::POAManager::_nil. By specifying _nil cf Advanced CORBA Programming with C++ p 506
-  // a new POA manager is created. This POA manager is independant from POA manager of the son ones.
-  _poa_for_request_control=poa->create_POA("4RqstSwitcher",PortableServer::POAManager::_nil(),policies);
-  threadPol->destroy();
-  PortableServer::POAManager_var mgr(_poa_for_request_control->the_POAManager());
-  mgr->activate();
 }
 
-void RequestSwitcher::holdRequests()
+SALOME::StringVec *RequestSwitcher::listVars()
+{
+  return _ds->listVars();
+}
+
+SALOME::ByteVec *RequestSwitcher::fetchSerializedContent(const char *varName)
 {
-  _poa_manager_under_control->hold_requests(true);
+  return _ds->fetchSerializedContent(varName);
 }
 
-void RequestSwitcher::activeRequests()
+void RequestSwitcher::fetchAndGetAccessOfVar(const char *varName, CORBA::String_out access, SALOME::ByteVec_out data)
 {
-  _poa_manager_under_control->activate();
+  return _ds->fetchAndGetAccessOfVar(varName,access,data);
 }
 
 DataScopeServerBase::DataScopeServerBase(CORBA::ORB_ptr orb, SALOME::DataScopeKiller_var killer, const std::string& scopeName):_globals(0),_locals(0),_pickler(0),_orb(CORBA::ORB::_duplicate(orb)),_name(scopeName),_killer(killer)
@@ -254,21 +258,32 @@ SALOME::SeqOfByteVec *DataScopeServerBase::getAllKeysOfVarWithTypeDict(const cha
   return ret;
 }
 
-SALOME::RequestSwitcher_ptr DataScopeServerBase::getRequestSwitcher()
+void DataScopeServerBase::takeANap(CORBA::Double napDurationInSec)
 {
-  if(_rs.isNull())
-    {
-      _rs=new RequestSwitcher(_orb);
-    }
-  CORBA::Object_var obj(_rs->activate());
-  return SALOME::RequestSwitcher::_narrow(obj);
+  if(napDurationInSec<0.)
+    throw Exception("DataScopeServerBase::takeANap : negative value !");
+#ifndef WIN32
+  struct timespec req,rem;
+  long nbSec((long)napDurationInSec);
+  double remainTime(napDurationInSec-(double)nbSec);
+  req.tv_sec=nbSec;
+  req.tv_nsec=(long)(remainTime*1000000.);
+  int ret(nanosleep(&req,&rem));
+  if(ret!=0)
+    throw Exception("DataScopeServerBase::takeANap : nap not finished as expected !");
+#else
+  throw Exception("DataScopeServerBase::takeANap : not implemented for Windows !");
+#endif
 }
 
 void DataScopeServerBase::initializePython(int argc, char *argv[])
 {
   Py_Initialize();
   PyEval_InitThreads();
-  PySys_SetArgv(argc,argv);
+  wchar_t **changed_argv = new wchar_t*[argc]; // Setting arguments
+  for (int i = 0; i < argc; i++)
+    changed_argv[i] = Py_DecodeLocale(argv[i], NULL);
+  PySys_SetArgv(argc, changed_argv);
   PyObject *mainmod(PyImport_AddModule("__main__"));
   _globals=PyModule_GetDict(mainmod);
   if(PyDict_GetItemString(_globals, "__builtins__") == NULL)
@@ -280,7 +295,7 @@ void DataScopeServerBase::initializePython(int argc, char *argv[])
     }
   _locals=PyDict_New();
   PyObject *tmp(PyList_New(0));
-  _pickler=PyImport_ImportModuleLevel(const_cast<char *>("cPickle"),_globals,_locals,tmp,-1);
+  _pickler=PyImport_ImportModuleLevel(const_cast<char *>("pickle"),_globals,_locals,tmp,0);
 }
 
 void DataScopeServerBase::registerToSalomePiDict() const
@@ -292,8 +307,8 @@ void DataScopeServerBase::registerToSalomePiDict() const
   if(!meth)
     { Py_XDECREF(mod); return ; }
   PyObject *args(PyTuple_New(2));
-  PyTuple_SetItem(args,0,PyInt_FromLong(getpid()));
-  PyTuple_SetItem(args,1,PyString_FromString("SALOME_DataScopeServerBase"));
+  PyTuple_SetItem(args,0,PyLong_FromLong(getpid()));
+  PyTuple_SetItem(args,1,PyUnicode_FromString("SALOME_DataScopeServerBase"));
   PyObject *res(PyObject_CallObject(meth,args));
   Py_XDECREF(args);
   Py_XDECREF(res);
@@ -330,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());
@@ -410,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));
@@ -434,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;
@@ -586,6 +604,51 @@ void DataScopeServerTransaction::createRdExtVarInternal(const std::string& varNa
   _vars.push_back(p);
 }
 
+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(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);
+    }
+  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 Sha1Keeper type !";
+          throw Exception(oss.str());
+        }
+      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);
+    }
+}
+
 void DataScopeServerTransaction::createRdExtInitVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
 {
   checkNotAlreadyExistingVar(varName);
@@ -620,6 +683,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 char *compareFuncContent)
+{// no check on varName done here. Will be done on perform
+  TransactionRdExtVarFreeStyleCreate *ret(new TransactionRdExtVarFreeStyleCreate(this,varName,constValue,compareFuncContent));
+  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);
@@ -645,24 +715,27 @@ void DataScopeServerTransaction::addWaitKey(KeyWaiter *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.
+  PyObject *args(PyTuple_New(1));
+  PyTuple_SetItem(args,0,keyObj); Py_XINCREF(keyObj);
   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));
+      PyObject *meth(PyObject_GetAttrString(waitKey,"__eq__"));
+      if(!meth)
+      {
+         std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " no __eq__ in pyobj !";
+         throw Exception(oss.str());
+      }
+      PyObject *res(PyObject_CallObject(meth,args));
+      Py_XDECREF(meth);
       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);
+      PyBool_Check(res);
       if(PyErr_Occurred())
         {
           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " error during interpretation of cmp(k,wk[i]) !";
@@ -670,16 +743,14 @@ void DataScopeServerTransaction::pingKey(PyObject *keyObj)
         }
       Py_XDECREF(res);
     }
+  Py_XDECREF(args);
 }
 
 void DataScopeServerTransaction::notifyKey(const std::string& varName, 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);
+  PyObject *args(PyTuple_New(1));
+  PyTuple_SetItem(args,0,keyObj); Py_XINCREF(keyObj);
   std::list< KeyWaiter *> newList,listOfEltToWakeUp;
   for(std::list< KeyWaiter *>::iterator it=_waiting_keys.begin();it!=_waiting_keys.end();it++,ii++)
     {
@@ -689,25 +760,31 @@ void DataScopeServerTransaction::notifyKey(const std::string& varName, PyObject
           continue;
         }
       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));
+      PyObject *meth(PyObject_GetAttrString(waitKey,"__eq__"));
+      if(!meth)
+      {
+         std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " no __eq__ in pyobj !";
+         throw Exception(oss.str());
+      }
+      PyObject *res(PyObject_CallObject(meth,args));
+      Py_XDECREF(meth);
+      if(!PyBool_Check(res))
+      {
+         std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " no __eq__ in pyobj !";
+         throw Exception(oss.str());
+      }
       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)
+      if(res==Py_True)
         listOfEltToWakeUp.push_back(*it);
       else
         newList.push_back(*it);
+      Py_XDECREF(res);
     }
+  Py_XDECREF(args);
   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++)
@@ -803,7 +880,7 @@ SALOME::ByteVec *DataScopeServerTransaction::waitForMonoThrRev(SALOME::KeyWaiter
   KeyWaiter *retc(dynamic_cast<KeyWaiter *>(ret));
   if(!retc)
     throw Exception("DataScopeServerTransaction::invokeMonoThr : internal error 1 !");
-  retc->_remove_ref();// restore the counter afer _poa_for_key_waiter->reference_to_servant(kw)
+  retc->_remove_ref();// restore the counter after _poa_for_key_waiter->reference_to_servant(kw)
   SALOME::ByteVec *zeRet(retc->waitForMonoThr());
   retc->enforcedRelease();
   return zeRet;
@@ -820,7 +897,7 @@ SALOME::ByteVec *DataScopeServerTransaction::waitForAndKill(SALOME::KeyWaiter_pt
   KeyWaiter *retc(dynamic_cast<KeyWaiter *>(ret));
   if(!retc)
     throw Exception("DataScopeServerTransaction::invokeMonoThr : internal error 1 !");
-  retc->_remove_ref();// restore the counter afer _poa_for_key_waiter->reference_to_servant(kw)
+  retc->_remove_ref();// restore the counter after _poa_for_key_waiter->reference_to_servant(kw)
   SALOME::ByteVec *zeRet(retc->waitForAndKill());
   retc->enforcedRelease();
   return zeRet;
@@ -867,24 +944,16 @@ void DataScopeServerTransaction::atomicApply(const SALOME::ListOfTransaction& tr
     transactionsCpp[i]->notify();
 }
 
-/*!
- * Returns borrowed reference.
- */
-PyObject *DataScopeServerTransaction::getPyCmpFunc()
+DataScopeServerTransaction::~DataScopeServerTransaction()
 {
-  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()
+SALOME::RequestSwitcher_ptr DataScopeServerTransaction::getRequestSwitcher()
 {
+  if(_rs.isNull())
+    {
+      _rs=new RequestSwitcher(_orb,this);
+    }
+  CORBA::Object_var obj(_rs->activate());
+  return SALOME::RequestSwitcher::_narrow(obj);
 }
-