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