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