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