Salome HOME
Merge remote-tracking branch 'origin/V8_3_BR' into ngr/python3_dev
[modules/kernel.git] / src / SALOMESDS / SALOMESDS_DataScopeServer.cxx
1 // Copyright (C) 2007-2016  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 wchar_t*
51 Py_DecodeLocale(const char *arg, size_t *size)
52 {
53     wchar_t *res;
54     unsigned char *in;
55     wchar_t *out;
56     size_t argsize = strlen(arg) + 1;
57
58     if (argsize > PY_SSIZE_T_MAX/sizeof(wchar_t))
59         return NULL;
60     res = (wchar_t*) PyMem_RawMalloc(argsize*sizeof(wchar_t));
61     if (!res)
62         return NULL;
63
64     in = (unsigned char*)arg;
65     out = res;
66     while(*in)
67         if(*in < 128)
68             *out++ = *in++;
69         else
70             *out++ = 0xdc00 + *in++;
71     *out = 0;
72     if (size != NULL)
73         *size = out - res;
74     return res;
75 }
76 #endif
77
78 void DataScopeKiller::shutdown()
79 {
80   Py_Finalize();
81   _orb->shutdown(0);
82 }
83
84 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)
85 {
86 }
87
88 DataScopeServerBase::DataScopeServerBase(const DataScopeServerBase& other):omniServant(other),ServantBase(other),_globals(0),_locals(0),_pickler(0),_name(other._name),_vars(other._vars),_killer(other._killer)
89 {
90 }
91
92 DataScopeServerBase::~DataScopeServerBase()
93 {
94   // _globals is borrowed ref -> do nothing
95   Py_XDECREF(_locals);
96   Py_XDECREF(_pickler);
97   for(std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it=_vars.begin();it!=_vars.end();it++)
98     {
99        BasicDataServer *obj((*it).second);
100        if(obj)
101          {
102            obj->decrRef();
103          }
104     }
105 }
106
107 /*!
108  * Called remotely -> to protect against throw
109  */
110 void DataScopeServerBase::ping()
111 {
112 }
113
114 /*!
115  * Called remotely -> to protect against throw
116  */
117 char *DataScopeServerBase::getScopeName()
118 {
119   return CORBA::string_dup(_name.c_str());
120 }
121
122 /*!
123  * Called remotely -> to protect against throw
124  */
125 SALOME::StringVec *DataScopeServerBase::listVars()
126 {
127   SALOME::StringVec *ret(new SALOME::StringVec);
128   std::size_t sz(_vars.size());
129   ret->length(sz);
130   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(_vars.begin());
131   for(std::size_t i=0;i<sz;it++,i++)
132     {
133       BasicDataServer *obj((*it).second);
134       std::string name(obj->getVarNameCpp());
135       (*ret)[i]=CORBA::string_dup(name.c_str());
136     }
137   return ret;
138 }
139
140 CORBA::Boolean DataScopeServerBase::existVar(const char *varName)
141 {
142   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it(_vars.begin());
143   for(;it!=_vars.end();it++)
144     if((*it).second->getVarNameCpp()==varName)
145       return true;
146   return false;
147 }
148
149 SALOME::BasicDataServer_ptr DataScopeServerBase::retrieveVarInternal(const char *varName)
150 {
151   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(retrieveVarInternal3(varName));
152   return SALOME::BasicDataServer::_duplicate((*it0).first);
153 }
154
155 BasicDataServer *DataScopeServerBase::retrieveVarInternal2(const std::string& varName)
156 {
157   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(retrieveVarInternal3(varName));
158   return (*it0).second;
159 }
160
161 void DataScopeServerBase::deleteVar(const char *varName)
162 {
163   std::string varNameCpp(varName);
164   std::vector<std::string> allNames(getAllVarNames());
165   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varNameCpp));
166   if(it==allNames.end())
167     {
168       std::ostringstream oss; oss << "DataScopeServerBase::deleteVar : name \"" << varNameCpp << "\" does not exists ! Possibilities are :";
169       std::copy(allNames.begin(),allNames.end(),std::ostream_iterator<std::string>(oss,", "));
170       throw Exception(oss.str());
171     }
172   std::size_t pos(std::distance(allNames.begin(),it));
173   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it0(_vars.begin());
174   for(std::size_t ii=0;ii<pos;ii++,it0++);
175   (*it0).second->decrRef();
176   _vars.erase(it0);
177 }
178
179 CORBA::Boolean DataScopeServerBase::shutdownIfNotHostedByDSM(SALOME::DataScopeKiller_out killer)
180 {
181   SALOME_NamingService ns(_orb);
182   CORBA::Object_var obj(ns.Resolve(DataServerManager::NAME_IN_NS));
183   SALOME::DataServerManager_var dsm(SALOME::DataServerManager::_narrow(obj));
184   if(CORBA::is_nil(dsm))
185     throw Exception("Unable to reach in the NS the unique DataServerManager instance of the Session !");
186   // destroy ref in the naming service
187   std::string fullScopeName(SALOMESDS::DataServerManager::CreateAbsNameInNSFromScopeName(_name));
188   ns.Destroy_Name(fullScopeName.c_str());
189   // establish if dsm and this shared the same POA. If yes dsm and this are collocated !
190   PortableServer::ServantBase *ret(0);
191   try
192     {
193       ret=_poa->reference_to_servant(dsm);
194     }
195   catch(...) { ret=0; }
196   //
197   if(!ret)
198     {
199       enforcedRelease();
200       killer=SALOME::DataScopeKiller::_duplicate(_killer);
201       return true;
202     }
203   else
204     {
205       ret->_remove_ref();
206       enforcedRelease();
207       killer=SALOME::DataScopeKiller::_duplicate(_killer);
208       return false;
209     }
210 }
211
212 SALOME::ByteVec *DataScopeServerBase::fetchSerializedContent(const char *varName)
213 {
214   BasicDataServer *var(retrieveVarInternal2(varName));
215   PickelizedPyObjServer *varc(dynamic_cast<PickelizedPyObjServer *>(var));
216   if(!varc)
217     {
218       std::ostringstream oss; oss << "DataScopeServerBase::fetchSerializedContent : var \"" << varName << "\" exists but it is not serialized !";
219       throw Exception(oss.str());
220     }
221   return varc->fetchSerializedContent();
222 }
223
224 SALOME::SeqOfByteVec *DataScopeServerBase::getAllKeysOfVarWithTypeDict(const char *varName)
225 {
226   BasicDataServer *var(retrieveVarInternal2(varName));
227   PickelizedPyObjServer *varc(dynamic_cast<PickelizedPyObjServer *>(var));
228   if(!varc)
229     {
230       std::ostringstream oss; oss << "DataScopeServerBase::getAllKeysOfVarWithTypeDict : var \"" << varName << "\" exists but it is not serialized !";
231       throw Exception(oss.str());
232     }
233   if(!varc->isDict())
234     {
235       std::ostringstream oss; oss << "DataScopeServerBase::getAllKeysOfVarWithTypeDict : var \"" << varName << "\" exists but it is not a PyDict !";
236       throw Exception(oss.str());
237     }
238   PyObject *keys(PyDict_Keys(varc->getPyObj()));
239   if(!PyList_Check(keys))
240     {
241       std::ostringstream oss; oss << "DataScopeServerBase::getAllKeysOfVarWithTypeDict : var \"" << varName << "\" has keys but not of type list !";
242       throw Exception(oss.str());
243     }
244   Py_ssize_t sz(PyList_Size(keys));
245   SALOME::SeqOfByteVec *ret(new SALOME::SeqOfByteVec);
246   ret->length(sz);
247   for(Py_ssize_t i=0;i<sz;i++)
248     {
249       PyObject *item(PyList_GetItem(keys,i));
250       Py_XINCREF(item);
251       std::string pickel(varc->pickelize(item));//item consumed
252       PickelizedPyObjServer::FromCppToByteSeq(pickel,(*ret)[i]);
253     }
254   Py_XDECREF(keys);
255   return ret;
256 }
257
258 void DataScopeServerBase::initializePython(int argc, char *argv[])
259 {
260   Py_Initialize();
261   PyEval_InitThreads();
262   wchar_t **changed_argv = new wchar_t*[argc]; // Setting arguments
263   for (int i = 0; i < argc; i++)
264     changed_argv[i] = Py_DecodeLocale(argv[i], NULL);
265   PySys_SetArgv(argc, changed_argv);
266   PyObject *mainmod(PyImport_AddModule("__main__"));
267   _globals=PyModule_GetDict(mainmod);
268   if(PyDict_GetItemString(_globals, "__builtins__") == NULL)
269     {
270       PyObject *bimod(PyImport_ImportModule("__builtin__"));
271       if (bimod == NULL || PyDict_SetItemString(_globals, "__builtins__", bimod) != 0)
272         Py_FatalError("can't add __builtins__ to __main__");
273       Py_XDECREF(bimod);
274     }
275   _locals=PyDict_New();
276   PyObject *tmp(PyList_New(0));
277   _pickler=PyImport_ImportModuleLevel(const_cast<char *>("pickle"),_globals,_locals,tmp,-1);
278 }
279
280 void DataScopeServerBase::registerToSalomePiDict() const
281 {
282   PyObject *mod(PyImport_ImportModule("addToKillList"));//new value
283   if(!mod)
284     return;
285   PyObject *meth(PyObject_GetAttrString(mod,"addToKillList"));//new value
286   if(!meth)
287     { Py_XDECREF(mod); return ; }
288   PyObject *args(PyTuple_New(2));
289   PyTuple_SetItem(args,0,PyLong_FromLong(getpid()));
290   PyTuple_SetItem(args,1,PyUnicode_FromString("SALOME_DataScopeServerBase"));
291   PyObject *res(PyObject_CallObject(meth,args));
292   Py_XDECREF(args);
293   Py_XDECREF(res);
294   Py_XDECREF(meth);
295   Py_XDECREF(mod);
296 }
297
298 void DataScopeServerBase::setPOA(PortableServer::POA_var poa)
299 {
300   _poa=poa;
301 }
302
303 void DataScopeServerBase::registerInNS(SALOME::DataScopeServerBase_ptr ptr)
304 {
305   std::string fullScopeName(SALOMESDS::DataServerManager::CreateAbsNameInNSFromScopeName(_name));
306   SALOME_NamingService ns(_orb);
307   ns.Register(ptr,fullScopeName.c_str());
308 }
309
310 std::string DataScopeServerBase::BuildTmpVarNameFrom(const std::string& varName)
311 {
312   std::ostringstream oss;
313   oss << varName << "@" << COUNTER++;
314   return oss.str();
315 }
316
317 std::vector< std::string > DataScopeServerBase::getAllVarNames() const
318 {
319   std::size_t sz(_vars.size());
320   std::vector<std::string> ret(sz);
321   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it(_vars.begin());
322   for(std::size_t i=0;i<sz;it++,i++)
323     ret[i]=(*it).second->getVarNameCpp();
324   return ret;
325 }
326
327 void DataScopeServerBase::checkNotAlreadyExistingVar(const std::string& varName) const
328 {
329   std::vector<std::string> allNames(getAllVarNames());
330   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
331   if(it!=allNames.end())
332     {
333       std::ostringstream oss; oss << "DataScopeServerBase::checkNotAlreadyExistingVar : name \"" << varName << "\" already exists !";
334       throw Exception(oss.str());
335     }
336 }
337
338 void DataScopeServerBase::checkExistingVar(const std::string& varName) const
339 {
340   std::vector<std::string> allNames(getAllVarNames());
341   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
342   if(it==allNames.end())
343     {
344       std::ostringstream oss; oss << "DataScopeServerBase::checkExistingVar : name \"" << varName << "\" does not exist !";
345       throw Exception(oss.str());
346     }
347 }
348
349 PickelizedPyObjServer *DataScopeServerBase::checkVarExistingAndDict(const std::string& varName)
350 {
351   checkExistingVar(varName);
352   BasicDataServer *var(retrieveVarInternal2(varName.c_str()));
353   PickelizedPyObjServer *ret(dynamic_cast<PickelizedPyObjServer *>(var));
354   if(!ret)
355     {
356       std::ostringstream oss; oss << "TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure : var \"" << varName << "\"exists but it is not serialized !";
357       throw Exception(oss.str());
358     }
359   if(!ret->isDict())
360     {
361       std::ostringstream oss; oss << "TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure : var \"" << varName << "\"exists but it is not a Dict !";
362       throw Exception(oss.str());
363     }
364   return ret;
365 }
366
367 void DataScopeServerBase::moveStatusOfVarFromRdWrToRdOnly(const std::string& varName)
368 {
369   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
370   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
371   PickelizedPyObjRdWrServer *varc(dynamic_cast<PickelizedPyObjRdWrServer *>(p.second));
372   if(!varc)
373     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdWrToRdOnly : var is not a RdWr !");
374   PyObject *pyobj(varc->getPyObj()); Py_XINCREF(pyobj);
375   PickelizedPyObjRdOnlyServer *newVar(new PickelizedPyObjRdOnlyServer(this,varName,pyobj));
376   CORBA::Object_var obj(newVar->activate());
377   SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
378   p.first=obj2; p.second=newVar;
379   varc->decrRef();
380 }
381
382 void DataScopeServerBase::moveStatusOfVarFromRdOnlyToRdWr(const std::string& varName)
383 {
384   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
385   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
386   PickelizedPyObjRdOnlyServer *varc(dynamic_cast<PickelizedPyObjRdOnlyServer *>(p.second));
387   if(!varc)
388     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdOnlyToRdWr : var is not a RdWr !");
389   PyObject *pyobj(varc->getPyObj()); Py_XINCREF(pyobj);
390   PickelizedPyObjRdWrServer *newVar(new PickelizedPyObjRdWrServer(this,varName,pyobj));
391   CORBA::Object_var obj(newVar->activate());
392   SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
393   p.first=obj2; p.second=newVar;
394   varc->decrRef();
395 }
396
397 void DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExtInit(const std::string& varName)
398 {
399   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
400   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
401   PickelizedPyObjRdExtServer *varc0(dynamic_cast<PickelizedPyObjRdExtServer *>(p.second));
402   PickelizedPyObjRdExtInitServer *varc1(dynamic_cast<PickelizedPyObjRdExtInitServer *>(p.second));
403   if(!varc0 && !varc1)
404     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExtInit : var is neither RdExt nor RdExtInit !");
405   if(varc0)
406     {
407       PyObject *pyobj(varc0->getPyObj()); Py_XINCREF(pyobj);
408       PickelizedPyObjRdExtInitServer *newVar(new PickelizedPyObjRdExtInitServer(this,varName,pyobj));
409       newVar->incrNbClients();
410       CORBA::Object_var obj(newVar->activate());
411       SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
412       p.first=obj2; p.second=newVar;
413       varc0->decrRef();
414     }
415   else
416     varc1->incrNbClients();
417 }
418
419 void DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExt(const std::string& varName)
420 {
421   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
422   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
423   PickelizedPyObjRdExtInitServer *varc0(dynamic_cast<PickelizedPyObjRdExtInitServer *>(p.second));
424   PickelizedPyObjRdExtServer *varc1(dynamic_cast<PickelizedPyObjRdExtServer *>(p.second));
425   if(!varc0 && !varc1)
426     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExt : var is not a RdExtInit !");
427   if(varc0)
428     {
429       if(varc0->decrNbClients())
430         {
431           PyObject *pyobj(varc0->getPyObj()); Py_XINCREF(pyobj);
432           PickelizedPyObjRdExtServer *newVar(new PickelizedPyObjRdExtServer(this,varName,pyobj));
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(CORBA::ORB_ptr orb, SALOME::DataScopeKiller_var killer, const std::string& scopeName):DataScopeServerBase(orb,killer,scopeName)
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(CORBA::ORB_ptr orb, SALOME::DataScopeKiller_var killer, const std::string& scopeName):DataScopeServerBase(orb,killer,scopeName)
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::createRdExtInitVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
584 {
585   checkNotAlreadyExistingVar(varName);
586   PickelizedPyObjRdExtInitServer *tmp(new PickelizedPyObjRdExtInitServer(this,varName,constValue));
587   CORBA::Object_var ret(tmp->activate());
588   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
589   _vars.push_back(p);
590 }
591
592 void DataScopeServerTransaction::createRdWrVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
593 {
594   checkNotAlreadyExistingVar(varName);
595   PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,varName,constValue));
596   CORBA::Object_var ret(tmp->activate());
597   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
598   _vars.push_back(p);
599 }
600
601 SALOME::Transaction_ptr DataScopeServerTransaction::createRdOnlyVarTransac(const char *varName, const SALOME::ByteVec& constValue)
602 {
603   checkNotAlreadyExistingVar(varName);
604   TransactionRdOnlyVarCreate *ret(new TransactionRdOnlyVarCreate(this,varName,constValue));
605   CORBA::Object_var obj(ret->activate());
606   return SALOME::Transaction::_narrow(obj);
607 }
608
609 SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtVarTransac(const char *varName, const SALOME::ByteVec& constValue)
610 {
611   checkNotAlreadyExistingVar(varName);
612   TransactionRdExtVarCreate *ret(new TransactionRdExtVarCreate(this,varName,constValue));
613   CORBA::Object_var obj(ret->activate());
614   return SALOME::Transaction::_narrow(obj);
615 }
616
617 SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtInitVarTransac(const char *varName, const SALOME::ByteVec& constValue)
618 {
619   checkNotAlreadyExistingVar(varName);
620   TransactionRdExtInitVarCreate *ret(new TransactionRdExtInitVarCreate(this,varName,constValue));
621   CORBA::Object_var obj(ret->activate());
622   return SALOME::Transaction::_narrow(obj);
623 }
624
625 SALOME::Transaction_ptr DataScopeServerTransaction::createRdWrVarTransac(const char *varName, const SALOME::ByteVec& constValue)
626 {
627   checkNotAlreadyExistingVar(varName);
628   TransactionRdWrVarCreate *ret(new TransactionRdWrVarCreate(this,varName,constValue));
629   CORBA::Object_var obj(ret->activate());
630   return SALOME::Transaction::_narrow(obj);
631 }
632
633 void DataScopeServerTransaction::addWaitKey(KeyWaiter *kw)
634 {
635   if(!kw)
636     throw Exception("DataScopeServerTransaction::addWaitKey : NULL input object !");
637   _waiting_keys.push_back(kw);
638 }
639
640 void DataScopeServerTransaction::pingKey(PyObject *keyObj)
641 {
642   PyObject *cmpObj(getPyCmpFunc());
643   if(!keyObj)
644     throw Exception("ataScopeServerTransaction::pingKey : Key Object is NULL !");
645   PyObject *args(PyTuple_New(2));
646   PyTuple_SetItem(args,0,keyObj); Py_XINCREF(keyObj);
647   std::size_t ii(0);
648   // this part does nothing except to be sure that in notify key all will be OK.
649   for(std::list< KeyWaiter *>::iterator it=_waiting_keys.begin();it!=_waiting_keys.end();it++,ii++)
650     {
651       PyObject *waitKey((*it)->getKeyPyObj());
652       PyTuple_SetItem(args,1,waitKey); Py_XINCREF(waitKey);
653       PyObject *res(PyObject_CallObject(cmpObj,args));
654       if(res==NULL)
655         {
656           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " error during cmp(k,wk[i]) !";
657           throw Exception(oss.str());
658         }
659       PyLong_AsLong(res);
660       if(PyErr_Occurred())
661         {
662           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " error during interpretation of cmp(k,wk[i]) !";
663           throw Exception(oss.str());
664         }
665       Py_XDECREF(res);
666     }
667 }
668
669 void DataScopeServerTransaction::notifyKey(const std::string& varName, PyObject *keyObj, PyObject *valueObj)
670 {
671   PyObject *cmpObj(getPyCmpFunc());
672   if(!keyObj)
673     throw Exception("DataScopeServerTransaction::notifyKey : MAIN INTERNAL ERROR ! Key Object is NULL !");
674   PyObject *args(PyTuple_New(2));
675   PyTuple_SetItem(args,0,keyObj); Py_XINCREF(keyObj);
676   std::size_t ii(0);
677   std::list< KeyWaiter *> newList,listOfEltToWakeUp;
678   for(std::list< KeyWaiter *>::iterator it=_waiting_keys.begin();it!=_waiting_keys.end();it++,ii++)
679     {
680       if((*it)->getVarName()!=varName)
681         {
682           newList.push_back(*it);
683           continue;
684         }
685       PyObject *waitKey((*it)->getKeyPyObj());
686       PyTuple_SetItem(args,1,waitKey); Py_XINCREF(waitKey);
687       PyObject *res(PyObject_CallObject(cmpObj,args));
688       if(res==NULL)
689         {
690           std::ostringstream oss; oss << "DataScopeServerTransaction::notifyKey : MAIN INTERNAL ERROR ! for object id #" << ii << " error during cmp(k,wk[i]) !";
691           throw Exception(oss.str());
692         }
693       long resCpp(PyLong_AsLong(res));
694       if(PyErr_Occurred())
695         {
696           std::ostringstream oss; oss << "DataScopeServerTransaction::notifyKey : MAIN INTERNAL ERROR ! for object id #" << ii << " error during interpretation of cmp(k,wk[i]) !";
697           throw Exception(oss.str());
698         }
699       Py_XDECREF(res);
700       if(resCpp==0)
701         listOfEltToWakeUp.push_back(*it);
702       else
703         newList.push_back(*it);
704     }
705   for(std::list< KeyWaiter *>::iterator it=listOfEltToWakeUp.begin();it!=listOfEltToWakeUp.end();it++)
706     (*it)->valueJustCome(valueObj);
707   for(std::list< KeyWaiter *>::iterator it=listOfEltToWakeUp.begin();it!=listOfEltToWakeUp.end();it++)
708     (*it)->go();
709   _waiting_keys=newList;
710 }
711
712 SALOME::Transaction_ptr DataScopeServerTransaction::addKeyValueInVarHard(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value)
713 {
714   checkVarExistingAndDict(varName);
715   TransactionAddKeyValueHard *ret(new TransactionAddKeyValueHard(this,varName,key,value));
716   CORBA::Object_var obj(ret->activate());
717   return SALOME::Transaction::_narrow(obj);
718 }
719
720 SALOME::Transaction_ptr DataScopeServerTransaction::addKeyValueInVarErrorIfAlreadyExisting(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value)
721 {
722   checkVarExistingAndDict(varName);
723   TransactionAddKeyValueErrorIfAlreadyExisting *ret(new TransactionAddKeyValueErrorIfAlreadyExisting(this,varName,key,value));
724   CORBA::Object_var obj(ret->activate());
725   return SALOME::Transaction::_narrow(obj);
726 }
727
728 SALOME::TransactionMultiKeyAddSession_ptr DataScopeServerTransaction::addMultiKeyValueSession(const char *varName)
729 {
730   checkVarExistingAndDict(varName);
731   TransactionMultiKeyAddSession *ret(new TransactionMultiKeyAddSession(this,varName));
732   CORBA::Object_var obj(ret->activate());
733   return SALOME::TransactionMultiKeyAddSession::_narrow(obj);
734 }
735
736 SALOME::Transaction_ptr DataScopeServerTransaction::removeKeyInVarErrorIfNotAlreadyExisting(const char *varName, const SALOME::ByteVec& key)
737 {
738   checkVarExistingAndDict(varName);
739   TransactionRemoveKeyInVarErrorIfNotAlreadyExisting *ret(new TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(this,varName,key));
740   CORBA::Object_var obj(ret->activate());
741   return SALOME::Transaction::_narrow(obj);
742 }
743
744 SALOME::TransactionRdWrAccess_ptr DataScopeServerTransaction::createWorkingVarTransac(const char *varName, const SALOME::ByteVec& constValue)
745 {
746   std::string varNameCpp(varName);
747   checkNotAlreadyExistingVar(varName);
748   PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,varNameCpp,constValue));
749   CORBA::Object_var obj(tmp->activate());
750   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(obj),tmp);
751   _vars.push_back(p);
752   //
753   TransactionMorphRdWrIntoRdOnly *ret(new TransactionMorphRdWrIntoRdOnly(this,varName));
754   CORBA::Object_var obj2(ret->activate());
755   return SALOME::TransactionRdWrAccess::_narrow(obj2);
756 }
757
758 SALOME::Transaction_ptr DataScopeServerTransaction::killVarTransac(const char *varName)
759 {
760   std::string varNameCpp(varName);
761   checkExistingVar(varNameCpp);
762   //
763   TransactionKillVar *ret(new TransactionKillVar(this,varName));
764   CORBA::Object_var obj2(ret->activate());
765   return SALOME::Transaction::_narrow(obj2);
766 }
767
768 SALOME::KeyWaiter_ptr DataScopeServerTransaction::waitForKeyInVar(const char *varName, const SALOME::ByteVec& keyVal)
769 {
770   PickelizedPyObjServer *pickelObj(checkVarExistingAndDict(varName));
771   KeyWaiter *ret(new KeyWaiter(pickelObj,keyVal));
772   CORBA::Object_var obj(ret->activate());//KeyWaiter instance activated inside a multithread POA contrary to all of objects in SALOMESDS in single thread !
773   return SALOME::KeyWaiter::_narrow(obj);
774 }
775
776 SALOME::KeyWaiter_ptr DataScopeServerTransaction::waitForKeyInVarAndKillIt(const char *varName, const SALOME::ByteVec& keyVal, SALOME::Transaction_out transac)
777 {
778   PickelizedPyObjServer *pickelObj(checkVarExistingAndDict(varName));
779   KeyWaiter *ret0(new KeyWaiter(pickelObj,keyVal));
780   CORBA::Object_var obj(ret0->activate());//KeyWaiter instance activated inside a multithread POA contrary to all of objects in SALOMESDS in single thread !
781   //
782   TransactionRemoveKeyInVarErrorIfNotAlreadyExisting *ret1(new TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(this,varName,keyVal));
783   CORBA::Object_var obj2(ret1->activate());
784   transac=SALOME::Transaction::_narrow(obj2);
785   //
786   return SALOME::KeyWaiter::_narrow(obj);
787 }
788
789 SALOME::ByteVec *DataScopeServerTransaction::waitForMonoThrRev(SALOME::KeyWaiter_ptr kw)
790 {
791   PortableServer::ServantBase *ret(0);
792   try
793     {
794       ret=_poa_for_key_waiter->reference_to_servant(kw);// Warning ref cnt of ret has been incremented !
795     }
796   catch(...) { ret=0; }
797   KeyWaiter *retc(dynamic_cast<KeyWaiter *>(ret));
798   if(!retc)
799     throw Exception("DataScopeServerTransaction::invokeMonoThr : internal error 1 !");
800   retc->_remove_ref();// restore the counter afer _poa_for_key_waiter->reference_to_servant(kw)
801   SALOME::ByteVec *zeRet(retc->waitForMonoThr());
802   retc->enforcedRelease();
803   return zeRet;
804 }
805
806 SALOME::ByteVec *DataScopeServerTransaction::waitForAndKill(SALOME::KeyWaiter_ptr kw)
807 {
808   PortableServer::ServantBase *ret(0);
809   try
810     {
811       ret=_poa_for_key_waiter->reference_to_servant(kw);// Warning ref cnt of ret has been incremented !
812     }
813   catch(...) { ret=0; }
814   KeyWaiter *retc(dynamic_cast<KeyWaiter *>(ret));
815   if(!retc)
816     throw Exception("DataScopeServerTransaction::invokeMonoThr : internal error 1 !");
817   retc->_remove_ref();// restore the counter afer _poa_for_key_waiter->reference_to_servant(kw)
818   SALOME::ByteVec *zeRet(retc->waitForAndKill());
819   retc->enforcedRelease();
820   return zeRet;
821 }
822
823 void DataScopeServerTransaction::atomicApply(const SALOME::ListOfTransaction& transactions)
824 {
825   std::size_t sz(transactions.length());
826   if(sz==0)
827     return ;
828   std::vector< AutoServantPtr<Transaction> > transactionsCpp(sz);
829   for(std::size_t i=0;i<sz;i++)
830     {
831       PortableServer::ServantBase *eltBase(0);
832       Transaction *elt(0);
833       try
834         {
835           eltBase=_poa->reference_to_servant(transactions[i]);
836           elt=dynamic_cast<Transaction *>(eltBase);
837         }
838       catch(...)
839         {
840           std::ostringstream oss; oss << "DataScopeServerTransaction::atomicApply : the elt #" << i << " is invalid !";
841           throw Exception(oss.str());
842         }
843       if(!elt)
844         {
845           std::ostringstream oss; oss << "DataScopeServerTransaction::atomicApply : the elt #" << i << " is null ?";
846           throw Exception(oss.str());
847         }
848       elt->_remove_ref();
849       transactionsCpp[i]=elt;
850     }
851   {// important do not merge loops ! 
852     std::vector<TrustTransaction> transactions2(sz);
853     bool mustRollback(true);
854     for(std::size_t i=0;i<sz;i++)
855       transactions2[i].setTransaction(transactionsCpp[i],&mustRollback);
856     for(std::size_t i=0;i<sz;i++)
857       transactions2[i].operate();
858     mustRollback=false;
859   }
860   for(std::size_t i=0;i<sz;i++)
861     transactionsCpp[i]->notify();
862 }
863
864 /*!
865  * Returns borrowed reference.
866  */
867 PyObject *DataScopeServerTransaction::getPyCmpFunc()
868 {
869   PyObject *builtins(PyDict_GetItemString(_globals,"__builtins__"));//borrowed
870   if(builtins==NULL)
871     throw Exception("Fail to find reference to builtins !");
872   PyObject *builtins2(PyModule_GetDict(builtins));//borrowed
873   if(builtins2==NULL)
874     throw Exception("Fail to invoke __dict__ on builtins !");
875   PyObject *cmpObj(PyDict_GetItemString(builtins2,"cmp"));
876   if(cmpObj==NULL)
877     throw Exception("Fail to find cmp in __builtins__ !");
878   return cmpObj;
879 }
880
881 DataScopeServerTransaction::~DataScopeServerTransaction()
882 {
883 }
884