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