Salome HOME
Copyright update 2020
[modules/kernel.git] / src / SALOMESDS / SALOMESDS_DataScopeServer.cxx
1 // Copyright (C) 2007-2020  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.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):_pyHelper(pyHelper),_orb(CORBA::ORB::_duplicate(orb)),_name(scopeName),_killer(killer)
75 {
76 }
77
78 DataScopeServerBase::DataScopeServerBase(const DataScopeServerBase& other):omniServant(other),ServantBase(other),_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 }
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(sz);
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)[i]=CORBA::string_dup(name.c_str());
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   SALOME_NamingService ns(_orb);
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(sz);
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)[i]);
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   SALOME_NamingService ns(_orb);
306   ns.Register(ptr,fullScopeName.c_str());
307 }
308
309 std::string DataScopeServerBase::BuildTmpVarNameFrom(const std::string& varName)
310 {
311   std::ostringstream oss;
312   oss << varName << "@" << COUNTER++;
313   return oss.str();
314 }
315
316 std::vector< std::string > DataScopeServerBase::getAllVarNames() const
317 {
318   std::size_t sz(_vars.size());
319   std::vector<std::string> ret(sz);
320   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it(_vars.begin());
321   for(std::size_t i=0;i<sz;it++,i++)
322     ret[i]=(*it).second->getVarNameCpp();
323   return ret;
324 }
325
326 bool DataScopeServerBase::isExistingVar(const std::string& varName) const
327 {
328   std::vector<std::string> allNames(getAllVarNames());
329   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
330   return it!=allNames.end();
331 }
332
333 void DataScopeServerBase::checkNotAlreadyExistingVar(const std::string& varName) const
334 {
335   if(isExistingVar(varName))
336     {
337       std::ostringstream oss; oss << "DataScopeServerBase::checkNotAlreadyExistingVar : name \"" << varName << "\" already exists !";
338       throw Exception(oss.str());
339     }
340 }
341
342 void DataScopeServerBase::checkExistingVar(const std::string& varName) const
343 {
344   std::vector<std::string> allNames(getAllVarNames());
345   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
346   if(it==allNames.end())
347     {
348       std::ostringstream oss; oss << "DataScopeServerBase::checkExistingVar : name \"" << varName << "\" does not exist !";
349       throw Exception(oss.str());
350     }
351 }
352
353 PickelizedPyObjServer *DataScopeServerBase::checkVarExistingAndDict(const std::string& varName)
354 {
355   checkExistingVar(varName);
356   BasicDataServer *var(retrieveVarInternal2(varName.c_str()));
357   PickelizedPyObjServer *ret(dynamic_cast<PickelizedPyObjServer *>(var));
358   if(!ret)
359     {
360       std::ostringstream oss; oss << "TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure : var \"" << varName << "\"exists but it is not serialized !";
361       throw Exception(oss.str());
362     }
363   if(!ret->isDict())
364     {
365       std::ostringstream oss; oss << "TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure : var \"" << varName << "\"exists but it is not a Dict !";
366       throw Exception(oss.str());
367     }
368   return ret;
369 }
370
371 void DataScopeServerBase::moveStatusOfVarFromRdWrToRdOnly(const std::string& varName)
372 {
373   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
374   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
375   PickelizedPyObjRdWrServer *varc(dynamic_cast<PickelizedPyObjRdWrServer *>(p.second));
376   if(!varc)
377     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdWrToRdOnly : var is not a RdWr !");
378   PyObject *pyobj(varc->getPyObj()); Py_XINCREF(pyobj);
379   PickelizedPyObjRdOnlyServer *newVar(new PickelizedPyObjRdOnlyServer(this,varName,pyobj));
380   CORBA::Object_var obj(newVar->activate());
381   SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
382   p.first=obj2; p.second=newVar;
383   varc->decrRef();
384 }
385
386 void DataScopeServerBase::moveStatusOfVarFromRdOnlyToRdWr(const std::string& varName)
387 {
388   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
389   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
390   PickelizedPyObjRdOnlyServer *varc(dynamic_cast<PickelizedPyObjRdOnlyServer *>(p.second));
391   if(!varc)
392     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdOnlyToRdWr : var is not a RdWr !");
393   PyObject *pyobj(varc->getPyObj()); Py_XINCREF(pyobj);
394   PickelizedPyObjRdWrServer *newVar(new PickelizedPyObjRdWrServer(this,varName,pyobj));
395   CORBA::Object_var obj(newVar->activate());
396   SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
397   p.first=obj2; p.second=newVar;
398   varc->decrRef();
399 }
400
401 void DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExtInit(const std::string& varName)
402 {
403   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
404   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
405   PickelizedPyObjRdExtServer *varc0(dynamic_cast<PickelizedPyObjRdExtServer *>(p.second));
406   PickelizedPyObjRdExtInitServer *varc1(dynamic_cast<PickelizedPyObjRdExtInitServer *>(p.second));
407   if(!varc0 && !varc1)
408     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExtInit : var is neither RdExt nor RdExtInit !");
409   if(varc0)
410     {
411       PickelizedPyObjRdExtInitServer *newVar(varc0->buildInitInstanceFrom(varName));
412       newVar->incrNbClients();
413       CORBA::Object_var obj(newVar->activate());
414       SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
415       p.first=obj2; p.second=newVar;
416       varc0->decrRef();
417     }
418   else
419     varc1->incrNbClients();
420 }
421
422 void DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExt(const std::string& varName)
423 {
424   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
425   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
426   PickelizedPyObjRdExtInitServer *varc0(dynamic_cast<PickelizedPyObjRdExtInitServer *>(p.second));
427   PickelizedPyObjRdExtServer *varc1(dynamic_cast<PickelizedPyObjRdExtServer *>(p.second));
428   if(!varc0 && !varc1)
429     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExt : var is not a RdExtInit !");
430   if(varc0)
431     {
432       if(varc0->decrNbClients())
433         {
434           PickelizedPyObjRdExtServer *newVar(varc0->buildStdInstanceFrom(varName));
435           CORBA::Object_var obj(newVar->activate());
436           SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
437           p.first=obj2; p.second=newVar;
438           varc0->decrRef();
439         }
440     }
441 }
442
443 std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator DataScopeServerBase::retrieveVarInternal3(const std::string& varName) const
444 {
445   std::vector<std::string> allNames(getAllVarNames());
446   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
447   if(it==allNames.end())
448     {
449       std::ostringstream oss; oss << "DataScopeServerBase::retrieveVarInternal3 : name \"" << varName << "\" does not exists ! Possibilities are :";
450       std::copy(allNames.begin(),allNames.end(),std::ostream_iterator<std::string>(oss,", "));
451       throw Exception(oss.str());
452     }
453   std::size_t pos(std::distance(allNames.begin(),it));
454   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(_vars.begin());
455   for(std::size_t i=0;i<pos;i++,it0++);
456   return it0;
457 }
458
459 std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator DataScopeServerBase::retrieveVarInternal4(const std::string& varName)
460 {
461   std::vector<std::string> allNames(getAllVarNames());
462   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
463   if(it==allNames.end())
464     {
465       std::ostringstream oss; oss << "DataScopeServerBase::retrieveVarInternal4 : name \"" << varName << "\" does not exists ! Possibilities are :";
466       std::copy(allNames.begin(),allNames.end(),std::ostream_iterator<std::string>(oss,", "));
467       throw Exception(oss.str());
468     }
469   std::size_t pos(std::distance(allNames.begin(),it));
470   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it0(_vars.begin());
471   for(std::size_t i=0;i<pos;i++,it0++);
472   return it0;
473 }
474
475 ///////
476
477 DataScopeServer::DataScopeServer(const SALOME_CPythonHelper *pyHelper, CORBA::ORB_ptr orb, SALOME::DataScopeKiller_var killer, const std::string& scopeName):DataScopeServerBase(pyHelper,orb,killer,scopeName)
478 {
479 }
480
481 DataScopeServer::DataScopeServer(const DataScopeServer& other):omniServant(other),ServantBase(other),DataScopeServerBase(other)
482 {
483 }
484
485 SALOME::PickelizedPyObjRdOnlyServer_ptr DataScopeServer::createRdOnlyVar(const char *varName, const SALOME::ByteVec& constValue)
486 {
487   std::string varNameCpp(varName);
488   checkNotAlreadyExistingVar(varNameCpp);
489   PickelizedPyObjRdOnlyServer *tmp(new PickelizedPyObjRdOnlyServer(this,varNameCpp,constValue));
490   CORBA::Object_var ret(tmp->activate());
491   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
492   _vars.push_back(p);
493   return SALOME::PickelizedPyObjRdOnlyServer::_narrow(ret);
494 }
495
496 SALOME::PickelizedPyObjRdExtServer_ptr DataScopeServer::createRdExtVar(const char *varName, const SALOME::ByteVec& constValue)
497 {
498   std::string varNameCpp(varName);
499   checkNotAlreadyExistingVar(varNameCpp);
500   PickelizedPyObjRdExtServer *tmp(new PickelizedPyObjRdExtServer(this,varNameCpp,constValue));
501   CORBA::Object_var ret(tmp->activate());
502   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
503   _vars.push_back(p);
504   return SALOME::PickelizedPyObjRdExtServer::_narrow(ret);
505 }
506
507 SALOME::PickelizedPyObjRdWrServer_ptr DataScopeServer::createRdWrVar(const char *typeName, const char *varName)
508 {
509   std::string varNameCpp(varName),typeNameCpp(typeName);
510   checkNotAlreadyExistingVar(varNameCpp);
511   PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,typeNameCpp,varNameCpp));
512   CORBA::Object_var ret(tmp->activate());
513   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
514   _vars.push_back(p);
515   return SALOME::PickelizedPyObjRdWrServer::_narrow(ret);
516 }
517
518 DataScopeServer::~DataScopeServer()
519 {
520 }
521
522 ////////
523
524 DataScopeServerTransaction::DataScopeServerTransaction(const SALOME_CPythonHelper *pyHelper, CORBA::ORB_ptr orb, SALOME::DataScopeKiller_var killer, const std::string& scopeName):DataScopeServerBase(pyHelper,orb,killer,scopeName)
525 {
526   CORBA::Object_var obj(_orb->resolve_initial_references("RootPOA"));
527   PortableServer::POA_var poa(PortableServer::POA::_narrow(obj));
528   //
529   PortableServer::POAManager_var mgr(poa->the_POAManager());
530   CORBA::PolicyList policies;
531   policies.length(1);
532   PortableServer::ThreadPolicy_var threadPol(poa->create_thread_policy(PortableServer::ORB_CTRL_MODEL));
533   policies[0]=PortableServer::ThreadPolicy::_duplicate(threadPol);
534   PortableServer::POA_var poa2(poa->create_POA("POAForWaiters",mgr,policies));
535   threadPol->destroy();
536   //
537   _poa_for_key_waiter=poa2;
538 }
539
540 DataScopeServerTransaction::DataScopeServerTransaction(const DataScopeServerTransaction& other):omniServant(other),ServantBase(other),DataScopeServerBase(other),_poa_for_key_waiter(other.getPOA4KeyWaiter())
541 {
542 }
543
544 char *DataScopeServerTransaction::getAccessOfVar(const char *varName)
545 {
546   std::string varNameCpp(varName);
547   checkExistingVar(varNameCpp);
548   BasicDataServer *var(retrieveVarInternal2(varName));
549   if(!var)
550     throw Exception("DataScopeServerTransaction::getAccessOfVar : variable is NULL !");
551   PickelizedPyObjServer *varc(dynamic_cast<PickelizedPyObjServer *>(var));
552   if(!varc)
553     throw Exception("DataScopeServerTransaction::getAccessOfVar : variable is not of type PickelizedPyObjServer !");
554   std::string ret(varc->getAccessStr());
555   return CORBA::string_dup(ret.c_str());
556 }
557
558 /*!
559  * This method is here to retrieve atomically accessStr and picklization.
560  */
561 void DataScopeServerTransaction::fetchAndGetAccessOfVar(const char *varName, CORBA::String_out access, SALOME::ByteVec_out data)
562 {
563   access=getAccessOfVar(varName);
564   data=fetchSerializedContent(varName);
565 }
566
567 void DataScopeServerTransaction::createRdOnlyVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
568 {
569   checkNotAlreadyExistingVar(varName);
570   PickelizedPyObjRdOnlyServer *tmp(new PickelizedPyObjRdOnlyServer(this,varName,constValue));
571   CORBA::Object_var ret(tmp->activate());
572   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
573   _vars.push_back(p);
574 }
575
576 void DataScopeServerTransaction::createRdExtVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
577 {
578   checkNotAlreadyExistingVar(varName);
579   PickelizedPyObjRdExtServer *tmp(new PickelizedPyObjRdExtServer(this,varName,constValue));
580   CORBA::Object_var ret(tmp->activate());
581   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
582   _vars.push_back(p);
583 }
584
585 void DataScopeServerTransaction::createRdExtVarFreeStyleInternal(const std::string& varName, const SALOME::ByteVec& constValue, std::string&& compareFuncContent, SALOME::AutoPyRef&& compareFunc)
586 {
587   if(!isExistingVar(varName))
588     {
589       PickelizedPyObjRdExtFreeStyleServer *tmp(new PickelizedPyObjRdExtFreeStyleServer(this,varName,constValue,std::move(compareFuncContent),std::move(compareFunc)));
590       CORBA::Object_var ret(tmp->activate());
591       std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
592       _vars.push_back(p);
593     }
594   else
595     {
596       BasicDataServer *ds(retrieveVarInternal2(varName));
597       if(!ds)
598         {
599           std::ostringstream oss;
600           oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : internal error 1 for varname \"" << varName << "\"!";
601           throw Exception(oss.str());
602         }
603       Sha1Keeper *ds2(dynamic_cast<Sha1Keeper *>(ds));
604       if(!ds2)
605         {
606           std::ostringstream oss;
607           oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : varname \"" << varName << "\" already exists with a non Sha1Keeper type !";
608           throw Exception(oss.str());
609         }
610       PickelizedPyObjServer *ds3(dynamic_cast<PickelizedPyObjServer *>(ds));
611       if(!ds3)
612         {
613           std::ostringstream oss;
614           oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : varname \"" << varName << "\" already exists with a non PickelizedPyObjServer type !";
615           throw Exception(oss.str());
616         }
617       std::vector<unsigned char> constValueAsCpp;
618       Transaction::FromByteSeqToVB(constValue,constValueAsCpp);
619       SALOME::AutoPyRef newObj(PickelizedPyObjServer::GetPyObjFromPickled(constValueAsCpp,this));
620       if(newObj.isNull())
621         {
622           std::ostringstream oss;
623           oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : varname \"" << varName << "\" already exists but input pickelized object is not loadable !";
624           throw Exception(oss.str());
625         }
626       ds2->checkSame(varName,compareFuncContent,ds3->getPyObj(),newObj);
627     }
628 }
629
630 void DataScopeServerTransaction::createRdExtInitVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
631 {
632   checkNotAlreadyExistingVar(varName);
633   PickelizedPyObjRdExtInitServer *tmp(new PickelizedPyObjRdExtInitServer(this,varName,constValue));
634   CORBA::Object_var ret(tmp->activate());
635   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
636   _vars.push_back(p);
637 }
638
639 void DataScopeServerTransaction::createRdWrVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
640 {
641   checkNotAlreadyExistingVar(varName);
642   PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,varName,constValue));
643   CORBA::Object_var ret(tmp->activate());
644   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
645   _vars.push_back(p);
646 }
647
648 SALOME::Transaction_ptr DataScopeServerTransaction::createRdOnlyVarTransac(const char *varName, const SALOME::ByteVec& constValue)
649 {
650   checkNotAlreadyExistingVar(varName);
651   TransactionRdOnlyVarCreate *ret(new TransactionRdOnlyVarCreate(this,varName,constValue));
652   CORBA::Object_var obj(ret->activate());
653   return SALOME::Transaction::_narrow(obj);
654 }
655
656 SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtVarTransac(const char *varName, const SALOME::ByteVec& constValue)
657 {
658   checkNotAlreadyExistingVar(varName);
659   TransactionRdExtVarCreate *ret(new TransactionRdExtVarCreate(this,varName,constValue));
660   CORBA::Object_var obj(ret->activate());
661   return SALOME::Transaction::_narrow(obj);
662 }
663
664 SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtVarFreeStyleTransac(const char *varName, const SALOME::ByteVec& constValue, const char *compareFuncContent)
665 {// no check on varName done here. Will be done on perform
666   TransactionRdExtVarFreeStyleCreate *ret(new TransactionRdExtVarFreeStyleCreate(this,varName,constValue,compareFuncContent));
667   CORBA::Object_var obj(ret->activate());
668   return SALOME::Transaction::_narrow(obj);
669 }
670
671 SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtInitVarTransac(const char *varName, const SALOME::ByteVec& constValue)
672 {
673   checkNotAlreadyExistingVar(varName);
674   TransactionRdExtInitVarCreate *ret(new TransactionRdExtInitVarCreate(this,varName,constValue));
675   CORBA::Object_var obj(ret->activate());
676   return SALOME::Transaction::_narrow(obj);
677 }
678
679 SALOME::Transaction_ptr DataScopeServerTransaction::createRdWrVarTransac(const char *varName, const SALOME::ByteVec& constValue)
680 {
681   checkNotAlreadyExistingVar(varName);
682   TransactionRdWrVarCreate *ret(new TransactionRdWrVarCreate(this,varName,constValue));
683   CORBA::Object_var obj(ret->activate());
684   return SALOME::Transaction::_narrow(obj);
685 }
686
687 void DataScopeServerTransaction::addWaitKey(KeyWaiter *kw)
688 {
689   if(!kw)
690     throw Exception("DataScopeServerTransaction::addWaitKey : NULL input object !");
691   _waiting_keys.push_back(kw);
692 }
693
694 void DataScopeServerTransaction::pingKey(PyObject *keyObj)
695 {
696   std::size_t ii(0);
697   // this part does nothing except to be sure that in notify key all will be OK.
698   PyObject *args(PyTuple_New(1));
699   PyTuple_SetItem(args,0,keyObj); Py_XINCREF(keyObj);
700   for(std::list< KeyWaiter *>::iterator it=_waiting_keys.begin();it!=_waiting_keys.end();it++,ii++)
701     {
702       PyObject *waitKey((*it)->getKeyPyObj());
703       PyObject *meth(PyObject_GetAttrString(waitKey,"__eq__"));
704       if(!meth)
705       {
706           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " no __eq__ in pyobj !";
707           throw Exception(oss.str());
708       }
709       PyObject *res(PyObject_CallObject(meth,args));
710       Py_XDECREF(meth);
711       if(res==NULL)
712         {
713           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " error during cmp(k,wk[i]) !";
714           throw Exception(oss.str());
715         }
716       PyBool_Check(res);
717       if(PyErr_Occurred())
718         {
719           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " error during interpretation of cmp(k,wk[i]) !";
720           throw Exception(oss.str());
721         }
722       Py_XDECREF(res);
723     }
724   Py_XDECREF(args);
725 }
726
727 void DataScopeServerTransaction::notifyKey(const std::string& varName, PyObject *keyObj, PyObject *valueObj)
728 {
729   std::size_t ii(0);
730   PyObject *args(PyTuple_New(1));
731   PyTuple_SetItem(args,0,keyObj); Py_XINCREF(keyObj);
732   std::list< KeyWaiter *> newList,listOfEltToWakeUp;
733   for(std::list< KeyWaiter *>::iterator it=_waiting_keys.begin();it!=_waiting_keys.end();it++,ii++)
734     {
735       if((*it)->getVarName()!=varName)
736         {
737           newList.push_back(*it);
738           continue;
739         }
740       PyObject *waitKey((*it)->getKeyPyObj());
741       PyObject *meth(PyObject_GetAttrString(waitKey,"__eq__"));
742       if(!meth)
743       {
744           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " no __eq__ in pyobj !";
745           throw Exception(oss.str());
746       }
747       PyObject *res(PyObject_CallObject(meth,args));
748       Py_XDECREF(meth);
749       if(!PyBool_Check(res))
750       {
751           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " no __eq__ in pyobj !";
752           throw Exception(oss.str());
753       }
754       if(PyErr_Occurred())
755         {
756           std::ostringstream oss; oss << "DataScopeServerTransaction::notifyKey : MAIN INTERNAL ERROR ! for object id #" << ii << " error during interpretation of cmp(k,wk[i]) !";
757           throw Exception(oss.str());
758         }
759       if(res==Py_True)
760         listOfEltToWakeUp.push_back(*it);
761       else
762         newList.push_back(*it);
763       Py_XDECREF(res);
764     }
765   Py_XDECREF(args);
766   for(std::list< KeyWaiter *>::iterator it=listOfEltToWakeUp.begin();it!=listOfEltToWakeUp.end();it++)
767     (*it)->valueJustCome(valueObj);
768   for(std::list< KeyWaiter *>::iterator it=listOfEltToWakeUp.begin();it!=listOfEltToWakeUp.end();it++)
769     (*it)->go();
770   _waiting_keys=newList;
771 }
772
773 SALOME::Transaction_ptr DataScopeServerTransaction::addKeyValueInVarHard(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value)
774 {
775   checkVarExistingAndDict(varName);
776   TransactionAddKeyValueHard *ret(new TransactionAddKeyValueHard(this,varName,key,value));
777   CORBA::Object_var obj(ret->activate());
778   return SALOME::Transaction::_narrow(obj);
779 }
780
781 SALOME::Transaction_ptr DataScopeServerTransaction::addKeyValueInVarErrorIfAlreadyExisting(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value)
782 {
783   checkVarExistingAndDict(varName);
784   TransactionAddKeyValueErrorIfAlreadyExisting *ret(new TransactionAddKeyValueErrorIfAlreadyExisting(this,varName,key,value));
785   CORBA::Object_var obj(ret->activate());
786   return SALOME::Transaction::_narrow(obj);
787 }
788
789 SALOME::TransactionMultiKeyAddSession_ptr DataScopeServerTransaction::addMultiKeyValueSession(const char *varName)
790 {
791   checkVarExistingAndDict(varName);
792   TransactionMultiKeyAddSession *ret(new TransactionMultiKeyAddSession(this,varName));
793   CORBA::Object_var obj(ret->activate());
794   return SALOME::TransactionMultiKeyAddSession::_narrow(obj);
795 }
796
797 SALOME::Transaction_ptr DataScopeServerTransaction::removeKeyInVarErrorIfNotAlreadyExisting(const char *varName, const SALOME::ByteVec& key)
798 {
799   checkVarExistingAndDict(varName);
800   TransactionRemoveKeyInVarErrorIfNotAlreadyExisting *ret(new TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(this,varName,key));
801   CORBA::Object_var obj(ret->activate());
802   return SALOME::Transaction::_narrow(obj);
803 }
804
805 SALOME::TransactionRdWrAccess_ptr DataScopeServerTransaction::createWorkingVarTransac(const char *varName, const SALOME::ByteVec& constValue)
806 {
807   std::string varNameCpp(varName);
808   checkNotAlreadyExistingVar(varName);
809   PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,varNameCpp,constValue));
810   CORBA::Object_var obj(tmp->activate());
811   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(obj),tmp);
812   _vars.push_back(p);
813   //
814   TransactionMorphRdWrIntoRdOnly *ret(new TransactionMorphRdWrIntoRdOnly(this,varName));
815   CORBA::Object_var obj2(ret->activate());
816   return SALOME::TransactionRdWrAccess::_narrow(obj2);
817 }
818
819 SALOME::Transaction_ptr DataScopeServerTransaction::killVarTransac(const char *varName)
820 {
821   std::string varNameCpp(varName);
822   checkExistingVar(varNameCpp);
823   //
824   TransactionKillVar *ret(new TransactionKillVar(this,varName));
825   CORBA::Object_var obj2(ret->activate());
826   return SALOME::Transaction::_narrow(obj2);
827 }
828
829 SALOME::KeyWaiter_ptr DataScopeServerTransaction::waitForKeyInVar(const char *varName, const SALOME::ByteVec& keyVal)
830 {
831   PickelizedPyObjServer *pickelObj(checkVarExistingAndDict(varName));
832   KeyWaiter *ret(new KeyWaiter(pickelObj,keyVal));
833   CORBA::Object_var obj(ret->activate());//KeyWaiter instance activated inside a multithread POA contrary to all of objects in SALOMESDS in single thread !
834   return SALOME::KeyWaiter::_narrow(obj);
835 }
836
837 SALOME::KeyWaiter_ptr DataScopeServerTransaction::waitForKeyInVarAndKillIt(const char *varName, const SALOME::ByteVec& keyVal, SALOME::Transaction_out transac)
838 {
839   PickelizedPyObjServer *pickelObj(checkVarExistingAndDict(varName));
840   KeyWaiter *ret0(new KeyWaiter(pickelObj,keyVal));
841   CORBA::Object_var obj(ret0->activate());//KeyWaiter instance activated inside a multithread POA contrary to all of objects in SALOMESDS in single thread !
842   //
843   TransactionRemoveKeyInVarErrorIfNotAlreadyExisting *ret1(new TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(this,varName,keyVal));
844   CORBA::Object_var obj2(ret1->activate());
845   transac=SALOME::Transaction::_narrow(obj2);
846   //
847   return SALOME::KeyWaiter::_narrow(obj);
848 }
849
850 SALOME::ByteVec *DataScopeServerTransaction::waitForMonoThrRev(SALOME::KeyWaiter_ptr kw)
851 {
852   PortableServer::ServantBase *ret(0);
853   try
854     {
855       ret=_poa_for_key_waiter->reference_to_servant(kw);// Warning ref cnt of ret has been incremented !
856     }
857   catch(...) { ret=0; }
858   KeyWaiter *retc(dynamic_cast<KeyWaiter *>(ret));
859   if(!retc)
860     throw Exception("DataScopeServerTransaction::invokeMonoThr : internal error 1 !");
861   retc->_remove_ref();// restore the counter after _poa_for_key_waiter->reference_to_servant(kw)
862   SALOME::ByteVec *zeRet(retc->waitForMonoThr());
863   retc->enforcedRelease();
864   return zeRet;
865 }
866
867 SALOME::ByteVec *DataScopeServerTransaction::waitForAndKill(SALOME::KeyWaiter_ptr kw)
868 {
869   PortableServer::ServantBase *ret(0);
870   try
871     {
872       ret=_poa_for_key_waiter->reference_to_servant(kw);// Warning ref cnt of ret has been incremented !
873     }
874   catch(...) { ret=0; }
875   KeyWaiter *retc(dynamic_cast<KeyWaiter *>(ret));
876   if(!retc)
877     throw Exception("DataScopeServerTransaction::invokeMonoThr : internal error 1 !");
878   retc->_remove_ref();// restore the counter after _poa_for_key_waiter->reference_to_servant(kw)
879   SALOME::ByteVec *zeRet(retc->waitForAndKill());
880   retc->enforcedRelease();
881   return zeRet;
882 }
883
884 void DataScopeServerTransaction::atomicApply(const SALOME::ListOfTransaction& transactions)
885 {
886   std::size_t sz(transactions.length());
887   if(sz==0)
888     return ;
889   std::vector< AutoServantPtr<Transaction> > transactionsCpp(sz);
890   for(std::size_t i=0;i<sz;i++)
891     {
892       PortableServer::ServantBase *eltBase(0);
893       Transaction *elt(0);
894       try
895         {
896           eltBase=_poa->reference_to_servant(transactions[i]);
897           elt=dynamic_cast<Transaction *>(eltBase);
898         }
899       catch(...)
900         {
901           std::ostringstream oss; oss << "DataScopeServerTransaction::atomicApply : the elt #" << i << " is invalid !";
902           throw Exception(oss.str());
903         }
904       if(!elt)
905         {
906           std::ostringstream oss; oss << "DataScopeServerTransaction::atomicApply : the elt #" << i << " is null ?";
907           throw Exception(oss.str());
908         }
909       elt->_remove_ref();
910       transactionsCpp[i]=elt;
911     }
912   {// important do not merge loops ! 
913     std::vector<TrustTransaction> transactions2(sz);
914     bool mustRollback(true);
915     for(std::size_t i=0;i<sz;i++)
916       transactions2[i].setTransaction(transactionsCpp[i],&mustRollback);
917     for(std::size_t i=0;i<sz;i++)
918       transactions2[i].operate();
919     mustRollback=false;
920   }
921   for(std::size_t i=0;i<sz;i++)
922     transactionsCpp[i]->notify();
923 }
924
925 DataScopeServerTransaction::~DataScopeServerTransaction()
926 {
927 }
928
929 SALOME::RequestSwitcher_ptr DataScopeServerTransaction::getRequestSwitcher()
930 {
931   if(_rs.isNull())
932     {
933       _rs=new RequestSwitcher(_orb,this);
934     }
935   CORBA::Object_var obj(_rs->activate());
936   return SALOME::RequestSwitcher::_narrow(obj);
937 }