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