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