Salome HOME
Padder execution error management (the errors are raised toward the gui)
[modules/smesh.git] / src / Tools / padder / meshjob / impl / MeshJobManager_i.cxx
1 // Copyright (C) 2011-2012  EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Authors : Guillaume Boulant (EDF) - 01/03/2011
20
21 #ifdef WIN32
22 #include <winsock2.h>
23 #include <windows.h> 
24 #else
25 #include <sys/time.h>
26 #endif
27
28 #include "MeshJobManager_i.hxx"
29
30 #include <SALOMEconfig.h>
31 #include CORBA_SERVER_HEADER(SALOME_Exception)
32
33
34 #include "Basics_Utils.hxx"         // For standard logging
35 #undef LOG
36 #include "SALOME_KernelServices.hxx"   // For CORBA logging
37 #undef LOG
38
39 #define LOG STDLOG
40
41 //
42 // ====================================================================
43 // General purpose helper functions (to put elsewhere at least)
44 // ====================================================================
45 //
46
47 /*!
48  * This function must be used to associate a datetime tag to a job
49  */
50
51 #ifndef WIN32
52 static long timetag() {
53   timeval tv;
54   gettimeofday(&tv,0);
55   long tag = tv.tv_usec + tv.tv_sec*1000000;
56   return tag;
57 }
58 #endif
59
60 /*!
61  * This function returns true if the string text starts with the string
62  * token.
63  */
64 static bool myStartsWith(const std::string& text,const std::string& token){     
65   if(text.length() < token.length())
66     return false;
67   return (text.compare(0, token.length(), token) == 0);
68 }
69
70 /*!
71  * This function returns true if the file exists on the local file
72  * system.
73  */
74 #include <iostream>
75 #include <fstream>
76 static bool fexists(const char *filename)
77 {
78   std::ifstream ifile(filename);
79   if ((bool)ifile && ifile.good()) {
80     return true;
81   }
82   return false;
83 }
84
85 //
86 // ====================================================================
87 // Constructor/Destructor
88 // ====================================================================
89 //
90 MeshJobManager_i::MeshJobManager_i(CORBA::ORB_ptr orb,
91                                    PortableServer::POA_ptr poa,
92                                    PortableServer::ObjectId * contId,
93                                    const char *instanceName,
94                                    const char *interfaceName)
95   : Engines_Component_i(orb, poa, contId, instanceName, interfaceName)
96 {
97   LOG("Activating MESHJOB::MeshJobManager object");
98   _thisObj = this ;
99   _id = _poa->activate_object(_thisObj);
100
101   _salomeLauncher   = KERNEL::getSalomeLauncher();
102   if(CORBA::is_nil(_salomeLauncher)){
103     LOG("The SALOME launcher can't be reached ==> STOP");
104     throw KERNEL::createSalomeException("SALOME launcher can't be reached");
105   }
106
107   _resourcesManager = KERNEL::getResourcesManager();
108   if(CORBA::is_nil(_resourcesManager)){
109     LOG("The SALOME resource manager can't be reached ==> STOP");
110     throw KERNEL::createSalomeException("The SALOME resource manager can't be reached");
111   }
112
113   _lastErrorMessage = "";
114 }
115
116 MeshJobManager_i::~MeshJobManager_i() {
117   LOG("MeshJobManager_i::~MeshJobManager_i()");
118 }
119
120 //
121 // ====================================================================
122 // Helper functions to deals with the local and remote file systems
123 // ====================================================================
124 //
125 #include <fstream>     // to get the file streams
126 #ifdef WNT             
127 #include <stdlib.h>    // to get _splitpath
128 #include <direct.h>    // to get _mkdir
129 #else
130 #include <unistd.h>    // to get basename
131 #include <sys/stat.h>  // to get mkdir
132 #include <sys/types.h> // to get mkdir options
133 #endif
134
135 #include <stdlib.h>    // to get system and getenv
136
137 static std::string OUTPUTFILE("output.med");
138 static std::string DATAFILE("data.txt");
139 static std::string SCRIPTFILE("padder.sh");
140 static std::string SEPARATOR(" ");
141
142 static std::string USER(getenv("USER"));
143 static std::string LOCAL_INPUTDIR("/tmp/spadder.local.inputdir."+USER);
144 static std::string LOCAL_RESULTDIR("/tmp/spadder.local.resultdir."+USER);
145 static std::string REMOTE_WORKDIR("/tmp/spadder.remote.workdir."+USER);
146
147 /*!
148  * This function creates the padder text input file containing the
149  * input data (list of filenames and groupnames) and returns the path
150  * of the created file. This function is the one that knows the format
151  * of the padder input file. If the input file format changes, then
152  * this function (and only this one) should be updated. The file
153  * format is the following ([] means that the variable is optional):
154  *
155  * [<concreteMeshFile>   <concreteGroupName>]
156  * nbSteelBarMeshes <N>
157  * <steelBarMeshFile_1>   <steelBarGroupName_1>
158  * <steelBarMeshFile_2>   <steelBarGroupName_2>
159  * ...
160  * <steelBarMeshFile_N>   <steelBarGroupName_N>
161  * <outputMedFile>
162  */
163 const char * MeshJobManager_i::_writeDataFile(std::vector<MESHJOB::MeshJobParameter> listConcreteMesh,
164                                               std::vector<MESHJOB::MeshJobParameter> listSteelBarMesh) {
165 #ifdef WIN32
166   _mkdir(LOCAL_INPUTDIR.c_str());
167 #else
168   mkdir(LOCAL_INPUTDIR.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
169 #endif
170
171   // Make it static so that it's allocated once (constant name)
172   static std::string * dataFilename = new std::string(LOCAL_INPUTDIR+"/"+DATAFILE);
173   std::ofstream dataFile(dataFilename->c_str());
174
175   // Note that we use here the basename of the files because the files
176   // are supposed to be copied in the REMOTE_WORKDIR for execution.
177   std::string line;
178
179   // We first specify the concrete mesh data (filename and groupname)
180   if ( listConcreteMesh.size() > 0 ) {
181 #ifdef WIN32
182     char fname[ _MAX_FNAME ];
183     _splitpath( listConcreteMesh[0].file_name, NULL, NULL, fname, NULL );
184     char* bname = &fname[0];
185 #else
186     char* bname = basename(listConcreteMesh[0].file_name);
187 #endif
188     line = std::string(bname) + " " + std::string(listConcreteMesh[0].group_name);
189     dataFile << line.c_str() << std::endl;
190   }
191   // Then, we can specify the steelbar mesh data, starting by the
192   // number of meshes
193   int nbSteelBarMeshes=listSteelBarMesh.size();
194   line = std::string("nbSteelBarMeshes") + SEPARATOR + ToString(nbSteelBarMeshes);
195   dataFile << line.c_str() << std::endl;
196   for (int i=0; i<nbSteelBarMeshes; i++) {
197 #ifdef WIN32
198         char fname[ _MAX_FNAME ];
199         _splitpath( listSteelBarMesh[i].file_name, NULL, NULL, fname, NULL );
200         char* bname = &fname[0];
201 #else
202         char* bname = basename(listSteelBarMesh[i].file_name);
203 #endif
204     line = std::string(bname) + " " + std::string(listSteelBarMesh[i].group_name);
205     dataFile << line.c_str() << std::endl;
206   }
207   
208   // Finally, we conclude with the name of the output file
209   line = OUTPUTFILE;
210   dataFile << line.c_str() << std::endl;
211   dataFile.close();
212   return dataFilename->c_str();  
213 }
214
215 /*!
216  * This function creates a shell script that runs padder whith the
217  * specified data file, and returns the path of the created script
218  * file. The config id is used to retrieve the path to the binary file
219  * and other required files.
220  */
221 const char* MeshJobManager_i::_writeScriptFile(const char * dataFileName, const char * configId) {
222 #ifdef WIN32
223   _mkdir(LOCAL_INPUTDIR.c_str());
224 #else
225   mkdir(LOCAL_INPUTDIR.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
226 #endif
227
228   // Make it static so that it's allocated once (constant name)
229   static std::string * scriptFilename = new std::string(LOCAL_INPUTDIR+"/"+SCRIPTFILE);
230
231   char * binpath = _configMap[configId].binpath;
232   char * envpath = _configMap[configId].envpath;
233
234 #ifdef WIN32
235         char fname[ _MAX_FNAME ];
236         _splitpath( dataFileName, NULL, NULL, fname, NULL );
237         const char* bname = &fname[0];
238 #else
239         const char* bname = basename(dataFileName);
240 #endif
241
242
243   std::ofstream script(scriptFilename->c_str());
244   script << "#!/bin/sh"                                   << std::endl;
245   script << "here=$(dirname $0)"                          << std::endl;
246   script << ". " << envpath                               << std::endl;
247   script << binpath << " $here/" << bname                 << std::endl;
248   // Note that we use the basename of the datafile because all data
249   // files are supposed to have been copied in the REMOTE_WORKDIR.
250   script.close();
251   return scriptFilename->c_str();
252 }
253
254 //
255 // ====================================================================
256 // Functions to initialize and supervise the mesh computation job
257 // ====================================================================
258 //
259 bool MeshJobManager_i::configure(const char *configId,
260                                  const MESHJOB::ConfigParameter & configParameter)
261 {
262   beginService("MeshJobManager_i::configure");
263   
264   _configMap[configId] = configParameter;
265
266   LOG("Adding configuration for " << configId);
267   LOG("- binpath = " << _configMap[configId].binpath);
268   LOG("- envpath = " << _configMap[configId].envpath);
269
270   endService("MeshJobManager_i::configure");
271   return true;
272 }
273
274 long MeshJobManager_i::JOBID_UNDEFINED = -1;
275
276 /*! Initialize a smesh computation job and return the job identifier */
277 CORBA::Long MeshJobManager_i::initialize(const MESHJOB::MeshJobParameterList & meshJobParameterList,
278                                          const char * configId)
279 {
280   beginService("MeshJobManager_i::initialize");
281   //
282   // We first analyse the CORBA sequence to store data in C++ vectors
283   //
284   std::vector<MESHJOB::MeshJobParameter> listConcreteMesh;
285   std::vector<MESHJOB::MeshJobParameter> listSteelBarMesh;
286   for(CORBA::ULong i=0; i<meshJobParameterList.length(); i++) {
287     MESHJOB::MeshJobParameter currentMesh = meshJobParameterList[i];
288     switch ( currentMesh.file_type ) {
289     case MESHJOB::MED_CONCRETE:
290       listConcreteMesh.push_back(currentMesh);
291       break;
292     case MESHJOB::MED_STEELBAR:
293       listSteelBarMesh.push_back(currentMesh);
294       break;
295     default:
296       _lastErrorMessage =
297         std::string("The type of the file ")+
298         std::string(currentMesh.file_name)+
299         std::string(" is not recognized");
300       LOG(_lastErrorMessage);
301       return JOBID_UNDEFINED;
302     }
303   }
304   
305   // It is not possible to specify more than one concrete
306   // file. Converselly, it is possible to specify no concrete file.
307   if ( listConcreteMesh.size() > 1 ) {
308     // Not consistent with the specification
309     _lastErrorMessage = std::string("You specify more than one concrete mesh (not authorized)");
310     LOG(_lastErrorMessage);
311     return JOBID_UNDEFINED;
312   }
313   
314   LOG("Nb. concrete mesh = " << listConcreteMesh.size());
315   LOG("Nb. steelbar mesh = " << listSteelBarMesh.size());
316
317   // We initiate here a datetime to tag the files and folder
318   // associated to this job.
319 #ifdef WIN32
320   DWORD jobDatetimeTag = timeGetTime();
321 #else
322   long jobDatetimeTag = timetag();
323 #endif
324   // And a MESHJOB::MeshJobPaths structure to hold the directories
325   // where to find data
326   MESHJOB::MeshJobPaths * jobPaths = new MESHJOB::MeshJobPaths();
327   jobPaths->local_inputdir  = LOCAL_INPUTDIR.c_str();
328   jobPaths->local_resultdir = (LOCAL_RESULTDIR + "." + ToString(jobDatetimeTag)).c_str();
329   jobPaths->remote_workdir  = (REMOTE_WORKDIR + "." + ToString(jobDatetimeTag)).c_str();  
330
331   //
332   // Then, we have to create the padder input data file. This input
333   // data is a text file containing the list of file names and group
334   // names.
335   //
336   const char * dataFilename = this->_writeDataFile(listConcreteMesh, listSteelBarMesh);
337   LOG("dataFilename = " << dataFilename);
338   const char * scriptFilename = this->_writeScriptFile(dataFilename, configId);
339   LOG("scriptFilename = " << scriptFilename);
340
341   //
342   // Then, the following instructions consists in preparing the job
343   // parameters to request the SALOME launcher for creating a new
344   // job.
345   //
346   Engines::JobParameters_var jobParameters = new Engines::JobParameters;
347   jobParameters->job_type = CORBA::string_dup("command");
348   // CAUTION: the job_file must be a single filename specifying a
349   // self-consistent script to be executed without any argument on the
350   // remote host.
351   jobParameters->job_file = CORBA::string_dup(scriptFilename);
352
353   //
354   // Specification of the working spaces:
355   //
356   // - local_directory: can be used to specify where to find the input
357   //   files on the local resource. It's optionnal if you specify the
358   //   absolute path name of input files.
359   //
360   // - result_directory: must be used to specify where to download the
361   //   output files on the local resources
362   //
363   // - work_directory: must be used to specify the remote directory
364   //   where to put all the stuff to run the job. Note that the job
365   //   will be executed from within this directory, i.e. a change
366   //   directory toward this working directory is done by the batch
367   //   system before running the specified job script.
368   //
369   jobParameters->local_directory  = CORBA::string_dup("");
370   jobParameters->result_directory = CORBA::string_dup(jobPaths->local_resultdir);
371   jobParameters->work_directory   = CORBA::string_dup(jobPaths->remote_workdir);
372
373   // We specify the input files that are required to execute the
374   // job_file. If basenames are specified, then the files are supposed
375   // to be located in local_directory.
376   int nbcmesh = listConcreteMesh.size();
377   int nbsmesh = listSteelBarMesh.size();
378   int nbFiles = nbsmesh+nbcmesh+1;
379   // The number of input file is: 
380   //   (nb. of steelbar meshfile)
381   // + (1 or 0 concrete meshfile)
382   // + (1 padder input file)
383   jobParameters->in_files.length(nbFiles);
384   for (int i=0; i<nbcmesh; i++) {
385     jobParameters->in_files[i] = CORBA::string_dup(listConcreteMesh[i].file_name);
386   }
387   for (int i=0; i<nbsmesh; i++) {
388     jobParameters->in_files[nbcmesh+i] = CORBA::string_dup(listSteelBarMesh[i].file_name);
389   }
390   jobParameters->in_files[nbcmesh+nbsmesh] = CORBA::string_dup(dataFilename);
391   // Note that all these input files will be copied in the
392   // REMOTE_WORKDIR on the remote host. At this step, they should
393   // all exist, so we can check their presence on the local
394   // filesystem.
395   for (int i=0; i<nbFiles; i++) {
396     if ( fexists(jobParameters->in_files[i]) != true ) {
397       _lastErrorMessage = std::string("The input file ") + std::string(jobParameters->in_files[i]);
398       _lastErrorMessage+= std::string(" does not exists. Can't initialize the job");
399       LOG(_lastErrorMessage);
400       return JOBID_UNDEFINED;      
401     }
402   }
403
404   // Then, we have to specify the existance of an output filename. The
405   // path is supposed to be a path on the remote resource, i.e. where
406   // the job is executed.
407   jobParameters->out_files.length(1);
408   std::string outputfile_name = std::string(jobPaths->remote_workdir)+"/"+OUTPUTFILE;
409   jobParameters->out_files[0] = CORBA::string_dup(outputfile_name.c_str());
410
411   // CAUTION: the maximum duration has to be set with a format like "hh:mm"
412   jobParameters->maximum_duration = CORBA::string_dup("01:00");
413   jobParameters->queue = CORBA::string_dup("");
414
415   // Setting resource and additionnal properties (if needed)
416   // The resource parameters can be initiated from scratch, for
417   // example by specifying the values in hard coding:
418   // >>>
419   //jobParameters->resource_required.name = CORBA::string_dup("localhost");
420   //jobParameters->resource_required.hostname = CORBA::string_dup("localhost");
421   //jobParameters->resource_required.mem_mb = 1024 * 10;
422   //jobParameters->resource_required.nb_proc = 1;
423   // <<<
424   // But it's better to initiate these parameters from a resource
425   // definition known by the resource manager. This ensures that the
426   // resource will be available:
427   //const char * resourceName = "localhost";
428   //const char * resourceName = "boulant@claui2p1";
429   //const char * resourceName = "nepal@nepal";
430   const char * resourceName = _configMap[configId].resname;
431   
432   Engines::ResourceDefinition * resourceDefinition;
433   try {
434     resourceDefinition = _resourcesManager->GetResourceDefinition(resourceName);
435   }
436   catch (const CORBA::SystemException& ex) {
437     _lastErrorMessage = std::string("We can not access to the ressource ") + std::string(resourceName);
438     _lastErrorMessage+= std::string("(check the file CatalogResource.xml)");
439     LOG(_lastErrorMessage);
440     return JOBID_UNDEFINED;
441   }
442   // CAUTION: This resource should have been defined in the
443   // CatalogResource.xml associated to the SALOME application.
444   //
445   // Then, the values can be used to initiate the resource parameters
446   // of the job:
447   jobParameters->resource_required.name     = CORBA::string_dup(resourceDefinition->name.in());
448   // CAUTION: the additionnal two following parameters MUST be
449   // specified explicitly, because they are not provided by the
450   // resource definition:
451   jobParameters->resource_required.mem_mb   = resourceDefinition->mem_mb;
452   jobParameters->resource_required.nb_proc  = resourceDefinition->nb_proc_per_node;
453   // CAUTION: the parameter mem_mb specifies the maximum memory value
454   // that could be allocated for executing the job. This takes into
455   // account not only the data that could be loaded by the batch
456   // process but also the linked dynamic library.
457   //
458   // A possible problem, for exemple in the case where you use the ssh
459   // emulation of a batch system, is to get an error message as below
460   // when libBatch try to run the ssh command:
461   //
462   // ## /usr/bin/ssh: error while loading shared libraries: libcrypto.so.0.9.8: failed
463   // ## to map segment from shared object: Cannot allocate memory
464   //
465   // In this exemple, the mem_mb was set to 1MB, value that is not
466   // sufficient to load the dynamic libraries linked to the ssh
467   // executable (libcrypto.so in the error message).
468   //
469   // So, even in the case of a simple test shell script, you should
470   // set this value at least to a standard threshold as 500MB
471   int jobId = JOBID_UNDEFINED;
472   try {
473     jobId = _salomeLauncher->createJob(jobParameters);
474     // We register the datetime tag of this job
475     _jobDateTimeMap[jobId]=jobDatetimeTag;
476     _jobPathsMap[jobId] = jobPaths;
477   }
478   catch (const SALOME::SALOME_Exception & ex) {
479     LOG("SALOME Exception at initialization step !" <<ex.details.text.in());
480     _lastErrorMessage = ex.details.text.in();
481     return JOBID_UNDEFINED;
482   }
483   catch (const CORBA::SystemException& ex) {
484     LOG("Receive SALOME System Exception: "<<ex);
485     LOG("Check SALOME servers...");
486     _lastErrorMessage = "Check the SALOME servers (or try to restart SALOME)";
487     return JOBID_UNDEFINED;
488   }
489   
490   endService("MeshJobManager_i::initialize");
491   return jobId;
492 }
493
494 /*! Submit the job execution and return true if submission is OK */
495 bool MeshJobManager_i::start(CORBA::Long jobId) {
496   beginService("MeshJobManager_i::start");
497
498   try {
499     _salomeLauncher->launchJob(jobId);
500   }
501   catch (const SALOME::SALOME_Exception & ex) {
502     LOG("SALOME Exception in launchjob !" <<ex.details.text.in());
503     _lastErrorMessage = ex.details.text.in();
504     return false;
505   }
506   catch (const CORBA::SystemException& ex) {
507     LOG("Receive SALOME System Exception: "<<ex);
508     LOG("Check SALOME servers...");
509     _lastErrorMessage = "Check the SALOME servers (or try to restart SALOME)";
510     return false;
511   }
512
513   endService("MeshJobManager_i::initialize");
514   return true;
515 }
516
517 /*! Request the launch manager for the state of the specified job */
518 char* MeshJobManager_i::getState(CORBA::Long jobId) {
519   beginService("MeshJobManager_i::getState");
520
521   std::string state;
522   try
523   {
524     state = _salomeLauncher->getJobState(jobId);
525   }
526   catch (const SALOME::SALOME_Exception & ex)
527   {
528     LOG("SALOME Exception in getJobState !");
529     _lastErrorMessage = ex.details.text.in();
530     state = ex.details.text;
531   }
532   catch (const CORBA::SystemException& ex)
533   {
534     LOG("Receive SALOME System Exception: " << ex);
535     state="SALOME System Exception - see logs";
536   }
537   LOG("jobId="<<ToString(jobId)<<" state="<<state);
538   endService("MeshJobManager_i::getState");
539   return CORBA::string_dup(state.c_str());
540 }
541
542 MESHJOB::MeshJobPaths * MeshJobManager_i::getPaths(CORBA::Long jobId) {
543
544   MESHJOB::MeshJobPaths * jobPaths = _jobPathsMap[jobId];
545   if ( jobPaths == NULL ) {
546     LOG("You request the working paths for an undefined job (jobId="<<ToString(jobId)<<")");
547     return NULL; // Maybe raise an exception?
548   }
549   return jobPaths;
550 }
551
552
553 MESHJOB::MeshJobResults * MeshJobManager_i::finalize(CORBA::Long jobId) {
554   beginService("MeshJobManager_i::getResults");
555   MESHJOB::MeshJobResults * result = new MESHJOB::MeshJobResults();
556
557   MESHJOB::MeshJobPaths * jobPaths = this->getPaths(jobId);
558   std::string local_resultdir(jobPaths->local_resultdir);
559   result->results_dirname = local_resultdir.c_str();  
560   try
561   {
562     _salomeLauncher->getJobResults(jobId, local_resultdir.c_str());
563  
564     // __BUG__: to prevent from a bug of the MED driver (SALOME
565     // 5.1.5), we change the basename of the output file to force the
566     // complete reloading of data by the med driver.
567     long jobDatetimeTag = _jobDateTimeMap[jobId];
568     std::string outputFileName = "output"+ToString(jobDatetimeTag)+".med";
569     rename((local_resultdir+"/"+OUTPUTFILE).c_str(), (local_resultdir+"/"+outputFileName).c_str());
570
571     result->outputmesh_filename = outputFileName.c_str();
572     
573     if ( fexists( (local_resultdir+"/"+outputFileName).c_str()  ) != true ) {
574       _lastErrorMessage = std::string("The result file ")+
575         std::string((local_resultdir+"/"+outputFileName).c_str())+
576         std::string(" has not been created.");
577       result->status = false;
578     }
579     else {
580       result->status = true;
581     }
582  }
583   catch (const SALOME::SALOME_Exception & ex)
584   {
585     _lastErrorMessage = ex.details.text.in();
586     LOG(_lastErrorMessage);
587     result->status = false;
588   }
589   catch (const CORBA::SystemException& ex)
590   {
591     _lastErrorMessage = "The SALOME launcher can not retrieve the result data";
592     LOG(_lastErrorMessage);
593     result->status = false;
594   }
595   endService("MeshJobManager_i::getResults");
596   return result;
597 }
598
599
600 /*! Clean all data associated to this job and remove the job from the launch manager */
601 bool MeshJobManager_i::clean(CORBA::Long jobId) {
602   beginService("MeshJobManager_i::clean");
603   
604   // __GBO__ WORK IN PROGRESS: we just clean the temporary local
605   // directories. The remote working directories are tag with the
606   // execution datetime and the we prevent the task from conflict
607   // with files of another task.
608   MESHJOB::MeshJobPaths * jobPaths = this->getPaths(jobId);
609   if ( jobPaths == NULL ) return false;
610
611   // WARN: !!!!!
612   // For safety reason (and prevent from bug that could erase the
613   // filesystem), we cancel the operation in the case where the
614   // directories to delete are not in the /tmp folder.
615   std::string shell_command("rm -rf ");
616   std::string inputdir(jobPaths->local_inputdir);
617   std::string resultdir(jobPaths->local_resultdir);
618   if ( !myStartsWith(inputdir,"/tmp/") )  {
619     LOG("WRN: The directory "<<inputdir<<" is not in /tmp. NO DELETE is done");
620   } else {
621     shell_command+=inputdir+" ";
622   }
623   if ( !myStartsWith(resultdir,"/tmp/"))  {
624     LOG("WRN: The directory "<<resultdir<<" is not in /tmp. NO DELETE is done");
625   } else {
626     shell_command+=resultdir;
627   }
628
629   LOG("DBG: clean shell command = "<<shell_command);
630
631   bool cleanOk = false;
632   int error = system(shell_command.c_str());
633   if (error == 0) cleanOk = true;
634
635   endService("MeshJobManager_i::clean");
636   return cleanOk;
637 }
638
639
640 std::vector<std::string> * MeshJobManager_i::_getResourceNames() {
641
642   //
643   // These part is just to control the available resources
644   //
645   Engines::ResourceParameters params;
646   KERNEL::getLifeCycleCORBA()->preSet(params);
647
648   Engines::ResourceList * resourceList = _resourcesManager->GetFittingResources(params);
649   Engines::ResourceDefinition * resourceDefinition = NULL;
650   LOG("### resource list:");
651   std::vector<std::string>* resourceNames = new std::vector<std::string>();
652   if (resourceList) {
653     for (int i = 0; i < resourceList->length(); i++) {
654       const char* aResourceName = (*resourceList)[i];
655       resourceNames->push_back(std::string(aResourceName));
656       LOG("resource["<<i<<"] = "<<aResourceName);
657       resourceDefinition = _resourcesManager->GetResourceDefinition(aResourceName);
658       LOG("protocol["<<i<<"] = "<<resourceDefinition->protocol);
659     }
660   }
661
662   // Note: a ResourceDefinition is used to create a batch configuration
663   // in the Launcher. This operation is done at Launcher startup from
664   // the configuration file CatalogResources.xml provided by the
665   // SALOME application.
666   // In the code instructions, you just have to choose a resource
667   // configuration by its name and then define the ResourceParameters
668   // that specify additionnal properties for a specific job submission
669   // (use the attribute resource_required of the JobParameters).
670
671   return resourceNames;
672 }
673
674 char* MeshJobManager_i::getLastErrorMessage() {
675   beginService("MeshJobManager_i::getState");
676   endService("MeshJobManager_i::getState");
677   return CORBA::string_dup(_lastErrorMessage.c_str());
678 }
679
680 //
681 // ==========================================================================
682 // Factory services
683 // ==========================================================================
684 //
685 extern "C"
686 {
687   PortableServer::ObjectId * MeshJobManagerEngine_factory( CORBA::ORB_ptr orb,
688                                                            PortableServer::POA_ptr poa,
689                                                            PortableServer::ObjectId * contId,
690                                                            const char *instanceName,
691                                                            const char *interfaceName)
692   {
693     LOG("PortableServer::ObjectId * MeshJobManagerEngine_factory()");
694     MeshJobManager_i * myEngine = new MeshJobManager_i(orb, poa, contId, instanceName, interfaceName);
695     return myEngine->getId() ;
696   }
697 }