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