Salome HOME
DataServerManager is now available in SSL mode
[modules/kernel.git] / src / SALOMESDS / SALOMESDS_DataScopeServer.cxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony GEAY (EDF R&D)
20
21 #include "SALOMESDS_DataScopeServer.hxx"
22 #include "SALOMESDS_DataServerManager.hxx"
23 #include "SALOMESDS_PickelizedPyObjRdOnlyServer.hxx"
24 #include "SALOMESDS_PickelizedPyObjRdExtServer.hxx"
25 #include "SALOMESDS_PickelizedPyObjRdWrServer.hxx"
26 #include "SALOMESDS_PickelizedPyObjRdExtInitServer.hxx"
27 #include "SALOMESDS_TrustTransaction.hxx"
28 #include "SALOMESDS_KeyWaiter.hxx"
29 #include "SALOMESDS_Transaction.hxx"
30 #include "SALOME_NamingService_Abstract.hxx"
31 #include "SALOMESDS_Exception.hxx"
32
33 #include <sstream>
34 #include <iterator>
35 #include <algorithm>
36
37 // agy : awful, to be factorized with ContainerManager.
38 #ifndef WIN32
39 #include <unistd.h>
40 #else
41 #include <process.h>
42 #define getpid _getpid
43 #endif
44
45 using namespace SALOMESDS;
46
47 std::size_t DataScopeServerBase::COUNTER=0;
48
49 void DataScopeKiller::shutdown()
50 {
51   Py_Finalize();
52   _orb->shutdown(0);
53 }
54
55 RequestSwitcher::RequestSwitcher(CORBA::ORB_ptr orb, DataScopeServerTransaction *ds):RequestSwitcherBase(orb),_ds(ds)
56 {
57 }
58
59 SALOME::StringVec *RequestSwitcher::listVars()
60 {
61   return _ds->listVars();
62 }
63
64 SALOME::ByteVec *RequestSwitcher::fetchSerializedContent(const char *varName)
65 {
66   return _ds->fetchSerializedContent(varName);
67 }
68
69 void RequestSwitcher::fetchAndGetAccessOfVar(const char *varName, CORBA::String_out access, SALOME::ByteVec_out data)
70 {
71   return _ds->fetchAndGetAccessOfVar(varName,access,data);
72 }
73
74 DataScopeServerBase::DataScopeServerBase(const SALOME_CPythonHelper *pyHelper, CORBA::ORB_ptr orb, SALOME::DataScopeKiller_var killer, const std::string& scopeName, SALOME_NamingService_Abstract *ns):_ns(ns),_pyHelper(pyHelper),_orb(CORBA::ORB::_duplicate(orb)),_name(scopeName),_killer(killer)
75 {
76 }
77
78 DataScopeServerBase::DataScopeServerBase(const DataScopeServerBase& other):omniServant(other),ServantBase(other),_ns(other._ns->cloneCoVar()),_pyHelper(other._pyHelper),_name(other._name),_vars(other._vars),_killer(other._killer)
79 {
80 }
81
82 DataScopeServerBase::~DataScopeServerBase()
83 {
84   for(std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it=_vars.begin();it!=_vars.end();it++)
85     {
86        BasicDataServer *obj((*it).second);
87        if(obj)
88          {
89            obj->decrRef();
90          }
91     }
92   delete _ns;
93 }
94
95 /*!
96  * Called remotely -> to protect against throw
97  */
98 void DataScopeServerBase::ping()
99 {
100 }
101
102 /*!
103  * Called remotely -> to protect against throw
104  */
105 char *DataScopeServerBase::getScopeName()
106 {
107   return CORBA::string_dup(_name.c_str());
108 }
109
110 /*!
111  * Called remotely -> to protect against throw
112  */
113 SALOME::StringVec *DataScopeServerBase::listVars()
114 {
115   SALOME::StringVec *ret(new SALOME::StringVec);
116   std::size_t sz(_vars.size());
117   ret->length((CORBA::ULong)sz); //!< TODO: size_t to CORBA::ULong
118   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(_vars.begin());
119   for(std::size_t i=0;i<sz;it++,i++)
120     {
121       BasicDataServer *obj((*it).second);
122       std::string name(obj->getVarNameCpp());
123       (*ret)[(CORBA::ULong)i]=CORBA::string_dup(name.c_str()); //!< TODO: size_t to CORBA::ULong
124     }
125   return ret;
126 }
127
128 CORBA::Boolean DataScopeServerBase::existVar(const char *varName)
129 {
130   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it(_vars.begin());
131   for(;it!=_vars.end();it++)
132     if((*it).second->getVarNameCpp()==varName)
133       return true;
134   return false;
135 }
136
137 SALOME::BasicDataServer_ptr DataScopeServerBase::retrieveVarInternal(const char *varName)
138 {
139   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(retrieveVarInternal3(varName));
140   return SALOME::BasicDataServer::_duplicate((*it0).first);
141 }
142
143 BasicDataServer *DataScopeServerBase::retrieveVarInternal2(const std::string& varName)
144 {
145   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(retrieveVarInternal3(varName));
146   return (*it0).second;
147 }
148
149 void DataScopeServerBase::deleteVar(const char *varName)
150 {
151   std::string varNameCpp(varName);
152   std::vector<std::string> allNames(getAllVarNames());
153   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varNameCpp));
154   if(it==allNames.end())
155     {
156       std::ostringstream oss; oss << "DataScopeServerBase::deleteVar : name \"" << varNameCpp << "\" does not exists ! Possibilities are :";
157       std::copy(allNames.begin(),allNames.end(),std::ostream_iterator<std::string>(oss,", "));
158       throw Exception(oss.str());
159     }
160   std::size_t pos(std::distance(allNames.begin(),it));
161   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it0(_vars.begin());
162   for(std::size_t ii=0;ii<pos;ii++,it0++);
163   (*it0).second->decrRef();
164   _vars.erase(it0);
165 }
166
167 CORBA::Boolean DataScopeServerBase::shutdownIfNotHostedByDSM(SALOME::DataScopeKiller_out killer)
168 {
169   CORBA::Object_var obj(_ns->Resolve(DataServerManager::NAME_IN_NS));
170   SALOME::DataServerManager_var dsm(SALOME::DataServerManager::_narrow(obj));
171   if(CORBA::is_nil(dsm))
172     throw Exception("Unable to reach in the NS the unique DataServerManager instance of the Session !");
173   // destroy ref in the naming service
174   std::string fullScopeName(SALOMESDS::DataServerManager::CreateAbsNameInNSFromScopeName(_name));
175   _ns->Destroy_Name(fullScopeName.c_str());
176   // establish if dsm and this shared the same POA. If yes dsm and this are collocated !
177   PortableServer::ServantBase *ret(0);
178   try
179     {
180       ret=_poa->reference_to_servant(dsm);
181     }
182   catch(...) { ret=0; }
183   //
184   if(!ret)
185     {
186       enforcedRelease();
187       killer=SALOME::DataScopeKiller::_duplicate(_killer);
188       return true;
189     }
190   else
191     {
192       ret->_remove_ref();
193       enforcedRelease();
194       killer=SALOME::DataScopeKiller::_duplicate(_killer);
195       return false;
196     }
197 }
198
199 SALOME::ByteVec *DataScopeServerBase::fetchSerializedContent(const char *varName)
200 {
201   BasicDataServer *var(retrieveVarInternal2(varName));
202   PickelizedPyObjServer *varc(dynamic_cast<PickelizedPyObjServer *>(var));
203   if(!varc)
204     {
205       std::ostringstream oss; oss << "DataScopeServerBase::fetchSerializedContent : var \"" << varName << "\" exists but it is not serialized !";
206       throw Exception(oss.str());
207     }
208   return varc->fetchSerializedContent();
209 }
210
211 SALOME::SeqOfByteVec *DataScopeServerBase::getAllKeysOfVarWithTypeDict(const char *varName)
212 {
213   BasicDataServer *var(retrieveVarInternal2(varName));
214   PickelizedPyObjServer *varc(dynamic_cast<PickelizedPyObjServer *>(var));
215   if(!varc)
216     {
217       std::ostringstream oss; oss << "DataScopeServerBase::getAllKeysOfVarWithTypeDict : var \"" << varName << "\" exists but it is not serialized !";
218       throw Exception(oss.str());
219     }
220   if(!varc->isDict())
221     {
222       std::ostringstream oss; oss << "DataScopeServerBase::getAllKeysOfVarWithTypeDict : var \"" << varName << "\" exists but it is not a PyDict !";
223       throw Exception(oss.str());
224     }
225   PyObject *keys(PyDict_Keys(varc->getPyObj()));
226   if(!PyList_Check(keys))
227     {
228       std::ostringstream oss; oss << "DataScopeServerBase::getAllKeysOfVarWithTypeDict : var \"" << varName << "\" has keys but not of type list !";
229       throw Exception(oss.str());
230     }
231   Py_ssize_t sz(PyList_Size(keys));
232   SALOME::SeqOfByteVec *ret(new SALOME::SeqOfByteVec);
233   ret->length((CORBA::ULong)sz); //!< TODO: convert Py_ssize_t in CORBA::ULong
234   for(Py_ssize_t i=0;i<sz;i++)
235     {
236       PyObject *item(PyList_GetItem(keys,i));
237       Py_XINCREF(item);
238       std::string pickel(varc->pickelize(item));//item consumed
239       PickelizedPyObjServer::FromCppToByteSeq(pickel,(*ret)[(CORBA::ULong)i]); //!< TODO: convert Py_ssize_t in CORBA::ULong
240     }
241   Py_XDECREF(keys);
242   return ret;
243 }
244
245 SALOME::ByteVec *DataScopeServerBase::getValueOfVarWithTypeDict(const char *varName, const SALOME::ByteVec& constKey)
246 {
247   BasicDataServer *var(retrieveVarInternal2(varName));
248   PickelizedPyObjServer *varc(dynamic_cast<PickelizedPyObjServer *>(var));
249   if(!varc)
250     {
251       std::ostringstream oss; oss << "DataScopeServerBase::getValueOfVarWithTypeDict : var \"" << varName << "\" exists but it is not serialized !";
252       throw Exception(oss.str());
253     }
254   if(!varc->isDict())
255     {
256       std::ostringstream oss; oss << "DataScopeServerBase::getValueOfVarWithTypeDict : var \"" << varName << "\" exists but it is not a PyDict !";
257       throw Exception(oss.str());
258     }
259   //
260   std::string keyCpp;
261   PickelizedPyObjServer::FromByteSeqToCpp(constKey,keyCpp);
262   SALOME::AutoPyRef key(PickelizedPyObjServer::GetPyObjFromPickled(keyCpp,this));
263   PyObject *value(PyDict_GetItem(varc->getPyObj(),key.get()));//borrowed
264   if(!value)
265     {
266       std::ostringstream oss; oss << "DataScopeServerBase::getValueOfVarWithTypeDict : var \"" << varName << "\" seems to not have key specified !";
267       throw Exception(oss.str());
268     }
269   Py_XINCREF(value);
270   std::string ret(PickelizedPyObjServer::Pickelize(value,this));//value is consumed
271   return PickelizedPyObjServer::FromCppToByteSeq(ret);
272 }
273
274 void DataScopeServerBase::takeANap(CORBA::Double napDurationInSec)
275 {
276   if(napDurationInSec<0.)
277     throw Exception("DataScopeServerBase::takeANap : negative value !");
278 #ifndef WIN32
279   struct timespec req,rem;
280   long nbSec((long)napDurationInSec);
281   double remainTime(napDurationInSec-(double)nbSec);
282   req.tv_sec=nbSec;
283   req.tv_nsec=(long)(remainTime*1000000.);
284   int ret(nanosleep(&req,&rem));
285   if(ret!=0)
286     throw Exception("DataScopeServerBase::takeANap : nap not finished as expected !");
287 #else
288   throw Exception("DataScopeServerBase::takeANap : not implemented for Windows !");
289 #endif
290 }
291
292 void DataScopeServerBase::registerToSalomePiDict() const
293 {
294   _pyHelper->registerToSalomePiDict("SALOME_DataScopeServerBase",getpid());
295 }
296
297 void DataScopeServerBase::setPOA(PortableServer::POA_var poa)
298 {
299   _poa=poa;
300 }
301
302 void DataScopeServerBase::registerInNS(SALOME::DataScopeServerBase_ptr ptr)
303 {
304   std::string fullScopeName(SALOMESDS::DataServerManager::CreateAbsNameInNSFromScopeName(_name));
305   _ns->Register(ptr,fullScopeName.c_str());
306 }
307
308 std::string DataScopeServerBase::BuildTmpVarNameFrom(const std::string& varName)
309 {
310   std::ostringstream oss;
311   oss << varName << "@" << COUNTER++;
312   return oss.str();
313 }
314
315 std::vector< std::string > DataScopeServerBase::getAllVarNames() const
316 {
317   std::size_t sz(_vars.size());
318   std::vector<std::string> ret(sz);
319   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it(_vars.begin());
320   for(std::size_t i=0;i<sz;it++,i++)
321     ret[i]=(*it).second->getVarNameCpp();
322   return ret;
323 }
324
325 bool DataScopeServerBase::isExistingVar(const std::string& varName) const
326 {
327   std::vector<std::string> allNames(getAllVarNames());
328   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
329   return it!=allNames.end();
330 }
331
332 void DataScopeServerBase::checkNotAlreadyExistingVar(const std::string& varName) const
333 {
334   if(isExistingVar(varName))
335     {
336       std::ostringstream oss; oss << "DataScopeServerBase::checkNotAlreadyExistingVar : name \"" << varName << "\" already exists !";
337       throw Exception(oss.str());
338     }
339 }
340
341 void DataScopeServerBase::checkExistingVar(const std::string& varName) const
342 {
343   std::vector<std::string> allNames(getAllVarNames());
344   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
345   if(it==allNames.end())
346     {
347       std::ostringstream oss; oss << "DataScopeServerBase::checkExistingVar : name \"" << varName << "\" does not exist !";
348       throw Exception(oss.str());
349     }
350 }
351
352 PickelizedPyObjServer *DataScopeServerBase::checkVarExistingAndDict(const std::string& varName)
353 {
354   checkExistingVar(varName);
355   BasicDataServer *var(retrieveVarInternal2(varName.c_str()));
356   PickelizedPyObjServer *ret(dynamic_cast<PickelizedPyObjServer *>(var));
357   if(!ret)
358     {
359       std::ostringstream oss; oss << "TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure : var \"" << varName << "\"exists but it is not serialized !";
360       throw Exception(oss.str());
361     }
362   if(!ret->isDict())
363     {
364       std::ostringstream oss; oss << "TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure : var \"" << varName << "\"exists but it is not a Dict !";
365       throw Exception(oss.str());
366     }
367   return ret;
368 }
369
370 void DataScopeServerBase::moveStatusOfVarFromRdWrToRdOnly(const std::string& varName)
371 {
372   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
373   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
374   PickelizedPyObjRdWrServer *varc(dynamic_cast<PickelizedPyObjRdWrServer *>(p.second));
375   if(!varc)
376     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdWrToRdOnly : var is not a RdWr !");
377   PyObject *pyobj(varc->getPyObj()); Py_XINCREF(pyobj);
378   PickelizedPyObjRdOnlyServer *newVar(new PickelizedPyObjRdOnlyServer(this,varName,pyobj));
379   CORBA::Object_var obj(newVar->activate());
380   SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
381   p.first=obj2; p.second=newVar;
382   varc->decrRef();
383 }
384
385 void DataScopeServerBase::moveStatusOfVarFromRdOnlyToRdWr(const std::string& varName)
386 {
387   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
388   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
389   PickelizedPyObjRdOnlyServer *varc(dynamic_cast<PickelizedPyObjRdOnlyServer *>(p.second));
390   if(!varc)
391     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdOnlyToRdWr : var is not a RdWr !");
392   PyObject *pyobj(varc->getPyObj()); Py_XINCREF(pyobj);
393   PickelizedPyObjRdWrServer *newVar(new PickelizedPyObjRdWrServer(this,varName,pyobj));
394   CORBA::Object_var obj(newVar->activate());
395   SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
396   p.first=obj2; p.second=newVar;
397   varc->decrRef();
398 }
399
400 void DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExtInit(const std::string& varName)
401 {
402   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
403   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
404   PickelizedPyObjRdExtServer *varc0(dynamic_cast<PickelizedPyObjRdExtServer *>(p.second));
405   PickelizedPyObjRdExtInitServer *varc1(dynamic_cast<PickelizedPyObjRdExtInitServer *>(p.second));
406   if(!varc0 && !varc1)
407     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExtInit : var is neither RdExt nor RdExtInit !");
408   if(varc0)
409     {
410       PickelizedPyObjRdExtInitServer *newVar(varc0->buildInitInstanceFrom(varName));
411       newVar->incrNbClients();
412       CORBA::Object_var obj(newVar->activate());
413       SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
414       p.first=obj2; p.second=newVar;
415       varc0->decrRef();
416     }
417   else
418     varc1->incrNbClients();
419 }
420
421 void DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExt(const std::string& varName)
422 {
423   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
424   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
425   PickelizedPyObjRdExtInitServer *varc0(dynamic_cast<PickelizedPyObjRdExtInitServer *>(p.second));
426   PickelizedPyObjRdExtServer *varc1(dynamic_cast<PickelizedPyObjRdExtServer *>(p.second));
427   if(!varc0 && !varc1)
428     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExt : var is not a RdExtInit !");
429   if(varc0)
430     {
431       if(varc0->decrNbClients())
432         {
433           PickelizedPyObjRdExtServer *newVar(varc0->buildStdInstanceFrom(varName));
434           CORBA::Object_var obj(newVar->activate());
435           SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
436           p.first=obj2; p.second=newVar;
437           varc0->decrRef();
438         }
439     }
440 }
441
442 std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator DataScopeServerBase::retrieveVarInternal3(const std::string& varName) const
443 {
444   std::vector<std::string> allNames(getAllVarNames());
445   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
446   if(it==allNames.end())
447     {
448       std::ostringstream oss; oss << "DataScopeServerBase::retrieveVarInternal3 : name \"" << varName << "\" does not exists ! Possibilities are :";
449       std::copy(allNames.begin(),allNames.end(),std::ostream_iterator<std::string>(oss,", "));
450       throw Exception(oss.str());
451     }
452   std::size_t pos(std::distance(allNames.begin(),it));
453   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(_vars.begin());
454   for(std::size_t i=0;i<pos;i++,it0++);
455   return it0;
456 }
457
458 std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator DataScopeServerBase::retrieveVarInternal4(const std::string& varName)
459 {
460   std::vector<std::string> allNames(getAllVarNames());
461   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
462   if(it==allNames.end())
463     {
464       std::ostringstream oss; oss << "DataScopeServerBase::retrieveVarInternal4 : name \"" << varName << "\" does not exists ! Possibilities are :";
465       std::copy(allNames.begin(),allNames.end(),std::ostream_iterator<std::string>(oss,", "));
466       throw Exception(oss.str());
467     }
468   std::size_t pos(std::distance(allNames.begin(),it));
469   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it0(_vars.begin());
470   for(std::size_t i=0;i<pos;i++,it0++);
471   return it0;
472 }
473
474 ///////
475
476 DataScopeServer::DataScopeServer(const SALOME_CPythonHelper *pyHelper, CORBA::ORB_ptr orb, SALOME::DataScopeKiller_var killer, const std::string& scopeName, SALOME_NamingService_Abstract *ns):DataScopeServerBase(pyHelper,orb,killer,scopeName,ns)
477 {
478 }
479
480 DataScopeServer::DataScopeServer(const DataScopeServer& other):omniServant(other),ServantBase(other),DataScopeServerBase(other)
481 {
482 }
483
484 SALOME::PickelizedPyObjRdOnlyServer_ptr DataScopeServer::createRdOnlyVar(const char *varName, const SALOME::ByteVec& constValue)
485 {
486   std::string varNameCpp(varName);
487   checkNotAlreadyExistingVar(varNameCpp);
488   PickelizedPyObjRdOnlyServer *tmp(new PickelizedPyObjRdOnlyServer(this,varNameCpp,constValue));
489   CORBA::Object_var ret(tmp->activate());
490   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
491   _vars.push_back(p);
492   return SALOME::PickelizedPyObjRdOnlyServer::_narrow(ret);
493 }
494
495 SALOME::PickelizedPyObjRdExtServer_ptr DataScopeServer::createRdExtVar(const char *varName, const SALOME::ByteVec& constValue)
496 {
497   std::string varNameCpp(varName);
498   checkNotAlreadyExistingVar(varNameCpp);
499   PickelizedPyObjRdExtServer *tmp(new PickelizedPyObjRdExtServer(this,varNameCpp,constValue));
500   CORBA::Object_var ret(tmp->activate());
501   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
502   _vars.push_back(p);
503   return SALOME::PickelizedPyObjRdExtServer::_narrow(ret);
504 }
505
506 SALOME::PickelizedPyObjRdWrServer_ptr DataScopeServer::createRdWrVar(const char *typeName, const char *varName)
507 {
508   std::string varNameCpp(varName),typeNameCpp(typeName);
509   checkNotAlreadyExistingVar(varNameCpp);
510   PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,typeNameCpp,varNameCpp));
511   CORBA::Object_var ret(tmp->activate());
512   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
513   _vars.push_back(p);
514   return SALOME::PickelizedPyObjRdWrServer::_narrow(ret);
515 }
516
517 DataScopeServer::~DataScopeServer()
518 {
519 }
520
521 ////////
522
523 DataScopeServerTransaction::DataScopeServerTransaction(const SALOME_CPythonHelper *pyHelper, CORBA::ORB_ptr orb, SALOME::DataScopeKiller_var killer, const std::string& scopeName, SALOME_NamingService_Abstract *ns):DataScopeServerBase(pyHelper,orb,killer,scopeName,ns)
524 {
525   CORBA::Object_var obj(_orb->resolve_initial_references("RootPOA"));
526   PortableServer::POA_var poa(PortableServer::POA::_narrow(obj));
527   //
528   PortableServer::POAManager_var mgr(poa->the_POAManager());
529   CORBA::PolicyList policies;
530   policies.length(1);
531   PortableServer::ThreadPolicy_var threadPol(poa->create_thread_policy(PortableServer::ORB_CTRL_MODEL));
532   policies[0]=PortableServer::ThreadPolicy::_duplicate(threadPol);
533   PortableServer::POA_var poa2(poa->create_POA("POAForWaiters",mgr,policies));
534   threadPol->destroy();
535   //
536   _poa_for_key_waiter=poa2;
537 }
538
539 DataScopeServerTransaction::DataScopeServerTransaction(const DataScopeServerTransaction& other):omniServant(other),ServantBase(other),DataScopeServerBase(other),_poa_for_key_waiter(other.getPOA4KeyWaiter())
540 {
541 }
542
543 char *DataScopeServerTransaction::getAccessOfVar(const char *varName)
544 {
545   std::string varNameCpp(varName);
546   checkExistingVar(varNameCpp);
547   BasicDataServer *var(retrieveVarInternal2(varName));
548   if(!var)
549     throw Exception("DataScopeServerTransaction::getAccessOfVar : variable is NULL !");
550   PickelizedPyObjServer *varc(dynamic_cast<PickelizedPyObjServer *>(var));
551   if(!varc)
552     throw Exception("DataScopeServerTransaction::getAccessOfVar : variable is not of type PickelizedPyObjServer !");
553   std::string ret(varc->getAccessStr());
554   return CORBA::string_dup(ret.c_str());
555 }
556
557 /*!
558  * This method is here to retrieve atomically accessStr and picklization.
559  */
560 void DataScopeServerTransaction::fetchAndGetAccessOfVar(const char *varName, CORBA::String_out access, SALOME::ByteVec_out data)
561 {
562   access=getAccessOfVar(varName);
563   data=fetchSerializedContent(varName);
564 }
565
566 void DataScopeServerTransaction::createRdOnlyVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
567 {
568   checkNotAlreadyExistingVar(varName);
569   PickelizedPyObjRdOnlyServer *tmp(new PickelizedPyObjRdOnlyServer(this,varName,constValue));
570   CORBA::Object_var ret(tmp->activate());
571   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
572   _vars.push_back(p);
573 }
574
575 void DataScopeServerTransaction::createRdExtVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
576 {
577   checkNotAlreadyExistingVar(varName);
578   PickelizedPyObjRdExtServer *tmp(new PickelizedPyObjRdExtServer(this,varName,constValue));
579   CORBA::Object_var ret(tmp->activate());
580   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
581   _vars.push_back(p);
582 }
583
584 void DataScopeServerTransaction::createRdExtVarFreeStyleInternal(const std::string& varName, const SALOME::ByteVec& constValue, std::string&& compareFuncContent, SALOME::AutoPyRef&& compareFunc)
585 {
586   if(!isExistingVar(varName))
587     {
588       PickelizedPyObjRdExtFreeStyleServer *tmp(new PickelizedPyObjRdExtFreeStyleServer(this,varName,constValue,std::move(compareFuncContent),std::move(compareFunc)));
589       CORBA::Object_var ret(tmp->activate());
590       std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
591       _vars.push_back(p);
592     }
593   else
594     {
595       BasicDataServer *ds(retrieveVarInternal2(varName));
596       if(!ds)
597         {
598           std::ostringstream oss;
599           oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : internal error 1 for varname \"" << varName << "\"!";
600           throw Exception(oss.str());
601         }
602       Sha1Keeper *ds2(dynamic_cast<Sha1Keeper *>(ds));
603       if(!ds2)
604         {
605           std::ostringstream oss;
606           oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : varname \"" << varName << "\" already exists with a non Sha1Keeper type !";
607           throw Exception(oss.str());
608         }
609       PickelizedPyObjServer *ds3(dynamic_cast<PickelizedPyObjServer *>(ds));
610       if(!ds3)
611         {
612           std::ostringstream oss;
613           oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : varname \"" << varName << "\" already exists with a non PickelizedPyObjServer type !";
614           throw Exception(oss.str());
615         }
616       std::vector<unsigned char> constValueAsCpp;
617       Transaction::FromByteSeqToVB(constValue,constValueAsCpp);
618       SALOME::AutoPyRef newObj(PickelizedPyObjServer::GetPyObjFromPickled(constValueAsCpp,this));
619       if(newObj.isNull())
620         {
621           std::ostringstream oss;
622           oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : varname \"" << varName << "\" already exists but input pickelized object is not loadable !";
623           throw Exception(oss.str());
624         }
625       ds2->checkSame(varName,compareFuncContent,ds3->getPyObj(),newObj);
626     }
627 }
628
629 void DataScopeServerTransaction::createRdExtInitVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
630 {
631   checkNotAlreadyExistingVar(varName);
632   PickelizedPyObjRdExtInitServer *tmp(new PickelizedPyObjRdExtInitServer(this,varName,constValue));
633   CORBA::Object_var ret(tmp->activate());
634   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
635   _vars.push_back(p);
636 }
637
638 void DataScopeServerTransaction::createRdWrVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
639 {
640   checkNotAlreadyExistingVar(varName);
641   PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,varName,constValue));
642   CORBA::Object_var ret(tmp->activate());
643   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
644   _vars.push_back(p);
645 }
646
647 SALOME::Transaction_ptr DataScopeServerTransaction::createRdOnlyVarTransac(const char *varName, const SALOME::ByteVec& constValue)
648 {
649   checkNotAlreadyExistingVar(varName);
650   TransactionRdOnlyVarCreate *ret(new TransactionRdOnlyVarCreate(this,varName,constValue));
651   CORBA::Object_var obj(ret->activate());
652   return SALOME::Transaction::_narrow(obj);
653 }
654
655 SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtVarTransac(const char *varName, const SALOME::ByteVec& constValue)
656 {
657   checkNotAlreadyExistingVar(varName);
658   TransactionRdExtVarCreate *ret(new TransactionRdExtVarCreate(this,varName,constValue));
659   CORBA::Object_var obj(ret->activate());
660   return SALOME::Transaction::_narrow(obj);
661 }
662
663 SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtVarFreeStyleTransac(const char *varName, const SALOME::ByteVec& constValue, const char *compareFuncContent)
664 {// no check on varName done here. Will be done on perform
665   TransactionRdExtVarFreeStyleCreate *ret(new TransactionRdExtVarFreeStyleCreate(this,varName,constValue,compareFuncContent));
666   CORBA::Object_var obj(ret->activate());
667   return SALOME::Transaction::_narrow(obj);
668 }
669
670 SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtInitVarTransac(const char *varName, const SALOME::ByteVec& constValue)
671 {
672   checkNotAlreadyExistingVar(varName);
673   TransactionRdExtInitVarCreate *ret(new TransactionRdExtInitVarCreate(this,varName,constValue));
674   CORBA::Object_var obj(ret->activate());
675   return SALOME::Transaction::_narrow(obj);
676 }
677
678 SALOME::Transaction_ptr DataScopeServerTransaction::createRdWrVarTransac(const char *varName, const SALOME::ByteVec& constValue)
679 {
680   checkNotAlreadyExistingVar(varName);
681   TransactionRdWrVarCreate *ret(new TransactionRdWrVarCreate(this,varName,constValue));
682   CORBA::Object_var obj(ret->activate());
683   return SALOME::Transaction::_narrow(obj);
684 }
685
686 void DataScopeServerTransaction::addWaitKey(KeyWaiter *kw)
687 {
688   if(!kw)
689     throw Exception("DataScopeServerTransaction::addWaitKey : NULL input object !");
690   _waiting_keys.push_back(kw);
691 }
692
693 void DataScopeServerTransaction::pingKey(PyObject *keyObj)
694 {
695   std::size_t ii(0);
696   // this part does nothing except to be sure that in notify key all will be OK.
697   PyObject *args(PyTuple_New(1));
698   PyTuple_SetItem(args,0,keyObj); Py_XINCREF(keyObj);
699   for(std::list< KeyWaiter *>::iterator it=_waiting_keys.begin();it!=_waiting_keys.end();it++,ii++)
700     {
701       PyObject *waitKey((*it)->getKeyPyObj());
702       PyObject *meth(PyObject_GetAttrString(waitKey,"__eq__"));
703       if(!meth)
704       {
705           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " no __eq__ in pyobj !";
706           throw Exception(oss.str());
707       }
708       PyObject *res(PyObject_CallObject(meth,args));
709       Py_XDECREF(meth);
710       if(res==NULL)
711         {
712           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " error during cmp(k,wk[i]) !";
713           throw Exception(oss.str());
714         }
715       PyBool_Check(res);
716       if(PyErr_Occurred())
717         {
718           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " error during interpretation of cmp(k,wk[i]) !";
719           throw Exception(oss.str());
720         }
721       Py_XDECREF(res);
722     }
723   Py_XDECREF(args);
724 }
725
726 void DataScopeServerTransaction::notifyKey(const std::string& varName, PyObject *keyObj, PyObject *valueObj)
727 {
728   std::size_t ii(0);
729   PyObject *args(PyTuple_New(1));
730   PyTuple_SetItem(args,0,keyObj); Py_XINCREF(keyObj);
731   std::list< KeyWaiter *> newList,listOfEltToWakeUp;
732   for(std::list< KeyWaiter *>::iterator it=_waiting_keys.begin();it!=_waiting_keys.end();it++,ii++)
733     {
734       if((*it)->getVarName()!=varName)
735         {
736           newList.push_back(*it);
737           continue;
738         }
739       PyObject *waitKey((*it)->getKeyPyObj());
740       PyObject *meth(PyObject_GetAttrString(waitKey,"__eq__"));
741       if(!meth)
742       {
743           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " no __eq__ in pyobj !";
744           throw Exception(oss.str());
745       }
746       PyObject *res(PyObject_CallObject(meth,args));
747       Py_XDECREF(meth);
748       if(!PyBool_Check(res))
749       {
750           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " no __eq__ in pyobj !";
751           throw Exception(oss.str());
752       }
753       if(PyErr_Occurred())
754         {
755           std::ostringstream oss; oss << "DataScopeServerTransaction::notifyKey : MAIN INTERNAL ERROR ! for object id #" << ii << " error during interpretation of cmp(k,wk[i]) !";
756           throw Exception(oss.str());
757         }
758       if(res==Py_True)
759         listOfEltToWakeUp.push_back(*it);
760       else
761         newList.push_back(*it);
762       Py_XDECREF(res);
763     }
764   Py_XDECREF(args);
765   for(std::list< KeyWaiter *>::iterator it=listOfEltToWakeUp.begin();it!=listOfEltToWakeUp.end();it++)
766     (*it)->valueJustCome(valueObj);
767   for(std::list< KeyWaiter *>::iterator it=listOfEltToWakeUp.begin();it!=listOfEltToWakeUp.end();it++)
768     (*it)->go();
769   _waiting_keys=newList;
770 }
771
772 SALOME::Transaction_ptr DataScopeServerTransaction::addKeyValueInVarHard(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value)
773 {
774   checkVarExistingAndDict(varName);
775   TransactionAddKeyValueHard *ret(new TransactionAddKeyValueHard(this,varName,key,value));
776   CORBA::Object_var obj(ret->activate());
777   return SALOME::Transaction::_narrow(obj);
778 }
779
780 SALOME::Transaction_ptr DataScopeServerTransaction::addKeyValueInVarErrorIfAlreadyExisting(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value)
781 {
782   checkVarExistingAndDict(varName);
783   TransactionAddKeyValueErrorIfAlreadyExisting *ret(new TransactionAddKeyValueErrorIfAlreadyExisting(this,varName,key,value));
784   CORBA::Object_var obj(ret->activate());
785   return SALOME::Transaction::_narrow(obj);
786 }
787
788 SALOME::TransactionMultiKeyAddSession_ptr DataScopeServerTransaction::addMultiKeyValueSession(const char *varName)
789 {
790   checkVarExistingAndDict(varName);
791   TransactionMultiKeyAddSession *ret(new TransactionMultiKeyAddSession(this,varName));
792   CORBA::Object_var obj(ret->activate());
793   return SALOME::TransactionMultiKeyAddSession::_narrow(obj);
794 }
795
796 SALOME::Transaction_ptr DataScopeServerTransaction::removeKeyInVarErrorIfNotAlreadyExisting(const char *varName, const SALOME::ByteVec& key)
797 {
798   checkVarExistingAndDict(varName);
799   TransactionRemoveKeyInVarErrorIfNotAlreadyExisting *ret(new TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(this,varName,key));
800   CORBA::Object_var obj(ret->activate());
801   return SALOME::Transaction::_narrow(obj);
802 }
803
804 SALOME::TransactionRdWrAccess_ptr DataScopeServerTransaction::createWorkingVarTransac(const char *varName, const SALOME::ByteVec& constValue)
805 {
806   std::string varNameCpp(varName);
807   checkNotAlreadyExistingVar(varName);
808   PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,varNameCpp,constValue));
809   CORBA::Object_var obj(tmp->activate());
810   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(obj),tmp);
811   _vars.push_back(p);
812   //
813   TransactionMorphRdWrIntoRdOnly *ret(new TransactionMorphRdWrIntoRdOnly(this,varName));
814   CORBA::Object_var obj2(ret->activate());
815   return SALOME::TransactionRdWrAccess::_narrow(obj2);
816 }
817
818 SALOME::Transaction_ptr DataScopeServerTransaction::killVarTransac(const char *varName)
819 {
820   std::string varNameCpp(varName);
821   checkExistingVar(varNameCpp);
822   //
823   TransactionKillVar *ret(new TransactionKillVar(this,varName));
824   CORBA::Object_var obj2(ret->activate());
825   return SALOME::Transaction::_narrow(obj2);
826 }
827
828 SALOME::KeyWaiter_ptr DataScopeServerTransaction::waitForKeyInVar(const char *varName, const SALOME::ByteVec& keyVal)
829 {
830   PickelizedPyObjServer *pickelObj(checkVarExistingAndDict(varName));
831   KeyWaiter *ret(new KeyWaiter(pickelObj,keyVal));
832   CORBA::Object_var obj(ret->activate());//KeyWaiter instance activated inside a multithread POA contrary to all of objects in SALOMESDS in single thread !
833   return SALOME::KeyWaiter::_narrow(obj);
834 }
835
836 SALOME::KeyWaiter_ptr DataScopeServerTransaction::waitForKeyInVarAndKillIt(const char *varName, const SALOME::ByteVec& keyVal, SALOME::Transaction_out transac)
837 {
838   PickelizedPyObjServer *pickelObj(checkVarExistingAndDict(varName));
839   KeyWaiter *ret0(new KeyWaiter(pickelObj,keyVal));
840   CORBA::Object_var obj(ret0->activate());//KeyWaiter instance activated inside a multithread POA contrary to all of objects in SALOMESDS in single thread !
841   //
842   TransactionRemoveKeyInVarErrorIfNotAlreadyExisting *ret1(new TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(this,varName,keyVal));
843   CORBA::Object_var obj2(ret1->activate());
844   transac=SALOME::Transaction::_narrow(obj2);
845   //
846   return SALOME::KeyWaiter::_narrow(obj);
847 }
848
849 SALOME::ByteVec *DataScopeServerTransaction::waitForMonoThrRev(SALOME::KeyWaiter_ptr kw)
850 {
851   PortableServer::ServantBase *ret(0);
852   try
853     {
854       ret=_poa_for_key_waiter->reference_to_servant(kw);// Warning ref cnt of ret has been incremented !
855     }
856   catch(...) { ret=0; }
857   KeyWaiter *retc(dynamic_cast<KeyWaiter *>(ret));
858   if(!retc)
859     throw Exception("DataScopeServerTransaction::invokeMonoThr : internal error 1 !");
860   retc->_remove_ref();// restore the counter after _poa_for_key_waiter->reference_to_servant(kw)
861   SALOME::ByteVec *zeRet(retc->waitForMonoThr());
862   retc->enforcedRelease();
863   return zeRet;
864 }
865
866 SALOME::ByteVec *DataScopeServerTransaction::waitForAndKill(SALOME::KeyWaiter_ptr kw)
867 {
868   PortableServer::ServantBase *ret(0);
869   try
870     {
871       ret=_poa_for_key_waiter->reference_to_servant(kw);// Warning ref cnt of ret has been incremented !
872     }
873   catch(...) { ret=0; }
874   KeyWaiter *retc(dynamic_cast<KeyWaiter *>(ret));
875   if(!retc)
876     throw Exception("DataScopeServerTransaction::invokeMonoThr : internal error 1 !");
877   retc->_remove_ref();// restore the counter after _poa_for_key_waiter->reference_to_servant(kw)
878   SALOME::ByteVec *zeRet(retc->waitForAndKill());
879   retc->enforcedRelease();
880   return zeRet;
881 }
882
883 void DataScopeServerTransaction::atomicApply(const SALOME::ListOfTransaction& transactions)
884 {
885   std::size_t sz(transactions.length());
886   if(sz==0)
887     return ;
888   std::vector< AutoServantPtr<Transaction> > transactionsCpp(sz);
889   for(std::size_t i=0;i<sz;i++)
890     {
891       PortableServer::ServantBase *eltBase(0);
892       Transaction *elt(0);
893       try
894         {
895           eltBase=_poa->reference_to_servant(transactions[(CORBA::ULong)i]); //!< TODO: size_t to CORBA::ULong
896           elt=dynamic_cast<Transaction *>(eltBase);
897         }
898       catch(...)
899         {
900           std::ostringstream oss; oss << "DataScopeServerTransaction::atomicApply : the elt #" << i << " is invalid !";
901           throw Exception(oss.str());
902         }
903       if(!elt)
904         {
905           std::ostringstream oss; oss << "DataScopeServerTransaction::atomicApply : the elt #" << i << " is null ?";
906           throw Exception(oss.str());
907         }
908       elt->_remove_ref();
909       transactionsCpp[i]=elt;
910     }
911   {// important do not merge loops ! 
912     std::vector<TrustTransaction> transactions2(sz);
913     bool mustRollback(true);
914     for(std::size_t i=0;i<sz;i++)
915       transactions2[i].setTransaction(transactionsCpp[i],&mustRollback);
916     for(std::size_t i=0;i<sz;i++)
917       transactions2[i].operate();
918     mustRollback=false;
919   }
920   for(std::size_t i=0;i<sz;i++)
921     transactionsCpp[i]->notify();
922 }
923
924 DataScopeServerTransaction::~DataScopeServerTransaction()
925 {
926 }
927
928 SALOME::RequestSwitcher_ptr DataScopeServerTransaction::getRequestSwitcher()
929 {
930   if(_rs.isNull())
931     {
932       _rs=new RequestSwitcher(_orb,this);
933     }
934   CORBA::Object_var obj(_rs->activate());
935   return SALOME::RequestSwitcher::_narrow(obj);
936 }