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