Salome HOME
Porting to Mandrake 10.1 and new products:
[modules/kernel.git] / src / LifeCycleCORBA / SALOME_LifeCycleCORBA.cxx
1 //  SALOME LifeCycleCORBA : implementation of containers and engines life cycle both in Python and C++
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SALOME_LifeCycleCORBA.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SALOME
27 //  $Header$
28
29 #include <iostream>
30 #include <fstream>
31 #include <sstream>
32 #include <iomanip>
33
34 #include "OpUtil.hxx"
35 #include "utilities.h"
36 #include "Launchers.hxx"
37
38 #include <ServiceUnreachable.hxx>
39
40 #include "SALOME_LifeCycleCORBA.hxx"
41 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
42 #include "SALOME_ContainerManager.hxx"
43 #include "SALOME_Component_i.hxx"
44 #include "SALOME_NamingService.hxx"
45 using namespace std;
46
47 SALOME_LifeCycleCORBA::SALOME_LifeCycleCORBA(SALOME_NamingService *ns)
48 {
49   _NS = ns;
50   //add try catch
51   _NS->Change_Directory("/"); // mpv 250105: current directory may be not root (in SALOMEDS for an example)
52   CORBA::Object_var obj=_NS->Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS);
53   ASSERT( !CORBA::is_nil(obj));
54   _ContManager=Engines::ContainerManager::_narrow(obj);
55 }
56
57 SALOME_LifeCycleCORBA::~SALOME_LifeCycleCORBA()
58 {
59 }
60
61 string SALOME_LifeCycleCORBA::ContainerName(
62                                          const char * aComputerContainer ,
63                                          string * theComputer ,
64                                          string * theContainer ) {
65   char * ContainerName = new char [ strlen( aComputerContainer ) + 1 ] ;
66   strcpy( ContainerName , aComputerContainer ) ;
67   string theComputerContainer("/Containers/");
68   char * slash = strchr( ContainerName , '/' ) ;
69   if ( !slash ) {
70     *theComputer = GetHostname() ;
71     theComputerContainer += *theComputer ;
72     theComputerContainer += "/" ;
73     *theContainer = ContainerName ;
74     theComputerContainer += *theContainer ;
75   }
76   else {
77     slash[ 0 ] = '\0' ;
78     slash += 1 ;
79     *theContainer = slash ;
80     if ( !strcmp( ContainerName , "localhost" ) ) {
81       *theComputer = GetHostname() ;
82     }
83     else {
84       *theComputer = ContainerName ;
85     }
86     theComputerContainer += *theComputer ;
87     theComputerContainer += "/" ;
88     theComputerContainer += *theContainer ;
89   }
90   delete [] ContainerName;
91   return theComputerContainer ;
92 }
93
94 bool SALOME_LifeCycleCORBA::isKnownComponentClass(const char *componentName)
95 {
96
97   try
98     {
99       CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog");
100       SALOME_ModuleCatalog::ModuleCatalog_var Catalog = 
101         SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
102       SALOME_ModuleCatalog::Acomponent_ptr compoInfo = 
103         Catalog->GetComponent(componentName);
104       if (CORBA::is_nil (compoInfo)) 
105         {
106           INFOS("Catalog Error : Component not found in the catalog");
107           return false;
108         }
109       else return true;
110     }
111   catch (ServiceUnreachable&)
112     {
113       INFOS("Caught exception: Naming Service Unreachable");
114     }
115   catch (...)
116     {
117       INFOS("Caught unknown exception.");
118     }
119   return false;
120 }
121
122 string SALOME_LifeCycleCORBA::ComputerPath(
123                                          const char * theComputer ) {
124   CORBA::String_var path;
125   CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog");
126   SALOME_ModuleCatalog::ModuleCatalog_var Catalog = 
127                      SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
128   try {
129     path = Catalog->GetPathPrefix( theComputer );
130   }
131   catch (SALOME_ModuleCatalog::NotFound&) {
132     INFOS("GetPathPrefix(" << theComputer << ") not found!");
133     path = "" ;
134   }
135   SCRUTE( path ) ;
136   return CORBA::string_dup( path ) ;
137 }
138
139 Engines::Container_ptr SALOME_LifeCycleCORBA::FindContainer(const char *containerName)
140 {
141   ASSERT(_NS != NULL);
142   string cont ;
143   if ( strncmp( containerName , "/Containers/" , 12 ) ) { // Compatibility ...
144     string theComputer ;
145     string theContainer ;
146     cont = ContainerName( containerName , &theComputer , &theContainer ) ;
147   }
148   else {
149     cont = containerName ;
150   }
151   try {
152
153     SCRUTE( cont );
154
155     CORBA::Object_var obj = _NS->Resolve( cont.c_str() );
156     if( !CORBA::is_nil( obj ) ) {
157       return Engines::Container::_narrow( obj ) ;
158     }
159   }
160   catch (ServiceUnreachable&) {
161     INFOS("Caught exception: Naming Service Unreachable");
162   }
163   catch (...) {
164     INFOS("Caught unknown exception.");
165   }
166   return Engines::Container::_nil();
167 }
168
169 Engines::Component_ptr SALOME_LifeCycleCORBA::FindOrLoad_Component
170                                   (const char *containerName,
171                                    const char *componentName)
172 {
173   if (! isKnownComponentClass(componentName)) return Engines::Component::_nil();
174   char *stContainer=strdup(containerName);
175   string st2Container(stContainer);
176   int rg=st2Container.find("/");
177   if(rg>=0)
178     {
179       stContainer[rg]='\0';
180       if(strcmp(stContainer,"localhost")==0)
181         {
182           Engines::Component_ptr ret=FindOrLoad_Component(stContainer+rg+1,componentName);
183           free(stContainer);
184           return ret;
185         }
186     }
187   if(rg<0) {
188     //containerName doesn't contain "/" => Local container
189     free(stContainer);
190     Engines::MachineList_var listOfMachine=new Engines::MachineList;
191     listOfMachine->length(1);
192     listOfMachine[0]=CORBA::string_dup(GetHostname().c_str());
193     Engines::Component_ptr ret=FindComponent(containerName,componentName,listOfMachine.in());
194     if(CORBA::is_nil(ret))
195       return LoadComponent(containerName,componentName,listOfMachine);
196     else
197       return ret;
198   }
199   else {
200     //containerName contains "/" => Remote container
201     stContainer[rg]='\0';
202     Engines::MachineParameters_var params=new Engines::MachineParameters;
203     params->container_name=CORBA::string_dup(stContainer+rg+1);
204     params->hostname=CORBA::string_dup(stContainer);
205     params->OS=CORBA::string_dup("LINUX");
206     free(stContainer);
207     return FindOrLoad_Component(params,componentName);
208   }
209 }
210
211 Engines::Component_ptr SALOME_LifeCycleCORBA::FindOrLoad_Component(const Engines::MachineParameters& params,
212                                                                    const char *componentName)
213 {
214   if (! isKnownComponentClass(componentName)) return Engines::Component::_nil();
215   Engines::MachineList_var listOfMachine=_ContManager->GetFittingResources(params,componentName);
216   Engines::Component_ptr ret=FindComponent(params.container_name,componentName,listOfMachine);
217   if(CORBA::is_nil(ret))
218     return LoadComponent(params.container_name,componentName,listOfMachine);
219   else
220     return ret;
221 }
222
223 Engines::Component_ptr SALOME_LifeCycleCORBA::FindComponent(const char *containerName,
224                                                                  const char *componentName,
225                                                                  const Engines::MachineList& listOfMachines)
226 {
227   if (! isKnownComponentClass(componentName)) return Engines::Component::_nil();
228   if(containerName[0]!='\0')
229     {
230       Engines::MachineList_var machinesOK=new Engines::MachineList;
231       unsigned int lghtOfmachinesOK=0;
232       machinesOK->length(listOfMachines.length());
233       for(unsigned int i=0;i<listOfMachines.length();i++)
234         {
235           const char *currentMachine=listOfMachines[i];
236           string componentNameForNS=Engines_Component_i::BuildComponentNameForNS(componentName,containerName,currentMachine);
237           CORBA::Object_var obj = _NS->Resolve(componentNameForNS.c_str());
238           if(!CORBA::is_nil(obj))
239             {
240               machinesOK[lghtOfmachinesOK++]=CORBA::string_dup(currentMachine);
241             }
242         }
243       if(lghtOfmachinesOK!=0)
244         {
245           machinesOK->length(lghtOfmachinesOK);
246           CORBA::String_var bestMachine=_ContManager->FindBest(machinesOK);
247           string componentNameForNS=Engines_Component_i::BuildComponentNameForNS(componentName,containerName,bestMachine);
248           CORBA::Object_var obj=_NS->Resolve(componentNameForNS.c_str());
249           return Engines::Component::_narrow(obj);
250         }
251       else
252         return Engines::Component::_nil();
253     }
254   else
255     {
256       //user specified no container name so trying to find a component in the best machine among listOfMachines
257       CORBA::String_var bestMachine=_ContManager->FindBest(listOfMachines);
258       //Normally look at all containers launched on bestMachine to see if componentName is already launched on one of them. To do..
259       string componentNameForNS=Engines_Component_i::BuildComponentNameForNS(componentName,containerName,bestMachine);
260       CORBA::Object_var obj = _NS->Resolve(componentNameForNS.c_str());
261       return Engines::Component::_narrow(obj);
262     }
263 }
264
265 Engines::Component_ptr SALOME_LifeCycleCORBA::LoadComponent(const char *containerName, const char *componentName, const Engines::MachineList& listOfMachines)
266 {
267   Engines::Container_var cont=_ContManager->FindOrStartContainer(containerName,listOfMachines);
268   string implementation=Engines_Component_i::GetDynLibraryName(componentName);
269   return cont->load_impl(componentName, implementation.c_str());
270 }
271
272
273 Engines::Container_ptr SALOME_LifeCycleCORBA::FindOrStartContainer(
274                                               const string aComputerContainer ,
275                                               const string theComputer ,
276                                               const string theContainer ) {
277   SCRUTE( aComputerContainer ) ;
278   SCRUTE( theComputer ) ;
279   SCRUTE( theContainer ) ;
280
281   Engines::Container_var aContainer = FindContainer( aComputerContainer.c_str() ) ;
282
283   if ( !CORBA::is_nil( aContainer ) ) {
284     return aContainer ;
285   }
286
287   Engines::Container_var aFactoryServer ;
288
289   bool pyCont = false ;
290   int len = theContainer.length() ;
291   if ( !strcmp( &theContainer.c_str()[len-2] , "Py" ) ) {
292     pyCont = true ;
293   }
294
295   string addr=_NS->getIORaddr();
296   string CMD="SALOME_Container";
297   if ( pyCont ) {
298     CMD="SALOME_ContainerPy.py";
299   }
300   CMD=CMD + " " + theContainer;
301   CMD=CMD + " -ORBInitRef NameService="+addr;
302
303   /*
304    *  Get the appropriate launcher and ask to launch
305    */
306   PyObject * launcher=getLauncher((char *)theComputer.c_str());
307   Launcher_Slaunch(launcher,(char *)theComputer.c_str(),(char *)CMD.c_str());
308   /*
309    *  Wait until the container is registered in Naming Service
310    */
311   int count = 5 ;
312   while ( CORBA::is_nil( aFactoryServer ) && count ) {
313       sleep( 1 ) ;
314       count-- ;
315       if ( count != 10 )
316             MESSAGE( count << ". Waiting for FactoryServer on " << theComputer)
317       aFactoryServer = FindContainer( aComputerContainer.c_str() ) ;
318   }
319   if ( !CORBA::is_nil( aFactoryServer ) ) {
320      return aFactoryServer;
321   }
322   MESSAGE("SALOME_LifeCycleCORBA::StartOrFindContainer rsh failed") ;
323   return Engines::Container::_nil();
324 }