Salome HOME
Integrate missing files
[modules/kernel.git] / src / Container / SALOME_ContainerManager.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 #include "SALOME_ContainerManager.hxx"
21 #include "SALOME_NamingService.hxx"
22 #include "OpUtil.hxx"
23 #include <sys/types.h>
24 #ifndef WNT
25 #include <unistd.h>
26 #endif
27 #include <vector>
28 #include "Utils_CorbaException.hxx"
29
30 #define TIME_OUT_TO_LAUNCH_CONT 21
31
32 using namespace std;
33
34 const char *SALOME_ContainerManager::_ContainerManagerNameInNS = 
35   "/ContainerManager";
36
37 //=============================================================================
38 /*! 
39  *  Constructor
40  *  \param orb
41  *  Define a CORBA single thread policy for the server, which avoid to deal
42  *  with non thread-safe usage like Change_Directory in SALOME naming service
43  */
44 //=============================================================================
45
46 SALOME_ContainerManager::SALOME_ContainerManager(CORBA::ORB_ptr orb)
47 {
48   MESSAGE("constructor");
49   _NS = new SALOME_NamingService(orb);
50   _ResManager = new SALOME_ResourcesManager(orb);
51   _id=0;
52   PortableServer::POA_var root_poa = PortableServer::POA::_the_root_poa();
53   PortableServer::POAManager_var pman = root_poa->the_POAManager();
54   PortableServer::POA_var my_poa;
55
56   CORBA::PolicyList policies;
57   policies.length(1);
58   PortableServer::ThreadPolicy_var threadPol = 
59     root_poa->create_thread_policy(PortableServer::SINGLE_THREAD_MODEL);
60   policies[0] = PortableServer::ThreadPolicy::_duplicate(threadPol);
61
62   my_poa = 
63     root_poa->create_POA("SThreadPOA",pman,policies);
64   threadPol->destroy();
65   PortableServer::ObjectId_var id = my_poa->activate_object(this);
66   CORBA::Object_var obj = my_poa->id_to_reference(id);
67   Engines::ContainerManager_var refContMan =
68     Engines::ContainerManager::_narrow(obj);
69
70   _NS->Register(refContMan,_ContainerManagerNameInNS);
71   MESSAGE("constructor end");
72 }
73
74 //=============================================================================
75 /*! 
76  * destructor
77  */
78 //=============================================================================
79
80 SALOME_ContainerManager::~SALOME_ContainerManager()
81 {
82   MESSAGE("destructor");
83   delete _NS;
84   delete _ResManager;
85 }
86
87 //=============================================================================
88 /*! CORBA method:
89  *  shutdown all the containers, then the ContainerManager servant
90  */
91 //=============================================================================
92
93 void SALOME_ContainerManager::Shutdown()
94 {
95   MESSAGE("Shutdown");
96   ShutdownContainers();
97   PortableServer::ObjectId_var oid = _default_POA()->servant_to_id(this);
98   _default_POA()->deactivate_object(oid);
99   _remove_ref();
100   
101 }
102
103 //=============================================================================
104 /*! CORBA Method:
105  *  Loop on all the containers listed in naming service, ask shutdown on each
106  */
107 //=============================================================================
108
109 void SALOME_ContainerManager::ShutdownContainers()
110 {
111   MESSAGE("ShutdownContainers");
112   _NS->Change_Directory("/Containers");
113   vector<string> vec = _NS->list_directory_recurs();
114   list<string> lstCont;
115   for(vector<string>::iterator iter = vec.begin();iter!=vec.end();iter++)
116     {
117       SCRUTE((*iter));
118       CORBA::Object_var obj=_NS->Resolve((*iter).c_str());
119       Engines::Container_var cont=Engines::Container::_narrow(obj);
120       if(!CORBA::is_nil(cont))
121         {
122           lstCont.push_back((*iter));
123         }
124     }
125   MESSAGE("Container list: ");
126   for(list<string>::iterator iter=lstCont.begin();iter!=lstCont.end();iter++)
127     {
128       SCRUTE((*iter));
129     }
130   for(list<string>::iterator iter=lstCont.begin();iter!=lstCont.end();iter++)
131     {
132       SCRUTE((*iter));
133       CORBA::Object_var obj=_NS->Resolve((*iter).c_str());
134       Engines::Container_var cont=Engines::Container::_narrow(obj);
135       if(!CORBA::is_nil(cont))
136         {
137           MESSAGE("ShutdownContainers: " << (*iter));
138           cont->Shutdown();
139         }
140       else MESSAGE("ShutdownContainers: no container ref for " << (*iter));
141     }
142 }
143
144 //=============================================================================
145 /*! CORBA Method:
146  *  Find a suitable Container in a list of machines, or start one
147  *  \param params            Machine Parameters required for the container
148  *  \param possibleComputers list of machines usable for find or start
149  */
150 //=============================================================================
151
152 Engines::Container_ptr
153 SALOME_ContainerManager::
154 FindOrStartContainer(const Engines::MachineParameters& params,
155                      const Engines::MachineList& possibleComputers)
156 {
157   long id;
158   string containerNameInNS;
159   char idc[3*sizeof(long)];
160
161   Engines::Container_ptr ret = FindContainer(params,possibleComputers);
162   if(!CORBA::is_nil(ret))
163     return ret;
164   MESSAGE("Container doesn't exist try to launch it ...");
165   MESSAGE("SALOME_ContainerManager::FindOrStartContainer " <<
166           possibleComputers.length());
167   //vector<string> vector;
168   string theMachine=_ResManager->FindBest(possibleComputers);
169   MESSAGE("try to launch it on " << theMachine);
170
171   // Get Id for container: a parallel container registers in Naming Service
172   // on the machine where is process 0. ContainerManager does'nt know the name
173   // of this machine before the launch of the parallel container. So to get
174   // the IOR of the parallel container in Naming Service, ContainerManager
175   // gives a unique Id. The parallel container registers his name under
176   // /ContainerManager/Id directory in NamingService
177
178   id = GetIdForContainer();
179
180   string command;
181   if(theMachine=="")
182     {
183       MESSAGE("SALOME_ContainerManager::FindOrStartContainer : " <<
184               "no possible computer");
185       return Engines::Container::_nil();
186     }
187   else if(theMachine==GetHostname())
188     {
189       command=_ResManager->BuildCommandToLaunchLocalContainer(params,id);
190     }
191   else
192     command =
193       _ResManager->BuildCommandToLaunchRemoteContainer(theMachine,params,id);
194
195   _ResManager->RmTmpFile();
196   int status=system(command.c_str());
197   if (status == -1)
198     {
199       MESSAGE("SALOME_LifeCycleCORBA::StartOrFindContainer rsh failed " <<
200               "(system command status -1)");
201       return Engines::Container::_nil();
202     }
203   else if (status == 217)
204     {
205       MESSAGE("SALOME_LifeCycleCORBA::StartOrFindContainer rsh failed " <<
206               "(system command status 217)");
207       return Engines::Container::_nil();
208     }
209   else
210     {
211       int count=TIME_OUT_TO_LAUNCH_CONT;
212       while ( CORBA::is_nil(ret) && count )
213         {
214 #ifndef WNT
215           sleep( 1 ) ;
216 #else
217           Sleep(1000);
218 #endif
219           count-- ;
220           if ( count != 10 )
221             MESSAGE( count << ". Waiting for FactoryServer on " << theMachine);
222           if(params.isMPI)
223             {
224               containerNameInNS = "/ContainerManager/id";
225               sprintf(idc,"%ld",id);
226               containerNameInNS += idc;
227             }
228           else
229             containerNameInNS =
230               _NS->BuildContainerNameForNS(params,theMachine.c_str());
231           SCRUTE(containerNameInNS);
232           CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str());
233           ret=Engines::Container::_narrow(obj);
234         }
235       if ( CORBA::is_nil(ret) )
236         {
237           MESSAGE("SALOME_LifeCycleCORBA::StartOrFindContainer rsh failed");
238         }
239       return ret;
240     }
241 }
242
243 //=============================================================================
244 /*! 
245  * 
246  */
247 //=============================================================================
248
249 Engines::MachineList *
250 SALOME_ContainerManager::
251 GetFittingResources(const Engines::MachineParameters& params,
252                     const char *componentName)
253 {
254   MESSAGE("SALOME_ContainerManager::GetFittingResources");
255   Engines::MachineList *ret=new Engines::MachineList;
256   vector<string> vec;
257   try
258     {
259       vec = _ResManager->GetFittingResources(params,componentName);
260     }
261   catch(const SALOME_Exception &ex)
262     {
263       INFOS("Caught exception.");
264       THROW_SALOME_CORBA_EXCEPTION(ex.what(),SALOME::BAD_PARAM);
265       //return ret;
266     }
267
268   //  MESSAGE("Machine list length "<<vec.size());
269   ret->length(vec.size());
270   for(unsigned int i=0;i<vec.size();i++)
271     {
272       (*ret)[i]=(vec[i]).c_str();
273     }
274   return ret;
275 }
276
277 //=============================================================================
278 /*! 
279  * 
280  */
281 //=============================================================================
282
283 char*
284 SALOME_ContainerManager::
285 FindBest(const Engines::MachineList& possibleComputers)
286 {
287   string theMachine=_ResManager->FindBest(possibleComputers);
288   return CORBA::string_dup(theMachine.c_str());
289 }
290
291 //=============================================================================
292 /*! 
293  * 
294  */
295 //=============================================================================
296
297 Engines::Container_ptr
298 SALOME_ContainerManager::
299 FindContainer(const Engines::MachineParameters& params,
300               const char *theMachine)
301 {
302   string containerNameInNS(_NS->BuildContainerNameForNS(params,theMachine));
303   CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str());
304   if( !CORBA::is_nil(obj) )
305     return Engines::Container::_narrow(obj);
306   else
307     return Engines::Container::_nil();
308 }
309
310 //=============================================================================
311 /*! 
312  * 
313  */
314 //=============================================================================
315
316 Engines::Container_ptr
317 SALOME_ContainerManager::
318 FindContainer(const Engines::MachineParameters& params,
319               const Engines::MachineList& possibleComputers)
320 {
321   MESSAGE("FindContainer "<<possibleComputers.length());
322   for(unsigned int i=0;i<possibleComputers.length();i++)
323     {
324       MESSAGE("FindContainer possible " << possibleComputers[i]);
325       Engines::Container_ptr cont = FindContainer(params,possibleComputers[i]);
326       if( !CORBA::is_nil(cont) )
327         return cont;
328     }
329   MESSAGE("FindContainer: not found");
330   return Engines::Container::_nil();
331 }
332
333 //=============================================================================
334 /*! 
335  * Get Id for container: a parallel container registers in Naming Service
336  * on the machine where is process 0. ContainerManager does'nt know the name
337  * of this machine before the launch of the parallel container. So to get
338  * the IOR of the parallel container in Naming Service, ContainerManager
339  * gives a unique Id. The parallel container registers his name under
340  * /ContainerManager/Id directory in NamingService
341  */
342 //=============================================================================
343
344
345 long SALOME_ContainerManager::GetIdForContainer(void)
346 {
347   _id++;
348   return _id;
349 }
350