Salome HOME
34ae0258378a55512c17845d3283d0342ee243f3
[modules/kernel.git] / src / SALOMESDS / SALOMESDS_DataServerManager.cxx
1 // Copyright (C) 2007-2023  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_DataServerManager.hxx"
22 #include "SALOMESDS_Exception.hxx"
23
24 #include "SALOME_ContainerManager.hxx"
25 #include "SALOME_NamingService.hxx"
26 #include "SALOME_Embedded_NamingService.hxx"
27 #include "KernelBasis.hxx"
28
29 #include <sstream>
30 #include <algorithm>
31
32 using namespace SALOMESDS;
33
34 const char DataServerManager::NAME_IN_NS[]="/DataServerManager";
35
36 const char DataServerManager::DFT_SCOPE_NAME_IN_NS[]="Default";
37
38 SALOME::StringVec *RequestSwitcherDSM::listScopes()
39 {
40   return _dsm->listScopes_unsafe();
41 }
42
43 SALOME::DataScopeServerTransaction_ptr RequestSwitcherDSM::giveADataScopeTransactionCalled(const char *scopeName, CORBA::Boolean& isCreated)
44 {
45   return _dsm->giveADataScopeTransactionCalled_unsafe(scopeName,isCreated);
46 }
47
48 void RequestSwitcherDSM::holdRequests()
49 {
50   _dsm->holdRequests();
51 }
52
53 void RequestSwitcherDSM::activeRequests()
54 {
55   _dsm->activeRequests();
56 }
57
58
59 DataServerManager::DataServerManager(const SALOME_CPythonHelper *pyHelper, CORBA::ORB_ptr orb, PortableServer::POA_ptr poa, SALOME_NamingService_Abstract *ns):_orb(CORBA::ORB::_duplicate(orb))
60 {
61   _ns = ns==nullptr?new SALOME_NamingService(_orb):ns;
62   DataScopeServer *dftScope(new DataScopeServer(pyHelper,orb,SALOME::DataScopeKiller::_nil(),DFT_SCOPE_NAME_IN_NS,_ns->cloneCoVar()));//_remove_ref will be call by DataScopeServer::shutdownIfNotHostedByDSM
63   PortableServer::POAManager_var pman(poa->the_POAManager());
64   CORBA::PolicyList policies;
65   policies.length(1);
66   PortableServer::ThreadPolicy_var threadPol(poa->create_thread_policy(PortableServer::SINGLE_THREAD_MODEL));
67   policies[0]=PortableServer::ThreadPolicy::_duplicate(threadPol);
68   PortableServer::POA_var safePoa = poa->create_POA("SingleThPOA4SDS",pman,policies);
69   _poa = poa;
70   threadPol->destroy();
71   // activate this to be ready to be usable from NS.
72   PortableServer::ObjectId_var id(_poa->activate_object(this));
73   CORBA::Object_var obj(_poa->id_to_reference(id));
74   SALOME::DataServerManager_var obj2(SALOME::DataServerManager::_narrow(obj));
75   // publish Data server manager in NS
76   _ns->Register(obj2,NAME_IN_NS);
77   // the default DataScopeServer object is the only one hosted by the current process
78   dftScope->setPOA(_poa);
79   obj=dftScope->activate();
80   SALOME::DataScopeServer_var dftScopePtr(SALOME::DataScopeServer::_narrow(obj));
81   dftScope->registerInNS(dftScopePtr);// agy : Very important ! invoke this method BEFORE activation ! Because this method initializes Python !
82 }
83
84 DataServerManager::~DataServerManager()
85 {
86   //_ns is owned by DataServerManager
87   delete _ns;
88 }
89
90 SALOME::StringVec * DataServerManager::listScopes_unsafe()
91 {
92   std::vector<std::string> scopes(listOfScopesCpp());
93   SALOME::StringVec *ret(new SALOME::StringVec);
94   std::size_t sz(scopes.size());
95   ret->length((CORBA::ULong)sz); //!< TODO: size_t to CORBA::ULong
96   for(std::size_t i=0;i<sz;i++)
97     (*ret)[(CORBA::ULong)i]=CORBA::string_dup(scopes[i].c_str()); //!< TODO: size_t to CORBA::ULong
98   return ret;
99 }
100
101 SALOME::StringVec *DataServerManager::listScopes()
102 {
103   const std::lock_guard<std::mutex> lock(_mutex);
104   return listScopes_unsafe();
105 }
106
107 SALOME::StringVec *DataServerManager::listAliveAndKickingScopes()
108 {
109   const std::lock_guard<std::mutex> lock(_mutex);
110   std::vector<std::string> scopes(listOfScopesCpp());
111   std::size_t sz(scopes.size());
112   std::vector<std::string> retCpp; retCpp.reserve(sz);
113   for(std::size_t i=0;i<sz;i++)
114     {
115       if(isAliveAndKicking_unsafe(scopes[i].c_str()))
116         retCpp.push_back(scopes[i]);
117     }
118   //
119   SALOME::StringVec *ret(new SALOME::StringVec);
120   sz=retCpp.size();
121   ret->length((CORBA::ULong)sz); //!< TODO: size_t to CORBA::ULong
122   for(std::size_t i=0;i<sz;i++)
123     (*ret)[(CORBA::ULong)i]=CORBA::string_dup(retCpp[i].c_str()); //!< TODO: size_t to CORBA::ULong
124   return ret;
125 }
126
127 SALOME::DataScopeServer_ptr DataServerManager::getDefaultScope()
128 {
129   const std::lock_guard<std::mutex> lock(_mutex);
130   SALOME::DataScopeServerBase_var ret(retriveDataScope_unsafe(DFT_SCOPE_NAME_IN_NS));
131   if(CORBA::is_nil(ret))
132     return SALOME::DataScopeServer::_narrow(ret);
133   SALOME::DataScopeServer_ptr ret2(SALOME::DataScopeServer::_narrow(ret));
134   if(CORBA::is_nil(ret2))
135     throw Exception("DataServerManager::getDefaultScope : exists but has not expected sub type !");
136   return ret2;
137 }
138
139 CORBA::Boolean DataServerManager::isAliveAndKicking(const char *scopeName)
140 {
141   const std::lock_guard<std::mutex> lock(_mutex);
142   return isAliveAndKicking_unsafe(scopeName);
143 }
144
145 CORBA::Boolean DataServerManager::isAliveAndKicking_unsafe(const char *scopeName)
146 {
147   SALOME::DataScopeServerBase_var scopePtr(getScopePtrGivenName(scopeName));
148   return IsAliveAndKicking(scopePtr);
149 }
150
151 template<class T>
152 typename T::PtrType CreateDataScope(CORBA::ORB_ptr orb, const std::string& scopeName, const std::vector<std::string>& scopes, SALOME_NamingService_Abstract& ns)
153 {
154   int isTransactionInt(T::IsTransaction);
155   if(std::find(scopes.begin(),scopes.end(),scopeName)!=scopes.end())
156     {
157       std::ostringstream oss; oss << "DataServerManager::createDataScope : scope name \"" << scopeName << "\" already exists !";
158       throw Exception(oss.str());
159     }
160   //
161   std::string fullScopeName(DataServerManager::CreateAbsNameInNSFromScopeName(scopeName));
162   std::ostringstream oss; 
163   if(!getSSLMode())
164   {
165     oss << "SALOME_DataScopeServer" << " " << scopeName << " " << isTransactionInt << " ";
166     SALOME_ContainerManager::AddOmninamesParams(oss,&ns);
167   }
168   else
169   {
170      oss << "SALOME_DataScopeServer_SSL" << " " << scopeName << " " << isTransactionInt << " ";
171      Engines::EmbeddedNamingService_var emb = GetEmbeddedNamingService();
172      CORBA::String_var ior = orb->object_to_string(emb);
173      oss << ior.in();
174   }
175   std::string command(oss.str());
176   SALOME_ContainerManager::MakeTheCommandToBeLaunchedASync(command);
177   int status(SALOME_ContainerManager::SystemThreadSafe(command.c_str()));
178   if(status!=0)
179     {
180       std::ostringstream oss2; oss2 << "CreateDataScope : Fail to launch \"" << command << "\" ! Return code was : " << status << " !";
181       throw Exception(oss2.str());
182     }
183   int count(SALOME_ContainerManager::GetTimeOutToLoaunchServer());
184   typename T::VarType ret(T::nil());
185   while (CORBA::is_nil(ret) && count)
186     {
187       SALOME_ContainerManager::SleepInSecond(1);
188       count--;
189       CORBA::Object_var obj(ns.Resolve(fullScopeName.c_str()));
190       ret=T::narrow(obj);
191     }
192   return T::duplicate(ret);
193 }
194
195 template<class T>
196 typename T::PtrType GiveADataScopeCalled(CORBA::ORB_ptr orb, const std::string& scopeName, const std::vector<std::string>& scopes, SALOME_NamingService_Abstract& ns, CORBA::Boolean& isCreated)
197 {
198   if(std::find(scopes.begin(),scopes.end(),scopeName)==scopes.end())
199     {
200       isCreated=true;
201       return CreateDataScope<T>(orb,scopeName,scopes,ns);
202     }
203   else
204     {
205       SALOME::DataScopeServerBase_var ret(SALOMESDS::DataServerManager::GetScopePtrGivenName(scopeName,scopes,&ns));
206       if(SALOMESDS::DataServerManager::IsAliveAndKicking(ret))
207         {
208           isCreated=false;
209           typename T::PtrType ret2(T::narrow(ret));
210           if(CORBA::is_nil(ret))
211             return ret2;
212           if(CORBA::is_nil(ret2))
213             {
214               std::ostringstream oss; oss << "DataServerManager::giveADataScopeCalled : scope \"" << scopeName << "\" exists but with invalid type !";
215               throw Exception(oss.str());
216             }
217           return ret2;
218         }
219       else
220         {
221           std::string fullScopeName(SALOMESDS::DataServerManager::CreateAbsNameInNSFromScopeName(scopeName));
222           ns.Destroy_Name(fullScopeName.c_str());
223           isCreated=true;
224           return CreateDataScope<T>(orb,scopeName,scopes,ns);
225         }
226     }
227 }
228
229 class NormalFunctor
230 {
231 public:
232   typedef SALOME::DataScopeServer_ptr PtrType;
233   typedef SALOME::DataScopeServer_var VarType;
234   typedef SALOME::DataScopeServer TheType;
235   static const bool IsTransaction=false;
236   static PtrType nil() { return SALOME::DataScopeServer::_nil(); }
237   static PtrType narrow(CORBA::Object_ptr obj) { return SALOME::DataScopeServer::_narrow(obj); }
238   static PtrType duplicate(PtrType obj) { return SALOME::DataScopeServer::_duplicate(obj); }
239 };
240
241 class TransactionFunctor
242 {
243 public:
244   typedef SALOME::DataScopeServerTransaction_ptr PtrType;
245   typedef SALOME::DataScopeServerTransaction_var VarType;
246   typedef SALOME::DataScopeServerTransaction TheType;
247   static const bool IsTransaction=true;
248   static PtrType nil() { return SALOME::DataScopeServerTransaction::_nil(); }
249   static PtrType narrow(CORBA::Object_ptr obj) { return SALOME::DataScopeServerTransaction::_narrow(obj); }
250   static PtrType duplicate(PtrType obj) { return SALOME::DataScopeServerTransaction::_duplicate(obj); }
251 };
252
253 SALOME::DataScopeServer_ptr DataServerManager::createDataScope(const char *scopeName)
254 {
255   const std::lock_guard<std::mutex> lock(_mutex);
256   return CreateDataScope<NormalFunctor>(_orb,scopeName,listOfScopesCpp(),*_ns);
257 }
258
259 SALOME::DataScopeServer_ptr DataServerManager::giveADataScopeCalled(const char *scopeName, CORBA::Boolean& isCreated)
260 {
261   const std::lock_guard<std::mutex> lock(_mutex);
262   return GiveADataScopeCalled<NormalFunctor>(_orb,scopeName,listOfScopesCpp(),*_ns,isCreated);
263 }
264
265 SALOME::DataScopeServerTransaction_ptr DataServerManager::createDataScopeTransaction(const char *scopeName)
266 {
267   const std::lock_guard<std::mutex> lock(_mutex);
268   return CreateDataScope<TransactionFunctor>(_orb,scopeName,listOfScopesCpp(),*_ns);
269 }
270
271 SALOME::DataScopeServerTransaction_ptr
272 DataServerManager::giveADataScopeTransactionCalled_unsafe(
273                               const char *scopeName, CORBA::Boolean& isCreated)
274 {
275   return GiveADataScopeCalled<TransactionFunctor>(_orb,scopeName,listOfScopesCpp(),*_ns,isCreated);
276 }
277
278
279 SALOME::DataScopeServerTransaction_ptr DataServerManager::giveADataScopeTransactionCalled(const char *scopeName, CORBA::Boolean& isCreated)
280 {
281   const std::lock_guard<std::mutex> lock(_mutex);
282   return giveADataScopeTransactionCalled_unsafe(scopeName, isCreated);
283 }
284
285 SALOME::DataScopeServerBase_ptr DataServerManager::retriveDataScope(const char *scopeName)
286 {
287   const std::lock_guard<std::mutex> lock(_mutex);
288   return retriveDataScope_unsafe(scopeName);
289 }
290
291 SALOME::DataScopeServerBase_ptr DataServerManager::retriveDataScope_unsafe(const char *scopeName)
292 {
293   SALOME::DataScopeServerBase_var ret(getScopePtrGivenName(scopeName));
294   return SALOME::DataScopeServerBase::_duplicate(ret);
295 }
296
297 void DataServerManager::removeDataScope(const char *scopeName)
298 {
299   const std::lock_guard<std::mutex> lock(_mutex);
300   SALOME::DataScopeServerBase_var scs(getScopePtrGivenName(scopeName));
301   SALOME::DataScopeKiller_ptr killer;
302   if(scs->shutdownIfNotHostedByDSM(killer))
303     killer->shutdown();
304   CORBA::release(killer);
305 }
306
307 void DataServerManager::cleanScopesInNS()
308 {
309   const std::lock_guard<std::mutex> lock(_mutex);
310   std::vector<std::string> scopes(listOfScopesCpp());
311   for(std::vector<std::string>::const_iterator it=scopes.begin();it!=scopes.end();it++)
312     {
313       if(!isAliveAndKicking_unsafe((*it).c_str()))
314         {
315           std::string fullScopeName(SALOMESDS::DataServerManager::CreateAbsNameInNSFromScopeName(*it));
316           _ns->Destroy_Name(fullScopeName.c_str());
317         }
318     }
319 }
320
321 void DataServerManager::shutdownScopes()
322 {
323   const std::lock_guard<std::mutex> lock(_mutex);
324   std::vector<std::string> scopeNames(listOfScopesCpp());
325   for(std::vector<std::string>::const_iterator it=scopeNames.begin();it!=scopeNames.end();it++)
326     {
327       SALOME::DataScopeServerBase_var scope(getScopePtrGivenName(*it));
328       SALOME::DataScopeKiller_ptr killer;
329       if(scope->shutdownIfNotHostedByDSM(killer))
330         killer->shutdown();
331       CORBA::release(killer);
332     }
333 }
334
335 std::string DataServerManager::CreateAbsNameInNSFromScopeName(const std::string& scopeName)
336 {
337   std::ostringstream oss; oss << NAME_IN_NS << "/" << scopeName;
338   return oss.str();
339 }
340
341 CORBA::Boolean DataServerManager::IsAliveAndKicking(SALOME::DataScopeServerBase_ptr scopePtr)
342 {
343   CORBA::Boolean ret(true);
344   try
345     {
346       scopePtr->ping();
347     }
348   catch(...)
349     { ret=false; }
350   return ret;
351 }
352
353 std::vector<std::string> DataServerManager::listOfScopesCpp()
354 {
355   _ns->Change_Directory(NAME_IN_NS);
356   std::vector<std::string> ret(_ns->list_directory());
357   return ret;
358 }
359
360 SALOME::DataScopeServerBase_var DataServerManager::GetScopePtrGivenName(const std::string& scopeName, const std::vector<std::string>& scopes, SALOME_NamingService_Abstract *ns)
361 {
362   if(std::find(scopes.begin(),scopes.end(),scopeName)==scopes.end())
363     {
364       std::ostringstream oss; oss << "DataServerManager::getScopePtrGivenName : scope name \"" << scopeName << "\" does not exist !";
365       throw Exception(oss.str());
366     }
367   std::string fullScopeName(CreateAbsNameInNSFromScopeName(scopeName));
368   CORBA::Object_var obj(ns->Resolve(fullScopeName.c_str()));
369   SALOME::DataScopeServerBase_var ret(SALOME::DataScopeServerBase::_narrow(obj));
370   return ret;
371 }
372
373 SALOME::DataScopeServerBase_var DataServerManager::getScopePtrGivenName(const std::string& scopeName)
374 {
375   return GetScopePtrGivenName(scopeName,listOfScopesCpp(),_ns);
376 }
377
378 SALOME::RequestSwitcherDSM_ptr DataServerManager::getRequestSwitcher()
379 {
380   const std::lock_guard<std::mutex> lock(_mutex);
381   if(_rs.isNull())
382     {
383       _rs=new RequestSwitcherDSM(_orb,this);
384     }
385   CORBA::Object_var obj(_rs->activate());
386   return SALOME::RequestSwitcherDSM::_narrow(obj);
387 }
388
389 void DataServerManager::holdRequests()
390 {
391   _mutex.lock();
392 }
393
394 void DataServerManager::activeRequests()
395 {
396   _mutex.unlock();
397 }