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