Salome HOME
Implementation of working glob var. Remove memory leak on TestSalomeSDS.py.
[modules/kernel.git] / src / SALOMESDS / SALOMESDS_DataScopeServer.cxx
1 // Copyright (C) 2007-2015  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_KeyWaiter.hxx"
27 #include "SALOMESDS_Transaction.hxx"
28 #include "SALOME_NamingService.hxx"
29 #include "SALOMESDS_Exception.hxx"
30
31 #include <sstream>
32 #include <iterator>
33 #include <algorithm>
34
35 // agy : awful, to be factorized with ContainerManager.
36 #ifndef WIN32
37 #include <unistd.h>
38 #else
39 #include <process.h>
40 #define getpid _getpid
41 #endif
42
43 using namespace SALOMESDS;
44
45 std::size_t DataScopeServerBase::COUNTER=0;
46
47 void DataScopeKiller::shutdown()
48 {
49   Py_Finalize();
50   _orb->shutdown(0);
51 }
52
53 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)
54 {
55 }
56
57 DataScopeServerBase::DataScopeServerBase(const DataScopeServerBase& other):_globals(0),_locals(0),_pickler(0),_name(other._name),_vars(other._vars),_killer(other._killer)
58 {
59 }
60
61 DataScopeServerBase::~DataScopeServerBase()
62 {
63   // _globals is borrowed ref -> do nothing
64   Py_XDECREF(_locals);
65   Py_XDECREF(_pickler);
66   for(std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it=_vars.begin();it!=_vars.end();it++)
67     {
68        BasicDataServer *obj((*it).second);
69        if(obj)
70          {
71            obj->decrRef();
72          }
73     }
74 }
75
76 /*!
77  * Called remotely -> to protect against throw
78  */
79 void DataScopeServerBase::ping()
80 {
81 }
82
83 /*!
84  * Called remotely -> to protect against throw
85  */
86 char *DataScopeServerBase::getScopeName()
87 {
88   return CORBA::string_dup(_name.c_str());
89 }
90
91 /*!
92  * Called remotely -> to protect against throw
93  */
94 SALOME::StringVec *DataScopeServerBase::listVars()
95 {
96   SALOME::StringVec *ret(new SALOME::StringVec);
97   std::size_t sz(_vars.size());
98   ret->length(sz);
99   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(_vars.begin());
100   for(std::size_t i=0;i<sz;it++,i++)
101     {
102       BasicDataServer *obj((*it).second);
103       std::string name(obj->getVarNameCpp());
104       (*ret)[i]=CORBA::string_dup(name.c_str());
105     }
106   return ret;
107 }
108
109 CORBA::Boolean DataScopeServerBase::existVar(const char *varName)
110 {
111   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it(_vars.begin());
112   for(;it!=_vars.end();it++)
113     if((*it).second->getVarNameCpp()==varName)
114       return true;
115   return false;
116 }
117
118 SALOME::BasicDataServer_ptr DataScopeServerBase::retrieveVarInternal(const char *varName)
119 {
120   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(retrieveVarInternal3(varName));
121   return SALOME::BasicDataServer::_duplicate((*it0).first);
122 }
123
124 BasicDataServer *DataScopeServerBase::retrieveVarInternal2(const std::string& varName)
125 {
126   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(retrieveVarInternal3(varName));
127   return (*it0).second;
128 }
129
130 void DataScopeServerBase::deleteVar(const char *varName)
131 {
132   std::string varNameCpp(varName);
133   std::vector<std::string> allNames(getAllVarNames());
134   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varNameCpp));
135   if(it==allNames.end())
136     {
137       std::ostringstream oss; oss << "DataScopeServerBase::deleteVar : name \"" << varNameCpp << "\" does not exists ! Possibilities are :";
138       std::copy(allNames.begin(),allNames.end(),std::ostream_iterator<std::string>(oss,", "));
139       throw Exception(oss.str());
140     }
141   std::size_t pos(std::distance(allNames.begin(),it));
142   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it0(_vars.begin());
143   for(std::size_t ii=0;ii<pos;ii++,it0++);
144   (*it0).second->decrRef();
145   _vars.erase(it0);
146 }
147
148 CORBA::Boolean DataScopeServerBase::shutdownIfNotHostedByDSM(SALOME::DataScopeKiller_out killer)
149 {
150   SALOME_NamingService ns(_orb);
151   CORBA::Object_var obj(ns.Resolve(DataServerManager::NAME_IN_NS));
152   SALOME::DataServerManager_var dsm(SALOME::DataServerManager::_narrow(obj));
153   if(CORBA::is_nil(dsm))
154     throw Exception("Unable to reach in the NS the unique DataServerManager instance of the Session !");
155   // destroy ref in the naming service
156   std::string fullScopeName(SALOMESDS::DataServerManager::CreateAbsNameInNSFromScopeName(_name));
157   ns.Destroy_Name(fullScopeName.c_str());
158   // establish if dsm and this shared the same POA. If yes dsm and this are collocated !
159   PortableServer::ServantBase *ret(0);
160   try
161     {
162       ret=_poa->reference_to_servant(dsm);
163     }
164   catch(...) { ret=0; }
165   //
166   if(!ret)
167     {
168       enforcedRelease();
169       killer=SALOME::DataScopeKiller::_duplicate(_killer);
170       return true;
171     }
172   else
173     {
174       ret->_remove_ref();
175       enforcedRelease();
176       killer=SALOME::DataScopeKiller::_duplicate(_killer);
177       return false;
178     }
179 }
180
181 SALOME::ByteVec *DataScopeServerBase::fetchSerializedContent(const char *varName)
182 {
183   BasicDataServer *var(retrieveVarInternal2(varName));
184   PickelizedPyObjServer *varc(dynamic_cast<PickelizedPyObjServer *>(var));
185   if(!varc)
186     {
187       std::ostringstream oss; oss << "DataScopeServerBase::fetchSerializedContent : var \"" << varName << "\" exists but it is not serialized !";
188       throw Exception(oss.str());
189     }
190   return varc->fetchSerializedContent();
191 }
192
193 SALOME::SeqOfByteVec *DataScopeServerBase::getAllKeysOfVarWithTypeDict(const char *varName)
194 {
195   BasicDataServer *var(retrieveVarInternal2(varName));
196   PickelizedPyObjServer *varc(dynamic_cast<PickelizedPyObjServer *>(var));
197   if(!varc)
198     {
199       std::ostringstream oss; oss << "DataScopeServerBase::getAllKeysOfVarWithTypeDict : var \"" << varName << "\" exists but it is not serialized !";
200       throw Exception(oss.str());
201     }
202   if(!varc->isDict())
203     {
204       std::ostringstream oss; oss << "DataScopeServerBase::getAllKeysOfVarWithTypeDict : var \"" << varName << "\" exists but it is not a PyDict !";
205       throw Exception(oss.str());
206     }
207   PyObject *keys(PyDict_Keys(varc->getPyObj()));
208   if(!PyList_Check(keys))
209     {
210       std::ostringstream oss; oss << "DataScopeServerBase::getAllKeysOfVarWithTypeDict : var \"" << varName << "\" has keys but not of type list !";
211       throw Exception(oss.str());
212     }
213   Py_ssize_t sz(PyList_Size(keys));
214   SALOME::SeqOfByteVec *ret(new SALOME::SeqOfByteVec);
215   ret->length(sz);
216   for(Py_ssize_t i=0;i<sz;i++)
217     {
218       PyObject *item(PyList_GetItem(keys,i));
219       Py_XINCREF(item);
220       std::string pickel(varc->pickelize(item));//item consumed
221       PickelizedPyObjServer::FromCppToByteSeq(pickel,(*ret)[i]);
222     }
223   Py_XDECREF(keys);
224   return ret;
225 }
226
227 void DataScopeServerBase::initializePython(int argc, char *argv[])
228 {
229   Py_Initialize();
230   PyEval_InitThreads();
231   PySys_SetArgv(argc,argv);
232   PyObject *mainmod(PyImport_AddModule("__main__"));
233   _globals=PyModule_GetDict(mainmod);
234   if(PyDict_GetItemString(_globals, "__builtins__") == NULL)
235     {
236       PyObject *bimod(PyImport_ImportModule("__builtin__"));
237       if (bimod == NULL || PyDict_SetItemString(_globals, "__builtins__", bimod) != 0)
238         Py_FatalError("can't add __builtins__ to __main__");
239       Py_XDECREF(bimod);
240     }
241   _locals=PyDict_New();
242   PyObject *tmp(PyList_New(0));
243   _pickler=PyImport_ImportModuleLevel(const_cast<char *>("cPickle"),_globals,_locals,tmp,-1);
244 }
245
246 void DataScopeServerBase::registerToSalomePiDict() const
247 {
248   PyObject *mod(PyImport_ImportModule("addToKillList"));
249   if(!mod)
250     return;
251   PyObject *meth(PyObject_GetAttrString(mod,"addToKillList"));
252   if(!meth)
253     { Py_XDECREF(mod); return ; }
254   PyObject *args(PyTuple_New(2));
255   PyTuple_SetItem(args,0,PyInt_FromLong(getpid()));
256   PyTuple_SetItem(args,1,PyString_FromString("SALOME_DataScopeServerBase"));
257   PyObject *res(PyObject_CallObject(meth,args));
258   Py_XDECREF(args);
259   Py_XDECREF(res);
260   Py_XDECREF(mod);
261 }
262
263 void DataScopeServerBase::setPOA(PortableServer::POA_var poa)
264 {
265   _poa=poa;
266 }
267
268 void DataScopeServerBase::registerInNS(SALOME::DataScopeServerBase_ptr ptr)
269 {
270   std::string fullScopeName(SALOMESDS::DataServerManager::CreateAbsNameInNSFromScopeName(_name));
271   SALOME_NamingService ns(_orb);
272   ns.Register(ptr,fullScopeName.c_str());
273 }
274
275 std::string DataScopeServerBase::BuildTmpVarNameFrom(const std::string& varName)
276 {
277   std::ostringstream oss;
278   oss << varName << "@" << COUNTER++;
279   return oss.str();
280 }
281
282 std::vector< std::string > DataScopeServerBase::getAllVarNames() const
283 {
284   std::size_t sz(_vars.size());
285   std::vector<std::string> ret(sz);
286   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it(_vars.begin());
287   for(std::size_t i=0;i<sz;it++,i++)
288     ret[i]=(*it).second->getVarNameCpp();
289   return ret;
290 }
291
292 void DataScopeServerBase::checkNotAlreadyExistingVar(const std::string& varName) const
293 {
294   std::vector<std::string> allNames(getAllVarNames());
295   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
296   if(it!=allNames.end())
297     {
298       std::ostringstream oss; oss << "DataScopeServerBase::checkNotAlreadyExistingVar : name \"" << varName << "\" already exists !";
299       throw Exception(oss.str());
300     }
301 }
302
303 void DataScopeServerBase::checkExistingVar(const std::string& varName) const
304 {
305   std::vector<std::string> allNames(getAllVarNames());
306   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
307   if(it==allNames.end())
308     {
309       std::ostringstream oss; oss << "DataScopeServerBase::checkExistingVar : name \"" << varName << "\" does not exist !";
310       throw Exception(oss.str());
311     }
312 }
313
314 PickelizedPyObjServer *DataScopeServerBase::checkVarExistingAndDict(const std::string& varName)
315 {
316   checkExistingVar(varName);
317   BasicDataServer *var(retrieveVarInternal2(varName.c_str()));
318   PickelizedPyObjServer *ret(dynamic_cast<PickelizedPyObjServer *>(var));
319   if(!ret)
320     {
321       std::ostringstream oss; oss << "TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure : var \"" << varName << "\"exists but it is not serialized !";
322       throw Exception(oss.str());
323     }
324   if(!ret->isDict())
325     {
326       std::ostringstream oss; oss << "TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure : var \"" << varName << "\"exists but it is not a Dict !";
327       throw Exception(oss.str());
328     }
329   return ret;
330 }
331
332 void DataScopeServerBase::moveStatusOfVarFromRdWrToRdOnly(const std::string& varName)
333 {
334   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
335   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
336   PickelizedPyObjRdWrServer *varc(dynamic_cast<PickelizedPyObjRdWrServer *>(p.second));
337   if(!varc)
338     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdWrToRdOnly : var is not a RdWr !");
339   PyObject *pyobj(varc->getPyObj()); Py_XINCREF(pyobj);
340   PickelizedPyObjRdOnlyServer *newVar(new PickelizedPyObjRdOnlyServer(this,varName,pyobj));
341   CORBA::Object_var obj(newVar->activate());
342   SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
343   p.first=obj2; p.second=newVar;
344   varc->decrRef();
345 }
346
347 void DataScopeServerBase::moveStatusOfVarFromRdOnlyToRdWr(const std::string& varName)
348 {
349   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
350   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
351   PickelizedPyObjRdOnlyServer *varc(dynamic_cast<PickelizedPyObjRdOnlyServer *>(p.second));
352   if(!varc)
353     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdOnlyToRdWr : var is not a RdWr !");
354   PyObject *pyobj(varc->getPyObj()); Py_XINCREF(pyobj);
355   PickelizedPyObjRdWrServer *newVar(new PickelizedPyObjRdWrServer(this,varName,pyobj));
356   CORBA::Object_var obj(newVar->activate());
357   SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
358   p.first=obj2; p.second=newVar;
359   varc->decrRef();
360 }
361
362 std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator DataScopeServerBase::retrieveVarInternal3(const std::string& varName) const
363 {
364   std::vector<std::string> allNames(getAllVarNames());
365   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
366   if(it==allNames.end())
367     {
368       std::ostringstream oss; oss << "DataScopeServerBase::retrieveVarInternal3 : name \"" << varName << "\" does not exists ! Possibilities are :";
369       std::copy(allNames.begin(),allNames.end(),std::ostream_iterator<std::string>(oss,", "));
370       throw Exception(oss.str());
371     }
372   std::size_t pos(std::distance(allNames.begin(),it));
373   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(_vars.begin());
374   for(std::size_t i=0;i<pos;i++,it0++);
375   return it0;
376 }
377
378 std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator DataScopeServerBase::retrieveVarInternal4(const std::string& varName)
379 {
380   std::vector<std::string> allNames(getAllVarNames());
381   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
382   if(it==allNames.end())
383     {
384       std::ostringstream oss; oss << "DataScopeServerBase::retrieveVarInternal4 : name \"" << varName << "\" does not exists ! Possibilities are :";
385       std::copy(allNames.begin(),allNames.end(),std::ostream_iterator<std::string>(oss,", "));
386       throw Exception(oss.str());
387     }
388   std::size_t pos(std::distance(allNames.begin(),it));
389   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it0(_vars.begin());
390   for(std::size_t i=0;i<pos;i++,it0++);
391   return it0;
392 }
393
394 ///////
395
396 DataScopeServer::DataScopeServer(CORBA::ORB_ptr orb, SALOME::DataScopeKiller_var killer, const std::string& scopeName):DataScopeServerBase(orb,killer,scopeName)
397 {
398 }
399
400 DataScopeServer::DataScopeServer(const DataScopeServer& other):DataScopeServerBase(other)
401 {
402 }
403
404 SALOME::PickelizedPyObjRdOnlyServer_ptr DataScopeServer::createRdOnlyVar(const char *varName, const SALOME::ByteVec& constValue)
405 {
406   std::string varNameCpp(varName);
407   checkNotAlreadyExistingVar(varNameCpp);
408   PickelizedPyObjRdOnlyServer *tmp(new PickelizedPyObjRdOnlyServer(this,varNameCpp,constValue));
409   CORBA::Object_var ret(tmp->activate());
410   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
411   _vars.push_back(p);
412   return SALOME::PickelizedPyObjRdOnlyServer::_narrow(ret);
413 }
414
415 SALOME::PickelizedPyObjRdExtServer_ptr DataScopeServer::createRdExtVar(const char *varName, const SALOME::ByteVec& constValue)
416 {
417   std::string varNameCpp(varName);
418   checkNotAlreadyExistingVar(varNameCpp);
419   PickelizedPyObjRdExtServer *tmp(new PickelizedPyObjRdExtServer(this,varNameCpp,constValue));
420   CORBA::Object_var ret(tmp->activate());
421   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
422   _vars.push_back(p);
423   return SALOME::PickelizedPyObjRdExtServer::_narrow(ret);
424 }
425
426 SALOME::PickelizedPyObjRdWrServer_ptr DataScopeServer::createRdWrVar(const char *typeName, const char *varName)
427 {
428   std::string varNameCpp(varName),typeNameCpp(typeName);
429   checkNotAlreadyExistingVar(varNameCpp);
430   PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,typeNameCpp,varNameCpp));
431   CORBA::Object_var ret(tmp->activate());
432   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
433   _vars.push_back(p);
434   return SALOME::PickelizedPyObjRdWrServer::_narrow(ret);
435 }
436
437 DataScopeServer::~DataScopeServer()
438 {
439 }
440
441 ////////
442
443 DataScopeServerTransaction::DataScopeServerTransaction(CORBA::ORB_ptr orb, SALOME::DataScopeKiller_var killer, const std::string& scopeName):DataScopeServerBase(orb,killer,scopeName)
444 {
445   CORBA::Object_var obj(_orb->resolve_initial_references("RootPOA"));
446   PortableServer::POA_var poa(PortableServer::POA::_narrow(obj));
447   //
448   PortableServer::POAManager_var mgr(poa->the_POAManager());
449   CORBA::PolicyList policies;
450   policies.length(1);
451   PortableServer::ThreadPolicy_var threadPol(poa->create_thread_policy(PortableServer::ORB_CTRL_MODEL));
452   policies[0]=PortableServer::ThreadPolicy::_duplicate(threadPol);
453   PortableServer::POA_var poa2(poa->create_POA("POAForWaiters",mgr,policies));
454   threadPol->destroy();
455   //
456   _poa_for_key_waiter=poa2;
457 }
458
459 DataScopeServerTransaction::DataScopeServerTransaction(const DataScopeServerTransaction& other):DataScopeServerBase(other),_poa_for_key_waiter(other.getPOA4KeyWaiter())
460 {
461 }
462
463 char *DataScopeServerTransaction::getAccessOfVar(const char *varName)
464 {
465   std::string varNameCpp(varName);
466   checkExistingVar(varNameCpp);
467   BasicDataServer *var(retrieveVarInternal2(varName));
468   if(!var)
469     throw Exception("DataScopeServerTransaction::getAccessOfVar : variable is NULL !");
470   PickelizedPyObjServer *varc(dynamic_cast<PickelizedPyObjServer *>(var));
471   if(!varc)
472     throw Exception("DataScopeServerTransaction::getAccessOfVar : variable is not of type PickelizedPyObjServer !");
473   std::string ret(varc->getAccessStr());
474   return CORBA::string_dup(ret.c_str());
475 }
476
477 void DataScopeServerTransaction::createRdOnlyVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
478 {
479   checkNotAlreadyExistingVar(varName);
480   PickelizedPyObjRdOnlyServer *tmp(new PickelizedPyObjRdOnlyServer(this,varName,constValue));
481   CORBA::Object_var ret(tmp->activate());
482   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
483   _vars.push_back(p);
484 }
485
486 void DataScopeServerTransaction::createRdExtVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
487 {
488   checkNotAlreadyExistingVar(varName);
489   PickelizedPyObjRdExtServer *tmp(new PickelizedPyObjRdExtServer(this,varName,constValue));
490   CORBA::Object_var ret(tmp->activate());
491   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
492   _vars.push_back(p);
493 }
494
495 void DataScopeServerTransaction::createRdWrVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
496 {
497   checkNotAlreadyExistingVar(varName);
498   PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,varName,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 }
503
504 SALOME::Transaction_ptr DataScopeServerTransaction::createRdOnlyVarTransac(const char *varName, const SALOME::ByteVec& constValue)
505 {
506   checkNotAlreadyExistingVar(varName);
507   TransactionRdOnlyVarCreate *ret(new TransactionRdOnlyVarCreate(this,varName,constValue));
508   CORBA::Object_var obj(ret->activate());
509   return SALOME::Transaction::_narrow(obj);
510 }
511
512 SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtVarTransac(const char *varName, const SALOME::ByteVec& constValue)
513 {
514   checkNotAlreadyExistingVar(varName);
515   TransactionRdExtVarCreate *ret(new TransactionRdExtVarCreate(this,varName,constValue));
516   CORBA::Object_var obj(ret->activate());
517   return SALOME::Transaction::_narrow(obj);
518 }
519
520 SALOME::Transaction_ptr DataScopeServerTransaction::createRdWrVarTransac(const char *varName, const SALOME::ByteVec& constValue)
521 {
522   checkNotAlreadyExistingVar(varName);
523   TransactionRdWrVarCreate *ret(new TransactionRdWrVarCreate(this,varName,constValue));
524   CORBA::Object_var obj(ret->activate());
525   return SALOME::Transaction::_narrow(obj);
526 }
527
528 void DataScopeServerTransaction::addWaitKey(KeyWaiter *kw)
529 {
530   if(!kw)
531     throw Exception("DataScopeServerTransaction::addWaitKey : NULL input object !");
532   _waiting_keys.push_back(kw);
533 }
534
535 void DataScopeServerTransaction::pingKey(PyObject *keyObj)
536 {
537   PyObject *cmpObj(getPyCmpFunc());
538   if(!keyObj)
539     throw Exception("ataScopeServerTransaction::pingKey : Key Object is NULL !");
540   PyObject *args(PyTuple_New(2));
541   PyTuple_SetItem(args,0,keyObj); Py_XINCREF(keyObj);
542   std::size_t ii(0);
543   // this part does nothing except to be sure that in notify key all will be OK.
544   for(std::list< KeyWaiter *>::iterator it=_waiting_keys.begin();it!=_waiting_keys.end();it++,ii++)
545     {
546       PyObject *waitKey((*it)->getKeyPyObj());
547       PyTuple_SetItem(args,1,waitKey); Py_XINCREF(waitKey);
548       PyObject *res(PyObject_CallObject(cmpObj,args));
549       if(res==NULL)
550         {
551           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " error during cmp(k,wk[i]) !";
552           throw Exception(oss.str());
553         }
554       PyInt_AsLong(res);
555       if(PyErr_Occurred())
556         {
557           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " error during interpretation of cmp(k,wk[i]) !";
558           throw Exception(oss.str());
559         }
560       Py_XDECREF(res);
561     }
562 }
563
564 void DataScopeServerTransaction::notifyKey(PyObject *keyObj, PyObject *valueObj)
565 {
566   PyObject *cmpObj(getPyCmpFunc());
567   if(!keyObj)
568     throw Exception("DataScopeServerTransaction::notifyKey : MAIN INTERNAL ERROR ! Key Object is NULL !");
569   PyObject *args(PyTuple_New(2));
570   PyTuple_SetItem(args,0,keyObj); Py_XINCREF(keyObj);
571   std::size_t ii(0);
572   std::list< KeyWaiter *> newList,listOfEltToWakeUp;
573   for(std::list< KeyWaiter *>::iterator it=_waiting_keys.begin();it!=_waiting_keys.end();it++,ii++)
574     {
575       PyObject *waitKey((*it)->getKeyPyObj());
576       PyTuple_SetItem(args,1,waitKey); Py_XINCREF(waitKey);
577       PyObject *res(PyObject_CallObject(cmpObj,args));
578       if(res==NULL)
579         {
580           std::ostringstream oss; oss << "DataScopeServerTransaction::notifyKey : MAIN INTERNAL ERROR ! for object id #" << ii << " error during cmp(k,wk[i]) !";
581           throw Exception(oss.str());
582         }
583       long resCpp(PyInt_AsLong(res));
584       if(PyErr_Occurred())
585         {
586           std::ostringstream oss; oss << "DataScopeServerTransaction::notifyKey : MAIN INTERNAL ERROR ! for object id #" << ii << " error during interpretation of cmp(k,wk[i]) !";
587           throw Exception(oss.str());
588         }
589       Py_XDECREF(res);
590       if(resCpp==0)
591         listOfEltToWakeUp.push_back(*it);
592       else
593         newList.push_back(*it);
594     }
595   for(std::list< KeyWaiter *>::iterator it=listOfEltToWakeUp.begin();it!=listOfEltToWakeUp.end();it++)
596     (*it)->valueJustCome(valueObj);
597   for(std::list< KeyWaiter *>::iterator it=listOfEltToWakeUp.begin();it!=listOfEltToWakeUp.end();it++)
598     (*it)->go();
599   _waiting_keys=newList;
600 }
601
602 SALOME::Transaction_ptr DataScopeServerTransaction::addKeyValueInVarHard(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value)
603 {
604   checkVarExistingAndDict(varName);
605   TransactionAddKeyValueHard *ret(new TransactionAddKeyValueHard(this,varName,key,value));
606   CORBA::Object_var obj(ret->activate());
607   return SALOME::Transaction::_narrow(obj);
608 }
609
610 SALOME::Transaction_ptr DataScopeServerTransaction::addKeyValueInVarErrorIfAlreadyExisting(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value)
611 {
612   checkVarExistingAndDict(varName);
613   TransactionAddKeyValueErrorIfAlreadyExisting *ret(new TransactionAddKeyValueErrorIfAlreadyExisting(this,varName,key,value));
614   CORBA::Object_var obj(ret->activate());
615   return SALOME::Transaction::_narrow(obj);
616 };
617
618 class TrustTransaction
619 {
620 public:
621   TrustTransaction():_must_rollback(0),_ptr(0) { }
622   void setTransaction(Transaction *t, bool *mustRollback) { if(!t || !mustRollback) throw Exception("TrustTransaction Error #1"); _ptr=t; _must_rollback=mustRollback; _ptr->prepareRollBackInCaseOfFailure(); }
623   void operate() { _ptr->perform(); }
624   ~TrustTransaction() { if(!_ptr) return ; if(*_must_rollback) _ptr->rollBack(); }
625 private:
626   bool *_must_rollback;
627   Transaction *_ptr;
628 };
629
630 void DataScopeServerTransaction::addKeyValueInVarErrorIfAlreadyExistingNow(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value)
631 {
632   checkVarExistingAndDict(varName);
633   TransactionAddKeyValueErrorIfAlreadyExisting ret(this,varName,key,value);
634   {
635     bool mustRollback(true);
636     TrustTransaction t;
637     t.setTransaction(&ret,&mustRollback);
638     t.operate();
639     mustRollback=false;
640   }
641 }
642
643 SALOME::Transaction_ptr DataScopeServerTransaction::removeKeyInVarErrorIfNotAlreadyExisting(const char *varName, const SALOME::ByteVec& key)
644 {
645   checkVarExistingAndDict(varName);
646   TransactionRemoveKeyInVarErrorIfNotAlreadyExisting *ret(new TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(this,varName,key));
647   CORBA::Object_var obj(ret->activate());
648   return SALOME::Transaction::_narrow(obj);
649 }
650
651 SALOME::TransactionRdWrAccess_ptr DataScopeServerTransaction::createWorkingVarTransac(const char *varName, const SALOME::ByteVec& constValue)
652 {
653   std::string varNameCpp(varName);
654   checkNotAlreadyExistingVar(varName);
655   PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,varNameCpp,constValue));
656   CORBA::Object_var obj(tmp->activate());
657   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(obj),tmp);
658   _vars.push_back(p);
659   //
660   TransactionMorphRdWrIntoRdOnly *ret(new TransactionMorphRdWrIntoRdOnly(this,varName));
661   CORBA::Object_var obj2(ret->activate());
662   return SALOME::TransactionRdWrAccess::_narrow(obj2);
663 }
664
665 SALOME::KeyWaiter_ptr DataScopeServerTransaction::waitForKeyInVar(const char *varName, const SALOME::ByteVec& keyVal)
666 {
667   PickelizedPyObjServer *pickelObj(checkVarExistingAndDict(varName));
668   KeyWaiter *ret(new KeyWaiter(pickelObj,keyVal));
669   CORBA::Object_var obj(ret->activate());//KeyWaiter instance activated inside a multithread POA contrary to all of objects in SALOMESDS in single thread !
670   return SALOME::KeyWaiter::_narrow(obj);
671 }
672
673 SALOME::KeyWaiter_ptr DataScopeServerTransaction::waitForKeyInVarAndKillIt(const char *varName, const SALOME::ByteVec& keyVal, SALOME::Transaction_out transac)
674 {
675   PickelizedPyObjServer *pickelObj(checkVarExistingAndDict(varName));
676   KeyWaiter *ret0(new KeyWaiter(pickelObj,keyVal));
677   CORBA::Object_var obj(ret0->activate());//KeyWaiter instance activated inside a multithread POA contrary to all of objects in SALOMESDS in single thread !
678   //
679   TransactionRemoveKeyInVarErrorIfNotAlreadyExisting *ret1(new TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(this,varName,keyVal));
680   CORBA::Object_var obj2(ret1->activate());
681   transac=SALOME::Transaction::_narrow(obj2);
682   //
683   return SALOME::KeyWaiter::_narrow(obj);
684 }
685
686 SALOME::ByteVec *DataScopeServerTransaction::waitForMonoThrRev(SALOME::KeyWaiter_ptr kw)
687 {
688   PortableServer::ServantBase *ret(0);
689   try
690     {
691       ret=_poa_for_key_waiter->reference_to_servant(kw);
692     }
693   catch(...) { ret=0; }
694   KeyWaiter *retc(dynamic_cast<KeyWaiter *>(ret));
695   if(!retc)
696     throw Exception("DataScopeServerTransaction::invokeMonoThr : internal error 1 !");
697   retc->_remove_ref();
698   retc->waitForMonoThr();
699 }
700
701 void DataScopeServerTransaction::atomicApply(const SALOME::ListOfTransaction& transactions)
702 {
703   std::size_t sz(transactions.length());
704   if(sz==0)
705     return ;
706   std::vector< AutoServantPtr<Transaction> > transactionsCpp(sz);
707   for(std::size_t i=0;i<sz;i++)
708     {
709       PortableServer::ServantBase *eltBase(0);
710       Transaction *elt(0);
711       try
712         {
713           eltBase=_poa->reference_to_servant(transactions[i]);
714           elt=dynamic_cast<Transaction *>(eltBase);
715         }
716       catch(...)
717         {
718           std::ostringstream oss; oss << "DataScopeServerTransaction::atomicApply : the elt #" << i << " is invalid !";
719           throw Exception(oss.str());
720         }
721       if(!elt)
722         {
723           std::ostringstream oss; oss << "DataScopeServerTransaction::atomicApply : the elt #" << i << " is null ?";
724           throw Exception(oss.str());
725         }
726       elt->_remove_ref();
727       transactionsCpp[i]=elt;
728     }
729   {// important do not merge loops ! 
730     std::vector<TrustTransaction> transactions2(sz);
731     bool mustRollback(true);
732     for(std::size_t i=0;i<sz;i++)
733       transactions2[i].setTransaction(transactionsCpp[i],&mustRollback);
734     for(std::size_t i=0;i<sz;i++)
735       transactions2[i].operate();
736     mustRollback=false;
737   }
738   for(std::size_t i=0;i<sz;i++)
739     transactionsCpp[i]->notify();
740 }
741
742 /*!
743  * Returns borrowed reference.
744  */
745 PyObject *DataScopeServerTransaction::getPyCmpFunc()
746 {
747   PyObject *builtins(PyDict_GetItemString(_globals,"__builtins__"));//borrowed
748   if(builtins==NULL)
749     throw Exception("Fail to find reference to builtins !");
750   PyObject *builtins2(PyModule_GetDict(builtins));//borrowed
751   if(builtins2==NULL)
752     throw Exception("Fail to invoke __dict__ on builtins !");
753   PyObject *cmpObj(PyDict_GetItemString(builtins2,"cmp"));
754   if(cmpObj==NULL)
755     throw Exception("Fail to find cmp in __builtins__ !");
756   return cmpObj;
757 }
758
759 DataScopeServerTransaction::~DataScopeServerTransaction()
760 {
761 }
762