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