]> SALOME platform Git repositories - modules/kernel.git/blob - src/SALOMESDS/SALOMESDS_DataScopeServer.cxx
Salome HOME
Merge branch 'V8_5_BR'
[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 bool DataScopeServerBase::isExistingVar(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   return it!=allNames.end();
337 }
338
339 void DataScopeServerBase::checkNotAlreadyExistingVar(const std::string& varName) const
340 {
341   if(isExistingVar(varName))
342     {
343       std::ostringstream oss; oss << "DataScopeServerBase::checkNotAlreadyExistingVar : name \"" << varName << "\" already exists !";
344       throw Exception(oss.str());
345     }
346 }
347
348 void DataScopeServerBase::checkExistingVar(const std::string& varName) const
349 {
350   std::vector<std::string> allNames(getAllVarNames());
351   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
352   if(it==allNames.end())
353     {
354       std::ostringstream oss; oss << "DataScopeServerBase::checkExistingVar : name \"" << varName << "\" does not exist !";
355       throw Exception(oss.str());
356     }
357 }
358
359 PickelizedPyObjServer *DataScopeServerBase::checkVarExistingAndDict(const std::string& varName)
360 {
361   checkExistingVar(varName);
362   BasicDataServer *var(retrieveVarInternal2(varName.c_str()));
363   PickelizedPyObjServer *ret(dynamic_cast<PickelizedPyObjServer *>(var));
364   if(!ret)
365     {
366       std::ostringstream oss; oss << "TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure : var \"" << varName << "\"exists but it is not serialized !";
367       throw Exception(oss.str());
368     }
369   if(!ret->isDict())
370     {
371       std::ostringstream oss; oss << "TransactionAddKeyValueHard::prepareRollBackInCaseOfFailure : var \"" << varName << "\"exists but it is not a Dict !";
372       throw Exception(oss.str());
373     }
374   return ret;
375 }
376
377 void DataScopeServerBase::moveStatusOfVarFromRdWrToRdOnly(const std::string& varName)
378 {
379   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
380   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
381   PickelizedPyObjRdWrServer *varc(dynamic_cast<PickelizedPyObjRdWrServer *>(p.second));
382   if(!varc)
383     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdWrToRdOnly : var is not a RdWr !");
384   PyObject *pyobj(varc->getPyObj()); Py_XINCREF(pyobj);
385   PickelizedPyObjRdOnlyServer *newVar(new PickelizedPyObjRdOnlyServer(this,varName,pyobj));
386   CORBA::Object_var obj(newVar->activate());
387   SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
388   p.first=obj2; p.second=newVar;
389   varc->decrRef();
390 }
391
392 void DataScopeServerBase::moveStatusOfVarFromRdOnlyToRdWr(const std::string& varName)
393 {
394   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
395   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
396   PickelizedPyObjRdOnlyServer *varc(dynamic_cast<PickelizedPyObjRdOnlyServer *>(p.second));
397   if(!varc)
398     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdOnlyToRdWr : var is not a RdWr !");
399   PyObject *pyobj(varc->getPyObj()); Py_XINCREF(pyobj);
400   PickelizedPyObjRdWrServer *newVar(new PickelizedPyObjRdWrServer(this,varName,pyobj));
401   CORBA::Object_var obj(newVar->activate());
402   SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
403   p.first=obj2; p.second=newVar;
404   varc->decrRef();
405 }
406
407 void DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExtInit(const std::string& varName)
408 {
409   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
410   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
411   PickelizedPyObjRdExtServer *varc0(dynamic_cast<PickelizedPyObjRdExtServer *>(p.second));
412   PickelizedPyObjRdExtInitServer *varc1(dynamic_cast<PickelizedPyObjRdExtInitServer *>(p.second));
413   if(!varc0 && !varc1)
414     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExtInit : var is neither RdExt nor RdExtInit !");
415   if(varc0)
416     {
417       PickelizedPyObjRdExtInitServer *newVar(varc0->buildInitInstanceFrom(varName));
418       newVar->incrNbClients();
419       CORBA::Object_var obj(newVar->activate());
420       SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
421       p.first=obj2; p.second=newVar;
422       varc0->decrRef();
423     }
424   else
425     varc1->incrNbClients();
426 }
427
428 void DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExt(const std::string& varName)
429 {
430   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it(retrieveVarInternal4(varName));
431   std::pair< SALOME::BasicDataServer_var, BasicDataServer * >& p(*it);
432   PickelizedPyObjRdExtInitServer *varc0(dynamic_cast<PickelizedPyObjRdExtInitServer *>(p.second));
433   PickelizedPyObjRdExtServer *varc1(dynamic_cast<PickelizedPyObjRdExtServer *>(p.second));
434   if(!varc0 && !varc1)
435     throw Exception("DataScopeServerBase::moveStatusOfVarFromRdExtOrRdExtInitToRdExt : var is not a RdExtInit !");
436   if(varc0)
437     {
438       if(varc0->decrNbClients())
439         {
440           PickelizedPyObjRdExtServer *newVar(varc0->buildStdInstanceFrom(varName));
441           CORBA::Object_var obj(newVar->activate());
442           SALOME::BasicDataServer_var obj2(SALOME::BasicDataServer::_narrow(obj));
443           p.first=obj2; p.second=newVar;
444           varc0->decrRef();
445         }
446     }
447 }
448
449 std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator DataScopeServerBase::retrieveVarInternal3(const std::string& varName) const
450 {
451   std::vector<std::string> allNames(getAllVarNames());
452   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
453   if(it==allNames.end())
454     {
455       std::ostringstream oss; oss << "DataScopeServerBase::retrieveVarInternal3 : name \"" << varName << "\" does not exists ! Possibilities are :";
456       std::copy(allNames.begin(),allNames.end(),std::ostream_iterator<std::string>(oss,", "));
457       throw Exception(oss.str());
458     }
459   std::size_t pos(std::distance(allNames.begin(),it));
460   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::const_iterator it0(_vars.begin());
461   for(std::size_t i=0;i<pos;i++,it0++);
462   return it0;
463 }
464
465 std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator DataScopeServerBase::retrieveVarInternal4(const std::string& varName)
466 {
467   std::vector<std::string> allNames(getAllVarNames());
468   std::vector<std::string>::iterator it(std::find(allNames.begin(),allNames.end(),varName));
469   if(it==allNames.end())
470     {
471       std::ostringstream oss; oss << "DataScopeServerBase::retrieveVarInternal4 : name \"" << varName << "\" does not exists ! Possibilities are :";
472       std::copy(allNames.begin(),allNames.end(),std::ostream_iterator<std::string>(oss,", "));
473       throw Exception(oss.str());
474     }
475   std::size_t pos(std::distance(allNames.begin(),it));
476   std::list< std::pair< SALOME::BasicDataServer_var, BasicDataServer * > >::iterator it0(_vars.begin());
477   for(std::size_t i=0;i<pos;i++,it0++);
478   return it0;
479 }
480
481 ///////
482
483 DataScopeServer::DataScopeServer(CORBA::ORB_ptr orb, SALOME::DataScopeKiller_var killer, const std::string& scopeName):DataScopeServerBase(orb,killer,scopeName)
484 {
485 }
486
487 DataScopeServer::DataScopeServer(const DataScopeServer& other):omniServant(other),ServantBase(other),DataScopeServerBase(other)
488 {
489 }
490
491 SALOME::PickelizedPyObjRdOnlyServer_ptr DataScopeServer::createRdOnlyVar(const char *varName, const SALOME::ByteVec& constValue)
492 {
493   std::string varNameCpp(varName);
494   checkNotAlreadyExistingVar(varNameCpp);
495   PickelizedPyObjRdOnlyServer *tmp(new PickelizedPyObjRdOnlyServer(this,varNameCpp,constValue));
496   CORBA::Object_var ret(tmp->activate());
497   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
498   _vars.push_back(p);
499   return SALOME::PickelizedPyObjRdOnlyServer::_narrow(ret);
500 }
501
502 SALOME::PickelizedPyObjRdExtServer_ptr DataScopeServer::createRdExtVar(const char *varName, const SALOME::ByteVec& constValue)
503 {
504   std::string varNameCpp(varName);
505   checkNotAlreadyExistingVar(varNameCpp);
506   PickelizedPyObjRdExtServer *tmp(new PickelizedPyObjRdExtServer(this,varNameCpp,constValue));
507   CORBA::Object_var ret(tmp->activate());
508   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
509   _vars.push_back(p);
510   return SALOME::PickelizedPyObjRdExtServer::_narrow(ret);
511 }
512
513 SALOME::PickelizedPyObjRdWrServer_ptr DataScopeServer::createRdWrVar(const char *typeName, const char *varName)
514 {
515   std::string varNameCpp(varName),typeNameCpp(typeName);
516   checkNotAlreadyExistingVar(varNameCpp);
517   PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,typeNameCpp,varNameCpp));
518   CORBA::Object_var ret(tmp->activate());
519   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
520   _vars.push_back(p);
521   return SALOME::PickelizedPyObjRdWrServer::_narrow(ret);
522 }
523
524 DataScopeServer::~DataScopeServer()
525 {
526 }
527
528 ////////
529
530 DataScopeServerTransaction::DataScopeServerTransaction(CORBA::ORB_ptr orb, SALOME::DataScopeKiller_var killer, const std::string& scopeName):DataScopeServerBase(orb,killer,scopeName)
531 {
532   CORBA::Object_var obj(_orb->resolve_initial_references("RootPOA"));
533   PortableServer::POA_var poa(PortableServer::POA::_narrow(obj));
534   //
535   PortableServer::POAManager_var mgr(poa->the_POAManager());
536   CORBA::PolicyList policies;
537   policies.length(1);
538   PortableServer::ThreadPolicy_var threadPol(poa->create_thread_policy(PortableServer::ORB_CTRL_MODEL));
539   policies[0]=PortableServer::ThreadPolicy::_duplicate(threadPol);
540   PortableServer::POA_var poa2(poa->create_POA("POAForWaiters",mgr,policies));
541   threadPol->destroy();
542   //
543   _poa_for_key_waiter=poa2;
544 }
545
546 DataScopeServerTransaction::DataScopeServerTransaction(const DataScopeServerTransaction& other):omniServant(other),ServantBase(other),DataScopeServerBase(other),_poa_for_key_waiter(other.getPOA4KeyWaiter())
547 {
548 }
549
550 char *DataScopeServerTransaction::getAccessOfVar(const char *varName)
551 {
552   std::string varNameCpp(varName);
553   checkExistingVar(varNameCpp);
554   BasicDataServer *var(retrieveVarInternal2(varName));
555   if(!var)
556     throw Exception("DataScopeServerTransaction::getAccessOfVar : variable is NULL !");
557   PickelizedPyObjServer *varc(dynamic_cast<PickelizedPyObjServer *>(var));
558   if(!varc)
559     throw Exception("DataScopeServerTransaction::getAccessOfVar : variable is not of type PickelizedPyObjServer !");
560   std::string ret(varc->getAccessStr());
561   return CORBA::string_dup(ret.c_str());
562 }
563
564 /*!
565  * This method is here to retrieve atomically accessStr and picklization.
566  */
567 void DataScopeServerTransaction::fetchAndGetAccessOfVar(const char *varName, CORBA::String_out access, SALOME::ByteVec_out data)
568 {
569   access=getAccessOfVar(varName);
570   data=fetchSerializedContent(varName);
571 }
572
573 void DataScopeServerTransaction::createRdOnlyVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
574 {
575   checkNotAlreadyExistingVar(varName);
576   PickelizedPyObjRdOnlyServer *tmp(new PickelizedPyObjRdOnlyServer(this,varName,constValue));
577   CORBA::Object_var ret(tmp->activate());
578   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
579   _vars.push_back(p);
580 }
581
582 void DataScopeServerTransaction::createRdExtVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
583 {
584   checkNotAlreadyExistingVar(varName);
585   PickelizedPyObjRdExtServer *tmp(new PickelizedPyObjRdExtServer(this,varName,constValue));
586   CORBA::Object_var ret(tmp->activate());
587   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
588   _vars.push_back(p);
589 }
590
591 void DataScopeServerTransaction::createRdExtVarFreeStyleInternal(const std::string& varName, const SALOME::ByteVec& constValue, std::vector<unsigned char>&& sha1)
592 {
593   if(!isExistingVar(varName))
594     {
595       PickelizedPyObjRdExtFreeStyleServer *tmp(new PickelizedPyObjRdExtFreeStyleServer(this,varName,constValue,std::move(sha1)));
596       CORBA::Object_var ret(tmp->activate());
597       std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
598       _vars.push_back(p);
599     }
600   else
601     {
602       BasicDataServer *ds(retrieveVarInternal2(varName));
603       if(!ds)
604         {
605           std::ostringstream oss;
606           oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : internal error 1 for varname \"" << varName << "\"!";
607           throw Exception(oss.str());
608         }
609       Sha1Keeper *ds2(dynamic_cast<Sha1Keeper *>(ds));
610       if(!ds2)
611         {
612           std::ostringstream oss;
613           oss << "DataScopeServerTransaction::createRdExtVarFreeStyleInternal : varname \"" << varName << "\" already exists with a non RdExtFreeStyle type !";
614           throw Exception(oss.str());
615         }
616       ds2->checkSha1(varName,sha1);
617     }
618 }
619
620 void DataScopeServerTransaction::createRdExtInitVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
621 {
622   checkNotAlreadyExistingVar(varName);
623   PickelizedPyObjRdExtInitServer *tmp(new PickelizedPyObjRdExtInitServer(this,varName,constValue));
624   CORBA::Object_var ret(tmp->activate());
625   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
626   _vars.push_back(p);
627 }
628
629 void DataScopeServerTransaction::createRdWrVarInternal(const std::string& varName, const SALOME::ByteVec& constValue)
630 {
631   checkNotAlreadyExistingVar(varName);
632   PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,varName,constValue));
633   CORBA::Object_var ret(tmp->activate());
634   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(ret),tmp);
635   _vars.push_back(p);
636 }
637
638 SALOME::Transaction_ptr DataScopeServerTransaction::createRdOnlyVarTransac(const char *varName, const SALOME::ByteVec& constValue)
639 {
640   checkNotAlreadyExistingVar(varName);
641   TransactionRdOnlyVarCreate *ret(new TransactionRdOnlyVarCreate(this,varName,constValue));
642   CORBA::Object_var obj(ret->activate());
643   return SALOME::Transaction::_narrow(obj);
644 }
645
646 SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtVarTransac(const char *varName, const SALOME::ByteVec& constValue)
647 {
648   checkNotAlreadyExistingVar(varName);
649   TransactionRdExtVarCreate *ret(new TransactionRdExtVarCreate(this,varName,constValue));
650   CORBA::Object_var obj(ret->activate());
651   return SALOME::Transaction::_narrow(obj);
652 }
653
654 SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtVarFreeStyleTransac(const char *varName, const SALOME::ByteVec& constValue, const SALOME::ByteVec& sha1)
655 {// no check on varName done here. Will be done on perform
656   TransactionRdExtVarFreeStyleCreate *ret(new TransactionRdExtVarFreeStyleCreate(this,varName,constValue,sha1));
657   CORBA::Object_var obj(ret->activate());
658   return SALOME::Transaction::_narrow(obj);
659 }
660
661 SALOME::Transaction_ptr DataScopeServerTransaction::createRdExtInitVarTransac(const char *varName, const SALOME::ByteVec& constValue)
662 {
663   checkNotAlreadyExistingVar(varName);
664   TransactionRdExtInitVarCreate *ret(new TransactionRdExtInitVarCreate(this,varName,constValue));
665   CORBA::Object_var obj(ret->activate());
666   return SALOME::Transaction::_narrow(obj);
667 }
668
669 SALOME::Transaction_ptr DataScopeServerTransaction::createRdWrVarTransac(const char *varName, const SALOME::ByteVec& constValue)
670 {
671   checkNotAlreadyExistingVar(varName);
672   TransactionRdWrVarCreate *ret(new TransactionRdWrVarCreate(this,varName,constValue));
673   CORBA::Object_var obj(ret->activate());
674   return SALOME::Transaction::_narrow(obj);
675 }
676
677 void DataScopeServerTransaction::addWaitKey(KeyWaiter *kw)
678 {
679   if(!kw)
680     throw Exception("DataScopeServerTransaction::addWaitKey : NULL input object !");
681   _waiting_keys.push_back(kw);
682 }
683
684 void DataScopeServerTransaction::pingKey(PyObject *keyObj)
685 {
686   PyObject *cmpObj(getPyCmpFunc());
687   if(!keyObj)
688     throw Exception("ataScopeServerTransaction::pingKey : Key Object is NULL !");
689   PyObject *args(PyTuple_New(2));
690   PyTuple_SetItem(args,0,keyObj); Py_XINCREF(keyObj);
691   std::size_t ii(0);
692   // this part does nothing except to be sure that in notify key all will be OK.
693   for(std::list< KeyWaiter *>::iterator it=_waiting_keys.begin();it!=_waiting_keys.end();it++,ii++)
694     {
695       PyObject *waitKey((*it)->getKeyPyObj());
696       PyTuple_SetItem(args,1,waitKey); Py_XINCREF(waitKey);
697       PyObject *res(PyObject_CallObject(cmpObj,args));
698       if(res==NULL)
699         {
700           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " error during cmp(k,wk[i]) !";
701           throw Exception(oss.str());
702         }
703       PyInt_AsLong(res);
704       if(PyErr_Occurred())
705         {
706           std::ostringstream oss; oss << "DataScopeServerTransaction::pingKey : for object id #" << ii << " error during interpretation of cmp(k,wk[i]) !";
707           throw Exception(oss.str());
708         }
709       Py_XDECREF(res);
710     }
711 }
712
713 void DataScopeServerTransaction::notifyKey(const std::string& varName, PyObject *keyObj, PyObject *valueObj)
714 {
715   PyObject *cmpObj(getPyCmpFunc());
716   if(!keyObj)
717     throw Exception("DataScopeServerTransaction::notifyKey : MAIN INTERNAL ERROR ! Key Object is NULL !");
718   PyObject *args(PyTuple_New(2));
719   PyTuple_SetItem(args,0,keyObj); Py_XINCREF(keyObj);
720   std::size_t ii(0);
721   std::list< KeyWaiter *> newList,listOfEltToWakeUp;
722   for(std::list< KeyWaiter *>::iterator it=_waiting_keys.begin();it!=_waiting_keys.end();it++,ii++)
723     {
724       if((*it)->getVarName()!=varName)
725         {
726           newList.push_back(*it);
727           continue;
728         }
729       PyObject *waitKey((*it)->getKeyPyObj());
730       PyTuple_SetItem(args,1,waitKey); Py_XINCREF(waitKey);
731       PyObject *res(PyObject_CallObject(cmpObj,args));
732       if(res==NULL)
733         {
734           std::ostringstream oss; oss << "DataScopeServerTransaction::notifyKey : MAIN INTERNAL ERROR ! for object id #" << ii << " error during cmp(k,wk[i]) !";
735           throw Exception(oss.str());
736         }
737       long resCpp(PyInt_AsLong(res));
738       if(PyErr_Occurred())
739         {
740           std::ostringstream oss; oss << "DataScopeServerTransaction::notifyKey : MAIN INTERNAL ERROR ! for object id #" << ii << " error during interpretation of cmp(k,wk[i]) !";
741           throw Exception(oss.str());
742         }
743       Py_XDECREF(res);
744       if(resCpp==0)
745         listOfEltToWakeUp.push_back(*it);
746       else
747         newList.push_back(*it);
748     }
749   for(std::list< KeyWaiter *>::iterator it=listOfEltToWakeUp.begin();it!=listOfEltToWakeUp.end();it++)
750     (*it)->valueJustCome(valueObj);
751   for(std::list< KeyWaiter *>::iterator it=listOfEltToWakeUp.begin();it!=listOfEltToWakeUp.end();it++)
752     (*it)->go();
753   _waiting_keys=newList;
754 }
755
756 SALOME::Transaction_ptr DataScopeServerTransaction::addKeyValueInVarHard(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value)
757 {
758   checkVarExistingAndDict(varName);
759   TransactionAddKeyValueHard *ret(new TransactionAddKeyValueHard(this,varName,key,value));
760   CORBA::Object_var obj(ret->activate());
761   return SALOME::Transaction::_narrow(obj);
762 }
763
764 SALOME::Transaction_ptr DataScopeServerTransaction::addKeyValueInVarErrorIfAlreadyExisting(const char *varName, const SALOME::ByteVec& key, const SALOME::ByteVec& value)
765 {
766   checkVarExistingAndDict(varName);
767   TransactionAddKeyValueErrorIfAlreadyExisting *ret(new TransactionAddKeyValueErrorIfAlreadyExisting(this,varName,key,value));
768   CORBA::Object_var obj(ret->activate());
769   return SALOME::Transaction::_narrow(obj);
770 }
771
772 SALOME::TransactionMultiKeyAddSession_ptr DataScopeServerTransaction::addMultiKeyValueSession(const char *varName)
773 {
774   checkVarExistingAndDict(varName);
775   TransactionMultiKeyAddSession *ret(new TransactionMultiKeyAddSession(this,varName));
776   CORBA::Object_var obj(ret->activate());
777   return SALOME::TransactionMultiKeyAddSession::_narrow(obj);
778 }
779
780 SALOME::Transaction_ptr DataScopeServerTransaction::removeKeyInVarErrorIfNotAlreadyExisting(const char *varName, const SALOME::ByteVec& key)
781 {
782   checkVarExistingAndDict(varName);
783   TransactionRemoveKeyInVarErrorIfNotAlreadyExisting *ret(new TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(this,varName,key));
784   CORBA::Object_var obj(ret->activate());
785   return SALOME::Transaction::_narrow(obj);
786 }
787
788 SALOME::TransactionRdWrAccess_ptr DataScopeServerTransaction::createWorkingVarTransac(const char *varName, const SALOME::ByteVec& constValue)
789 {
790   std::string varNameCpp(varName);
791   checkNotAlreadyExistingVar(varName);
792   PickelizedPyObjRdWrServer *tmp(new PickelizedPyObjRdWrServer(this,varNameCpp,constValue));
793   CORBA::Object_var obj(tmp->activate());
794   std::pair< SALOME::BasicDataServer_var, BasicDataServer * > p(SALOME::BasicDataServer::_narrow(obj),tmp);
795   _vars.push_back(p);
796   //
797   TransactionMorphRdWrIntoRdOnly *ret(new TransactionMorphRdWrIntoRdOnly(this,varName));
798   CORBA::Object_var obj2(ret->activate());
799   return SALOME::TransactionRdWrAccess::_narrow(obj2);
800 }
801
802 SALOME::Transaction_ptr DataScopeServerTransaction::killVarTransac(const char *varName)
803 {
804   std::string varNameCpp(varName);
805   checkExistingVar(varNameCpp);
806   //
807   TransactionKillVar *ret(new TransactionKillVar(this,varName));
808   CORBA::Object_var obj2(ret->activate());
809   return SALOME::Transaction::_narrow(obj2);
810 }
811
812 SALOME::KeyWaiter_ptr DataScopeServerTransaction::waitForKeyInVar(const char *varName, const SALOME::ByteVec& keyVal)
813 {
814   PickelizedPyObjServer *pickelObj(checkVarExistingAndDict(varName));
815   KeyWaiter *ret(new KeyWaiter(pickelObj,keyVal));
816   CORBA::Object_var obj(ret->activate());//KeyWaiter instance activated inside a multithread POA contrary to all of objects in SALOMESDS in single thread !
817   return SALOME::KeyWaiter::_narrow(obj);
818 }
819
820 SALOME::KeyWaiter_ptr DataScopeServerTransaction::waitForKeyInVarAndKillIt(const char *varName, const SALOME::ByteVec& keyVal, SALOME::Transaction_out transac)
821 {
822   PickelizedPyObjServer *pickelObj(checkVarExistingAndDict(varName));
823   KeyWaiter *ret0(new KeyWaiter(pickelObj,keyVal));
824   CORBA::Object_var obj(ret0->activate());//KeyWaiter instance activated inside a multithread POA contrary to all of objects in SALOMESDS in single thread !
825   //
826   TransactionRemoveKeyInVarErrorIfNotAlreadyExisting *ret1(new TransactionRemoveKeyInVarErrorIfNotAlreadyExisting(this,varName,keyVal));
827   CORBA::Object_var obj2(ret1->activate());
828   transac=SALOME::Transaction::_narrow(obj2);
829   //
830   return SALOME::KeyWaiter::_narrow(obj);
831 }
832
833 SALOME::ByteVec *DataScopeServerTransaction::waitForMonoThrRev(SALOME::KeyWaiter_ptr kw)
834 {
835   PortableServer::ServantBase *ret(0);
836   try
837     {
838       ret=_poa_for_key_waiter->reference_to_servant(kw);// Warning ref cnt of ret has been incremented !
839     }
840   catch(...) { ret=0; }
841   KeyWaiter *retc(dynamic_cast<KeyWaiter *>(ret));
842   if(!retc)
843     throw Exception("DataScopeServerTransaction::invokeMonoThr : internal error 1 !");
844   retc->_remove_ref();// restore the counter after _poa_for_key_waiter->reference_to_servant(kw)
845   SALOME::ByteVec *zeRet(retc->waitForMonoThr());
846   retc->enforcedRelease();
847   return zeRet;
848 }
849
850 SALOME::ByteVec *DataScopeServerTransaction::waitForAndKill(SALOME::KeyWaiter_ptr kw)
851 {
852   PortableServer::ServantBase *ret(0);
853   try
854     {
855       ret=_poa_for_key_waiter->reference_to_servant(kw);// Warning ref cnt of ret has been incremented !
856     }
857   catch(...) { ret=0; }
858   KeyWaiter *retc(dynamic_cast<KeyWaiter *>(ret));
859   if(!retc)
860     throw Exception("DataScopeServerTransaction::invokeMonoThr : internal error 1 !");
861   retc->_remove_ref();// restore the counter after _poa_for_key_waiter->reference_to_servant(kw)
862   SALOME::ByteVec *zeRet(retc->waitForAndKill());
863   retc->enforcedRelease();
864   return zeRet;
865 }
866
867 void DataScopeServerTransaction::atomicApply(const SALOME::ListOfTransaction& transactions)
868 {
869   std::size_t sz(transactions.length());
870   if(sz==0)
871     return ;
872   std::vector< AutoServantPtr<Transaction> > transactionsCpp(sz);
873   for(std::size_t i=0;i<sz;i++)
874     {
875       PortableServer::ServantBase *eltBase(0);
876       Transaction *elt(0);
877       try
878         {
879           eltBase=_poa->reference_to_servant(transactions[i]);
880           elt=dynamic_cast<Transaction *>(eltBase);
881         }
882       catch(...)
883         {
884           std::ostringstream oss; oss << "DataScopeServerTransaction::atomicApply : the elt #" << i << " is invalid !";
885           throw Exception(oss.str());
886         }
887       if(!elt)
888         {
889           std::ostringstream oss; oss << "DataScopeServerTransaction::atomicApply : the elt #" << i << " is null ?";
890           throw Exception(oss.str());
891         }
892       elt->_remove_ref();
893       transactionsCpp[i]=elt;
894     }
895   {// important do not merge loops ! 
896     std::vector<TrustTransaction> transactions2(sz);
897     bool mustRollback(true);
898     for(std::size_t i=0;i<sz;i++)
899       transactions2[i].setTransaction(transactionsCpp[i],&mustRollback);
900     for(std::size_t i=0;i<sz;i++)
901       transactions2[i].operate();
902     mustRollback=false;
903   }
904   for(std::size_t i=0;i<sz;i++)
905     transactionsCpp[i]->notify();
906 }
907
908 /*!
909  * Returns borrowed reference.
910  */
911 PyObject *DataScopeServerTransaction::getPyCmpFunc()
912 {
913   PyObject *builtins(PyDict_GetItemString(_globals,"__builtins__"));//borrowed
914   if(builtins==NULL)
915     throw Exception("Fail to find reference to builtins !");
916   PyObject *builtins2(PyModule_GetDict(builtins));//borrowed
917   if(builtins2==NULL)
918     throw Exception("Fail to invoke __dict__ on builtins !");
919   PyObject *cmpObj(PyDict_GetItemString(builtins2,"cmp"));
920   if(cmpObj==NULL)
921     throw Exception("Fail to find cmp in __builtins__ !");
922   return cmpObj;
923 }
924
925 DataScopeServerTransaction::~DataScopeServerTransaction()
926 {
927 }
928
929 SALOME::RequestSwitcher_ptr DataScopeServerTransaction::getRequestSwitcher()
930 {
931   if(_rs.isNull())
932     {
933       _rs=new RequestSwitcher(_orb,this);
934     }
935   CORBA::Object_var obj(_rs->activate());
936   return SALOME::RequestSwitcher::_narrow(obj);
937 }