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