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