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