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