]> SALOME platform Git repositories - modules/kernel.git/blob - src/Container/SALOME_ContainerManager.cxx
Salome HOME
merge from BR_V51_AR 7 may 09
[modules/kernel.git] / src / Container / SALOME_ContainerManager.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 #include "SALOME_ContainerManager.hxx"
23 #include "SALOME_NamingService.hxx"
24 #include "SALOME_ModuleCatalog.hh"
25 #include "Basics_Utils.hxx"
26 #include "Basics_DirUtils.hxx"
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #ifndef WIN32
30 #include <unistd.h>
31 #endif
32 #include <vector>
33 #include "Utils_CorbaException.hxx"
34 #include "Batch_Date.hxx"
35 #include <sstream>
36
37 #ifdef WITH_PACO_PARALLEL
38 #include "PaCOPP.hxx"
39 #endif
40
41 #define TIME_OUT_TO_LAUNCH_CONT 61
42
43 using namespace std;
44
45 vector<Engines::Container_ptr> SALOME_ContainerManager::_batchLaunchedContainers;
46
47 vector<Engines::Container_ptr>::iterator SALOME_ContainerManager::_batchLaunchedContainersIter;
48
49 const char *SALOME_ContainerManager::_ContainerManagerNameInNS = 
50   "/ContainerManager";
51
52 //=============================================================================
53 /*! 
54  *  Constructor
55  *  \param orb
56  *  Define a CORBA single thread policy for the server, which avoid to deal
57  *  with non thread-safe usage like Change_Directory in SALOME naming service
58  */
59 //=============================================================================
60
61 SALOME_ContainerManager::SALOME_ContainerManager(CORBA::ORB_ptr orb, PortableServer::POA_var poa, SALOME_ResourcesManager *rm, SALOME_NamingService *ns)
62 {
63   MESSAGE("constructor");
64   _NS = ns;
65   _ResManager = rm;
66
67   PortableServer::POAManager_var pman = poa->the_POAManager();
68   _orb = CORBA::ORB::_duplicate(orb) ;
69   CORBA::PolicyList policies;
70   policies.length(1);
71   PortableServer::ThreadPolicy_var threadPol = 
72     poa->create_thread_policy(PortableServer::SINGLE_THREAD_MODEL);
73   policies[0] = PortableServer::ThreadPolicy::_duplicate(threadPol);
74
75   _poa = poa->create_POA("SThreadPOA",pman,policies);
76   threadPol->destroy();
77   PortableServer::ObjectId_var id = _poa->activate_object(this);
78   CORBA::Object_var obj = _poa->id_to_reference(id);
79   Engines::ContainerManager_var refContMan =
80     Engines::ContainerManager::_narrow(obj);
81
82   _NS->Register(refContMan,_ContainerManagerNameInNS);
83   _isAppliSalomeDefined = (getenv("APPLI") != 0);
84   MESSAGE("constructor end");
85 }
86
87 //=============================================================================
88 /*! 
89  * destructor
90  */
91 //=============================================================================
92
93 SALOME_ContainerManager::~SALOME_ContainerManager()
94 {
95   MESSAGE("destructor");
96 }
97
98 //=============================================================================
99 //! shutdown all the containers, then the ContainerManager servant
100 /*! CORBA method:
101  */
102 //=============================================================================
103
104 void SALOME_ContainerManager::Shutdown()
105 {
106   MESSAGE("Shutdown");
107   ShutdownContainers();
108   _NS->Destroy_Name(_ContainerManagerNameInNS);
109   PortableServer::ObjectId_var oid = _poa->servant_to_id(this);
110   _poa->deactivate_object(oid);
111 }
112
113 //=============================================================================
114 //! Loop on all the containers listed in naming service, ask shutdown on each
115 /*! CORBA Method:
116  */
117 //=============================================================================
118
119 void SALOME_ContainerManager::ShutdownContainers()
120 {
121   MESSAGE("ShutdownContainers");
122   bool isOK;
123   isOK = _NS->Change_Directory("/Containers");
124   if( isOK ){
125     vector<string> vec = _NS->list_directory_recurs();
126     list<string> lstCont;
127     for(vector<string>::iterator iter = vec.begin();iter!=vec.end();iter++)
128       {
129         SCRUTE((*iter));
130         CORBA::Object_var obj=_NS->Resolve((*iter).c_str());
131         try
132           {
133             Engines::Container_var cont=Engines::Container::_narrow(obj);
134             if(!CORBA::is_nil(cont))
135               lstCont.push_back((*iter));
136           }
137         catch(const CORBA::Exception& e)
138           {
139             // ignore this entry and continue
140           }
141       }
142     MESSAGE("Container list: ");
143     for(list<string>::iterator iter=lstCont.begin();iter!=lstCont.end();iter++){
144       SCRUTE((*iter));
145     }
146     for(list<string>::iterator iter=lstCont.begin();iter!=lstCont.end();iter++)
147     {
148       try
149       {
150         SCRUTE((*iter));
151         CORBA::Object_var obj=_NS->Resolve((*iter).c_str());
152         Engines::Container_var cont=Engines::Container::_narrow(obj);
153         if(!CORBA::is_nil(cont))
154         {
155           MESSAGE("ShutdownContainers: " << (*iter));
156           cont->Shutdown();
157         }
158         else 
159           MESSAGE("ShutdownContainers: no container ref for " << (*iter));
160       }
161       catch(CORBA::SystemException& e)
162       {
163         INFOS("CORBA::SystemException ignored : " << e);
164       }
165       catch(CORBA::Exception&)
166       {
167         INFOS("CORBA::Exception ignored.");
168       }
169       catch(...)
170       {
171         INFOS("Unknown exception ignored.");
172       }
173     }
174   }
175 }
176
177 //=============================================================================
178 //! Give a suitable Container given constraints
179 /*! CORBA Method:
180  *  \param params            Machine Parameters required for the container
181  *  \return the container or nil
182  */
183 //=============================================================================
184
185 Engines::Container_ptr
186 SALOME_ContainerManager::GiveContainer(const Engines::MachineParameters& params)
187 {
188   char *valenv=getenv("SALOME_BATCH");
189   if(valenv)
190     if (strcmp(valenv,"1")==0)
191       {
192         if(_batchLaunchedContainers.empty())
193           fillBatchLaunchedContainers();
194
195         if (_batchLaunchedContainersIter == _batchLaunchedContainers.end())
196           _batchLaunchedContainersIter = _batchLaunchedContainers.begin();
197
198         Engines::Container_ptr rtn = Engines::Container::_duplicate(*_batchLaunchedContainersIter);
199         _batchLaunchedContainersIter++;
200         return rtn;
201       }
202   return StartContainer(params);
203 }
204
205 //=============================================================================
206 //! Start a suitable Container in a list of machines with constraints 
207 /*! C++ Method:
208  * Constraints are given by a machine parameters struct
209  *  \param params            Machine Parameters required for the container
210  *  \param possibleComputers list of machines usable for start
211  *  \param container_exe specific container executable (default=SALOME_Container)
212  */
213 //=============================================================================
214
215 Engines::Container_ptr
216 SALOME_ContainerManager::StartContainer(const Engines::MachineParameters& params,
217                const Engines::MachineList& possibleComputers,
218                const std::string& container_exe)
219 {
220 #ifdef WITH_PACO_PARALLEL
221   std::string parallelLib(params.parallelLib);
222   if (parallelLib != "")
223   {
224     Engines::MachineParameters myparams(params);
225     myparams.computerList=possibleComputers;
226     return StartParallelContainer(myparams);
227   }
228 #endif
229   string containerNameInNS;
230   Engines::Container_ptr ret = Engines::Container::_nil();
231
232   MESSAGE("SALOME_ContainerManager::StartContainer " << possibleComputers.length());
233
234   vector<string> lm;
235 // if mode is "get" keep only machines with existing containers 
236   if(std::string(params.mode.in())=="get")
237     {
238       for(unsigned int i=0;i<possibleComputers.length();i++)
239         {
240           Engines::Container_ptr cont = FindContainer(params,possibleComputers[i]);
241           try
242             {
243               if(!cont->_non_existent())
244                 lm.push_back(string(possibleComputers[i]));
245             }
246           catch(CORBA::Exception&)
247             {
248               // CORBA::Exception ignored.
249             }
250         }
251     }
252   else
253     {
254       for(unsigned int i=0;i<possibleComputers.length();i++)
255         lm.push_back(string(possibleComputers[i]));
256     }
257
258   string theMachine;
259   try
260     {
261       theMachine=_ResManager->GetImpl()->Find(params.policy.in(),lm);
262     }
263   catch( const SALOME_Exception &ex )
264     {
265       MESSAGE(ex.what());
266       return Engines::Container::_nil();
267     }
268
269   //If the machine name is localhost use the real name
270   if(theMachine == "localhost")
271     theMachine=Kernel_Utils::GetHostname();
272
273   //check if an entry exists in Naming service
274   //if params.mode == "start" or "" shutdown the existing container before launching a new one with that name
275   //if params.mode == "getorstart" or "get" use the existing container
276   containerNameInNS = _NS->BuildContainerNameForNS(params,theMachine.c_str());
277
278   SCRUTE(containerNameInNS);
279   CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str());
280   if ( !CORBA::is_nil(obj) )
281     {
282       try
283         {
284           Engines::Container_var cont=Engines::Container::_narrow(obj);
285           if(!cont->_non_existent())
286             {
287               if(std::string(params.mode.in())=="getorstart"||std::string(params.mode.in())=="get")
288                 return cont._retn(); /* the container exists and params.mode is getorstart or get use it*/
289               else
290                 cont->Shutdown(); // shutdown the registered container if it exists
291             }
292         }
293       catch(CORBA::Exception&)
294         {
295           INFOS("CORBA::Exception ignored.");
296         }
297     }
298
299   //try to launch a new container
300   MESSAGE("try to launch it on " << theMachine);
301
302   string command;
303   if(theMachine==""){
304     MESSAGE("SALOME_ContainerManager::StartContainer : no possible computer");
305     return Engines::Container::_nil();
306   }
307   else if(theMachine==Kernel_Utils::GetHostname())
308     command = BuildCommandToLaunchLocalContainer(params,container_exe);
309   else
310     command = BuildCommandToLaunchRemoteContainer(theMachine,params,container_exe);
311
312   //redirect stdout and stderr in a file
313   string logFilename="/tmp/"+_NS->ContainerName(params)+"_"+ theMachine +"_"+getenv( "USER" )+".log" ;
314   command += " > " + logFilename + " 2>&1 &";
315
316   // launch container with a system call
317   int status=system(command.c_str());
318
319   if (status == -1){
320     MESSAGE("SALOME_ContainerManager::StartContainer rsh failed (system command status -1)");
321     RmTmpFile(_TmpFileName); // command file can be removed here
322     return Engines::Container::_nil();
323   }
324   else if (status == 217){
325     MESSAGE("SALOME_ContainerManager::StartContainer rsh failed (system command status 217)");
326     RmTmpFile(_TmpFileName); // command file can be removed here
327     return Engines::Container::_nil();
328   }
329   else{
330     int count=TIME_OUT_TO_LAUNCH_CONT;
331     MESSAGE("count = "<<count);
332     while ( CORBA::is_nil(ret) && count ){
333 #ifndef WIN32
334       sleep( 1 ) ;
335 #else
336       Sleep(1000);
337 #endif
338       count-- ;
339       if ( count != 10 )
340         MESSAGE( count << ". Waiting for container on " << theMachine);
341
342       CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str());
343       ret=Engines::Container::_narrow(obj);
344     }
345     
346     if ( CORBA::is_nil(ret) )
347       {
348         MESSAGE("SALOME_ContainerManager::StartContainer rsh failed");
349       }
350     else
351       {
352         logFilename=":"+logFilename;
353         logFilename="@"+Kernel_Utils::GetHostname()+logFilename;
354         logFilename=getenv( "USER" )+logFilename;
355         ret->logfilename(logFilename.c_str());
356       }
357
358     RmTmpFile(_TmpFileName); // command file can be removed here
359     return ret;
360   }
361 }
362
363 //=============================================================================
364 //! Start a suitable Container given constraints 
365 /*! CORBA Method:
366  *  \param params            Machine Parameters required for the container
367  */
368 //=============================================================================
369
370 Engines::Container_ptr
371 SALOME_ContainerManager::StartContainer(const Engines::MachineParameters& params)
372 {
373   Engines::MachineList_var possibleComputers = _ResManager->GetFittingResources(params);
374
375   // Look into ModulCatalog if a specific container must be launched
376   CORBA::String_var container_exe;
377   int found=0;
378   try
379     {
380       CORBA::Object_var obj = _NS->Resolve("/Kernel/ModulCatalog");
381       SALOME_ModuleCatalog::ModuleCatalog_var Catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
382       if (CORBA::is_nil (Catalog))
383         return Engines::Container::_nil();
384       // Loop through component list
385       for(unsigned int i=0;i<params.componentList.length();i++)
386         {
387           const char* compoi = params.componentList[i];
388           SALOME_ModuleCatalog::Acomponent_var compoInfo = Catalog->GetComponent(compoi);
389           if (CORBA::is_nil (compoInfo))
390             {
391               continue;
392             }
393           SALOME_ModuleCatalog::ImplType impl=compoInfo->implementation_type();
394           container_exe=compoInfo->implementation_name();
395           if(impl==SALOME_ModuleCatalog::CEXE)
396             {
397               if(found)
398                 {
399                   INFOS("ContainerManager Error: you can't have 2 CEXE component in the same container" );
400                   return Engines::Container::_nil();
401                 }
402               found=1;
403             }
404         }
405     }
406   catch (ServiceUnreachable&)
407     {
408       INFOS("Caught exception: Naming Service Unreachable");
409       return Engines::Container::_nil();
410     }
411   catch (...)
412     {
413       INFOS("Caught unknown exception.");
414       return Engines::Container::_nil();
415     }
416
417   if(found)
418     return StartContainer(params,possibleComputers,container_exe.in());
419   else
420     return StartContainer(params,possibleComputers);
421 }
422
423 //=============================================================================
424 //!  Find or start a suitable Container given some constraints
425 /*! CORBA Method:
426  *  \param params            Machine Parameters required for the container
427  *  \return the container or nil
428  */
429 //=============================================================================
430
431 Engines::Container_ptr
432 SALOME_ContainerManager::FindOrStartContainer(const Engines::MachineParameters& params)
433 {
434   Engines::Container_ptr ret = FindContainer(params,params.computerList);
435   if(!CORBA::is_nil(ret))
436     return ret;
437   MESSAGE("Container doesn't exist try to launch it ...");
438
439   return StartContainer(params);
440 }
441
442 //=============================================================================
443 //! Find a container given constraints (params) on a list of machines (possibleComputers)
444 /*!
445  *
446  */
447 //=============================================================================
448
449 Engines::Container_ptr
450 SALOME_ContainerManager::FindContainer(const Engines::MachineParameters& params,
451                                        const Engines::MachineList& possibleComputers)
452 {
453   MESSAGE("FindContainer "<<possibleComputers.length());
454   for(unsigned int i=0;i<possibleComputers.length();i++)
455     {
456       MESSAGE("FindContainer possible " << possibleComputers[i]);
457       Engines::Container_ptr cont = FindContainer(params,possibleComputers[i]);
458       if( !CORBA::is_nil(cont) )
459         return cont;
460     }
461   MESSAGE("FindContainer: not found");
462   return Engines::Container::_nil();
463 }
464
465 //=============================================================================
466 //! Find a container given constraints (params) on a machine (theMachine)
467 /*!
468  *
469  */
470 //=============================================================================
471
472 Engines::Container_ptr
473 SALOME_ContainerManager::FindContainer(const Engines::MachineParameters& params,
474                                        const char *theMachine)
475 {
476   string containerNameInNS(_NS->BuildContainerNameForNS(params,theMachine));
477   CORBA::Object_var obj = _NS->Resolve(containerNameInNS.c_str());
478   try
479     {
480       if(obj->_non_existent())
481         return Engines::Container::_nil();
482       else
483         return Engines::Container::_narrow(obj);
484     }
485   catch(const CORBA::Exception& e)
486     {
487       return Engines::Container::_nil();
488     }
489 }
490
491 #ifdef WITH_PACO_PARALLEL
492 //=============================================================================
493 /*! CORBA Method:
494  *  Find or Start a suitable PaCO++ Parallel Container in a list of machines.
495  *  \param params            Machine Parameters required for the container
496  *  \return CORBA container reference.
497  */
498 //=============================================================================
499 Engines::Container_ptr
500 SALOME_ContainerManager::StartParallelContainer(const Engines::MachineParameters& params_const)
501 {
502   CORBA::Object_var obj;
503   PaCO::InterfaceManager_var container_proxy;
504   Engines::Container_ptr ret = Engines::Container::_nil();
505   Engines::MachineParameters params(params_const);
506
507   // Step 1 : Try to find a suitable container
508   // Currently not as good as could be since
509   // we have to verified the number of nodes of the container
510   // if a user tell that.
511   ret = FindContainer(params, params.computerList);
512   if(CORBA::is_nil(ret)) {
513     // Step 2 : Starting a new parallel container !
514     INFOS("[StartParallelContainer] Starting a PaCO++ parallel container");
515
516     // Step 3 : Choose a computer
517     std::string theMachine = _ResManager->FindFirst(params.computerList);
518     //If the machine name is localhost use the real name
519     if(theMachine == "localhost")
520       theMachine=Kernel_Utils::GetHostname();
521
522     if(theMachine == "") {
523       INFOS("[StartParallelContainer] !!!!!!!!!!!!!!!!!!!!!!!!!!");
524       INFOS("[StartParallelContainer] No possible computer found");
525       INFOS("[StartParallelContainer] !!!!!!!!!!!!!!!!!!!!!!!!!!");
526       return ret;
527     }
528     INFOS("[StartParallelContainer] on machine : " << theMachine);
529     params.hostname = CORBA::string_dup(theMachine.c_str());
530
531     // Step 4 : starting parallel container proxy
532     Engines::MachineParameters params_proxy(params);
533     std::string command_proxy;
534     SALOME_ContainerManager::actual_launch_machine_t proxy_machine;
535     try 
536     {
537       command_proxy = BuildCommandToLaunchParallelContainer("SALOME_ParallelContainerProxy", params_proxy, proxy_machine);
538     }
539     catch(const SALOME_Exception & ex)
540     {
541       INFOS("[StartParallelContainer] Exception in BuildCommandToLaunchParallelContainer");
542       INFOS(ex.what());
543       return ret;
544     }
545     params_proxy.nb_component_nodes = 0; // LaunchParallelContainer uses this value to know if it launches the proxy or the nodes
546     obj = LaunchParallelContainer(command_proxy, params_proxy, _NS->ContainerName(params_proxy), proxy_machine);
547     if (CORBA::is_nil(obj))
548     {
549       INFOS("[StartParallelContainer] LaunchParallelContainer for proxy returns NIL !");
550       return ret;
551     }
552     try 
553     {
554       container_proxy = PaCO::InterfaceManager::_narrow(obj);
555     }
556     catch(CORBA::SystemException& e)
557     {
558       INFOS("[StartParallelContainer] Exception in _narrow after LaunchParallelContainer for proxy !");
559       INFOS("CORBA::SystemException : " << e);
560       return ret;
561     }
562     catch(CORBA::Exception& e)
563     {
564       INFOS("[StartParallelContainer] Exception in _narrow after LaunchParallelContainer for proxy !");
565       INFOS("CORBA::Exception" << e);
566       return ret;
567     }
568     catch(...)
569     {
570       INFOS("[StartParallelContainer] Exception in _narrow after LaunchParallelContainer for proxy !");
571       INFOS("Unknown exception !");
572       return ret;
573     }
574     if (CORBA::is_nil(container_proxy))
575     {
576       INFOS("[StartParallelContainer] PaCO::InterfaceManager::_narrow returns NIL !");
577       return ret;
578     }
579
580     // Step 5 : starting parallel container nodes
581     std::string command_nodes;
582     Engines::MachineParameters params_nodes(params);
583     SALOME_ContainerManager::actual_launch_machine_t nodes_machines;
584     try 
585     {
586       command_nodes = BuildCommandToLaunchParallelContainer("SALOME_ParallelContainerNode", params_nodes, nodes_machines, proxy_machine[0]);
587     }
588     catch(const SALOME_Exception & ex)
589     {
590       INFOS("[StartParallelContainer] Exception in BuildCommandToLaunchParallelContainer");
591       INFOS(ex.what());
592       return ret;
593     }
594     std::string container_generic_node_name = _NS->ContainerName(params) + "Node";
595     obj = LaunchParallelContainer(command_nodes, params_nodes, container_generic_node_name, nodes_machines);
596     if (CORBA::is_nil(obj))
597     {
598       INFOS("[StartParallelContainer] LaunchParallelContainer for nodes returns NIL !");
599       // Il faut tuer le proxy
600       try 
601       {
602         Engines::Container_var proxy = Engines::Container::_narrow(container_proxy);
603         proxy->Shutdown();
604       }
605       catch (...)
606       {
607         INFOS("[StartParallelContainer] Exception catched from proxy Shutdown...");
608       }
609       return ret;
610     }
611
612     // Step 6 : connecting nodes and the proxy to actually create a parallel container
613     for (int i = 0; i < params.nb_component_nodes; i++) 
614     {
615       std::ostringstream tmp;
616       tmp << i;
617       std::string proc_number = tmp.str();
618       std::string container_node_name = container_generic_node_name + proc_number;
619
620       std::string theNodeMachine(nodes_machines[i]);
621       std::string containerNameInNS = _NS->BuildContainerNameForNS(container_node_name.c_str(), theNodeMachine.c_str());
622       obj = _NS->Resolve(containerNameInNS.c_str());
623       if (CORBA::is_nil(obj)) 
624       {
625         INFOS("[StartParallelContainer] CONNECTION FAILED From Naming Service !");
626         INFOS("[StartParallelContainer] Container name is " << containerNameInNS);
627         return ret;
628       }
629       try
630       {
631         MESSAGE("[StartParallelContainer] Deploying node : " << container_node_name);
632         PaCO::InterfaceParallel_var node = PaCO::InterfaceParallel::_narrow(obj);
633         node->deploy();
634         MESSAGE("[StartParallelContainer] node " << container_node_name << " is deployed");
635       }
636       catch(CORBA::SystemException& e)
637       {
638         INFOS("[StartParallelContainer] Exception in deploying node : " << containerNameInNS);
639         INFOS("CORBA::SystemException : " << e);
640         return ret;
641       }
642       catch(CORBA::Exception& e)
643       {
644         INFOS("[StartParallelContainer] Exception in deploying node : " << containerNameInNS);
645         INFOS("CORBA::Exception" << e);
646         return ret;
647       }
648       catch(...)
649       {
650         INFOS("[StartParallelContainer] Exception in deploying node : " << containerNameInNS);
651         INFOS("Unknown exception !");
652         return ret;
653       }
654     }
655
656     // Step 7 : starting parallel container
657     try 
658     {
659       MESSAGE ("[StartParallelContainer] Starting parallel object");
660       container_proxy->start();
661       MESSAGE ("[StartParallelContainer] Parallel object is started");
662       ret = Engines::Container::_narrow(container_proxy);
663     }
664     catch(CORBA::SystemException& e)
665     {
666       INFOS("Caught CORBA::SystemException. : " << e);
667     }
668     catch(PortableServer::POA::ServantAlreadyActive&)
669     {
670       INFOS("Caught CORBA::ServantAlreadyActiveException");
671     }
672     catch(CORBA::Exception&)
673     {
674       INFOS("Caught CORBA::Exception.");
675     }
676     catch(std::exception& exc)
677     {
678       INFOS("Caught std::exception - "<<exc.what()); 
679     }
680     catch(...)
681     {
682       INFOS("Caught unknown exception.");
683     }
684   }
685   return ret;
686 }
687 #else
688 //=============================================================================
689 /*! CORBA Method:
690  *  Find or Start a suitable PaCO++ Parallel Container in a list of machines.
691  *  \param params            Machine Parameters required for the container
692  *  \return CORBA container reference.
693  */
694 //=============================================================================
695 Engines::Container_ptr
696 SALOME_ContainerManager::StartParallelContainer(const Engines::MachineParameters& params)
697 {
698   Engines::Container_ptr ret = Engines::Container::_nil();
699   INFOS("[StartParallelContainer] is disabled !");
700   INFOS("[StartParallelContainer] recompile SALOME Kernel to enable parallel extension");
701   return ret;
702 }
703 #endif
704
705 //=============================================================================
706 /*! This method launches the parallel container.
707  *  It will may be placed on the ressources manager.
708  *
709  * \param command to launch
710  * \param container's parameters
711  * \param name of the container
712  *
713  * \return CORBA container reference
714  */
715 //=============================================================================
716 CORBA::Object_ptr 
717 SALOME_ContainerManager::LaunchParallelContainer(const std::string& command, 
718                                                  const Engines::MachineParameters& params,
719                                                  const std::string& name,
720                                                  SALOME_ContainerManager::actual_launch_machine_t & vect_machine)
721 {
722   CORBA::Object_ptr obj = CORBA::Object::_nil();
723   std::string containerNameInNS;
724   int count = TIME_OUT_TO_LAUNCH_CONT;
725
726   INFOS("[LaunchParallelContainer] Begin");
727   int status = system(command.c_str());
728   if (status == -1) {
729     INFOS("[LaunchParallelContainer] failed : system command status -1");
730     return obj;
731   }
732   else if (status == 217) {
733     INFOS("[LaunchParallelContainer] failed : system command status 217");
734     return obj;
735   }
736
737   if (params.nb_component_nodes == 0) 
738   {
739     std::string theMachine(vect_machine[0]);
740     // Proxy We have launch a proxy
741     containerNameInNS = _NS->BuildContainerNameForNS((char*) name.c_str(), theMachine.c_str());
742     INFOS("[LaunchParallelContainer]  Waiting for Parallel Container proxy " << containerNameInNS << " on " << theMachine);
743     while (CORBA::is_nil(obj) && count) 
744     {
745 #ifndef WIN32
746       sleep(1) ;
747 #else
748       Sleep(1000);
749 #endif
750       count-- ;
751       obj = _NS->Resolve(containerNameInNS.c_str());
752     }
753   }
754   else 
755   {
756     INFOS("[LaunchParallelContainer] launching the nodes of the parallel container");
757     // We are waiting all the nodes
758     for (int i = 0; i < params.nb_component_nodes; i++) 
759     {
760       obj = CORBA::Object::_nil();
761       std::string theMachine(vect_machine[i]);
762       // Name of the node
763       std::ostringstream tmp;
764       tmp << i;
765       std::string proc_number = tmp.str();
766       std::string container_node_name = name + proc_number;
767       containerNameInNS = _NS->BuildContainerNameForNS((char*) container_node_name.c_str(), theMachine.c_str());
768       INFOS("[LaunchParallelContainer]  Waiting for Parallel Container node " << containerNameInNS << " on " << theMachine);
769       while (CORBA::is_nil(obj) && count) {
770 #ifndef WIN32
771         sleep(1) ;
772 #else
773         Sleep(1000);
774 #endif
775         count-- ;
776         obj = _NS->Resolve(containerNameInNS.c_str());
777       }
778       if (CORBA::is_nil(obj))
779       {
780         INFOS("[LaunchParallelContainer] Launch of node failed (or not found) !");
781         return obj;
782       }
783     }
784   }
785   if (CORBA::is_nil(obj)) 
786     INFOS("[LaunchParallelContainer] failed");
787   
788   return obj;
789 }
790
791 void SALOME_ContainerManager::fillBatchLaunchedContainers()
792 {
793   _batchLaunchedContainers.clear();
794   _NS->Change_Directory("/Containers");
795   vector<string> vec = _NS->list_directory_recurs();
796   for(vector<string>::iterator iter = vec.begin();iter!=vec.end();iter++){
797     CORBA::Object_var obj=_NS->Resolve((*iter).c_str());
798     Engines::Container_ptr cont=Engines::Container::_narrow(obj);
799     if(!CORBA::is_nil(cont)){
800       _batchLaunchedContainers.push_back(cont);
801     }
802   }
803   _batchLaunchedContainersIter=_batchLaunchedContainers.begin();
804 }
805
806 //=============================================================================
807 /*!
808  *  This is no longer valid (C++ container are also python containers)
809  */ 
810 //=============================================================================
811
812 bool isPythonContainer(const char* ContainerName)
813 {
814   bool ret = false;
815   int len = strlen(ContainerName);
816
817   if (len >= 2)
818     if (strcmp(ContainerName + len - 2, "Py") == 0)
819       ret = true;
820
821   return ret;
822 }
823
824 //=============================================================================
825 /*!
826  *  Builds the script to be launched
827  *
828  *  If SALOME Application not defined ($APPLI),
829  *  see BuildTempFileToLaunchRemoteContainer()
830  *
831  *  Else rely on distant configuration. Command is under the form (example):
832  *  ssh user@machine distantPath/runRemote.sh hostNS portNS WORKINGDIR workingdir \
833  *                   SALOME_Container containerName &"
834
835  *  - where user is ommited if not specified in CatalogResources,
836  *  - where distant path is always relative to user@machine $HOME, and
837  *    equal to $APPLI if not specified in CatalogResources,
838  *  - where hostNS is the hostname of CORBA naming server (set by scripts to
839  *    use to launch SALOME and servers in $APPLI: runAppli.sh, runRemote.sh)
840  *  - where portNS is the port used by CORBA naming server (set by scripts to
841  *    use to launch SALOME and servers in $APPLI: runAppli.sh, runRemote.sh)
842  *  - where workingdir is the requested working directory for the container.
843  *    If WORKINGDIR (and workingdir) is not present the working dir will be $HOME
844  */ 
845 //=============================================================================
846
847 string
848 SALOME_ContainerManager::BuildCommandToLaunchRemoteContainer
849 (const string& machine,
850  const Engines::MachineParameters& params, const std::string& container_exe)
851 {
852   string command;
853   int nbproc;
854           
855   if ( ! _isAppliSalomeDefined )
856     command = BuildTempFileToLaunchRemoteContainer(machine, params);
857
858   else
859     {
860       const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(machine);
861
862       if (params.isMPI)
863         {
864           if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
865             nbproc = 1;
866           else if ( params.nb_node == 0 )
867             nbproc = params.nb_proc_per_node;
868           else if ( params.nb_proc_per_node == 0 )
869             nbproc = params.nb_node;
870           else
871             nbproc = params.nb_node * params.nb_proc_per_node;
872         }
873
874       // "ssh user@machine distantPath/runRemote.sh hostNS portNS WORKINGDIR workingdir \
875         //  SALOME_Container containerName &"
876
877       if (resInfo.Protocol == rsh)
878         command = "rsh ";
879       else if (resInfo.Protocol == ssh)
880         command = "ssh ";
881       else
882         throw SALOME_Exception("Unknown protocol");
883
884       if (resInfo.UserName != "")
885         {
886           command += resInfo.UserName;
887           command += "@";
888         }
889
890       command += machine;
891       command += " ";
892
893       if (resInfo.AppliPath != "")
894         command += resInfo.AppliPath; // path relative to user@machine $HOME
895       else
896         {
897           ASSERT(getenv("APPLI"));
898           command += getenv("APPLI"); // path relative to user@machine $HOME
899         }
900
901       command += "/runRemote.sh ";
902
903       ASSERT(getenv("NSHOST")); 
904       command += getenv("NSHOST"); // hostname of CORBA name server
905
906       command += " ";
907       ASSERT(getenv("NSPORT"));
908       command += getenv("NSPORT"); // port of CORBA name server
909
910       std::string wdir=params.workingdir.in();
911       if(wdir != "")
912         {
913           command += " WORKINGDIR ";
914           command += " '";
915           if(wdir == "$TEMPDIR")
916             wdir="\\$TEMPDIR";
917           command += wdir; // requested working directory
918           command += "'"; 
919         }
920
921       if(params.isMPI)
922         {
923           command += " mpirun -np ";
924           std::ostringstream o;
925           o << nbproc << " ";
926           command += o.str();
927 #ifdef WITHLAM
928           command += "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
929 #elif defined(WITHOPENMPI)
930           if( getenv("OMPI_URI_FILE") == NULL )
931             command += "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace";
932           else{
933             command += "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace -ompi-server file:";
934             command += getenv("OMPI_URI_FILE");
935           }
936 #endif  
937           command += " SALOME_MPIContainer ";
938         }
939       else
940         command += " " +container_exe+ " ";
941
942       command += _NS->ContainerName(params);
943       command += " -";
944       AddOmninamesParams(command);
945
946       MESSAGE("command =" << command);
947     }
948
949   return command;
950 }
951
952 //=============================================================================
953 /*!
954  *  builds the command to be launched.
955  */ 
956 //=============================================================================
957
958 string
959 SALOME_ContainerManager::BuildCommandToLaunchLocalContainer
960 (const Engines::MachineParameters& params, const std::string& container_exe)
961 {
962   _TmpFileName = BuildTemporaryFileName();
963   string command;
964   int nbproc = 0;
965
966   ofstream command_file( _TmpFileName.c_str() );
967
968   if (params.isMPI)
969     {
970       //command = "mpirun -np ";
971       command_file << "mpirun -np ";
972
973       if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
974         nbproc = 1;
975       else if ( params.nb_node == 0 )
976         nbproc = params.nb_proc_per_node;
977       else if ( params.nb_proc_per_node == 0 )
978         nbproc = params.nb_node;
979       else
980         nbproc = params.nb_node * params.nb_proc_per_node;
981
982       //std::ostringstream o;
983
984       //o << nbproc << " ";
985       command_file << nbproc << " ";
986
987       //command += o.str();
988 #ifdef WITHLAM
989       //command += "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
990       command_file << "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
991 #elif defined(WITHOPENMPI)
992       //command += "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace ";
993       if( getenv("OMPI_URI_FILE") == NULL )
994         command_file << "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace";
995       else
996         {
997           command_file << "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace -ompi-server file:";
998           command_file << getenv("OMPI_URI_FILE");
999         }
1000 #endif
1001
1002       if (isPythonContainer(params.container_name))
1003         //command += "pyMPI SALOME_ContainerPy.py ";
1004         command_file << " pyMPI SALOME_ContainerPy.py ";
1005       else
1006         //command += "SALOME_MPIContainer ";
1007         command_file << " SALOME_MPIContainer ";
1008     }
1009
1010   else
1011     {
1012       //command="";
1013       std::string wdir=params.workingdir.in();
1014       if(wdir != "")
1015         {
1016           // a working directory is requested
1017           if(wdir == "$TEMPDIR")
1018             {
1019               // a new temporary directory is requested
1020               string dir = Kernel_Utils::GetTmpDir();
1021 #ifdef WIN32
1022               //command += "cd /d "+ dir +";";
1023               command_file << "cd /d " << dir << endl;
1024 #else
1025               //command = "cd "+ dir +";";
1026               command_file << "cd " << dir << ";";
1027 #endif
1028
1029             }
1030           else
1031             {
1032               // a permanent directory is requested use it or create it
1033 #ifdef WIN32
1034               //command="mkdir " + wdir;
1035               command_file << "mkdir " + wdir << endl;
1036               command_file << "cd /D " + wdir << endl;
1037 #else
1038               //command="mkdir -p " + wdir + " && cd " + wdir + ";";
1039               command_file << "mkdir -p " << wdir << " && cd " << wdir + ";";
1040 #endif
1041             }
1042         }
1043       if (isPythonContainer(params.container_name))
1044         //command += "SALOME_ContainerPy.py ";
1045         command_file << "SALOME_ContainerPy.py ";
1046       else
1047         //command += container_exe + " ";
1048         command_file << container_exe + " ";
1049
1050     }
1051
1052   command_file << _NS->ContainerName(params);
1053   command_file << " -";
1054   AddOmninamesParams(command_file);
1055   command_file.close();
1056
1057 #ifndef WIN32
1058   chmod(_TmpFileName.c_str(), 0x1ED);
1059 #endif
1060   command = _TmpFileName;
1061
1062   MESSAGE("Command is file ... " << command);
1063   return command;
1064 }
1065
1066
1067 //=============================================================================
1068 /*!
1069  *  removes the generated temporary file in case of a remote launch.
1070  */ 
1071 //=============================================================================
1072
1073 void SALOME_ContainerManager::RmTmpFile(std::string& tmpFileName)
1074 {
1075   int lenght = tmpFileName.size();
1076   if ( lenght  > 0)
1077     {
1078 #ifdef WIN32
1079       string command = "del /F ";
1080 #else
1081       string command = "rm ";      
1082 #endif
1083       if ( lenght > 4 )
1084         command += tmpFileName.substr(0, lenght - 3 );
1085       else
1086         command += tmpFileName;
1087       command += '*';
1088       system(command.c_str());
1089       //if dir is empty - remove it
1090       string tmp_dir = Kernel_Utils::GetDirByPath( tmpFileName );
1091       if ( Kernel_Utils::IsEmptyDir( tmp_dir ) )
1092         {
1093 #ifdef WIN32
1094           command = "del /F " + tmp_dir;
1095 #else
1096           command = "rmdir " + tmp_dir;
1097 #endif
1098           system(command.c_str());
1099         }
1100     }
1101 }
1102
1103 //=============================================================================
1104 /*!
1105  *   add to command all options relative to naming service.
1106  */ 
1107 //=============================================================================
1108
1109 void SALOME_ContainerManager::AddOmninamesParams(string& command) const
1110 {
1111   CORBA::String_var iorstr = _NS->getIORaddr();
1112   command += "ORBInitRef NameService=";
1113   command += iorstr;
1114 }
1115
1116
1117 //=============================================================================
1118 /*!
1119  *  add to command all options relative to naming service.
1120  */ 
1121 //=============================================================================
1122
1123 void SALOME_ContainerManager::AddOmninamesParams(ofstream& fileStream) const
1124 {
1125   CORBA::String_var iorstr = _NS->getIORaddr();
1126   fileStream << "ORBInitRef NameService=";
1127   fileStream << iorstr;
1128 }
1129
1130 //=============================================================================
1131 /*!
1132  *  generate a file name in /tmp directory
1133  */ 
1134 //=============================================================================
1135
1136 string SALOME_ContainerManager::BuildTemporaryFileName() const
1137 {
1138   //build more complex file name to support multiple salome session
1139   string aFileName = Kernel_Utils::GetTmpFileName();
1140 #ifndef WIN32
1141   aFileName += ".sh";
1142 #else
1143   aFileName += ".bat";
1144 #endif
1145   return aFileName;
1146 }
1147
1148
1149 //=============================================================================
1150 /*!
1151  *  Builds in a temporary file the script to be launched.
1152  *  
1153  *  Used if SALOME Application ($APPLI) is not defined.
1154  *  The command is build with data from CatalogResources, in which every path
1155  *  used on remote computer must be defined.
1156  */ 
1157 //=============================================================================
1158
1159 string
1160 SALOME_ContainerManager::BuildTempFileToLaunchRemoteContainer
1161 (const string& machine,
1162  const Engines::MachineParameters& params) throw(SALOME_Exception)
1163 {
1164   int status;
1165
1166   _TmpFileName = BuildTemporaryFileName();
1167   ofstream tempOutputFile;
1168   tempOutputFile.open(_TmpFileName.c_str(), ofstream::out );
1169   const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(machine);
1170   tempOutputFile << "#! /bin/sh" << endl;
1171
1172   // --- set env vars
1173
1174   tempOutputFile << "export SALOME_trace=local" << endl; // mkr : 27.11.2006 : PAL13967 - Distributed supervision graphs - Problem with "SALOME_trace"
1175   //tempOutputFile << "source " << resInfo.PreReqFilePath << endl;
1176
1177   // ! env vars
1178
1179   if (params.isMPI)
1180     {
1181       tempOutputFile << "mpirun -np ";
1182       int nbproc;
1183
1184       if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
1185         nbproc = 1;
1186       else if ( params.nb_node == 0 )
1187         nbproc = params.nb_proc_per_node;
1188       else if ( params.nb_proc_per_node == 0 )
1189         nbproc = params.nb_node;
1190       else
1191         nbproc = params.nb_node * params.nb_proc_per_node;
1192
1193       std::ostringstream o;
1194
1195       tempOutputFile << nbproc << " ";
1196 #ifdef WITHLAM
1197       tempOutputFile << "-x PATH,LD_LIBRARY_PATH,OMNIORB_CONFIG,SALOME_trace ";
1198 #elif defined(WITHOPENMPI)
1199       if( getenv("OMPI_URI_FILE") == NULL )
1200         tempOutputFile << "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace";
1201       else{
1202         tempOutputFile << "-x PATH -x LD_LIBRARY_PATH -x OMNIORB_CONFIG -x SALOME_trace -ompi-server file:";
1203         tempOutputFile << getenv("OMPI_URI_FILE");
1204       }
1205 #endif
1206     }
1207
1208   tempOutputFile << getenv("KERNEL_ROOT_DIR") << "/bin/salome/";
1209
1210   if (params.isMPI)
1211     {
1212       if (isPythonContainer(params.container_name))
1213         tempOutputFile << " pyMPI SALOME_ContainerPy.py ";
1214       else
1215         tempOutputFile << " SALOME_MPIContainer ";
1216     }
1217
1218   else
1219     {
1220       if (isPythonContainer(params.container_name))
1221         tempOutputFile << "SALOME_ContainerPy.py ";
1222       else
1223         tempOutputFile << "SALOME_Container ";
1224     }
1225
1226   tempOutputFile << _NS->ContainerName(params) << " -";
1227   AddOmninamesParams(tempOutputFile);
1228   tempOutputFile << " &" << endl;
1229   tempOutputFile.flush();
1230   tempOutputFile.close();
1231 #ifndef WIN32
1232   chmod(_TmpFileName.c_str(), 0x1ED);
1233 #endif
1234
1235   // --- Build command
1236
1237   string command;
1238
1239   if (resInfo.Protocol == rsh)
1240     {
1241       command = "rsh ";
1242       string commandRcp = "rcp ";
1243       commandRcp += _TmpFileName;
1244       commandRcp += " ";
1245       commandRcp += machine;
1246       commandRcp += ":";
1247       commandRcp += _TmpFileName;
1248       status = system(commandRcp.c_str());
1249     }
1250
1251   else if (resInfo.Protocol == ssh)
1252     {
1253       command = "ssh ";
1254       string commandRcp = "scp ";
1255       commandRcp += _TmpFileName;
1256       commandRcp += " ";
1257       commandRcp += machine;
1258       commandRcp += ":";
1259       commandRcp += _TmpFileName;
1260       status = system(commandRcp.c_str());
1261     }
1262   else
1263     throw SALOME_Exception("Unknown protocol");
1264
1265   if(status)
1266     throw SALOME_Exception("Error of connection on remote host");    
1267
1268   command += machine;
1269   _CommandForRemAccess = command;
1270   command += " ";
1271   command += _TmpFileName;
1272
1273   SCRUTE(command);
1274
1275   return command;
1276
1277 }
1278
1279 //=============================================================================
1280 /*! Creates a command line that the container manager uses to launch
1281  * a parallel container.
1282  */ 
1283 //=============================================================================
1284 string 
1285 SALOME_ContainerManager::BuildCommandToLaunchParallelContainer(const std::string& exe_name,
1286                                                                const Engines::MachineParameters& params,
1287                                                                SALOME_ContainerManager::actual_launch_machine_t & vect_machine,
1288                                                                const std::string proxy_hostname)
1289 {
1290   // This method knows the differences between the proxy and the nodes.
1291   // nb_component_nodes is not used in the same way if it is a proxy or 
1292   // a node.
1293   
1294   //command = "gdb --args ";
1295   //command = "valgrind --tool=memcheck --log-file=val_log ";
1296   //command += real_exe_name;
1297
1298   // Step 0 : init some variables...
1299   std::string parallelLib(CORBA::string_dup(params.parallelLib));
1300   std::string real_exe_name  = exe_name + parallelLib;
1301   std::string machine_file_name("");
1302   bool remote = false;
1303   bool is_a_proxy = false; 
1304   std::string hostname(CORBA::string_dup(params.hostname));
1305
1306   std::ostringstream tmp_string;
1307   CORBA::Long nb_nodes = params.nb_component_nodes;
1308   tmp_string << nb_nodes;
1309   std::string nbproc = tmp_string.str();
1310
1311   Engines::MachineParameters_var rtn = new Engines::MachineParameters();
1312   rtn->container_name = params.container_name;
1313   rtn->hostname = params.hostname;
1314   rtn->OS = params.OS;
1315   rtn->mem_mb = params.mem_mb;
1316   rtn->cpu_clock = params.cpu_clock;
1317   rtn->nb_proc_per_node = params.nb_proc_per_node;
1318   rtn->nb_node = params.nb_node;
1319   rtn->isMPI = params.isMPI;
1320
1321   // Step 1 : local or remote launch ?
1322   if (hostname != std::string(Kernel_Utils::GetHostname()) )
1323   {
1324     MESSAGE("[BuildCommandToLaunchParallelContainer] remote machine case detected !");
1325     remote = true;
1326   }
1327
1328   // Step 2 : proxy or nodes launch ?
1329   std::string::size_type loc_proxy = exe_name.find("Proxy");
1330   if( loc_proxy != string::npos ) {
1331     is_a_proxy = true;
1332   } 
1333
1334   // Step 3 : Depending of the parallelLib, getting the machine file
1335   // ParallelLib Dummy has is own machine for this method
1336   if (remote)
1337   {
1338     if (is_a_proxy)
1339     {
1340       machine_file_name = _ResManager->getMachineFile(hostname,
1341                                                       1,
1342                                                       parallelLib);
1343     }
1344     else
1345     {
1346       machine_file_name = _ResManager->getMachineFile(hostname, 
1347                                                       params.nb_component_nodes,
1348                                                       parallelLib);
1349     }
1350     if (machine_file_name == "")
1351     {
1352       INFOS("[BuildCommandToLaunchParallelContainer] Error machine_file was not generated for machine " << hostname);
1353       throw SALOME_Exception("Error machine_file was not generated");
1354     }
1355     MESSAGE("[BuildCommandToLaunchParallelContainer] machine_file_name is : " << machine_file_name);
1356   }
1357
1358   // Step 4 : Log type choosen by the user
1359   std::string log_env("");
1360   char * get_val = getenv("PARALLEL_LOG");
1361   if (get_val)
1362     log_env = get_val;
1363   std::string command_begin("");
1364   std::string command_end("");
1365   if(log_env == "xterm")
1366   {
1367     command_begin = "/usr/X11R6/bin/xterm -e \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH; export PATH=$PATH;";
1368     command_end   = "\"&";
1369   }
1370   else if(log_env == "xterm_debug")
1371   {
1372     command_begin = "/usr/X11R6/bin/xterm -e \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH; export PATH=$PATH;";
1373     command_end   = "; cat \" &";
1374   }
1375   else
1376   {
1377     // default into a file...
1378     std::string logFilename = "/tmp/" + _NS->ContainerName(params) + "_" + hostname;
1379     if (is_a_proxy)
1380       logFilename += "_Proxy_";
1381     else
1382       logFilename += "_Node_";
1383     logFilename += std::string(getenv("USER")) + ".log";
1384     command_end = " > " + logFilename + " 2>&1 & ";
1385   }
1386
1387   // Step 5 : Building the command
1388   std::string command("");
1389   if (parallelLib == "Dummy")
1390   {
1391     if (is_a_proxy)
1392     {
1393       std::string command_remote("");
1394       if (remote)
1395       {
1396         std::string machine_name;
1397         std::ifstream machine_file(machine_file_name.c_str());
1398         std::getline(machine_file, machine_name);
1399         MESSAGE("[BuildCommandToLaunchParallelContainer] machine file name extracted is " << machine_name)
1400
1401         // We want to launch a command like : 
1402         // ssh user@machine distantPath/runRemote.sh hostNS portNS
1403         const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(machine_name);
1404         if (resInfo.Protocol == rsh)
1405           command_remote = "rsh ";
1406         else 
1407           command_remote = "ssh ";
1408         command_remote += resInfo.UserName;
1409         command_remote += "@";
1410         command_remote += machine_name;
1411         command_remote += " ";
1412         command_remote += resInfo.AppliPath; // path relative to user@machine $HOME
1413         command_remote += "/runRemote.sh ";
1414         ASSERT(getenv("NSHOST")); 
1415         command_remote += getenv("NSHOST"); // hostname of CORBA name server
1416         command_remote += " ";
1417         ASSERT(getenv("NSPORT"));
1418         command_remote += getenv("NSPORT"); // port of CORBA name server
1419         command_remote += " ";
1420
1421         hostname = machine_name;
1422       }
1423
1424       command =  real_exe_name;
1425       command += " " + _NS->ContainerName(rtn);
1426       command += " " + parallelLib;
1427       command += " " + hostname;
1428       command += " " + nbproc;
1429       command += " -";
1430       AddOmninamesParams(command);
1431
1432       command = command_begin + command_remote + command + command_end;
1433       vect_machine.push_back(hostname);
1434     }
1435     else
1436     {
1437       std::ifstream * machine_file = NULL;
1438       if (remote)
1439         machine_file = new std::ifstream(machine_file_name.c_str());
1440       for (int i= 0; i < nb_nodes; i++)
1441       {
1442         std::string command_remote("");
1443         if (remote)
1444         {
1445           std::string machine_name;
1446           std::getline(*machine_file, machine_name);
1447           MESSAGE("[BuildCommandToLaunchParallelContainer] machine file name extracted is " << machine_name)
1448
1449             // We want to launch a command like : 
1450             // ssh user@machine distantPath/runRemote.sh hostNS portNS
1451             const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(machine_name);
1452           if (resInfo.Protocol == rsh)
1453             command_remote = "rsh ";
1454           else 
1455             command_remote = "ssh ";
1456           command_remote += resInfo.UserName;
1457           command_remote += "@";
1458           command_remote += machine_name;
1459           command_remote += " ";
1460           command_remote += resInfo.AppliPath; // path relative to user@machine $HOME
1461           command_remote += "/runRemote.sh ";
1462           ASSERT(getenv("NSHOST")); 
1463           command_remote += getenv("NSHOST"); // hostname of CORBA name server
1464           command_remote += " ";
1465           ASSERT(getenv("NSPORT"));
1466           command_remote += getenv("NSPORT"); // port of CORBA name server
1467           command_remote += " ";
1468
1469           hostname = machine_name;
1470         }
1471
1472         std::ostringstream tmp;
1473         tmp << i;
1474         std::string proc_number = tmp.str();
1475
1476         std::string command_tmp("");
1477         command_tmp += real_exe_name;
1478         command_tmp += " " + _NS->ContainerName(rtn);
1479         command_tmp += " " + parallelLib;
1480         command_tmp += " " + proxy_hostname;
1481         command_tmp += " " + proc_number;
1482         command_tmp += " -";
1483         AddOmninamesParams(command_tmp);
1484
1485         // On change _Node_ par _Nodex_ pour avoir chaque noeud
1486         // sur un fichier
1487         std::string command_end_tmp = command_end;
1488         std::string::size_type loc_node = command_end_tmp.find("_Node_");
1489         if (loc_node != std::string::npos)
1490           command_end_tmp.insert(loc_node+5, proc_number);
1491         command += command_begin + command_remote + command_tmp + command_end_tmp;
1492         vect_machine.push_back(hostname);
1493       }
1494       if (machine_file)
1495         delete machine_file;
1496     }
1497   }
1498   else if (parallelLib == "Mpi")
1499   {
1500     // Step 0: if remote we have to copy the file
1501     // to the first machine of the file
1502     std::string remote_machine("");
1503     if (remote)
1504     {
1505       std::ifstream * machine_file = NULL;
1506       machine_file = new std::ifstream(machine_file_name.c_str());
1507       // Get first word of the line
1508       // For MPI implementation the first word is the 
1509       // machine name
1510       std::getline(*machine_file, remote_machine, ' ');
1511       machine_file->close();
1512       MESSAGE("[BuildCommandToLaunchParallelContainer] machine file name extracted is " << remote_machine)
1513
1514       // We want to launch a command like : 
1515       // scp mpi_machine_file user@machine:Path
1516       std::string command_remote("");
1517       const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(remote_machine);
1518       if (resInfo.Protocol == rsh)
1519         command_remote = "rcp ";
1520       else 
1521         command_remote = "scp ";
1522
1523       command_remote += machine_file_name;
1524       command_remote += " ";
1525       command_remote += resInfo.UserName;
1526       command_remote += "@";
1527       command_remote += remote_machine;
1528       command_remote += ":";
1529       command_remote += machine_file_name;
1530
1531       int status = system(command_remote.c_str());
1532       if (status == -1)
1533       {
1534         INFOS("copy of the mpi machine file failed !");
1535         return "";
1536       }
1537     }
1538
1539     if (is_a_proxy)
1540     {
1541       std::string command_remote("");
1542       if (remote)
1543       {
1544         // We want to launch a command like : 
1545         // ssh user@machine distantPath/runRemote.sh hostNS portNS
1546         const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(remote_machine);
1547         if (resInfo.Protocol == rsh)
1548           command_remote = "rsh ";
1549         else 
1550           command_remote = "ssh ";
1551         command_remote += resInfo.UserName;
1552         command_remote += "@";
1553         command_remote += remote_machine;
1554         command_remote += " ";
1555         command_remote += resInfo.AppliPath; // path relative to user@machine $HOME
1556         command_remote += "/runRemote.sh ";
1557         ASSERT(getenv("NSHOST")); 
1558         command_remote += getenv("NSHOST"); // hostname of CORBA name server
1559         command_remote += " ";
1560         ASSERT(getenv("NSPORT"));
1561         command_remote += getenv("NSPORT"); // port of CORBA name server
1562         command_remote += " ";
1563
1564         hostname = remote_machine;
1565       }
1566
1567       // We use Dummy proxy for MPI parallel containers
1568       real_exe_name  = exe_name + "Dummy";
1569       command =  real_exe_name;
1570       command += " " + _NS->ContainerName(rtn);
1571       command += " Dummy";
1572       command += " " + hostname;
1573       command += " " + nbproc;
1574       command += " -";
1575       AddOmninamesParams(command);
1576
1577       command = command_begin + command_remote + command + command_end;
1578       vect_machine.push_back(hostname);
1579     }
1580     else                                          
1581     {
1582       std::string command_remote("");
1583       if (remote)
1584       {
1585         const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(remote_machine);
1586         if (resInfo.Protocol == rsh)
1587           command_remote = "rsh ";
1588         else 
1589           command_remote = "ssh ";
1590         command_remote += resInfo.UserName;
1591         command_remote += "@";
1592         command_remote += remote_machine;
1593         command_remote += " ";
1594
1595         std::string new_real_exe_name("");
1596         new_real_exe_name += resInfo.AppliPath; // path relative to user@machine $HOME
1597         new_real_exe_name += "/runRemote.sh ";
1598         ASSERT(getenv("NSHOST")); 
1599         new_real_exe_name += getenv("NSHOST"); // hostname of CORBA name server
1600         new_real_exe_name += " ";
1601         ASSERT(getenv("NSPORT"));
1602         new_real_exe_name += getenv("NSPORT"); // port of CORBA name server
1603         new_real_exe_name += " ";
1604
1605         real_exe_name = new_real_exe_name + real_exe_name;
1606         hostname = remote_machine;
1607       }
1608
1609       const ParserResourcesType& resInfo = _ResManager->GetImpl()->GetResourcesList(hostname);
1610       if (resInfo.mpi == lam)
1611       {
1612         command = "mpiexec -ssi boot ";
1613         if (resInfo.Protocol == rsh)
1614           command += "rsh ";
1615         else 
1616           command += "ssh ";
1617         command += "-machinefile " + machine_file_name + " "; 
1618         command += "-n " + nbproc + " ";
1619         command += real_exe_name;
1620         command += " " + _NS->ContainerName(rtn);
1621         command += " " + parallelLib;
1622         command += " " + proxy_hostname;
1623         command += " -";
1624         AddOmninamesParams(command);
1625       }
1626       else
1627       {
1628         command = "mpirun -np " + nbproc + " ";
1629         command += real_exe_name;
1630         command += " " + _NS->ContainerName(rtn);
1631         command += " " + parallelLib;
1632         command += " " + proxy_hostname;
1633         command += " -";
1634         AddOmninamesParams(command);
1635       }
1636
1637       command = command_begin + command_remote + command + command_end;
1638       for (int i= 0; i < nb_nodes; i++)
1639         vect_machine.push_back(proxy_hostname);
1640     }
1641   }
1642   else
1643   {
1644     std::string message("Unknown parallelLib : " + parallelLib);
1645     throw SALOME_Exception(message.c_str());
1646   }
1647
1648   MESSAGE("Parallel launch is: " << command);
1649   return command;
1650 }
1651
1652 string SALOME_ContainerManager::GetMPIZeroNode(string machine)
1653 {
1654   int status;
1655   string zeronode;
1656   string cmd;
1657   string tmpFile = BuildTemporaryFileName();
1658
1659   cmd = "ssh " + machine + " mpirun -np 1 hostname > " + tmpFile;
1660
1661   status = system(cmd.c_str());
1662   if( status == 0 ){
1663     ifstream fp(tmpFile.c_str(),ios::in);
1664     fp >> zeronode;
1665   }
1666
1667   RmTmpFile(tmpFile);
1668
1669   return zeronode;
1670 }