Salome HOME
#18963 Minimize compiler warnings
[modules/smesh.git] / src / Tools / padder / meshjob / impl / MeshJobManager_i.cxx
index 72520fbabf811486d528ea35cb196834f4779948..5eee6858e4a47e14be97a7846161840c773b57c2 100644 (file)
@@ -1,9 +1,9 @@
-// Copyright (C) 2011-2012  EDF R&D
+// Copyright (C) 2011-2020  EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,6 +16,7 @@
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+
 // Authors : Guillaume Boulant (EDF) - 01/03/2011
 
 #ifdef WIN32
@@ -67,6 +68,21 @@ static bool myStartsWith(const std::string& text,const std::string& token){
   return (text.compare(0, token.length(), token) == 0);
 }
 
+/*!
+ * This function returns true if the file exists on the local file
+ * system.
+ */
+#include <iostream>
+#include <fstream>
+static bool fexists(const char *filename)
+{
+  std::ifstream ifile(filename);
+  if ((bool)ifile && ifile.good()) {
+    return true;
+  }
+  return false;
+}
+
 //
 // ====================================================================
 // Constructor/Destructor
@@ -94,6 +110,8 @@ MeshJobManager_i::MeshJobManager_i(CORBA::ORB_ptr orb,
     LOG("The SALOME resource manager can't be reached ==> STOP");
     throw KERNEL::createSalomeException("The SALOME resource manager can't be reached");
   }
