1 // Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "SALOME_ContainerManager.hxx"
21 #include "SALOME_NamingService.hxx"
23 #include <sys/types.h>
28 #include "Utils_CorbaException.hxx"
30 #define TIME_OUT_TO_LAUNCH_CONT 21
34 const char *SALOME_ContainerManager::_ContainerManagerNameInNS =
37 //=============================================================================
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
44 //=============================================================================
46 SALOME_ContainerManager::SALOME_ContainerManager(CORBA::ORB_ptr orb)
48 MESSAGE("constructor");
49 _NS = new SALOME_NamingService(orb);
50 _ResManager = new SALOME_ResourcesManager(orb);
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;
56 CORBA::PolicyList policies;
58 PortableServer::ThreadPolicy_var threadPol =
59 root_poa->create_thread_policy(PortableServer::SINGLE_THREAD_MODEL);
60 policies[0] = PortableServer::ThreadPolicy::_duplicate(threadPol);
63 root_poa->create_POA("SThreadPOA",pman,policies);
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);
70 _NS->Register(refContMan,_ContainerManagerNameInNS);
71 MESSAGE("constructor end");
74 //=============================================================================
78 //=============================================================================
80 SALOME_ContainerManager::~SALOME_ContainerManager()
82 MESSAGE("destructor");
87 //=============================================================================
89 * shutdown all the containers, then the ContainerManager servant
91 //=============================================================================
93 void SALOME_ContainerManager::Shutdown()
97 PortableServer::ObjectId_var oid = _default_POA()->servant_to_id(this);
98 _default_POA()->deactivate_object(oid);
103 //=============================================================================
105 * Loop on all the containers listed in naming service, ask shutdown on each
107 //=============================================================================
109 void SALOME_ContainerManager::ShutdownContainers()
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++)
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))
122 lstCont.push_back((*iter));
125 MESSAGE("Container list: ");
126 for(list<string>::iterator iter=lstCont.begin();iter!=lstCont.end();iter++)
130 for(list<string>::iterator iter=lstCont.begin();iter!=lstCont.end();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))
137 MESSAGE("ShutdownContainers: " << (*iter));
140 else MESSAGE("ShutdownContainers: no container ref for " << (*iter));
144 //=============================================================================
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
150 //=============================================================================
152 Engines::Container_ptr
153 SALOME_ContainerManager::
154 FindOrStartContainer(const Engines::MachineParameters& params,
155 const Engines::MachineList& possibleComputers)
158 string containerNameInNS;
159 char idc[3*sizeof(long)];
161 Engines::Container_ptr ret = FindContainer(params,possibleComputers);
162 if(!CORBA::is_nil(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);
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
178 id = GetIdForContainer();
183 MESSAGE("SALOME_ContainerManager::FindOrStartContainer : " <<
184 "no possible computer");
185 return Engines::Container::_nil();
187 else if(theMachine==GetHostname())
189 command=_ResManager->BuildCommandToLaunchLocalContainer(params,id);
193 _ResManager->BuildCommandToLaunchRemoteContainer(theMachine,params,id);
195 _ResManager->RmTmpFile();
196 int status=system(command.c_str());
199 MESSAGE("SALOME_LifeCycleCORBA::StartOrFindContainer rsh failed " <<
200 "(system command status -1)");
201 return Engines::Container::_nil();
203 else if (status == 217)
205 MESSAGE("SALOME_LifeCycleCORBA::StartOrFindContainer rsh failed " <<
206 "(system command status 217)");
207 return Engines::Container::_nil();
211 int count=TIME_OUT_TO_LAUNCH_CONT;
212 while ( CORBA::is_nil(ret) && count )
221 MESSAGE( count << ". Waiting for FactoryServer on " << theMachine);
224 containerNameInNS = "/ContainerManager/id";
225 sprintf(idc,"%ld",id);
226 containerNameInNS += idc;
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);
235 if ( CORBA::is_nil(ret) )
237 MESSAGE("SALOME_LifeCycleCORBA::StartOrFindContainer rsh failed");
243 //=============================================================================
247 //=============================================================================
249 Engines::MachineList *
250 SALOME_ContainerManager::
251 GetFittingResources(const Engines::MachineParameters& params,
252 const char *componentName)
254 MESSAGE("SALOME_ContainerManager::GetFittingResources");
255 Engines::MachineList *ret=new Engines::MachineList;
259 vec = _ResManager->GetFittingResources(params,componentName);
261 catch(const SALOME_Exception &ex)
263 INFOS("Caught exception.");
264 THROW_SALOME_CORBA_EXCEPTION(ex.what(),SALOME::BAD_PARAM);
268 // MESSAGE("Machine list length "<<vec.size());
269 ret->length(vec.size());
270 for(unsigned int i=0;i<vec.size();i++)
272 (*ret)[i]=(vec[i]).c_str();
277 //=============================================================================
281 //=============================================================================
284 SALOME_ContainerManager::
285 FindBest(const Engines::MachineList& possibleComputers)
287 string theMachine=_ResManager->FindBest(possibleComputers);
288 return CORBA::string_dup(theMachine.c_str());
291 //=============================================================================
295 //=============================================================================
297 Engines::Container_ptr
298 SALOME_ContainerManager::
299 FindContainer(const Engines::MachineParameters& params,
300 const char *theMachine)
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);
307 return Engines::Container::_nil();
310 //=============================================================================
314 //=============================================================================
316 Engines::Container_ptr
317 SALOME_ContainerManager::
318 FindContainer(const Engines::MachineParameters& params,
319 const Engines::MachineList& possibleComputers)
321 MESSAGE("FindContainer "<<possibleComputers.length());
322 for(unsigned int i=0;i<possibleComputers.length();i++)
324 MESSAGE("FindContainer possible " << possibleComputers[i]);
325 Engines::Container_ptr cont = FindContainer(params,possibleComputers[i]);
326 if( !CORBA::is_nil(cont) )
329 MESSAGE("FindContainer: not found");
330 return Engines::Container::_nil();
333 //=============================================================================
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
342 //=============================================================================
345 long SALOME_ContainerManager::GetIdForContainer(void)