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