+
+  _lastErrorMessage = "";
 }
 
 MeshJobManager_i::~MeshJobManager_i() {
@@ -106,11 +124,12 @@ MeshJobManager_i::~MeshJobManager_i() {
 // ====================================================================
 //
 #include <fstream>     // to get the file streams
-#ifdef WNT             
+#ifdef WIN32
 #include <stdlib.h>    // to get _splitpath
 #include <direct.h>    // to get _mkdir
 #else
 #include <unistd.h>    // to get basename
+#include <libgen.h>    // to get basename - as per posix
 #include <sys/stat.h>  // to get mkdir
 #include <sys/types.h> // to get mkdir options
 #endif
@@ -122,7 +141,12 @@ static std::string DATAFILE("data.txt");
 static std::string SCRIPTFILE("padder.sh");
 static std::string SEPARATOR(" ");
 
+#ifdef WIN32
+static std::string USER(getenv("USERNAME"));
+#else
 static std::string USER(getenv("USER"));
+#endif
+
 static std::string LOCAL_INPUTDIR("/tmp/spadder.local.inputdir."+USER);
 static std::string LOCAL_RESULTDIR("/tmp/spadder.local.resultdir."+USER);
 static std::string REMOTE_WORKDIR("/tmp/spadder.remote.workdir."+USER);
@@ -132,10 +156,20 @@ static std::string REMOTE_WORKDIR("/tmp/spadder.remote.workdir."+USER);
  * input data (list of filenames and groupnames) and returns the path
  * of the created file. This function is the one that knows the format
  * of the padder input file. If the input file format changes, then
- * this function (and only this one) should be updated.
+ * this function (and only this one) should be updated. The file
+ * format is the following ([] means that the variable is optional):
+ *
+ * [<concreteMeshFile>   <concreteGroupName>]
+ * nbSteelBarMeshes <N>
+ * <steelBarMeshFile_1>   <steelBarGroupName_1>
+ * <steelBarMeshFile_2>   <steelBarGroupName_2>
+ * ...
+ * <steelBarMeshFile_N>   <steelBarGroupName_N>
+ * <outputMedFile>
  */
-const char * MeshJobManager_i::_writeDataFile(std::vector<MESHJOB::MeshJobParameter> listConcreteMesh,
-                                              std::vector<MESHJOB::MeshJobParameter> listSteelBarMesh) {
+const char * MeshJobManager_i::_writeDataFile(std::vector<MESHJOB::MeshJobFile> listConcreteMesh,
+                                              std::vector<MESHJOB::MeshJobFile> listSteelBarMesh,
+                                              const MESHJOB::MeshJobParameterList & meshJobParameterList) {
 #ifdef WIN32
   _mkdir(LOCAL_INPUTDIR.c_str());
 #else
@@ -145,27 +179,29 @@ const char * MeshJobManager_i::_writeDataFile(std::vector<MESHJOB::MeshJobParame
   // Make it static so that it's allocated once (constant name)
   static std::string * dataFilename = new std::string(LOCAL_INPUTDIR+"/"+DATAFILE);
   std::ofstream dataFile(dataFilename->c_str());
-  
-  // We first specify the concrete mesh data (filename and groupname)
+
+  // Note that we use here the basename of the files because the files
+  // are supposed to be copied in the REMOTE_WORKDIR for execution.
   std::string line;
+
+  // We first specify the concrete mesh data (filename and groupname)
+  if ( listConcreteMesh.size() > 0 ) {
 #ifdef WIN32
-  char fname[ _MAX_FNAME ];
-  _splitpath( listConcreteMesh[0].file_name, NULL, NULL, fname, NULL );
-  char* bname = &fname[0];
+    char fname[ _MAX_FNAME ];
+    _splitpath( listConcreteMesh[0].file_name, NULL, NULL, fname, NULL );
+    char* bname = &fname[0];
 #else
-  char* bname = basename(listConcreteMesh[0].file_name);
+    char* bname = basename(listConcreteMesh[0].file_name);
 #endif
-  line = std::string(bname) + " " + std::string(listConcreteMesh[0].group_name);
-  dataFile << line.c_str() << std::endl;
-  // Note that we use here the basename because the files are supposed
-  // to be copied in the REMOTE_WORKDIR for execution.
-  
-  // The, we can specify the steelbar mesh data, starting by the
+    line = std::string(bname) + " " + std::string(listConcreteMesh[0].group_name);
+    dataFile << line.c_str() << std::endl;
+  }
+  // Then, we can specify the steelbar mesh data, starting by the
   // number of meshes
-  int nbSteelBarMesh=listSteelBarMesh.size();
-  line = std::string("nbSteelbarMesh") + SEPARATOR + ToString(nbSteelBarMesh);
+  int nbSteelBarMeshes=listSteelBarMesh.size();
+  line = std::string("nbSteelBarMeshes") + SEPARATOR + ToString(nbSteelBarMeshes);
   dataFile << line.c_str() << std::endl;
-  for (int i=0; i<nbSteelBarMesh; i++) {
+  for (int i=0; i<nbSteelBarMeshes; i++) {
 #ifdef WIN32
         char fname[ _MAX_FNAME ];
         _splitpath( listSteelBarMesh[i].file_name, NULL, NULL, fname, NULL );
@@ -177,15 +213,23 @@ const char * MeshJobManager_i::_writeDataFile(std::vector<MESHJOB::MeshJobParame
     dataFile << line.c_str() << std::endl;
   }
   
-  // Finally, we conclude with the name of the output file
+  // We conclude the list of files with the name of the output file
   line = OUTPUTFILE;
   dataFile << line.c_str() << std::endl;
+
+  // We put the numerical parameters at the end of the data file
+  for(CORBA::ULong i=0; i<meshJobParameterList.length(); i++) {
+    MESHJOB::MeshJobParameter param = meshJobParameterList[i];
+    line = std::string(param.name) + " " + std::string(param.value);
+    dataFile << line.c_str() << std::endl;
+  }
+
   dataFile.close();
   return dataFilename->c_str();  
 }
 
 /*!
- * This function creates a shell script that runs padder whith the
+ * This function creates a shell script that runs padder with the
  * specified data file, and returns the path of the created script
  * file. The config id is used to retrieve the path to the binary file
  * and other required files.
@@ -208,7 +252,7 @@ const char* MeshJobManager_i::_writeScriptFile(const char * dataFileName, const
         _splitpath( dataFileName, NULL, NULL, fname, NULL );
         const char* bname = &fname[0];
 #else
-        const char* bname = basename(dataFileName);
+        const char* bname = basename(const_cast<char *>(dataFileName));
 #endif
 
 
@@ -246,20 +290,18 @@ bool MeshJobManager_i::configure(const char *configId,
 long MeshJobManager_i::JOBID_UNDEFINED = -1;
 
 /*! Initialize a smesh computation job and return the job identifier */
-CORBA::Long MeshJobManager_i::initialize(const MESHJOB::MeshJobParameterList & meshJobParameterList,
+CORBA::Long MeshJobManager_i::initialize(const MESHJOB::MeshJobFileList & meshJobFileList,
+                                         const MESHJOB::MeshJobParameterList & meshJobParameterList,
                                          const char * configId)
 {
   beginService("MeshJobManager_i::initialize");
-  std::cerr << "##################################### initialize" << std::endl;
-  std::cerr << "#####################################" << std::endl;
-
   //
   // We first analyse the CORBA sequence to store data in C++ vectors
   //
-  std::vector<MESHJOB::MeshJobParameter> listConcreteMesh;
-  std::vector<MESHJOB::MeshJobParameter> listSteelBarMesh;
-  for(CORBA::ULong i=0; i<meshJobParameterList.length(); i++) {
-    MESHJOB::MeshJobParameter currentMesh = meshJobParameterList[i];
+  std::vector<MESHJOB::MeshJobFile> listConcreteMesh;
+  std::vector<MESHJOB::MeshJobFile> listSteelBarMesh;
+  for(CORBA::ULong i=0; i<meshJobFileList.length(); i++) {
+    MESHJOB::MeshJobFile currentMesh = meshJobFileList[i];
     switch ( currentMesh.file_type ) {
     case MESHJOB::MED_CONCRETE:
       listConcreteMesh.push_back(currentMesh);
@@ -268,14 +310,21 @@ CORBA::Long MeshJobManager_i::initialize(const MESHJOB::MeshJobParameterList & m
       listSteelBarMesh.push_back(currentMesh);
       break;
     default:
-      LOG("The type of the file is not recognized");
+      _lastErrorMessage =
+        std::string("The type of the file ")+
+        std::string(currentMesh.file_name)+
+        std::string(" is not recognized");
+      LOG(_lastErrorMessage);
       return JOBID_UNDEFINED;
     }
   }
   
-  if ( listConcreteMesh.size() != 1 ) {
+  // It is not possible to specify more than one concrete
+  // file. Converselly, it is possible to specify no concrete file.
+  if ( listConcreteMesh.size() > 1 ) {
     // Not consistent with the specification
-    LOG("You specify more than one concrete mesh");
+    _lastErrorMessage = std::string("You specify more than one concrete mesh (not authorized)");
+    LOG(_lastErrorMessage);
     return JOBID_UNDEFINED;
   }
   
@@ -301,7 +350,7 @@ CORBA::Long MeshJobManager_i::initialize(const MESHJOB::MeshJobParameterList & m
   // data is a text file containing the list of file names and group
   // names.
   //
-  const char * dataFilename = this->_writeDataFile(listConcreteMesh, listSteelBarMesh);
+  const char * dataFilename = this->_writeDataFile(listConcreteMesh, listSteelBarMesh, meshJobParameterList);
   LOG("dataFilename = " << dataFilename);
   const char * scriptFilename = this->_writeScriptFile(dataFilename, configId);
   LOG("scriptFilename = " << scriptFilename);
@@ -322,7 +371,7 @@ CORBA::Long MeshJobManager_i::initialize(const MESHJOB::MeshJobParameterList & m
   // Specification of the working spaces:
   //
   // - local_directory: can be used to specify where to find the input
-  //   files on the local resource. It's optionnal if you specify the
+  //   files on the local resource. It's optional if you specify the
   //   absolute path name of input files.
   //
   // - result_directory: must be used to specify where to download the
@@ -341,33 +390,46 @@ CORBA::Long MeshJobManager_i::initialize(const MESHJOB::MeshJobParameterList & m
   // We specify the input files that are required to execute the
   // job_file. If basenames are specified, then the files are supposed
   // to be located in local_directory.
-  int nbFiles = listSteelBarMesh.size()+2;
+  int nbcmesh = listConcreteMesh.size();
+  int nbsmesh = listSteelBarMesh.size();
+  int nbFiles = nbsmesh+nbcmesh+1;
   // The number of input file is: 
   //   (nb. of steelbar meshfile)
-  // + (1 concrete meshfile)
+  // + (1 or 0 concrete meshfile)
   // + (1 padder input file)
-  // = nb steelbar meshfile + 2
   jobParameters->in_files.length(nbFiles);
-  jobParameters->in_files[0] = CORBA::string_dup(listConcreteMesh[0].file_name);
-  for (int i=0; i<listSteelBarMesh.size(); i++) {
-    jobParameters->in_files[1+i] = CORBA::string_dup(listSteelBarMesh[i].file_name);
+  for (int i=0; i<nbcmesh; i++) {
+    jobParameters->in_files[i] = CORBA::string_dup(listConcreteMesh[i].file_name);
   }
-  jobParameters->in_files[1+listSteelBarMesh.size()] = CORBA::string_dup(dataFilename);
+  for (int i=0; i<nbsmesh; i++) {
+    jobParameters->in_files[nbcmesh+i] = CORBA::string_dup(listSteelBarMesh[i].file_name);
+  }
+  jobParameters->in_files[nbcmesh+nbsmesh] = CORBA::string_dup(dataFilename);
   // Note that all these input files will be copied in the
-  // REMOTE_WORKDIR on the remote host
-  
-  // Then, we have to specify the existance of an output
-  // filenames. The path is supposed to be a path on the remote
-  // resource, i.e. where the job is executed.
+  // REMOTE_WORKDIR on the remote host. At this step, they should
+  // all exist, so we can check their presence on the local
+  // filesystem.
+  for (int i=0; i<nbFiles; i++) {
+    if ( fexists(jobParameters->in_files[i]) != true ) {
+      _lastErrorMessage = std::string("The input file ") + std::string(jobParameters->in_files[i]);
+      _lastErrorMessage+= std::string(" does not exists. Can't initialize the job");
+      LOG(_lastErrorMessage);
+      return JOBID_UNDEFINED;      
+    }
+  }
+
+  // Then, we have to specify the existence of an output filename. The
+  // path is supposed to be a path on the remote resource, i.e. where
+  // the job is executed.
   jobParameters->out_files.length(1);
   std::string outputfile_name = std::string(jobPaths->remote_workdir)+"/"+OUTPUTFILE;
   jobParameters->out_files[0] = CORBA::string_dup(outputfile_name.c_str());
 
   // CAUTION: the maximum duration has to be set with a format like "hh:mm"
-  jobParameters->maximum_duration = CORBA::string_dup("01:00");
+  //jobParameters->maximum_duration = CORBA::string_dup("01:00");
   jobParameters->queue = CORBA::string_dup("");
 
-  // Setting resource and additionnal properties (if needed)
+  // Setting resource and additional properties (if needed)
   // The resource parameters can be initiated from scratch, for
   // example by specifying the values in hard coding:
   // >>>
@@ -383,14 +445,24 @@ CORBA::Long MeshJobManager_i::initialize(const MESHJOB::MeshJobParameterList & m
   //const char * resourceName = "boulant@claui2p1";
   //const char * resourceName = "nepal@nepal";
   const char * resourceName = _configMap[configId].resname;
-  Engines::ResourceDefinition * resourceDefinition = _resourcesManager->GetResourceDefinition(resourceName);
+  
+  Engines::ResourceDefinition * resourceDefinition;
+  try {
+    resourceDefinition = _resourcesManager->GetResourceDefinition(resourceName);
+  }
+  catch (const CORBA::SystemException& ex) {
+    _lastErrorMessage = std::string("We can not access the resource ") + std::string(resourceName);
+    _lastErrorMessage+= std::string("(check the file CatalogResource.xml)");
+    LOG(_lastErrorMessage);
+    return JOBID_UNDEFINED;
+  }
   // CAUTION: This resource should have been defined in the
   // CatalogResource.xml associated to the SALOME application.
   //
   // Then, the values can be used to initiate the resource parameters
   // of the job:
   jobParameters->resource_required.name     = CORBA::string_dup(resourceDefinition->name.in());
-  // CAUTION: the additionnal two following parameters MUST be
+  // CAUTION: the additional two following parameters MUST be
   // specified explicitly, because they are not provided by the
   // resource definition:
   jobParameters->resource_required.mem_mb   = resourceDefinition->mem_mb;
@@ -400,42 +472,35 @@ CORBA::Long MeshJobManager_i::initialize(const MESHJOB::MeshJobParameterList & m
   // account not only the data that could be loaded by the batch
   // process but also the linked dynamic library.
   //
-  // A possible problem, for exemple in the case where you use the ssh
+  // A possible problem, for example in the case where you use the ssh
   // emulation of a batch system, is to get an error message as below
   // when libBatch try to run the ssh command:
   //
   // ## /usr/bin/ssh: error while loading shared libraries: libcrypto.so.0.9.8: failed
   // ## to map segment from shared object: Cannot allocate memory
   //
-  // In this exemple, the mem_mb was set to 1MB, value that is not
+  // In this example, the mem_mb was set to 1MB, value that is not
   // sufficient to load the dynamic libraries linked to the ssh
   // executable (libcrypto.so in the error message).
   //
   // So, even in the case of a simple test shell script, you should
   // set this value at least to a standard threshold as 500MB
-
   int jobId = JOBID_UNDEFINED;
   try {
-    std::cerr << "#####################################" << std::endl;
-    std::cerr << "#####################################" << std::endl;
-    std::cerr << "jobUndef = " << JOBID_UNDEFINED << std::endl;
     jobId = _salomeLauncher->createJob(jobParameters);
-    std::cerr << "#####################################" << std::endl;
-    std::cerr << "#####################################" << std::endl;
-    std::cerr << "#####################################" << std::endl;
-    std::cerr << "jobId = " << jobId << std::endl;
     // We register the datetime tag of this job
     _jobDateTimeMap[jobId]=jobDatetimeTag;
     _jobPathsMap[jobId] = jobPaths;
   }
   catch (const SALOME::SALOME_Exception & ex) {
-    LOG("SALOME Exception in createJob !" <<ex.details.text.in());
-    //LOG(ex.details.text.in());
+    LOG("SALOME Exception at initialization step !" <<ex.details.text.in());
+    _lastErrorMessage = ex.details.text.in();
     return JOBID_UNDEFINED;
   }
   catch (const CORBA::SystemException& ex) {
     LOG("Receive SALOME System Exception: "<<ex);
     LOG("Check SALOME servers...");
+    _lastErrorMessage = "Check the SALOME servers (or try to restart SALOME)";
     return JOBID_UNDEFINED;
   }
   
@@ -452,12 +517,13 @@ bool MeshJobManager_i::start(CORBA::Long jobId) {
   }
   catch (const SALOME::SALOME_Exception & ex) {
     LOG("SALOME Exception in launchjob !" <<ex.details.text.in());
-    //LOG(ex.details.text.in());
+    _lastErrorMessage = ex.details.text.in();
     return false;
   }
   catch (const CORBA::SystemException& ex) {
     LOG("Receive SALOME System Exception: "<<ex);
     LOG("Check SALOME servers...");
+    _lastErrorMessage = "Check the SALOME servers (or try to restart SALOME)";
     return false;
   }
 
@@ -477,6 +543,7 @@ char* MeshJobManager_i::getState(CORBA::Long jobId) {
   catch (const SALOME::SALOME_Exception & ex)
   {
     LOG("SALOME Exception in getJobState !");
+    _lastErrorMessage = ex.details.text.in();
     state = ex.details.text;
   }
   catch (const CORBA::SystemException& ex)
@@ -519,17 +586,28 @@ MESHJOB::MeshJobResults * MeshJobManager_i::finalize(CORBA::Long jobId) {
     rename((local_resultdir+"/"+OUTPUTFILE).c_str(), (local_resultdir+"/"+outputFileName).c_str());
 
     result->outputmesh_filename = outputFileName.c_str();
-    result->status = "OK";
+    
+    if ( fexists( (local_resultdir+"/"+outputFileName).c_str()  ) != true ) {
+      _lastErrorMessage = std::string("The result file ")+
+        std::string((local_resultdir+"/"+outputFileName).c_str())+
+        std::string(" has not been created.");
+      result->status = false;
+    }
+    else {
+      result->status = true;
+    }
  }
   catch (const SALOME::SALOME_Exception & ex)
   {
-    LOG("SALOME Exception in getResults !");
-    result->status = "SALOME Exception in getResults !";
+    _lastErrorMessage = ex.details.text.in();
+    LOG(_lastErrorMessage);
+    result->status = false;
   }
   catch (const CORBA::SystemException& ex)
   {
-    LOG("Receive CORBA System Exception: " << ex);
-    result->status = "Receive CORBA System Exception: see log";
+    _lastErrorMessage = "The SALOME launcher can not retrieve the result data";
+    LOG(_lastErrorMessage);
+    result->status = false;
   }
   endService("MeshJobManager_i::getResults");
   return result;
@@ -589,12 +667,13 @@ std::vector<std::string> * MeshJobManager_i::_getResourceNames() {
   LOG("### resource list:");
   std::vector<std::string>* resourceNames = new std::vector<std::string>();
   if (resourceList) {
-    for (int i = 0; i < resourceList->length(); i++) {
+    for ( size_t i = 0; i < resourceList->length(); i++) {
       const char* aResourceName = (*resourceList)[i];
       resourceNames->push_back(std::string(aResourceName));
       LOG("resource["<<i<<"] = "<<aResourceName);
       resourceDefinition = _resourcesManager->GetResourceDefinition(aResourceName);
       LOG("protocol["<<i<<"] = "<<resourceDefinition->protocol);
+      (void)resourceDefinition; // unused in release mode
     }
   }
 
@@ -604,12 +683,17 @@ std::vector<std::string> * MeshJobManager_i::_getResourceNames() {
   // SALOME application.
   // In the code instructions, you just have to choose a resource
   // configuration by its name and then define the ResourceParameters
-  // that specify additionnal properties for a specific job submission
+  // that specify additional properties for a specific job submission
   // (use the attribute resource_required of the JobParameters).
 
   return resourceNames;
 }
 
+char* MeshJobManager_i::getLastErrorMessage() {
+  beginService("MeshJobManager_i::getState");
+  endService("MeshJobManager_i::getState");
+  return CORBA::string_dup(_lastErrorMessage.c_str());
+}
 
 //
 // ==========================================================================
@@ -618,6 +702,7 @@ std::vector<std::string> * MeshJobManager_i::_getResourceNames() {
 //
 extern "C"
 {
+  MESHJOBMANAGERENGINE_EXPORT
   PortableServer::ObjectId * MeshJobManagerEngine_factory( CORBA::ORB_ptr orb,
                                                            PortableServer::POA_ptr poa,
                                                            PortableServer::ObjectId * contId,