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