Back to index

salome-smesh  6.5.0
MeshJobManager_i.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2011-2012  EDF R&D
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 // Authors : Guillaume Boulant (EDF) - 01/03/2011
00020 
00021 #ifdef WIN32
00022 #include <winsock2.h>
00023 #include <windows.h> 
00024 #else
00025 #include <sys/time.h>
00026 #endif
00027 
00028 #include "MeshJobManager_i.hxx"
00029 
00030 #include <SALOMEconfig.h>
00031 #include CORBA_SERVER_HEADER(SALOME_Exception)
00032 
00033 
00034 #include "Basics_Utils.hxx"         // For standard logging
00035 #undef LOG
00036 #include "SALOME_KernelServices.hxx"   // For CORBA logging
00037 #undef LOG
00038 
00039 #define LOG STDLOG
00040 
00041 //
00042 // ====================================================================
00043 // General purpose helper functions (to put elsewhere at least)
00044 // ====================================================================
00045 //
00046 
00051 #ifndef WIN32
00052 static long timetag() {
00053   timeval tv;
00054   gettimeofday(&tv,0);
00055   long tag = tv.tv_usec + tv.tv_sec*1000000;
00056   return tag;
00057 }
00058 #endif
00059 
00064 static bool myStartsWith(const std::string& text,const std::string& token){     
00065   if(text.length() < token.length())
00066     return false;
00067   return (text.compare(0, token.length(), token) == 0);
00068 }
00069 
00070 //
00071 // ====================================================================
00072 // Constructor/Destructor
00073 // ====================================================================
00074 //
00075 MeshJobManager_i::MeshJobManager_i(CORBA::ORB_ptr orb,
00076                                    PortableServer::POA_ptr poa,
00077                                    PortableServer::ObjectId * contId,
00078                                    const char *instanceName,
00079                                    const char *interfaceName)
00080   : Engines_Component_i(orb, poa, contId, instanceName, interfaceName)
00081 {
00082   LOG("Activating MESHJOB::MeshJobManager object");
00083   _thisObj = this ;
00084   _id = _poa->activate_object(_thisObj);
00085 
00086   _salomeLauncher   = KERNEL::getSalomeLauncher();
00087   if(CORBA::is_nil(_salomeLauncher)){
00088     LOG("The SALOME launcher can't be reached ==> STOP");
00089     throw KERNEL::createSalomeException("SALOME launcher can't be reached");
00090   }
00091 
00092   _resourcesManager = KERNEL::getResourcesManager();
00093   if(CORBA::is_nil(_resourcesManager)){
00094     LOG("The SALOME resource manager can't be reached ==> STOP");
00095     throw KERNEL::createSalomeException("The SALOME resource manager can't be reached");
00096   }
00097 }
00098 
00099 MeshJobManager_i::~MeshJobManager_i() {
00100   LOG("MeshJobManager_i::~MeshJobManager_i()");
00101 }
00102 
00103 //
00104 // ====================================================================
00105 // Helper functions to deals with the local and remote file systems
00106 // ====================================================================
00107 //
00108 #include <fstream>     // to get the file streams
00109 #ifdef WNT             
00110 #include <stdlib.h>    // to get _splitpath
00111 #include <direct.h>    // to get _mkdir
00112 #else
00113 #include <unistd.h>    // to get basename
00114 #include <sys/stat.h>  // to get mkdir
00115 #include <sys/types.h> // to get mkdir options
00116 #endif
00117 
00118 #include <stdlib.h>    // to get system and getenv
00119 
00120 static std::string OUTPUTFILE("output.med");
00121 static std::string DATAFILE("data.txt");
00122 static std::string SCRIPTFILE("padder.sh");
00123 static std::string SEPARATOR(" ");
00124 
00125 static std::string USER(getenv("USER"));
00126 static std::string LOCAL_INPUTDIR("/tmp/spadder.local.inputdir."+USER);
00127 static std::string LOCAL_RESULTDIR("/tmp/spadder.local.resultdir."+USER);
00128 static std::string REMOTE_WORKDIR("/tmp/spadder.remote.workdir."+USER);
00129 
00137 const char * MeshJobManager_i::_writeDataFile(std::vector<MESHJOB::MeshJobParameter> listConcreteMesh,
00138                                               std::vector<MESHJOB::MeshJobParameter> listSteelBarMesh) {
00139 #ifdef WIN32
00140   _mkdir(LOCAL_INPUTDIR.c_str());
00141 #else
00142   mkdir(LOCAL_INPUTDIR.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
00143 #endif
00144 
00145   // Make it static so that it's allocated once (constant name)
00146   static std::string * dataFilename = new std::string(LOCAL_INPUTDIR+"/"+DATAFILE);
00147   std::ofstream dataFile(dataFilename->c_str());
00148   
00149   // We first specify the concrete mesh data (filename and groupname)
00150   std::string line;
00151 #ifdef WIN32
00152   char fname[ _MAX_FNAME ];
00153   _splitpath( listConcreteMesh[0].file_name, NULL, NULL, fname, NULL );
00154   char* bname = &fname[0];
00155 #else
00156   char* bname = basename(listConcreteMesh[0].file_name);
00157 #endif
00158   line = std::string(bname) + " " + std::string(listConcreteMesh[0].group_name);
00159   dataFile << line.c_str() << std::endl;
00160   // Note that we use here the basename because the files are supposed
00161   // to be copied in the REMOTE_WORKDIR for execution.
00162   
00163   // The, we can specify the steelbar mesh data, starting by the
00164   // number of meshes
00165   int nbSteelBarMesh=listSteelBarMesh.size();
00166   line = std::string("nbSteelbarMesh") + SEPARATOR + ToString(nbSteelBarMesh);
00167   dataFile << line.c_str() << std::endl;
00168   for (int i=0; i<nbSteelBarMesh; i++) {
00169 #ifdef WIN32
00170         char fname[ _MAX_FNAME ];
00171         _splitpath( listSteelBarMesh[i].file_name, NULL, NULL, fname, NULL );
00172         char* bname = &fname[0];
00173 #else
00174         char* bname = basename(listSteelBarMesh[i].file_name);
00175 #endif
00176     line = std::string(bname) + " " + std::string(listSteelBarMesh[i].group_name);
00177     dataFile << line.c_str() << std::endl;
00178   }
00179   
00180   // Finally, we conclude with the name of the output file
00181   line = OUTPUTFILE;
00182   dataFile << line.c_str() << std::endl;
00183   dataFile.close();
00184   return dataFilename->c_str();  
00185 }
00186 
00193 const char* MeshJobManager_i::_writeScriptFile(const char * dataFileName, const char * configId) {
00194 #ifdef WIN32
00195   _mkdir(LOCAL_INPUTDIR.c_str());
00196 #else
00197   mkdir(LOCAL_INPUTDIR.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
00198 #endif
00199 
00200   // Make it static so that it's allocated once (constant name)
00201   static std::string * scriptFilename = new std::string(LOCAL_INPUTDIR+"/"+SCRIPTFILE);
00202 
00203   char * binpath = _configMap[configId].binpath;
00204   char * envpath = _configMap[configId].envpath;
00205 
00206 #ifdef WIN32
00207         char fname[ _MAX_FNAME ];
00208         _splitpath( dataFileName, NULL, NULL, fname, NULL );
00209         const char* bname = &fname[0];
00210 #else
00211         const char* bname = basename(dataFileName);
00212 #endif
00213 
00214 
00215   std::ofstream script(scriptFilename->c_str());
00216   script << "#!/bin/sh"                                   << std::endl;
00217   script << "here=$(dirname $0)"                          << std::endl;
00218   script << ". " << envpath                               << std::endl;
00219   script << binpath << " $here/" << bname                 << std::endl;
00220   // Note that we use the basename of the datafile because all data
00221   // files are supposed to have been copied in the REMOTE_WORKDIR.
00222   script.close();
00223   return scriptFilename->c_str();
00224 }
00225 
00226 //
00227 // ====================================================================
00228 // Functions to initialize and supervise the mesh computation job
00229 // ====================================================================
00230 //
00231 bool MeshJobManager_i::configure(const char *configId,
00232                                  const MESHJOB::ConfigParameter & configParameter)
00233 {
00234   beginService("MeshJobManager_i::configure");
00235   
00236   _configMap[configId] = configParameter;
00237 
00238   LOG("Adding configuration for " << configId);
00239   LOG("- binpath = " << _configMap[configId].binpath);
00240   LOG("- envpath = " << _configMap[configId].envpath);
00241 
00242   endService("MeshJobManager_i::configure");
00243   return true;
00244 }
00245 
00246 long MeshJobManager_i::JOBID_UNDEFINED = -1;
00247 
00249 CORBA::Long MeshJobManager_i::initialize(const MESHJOB::MeshJobParameterList & meshJobParameterList,
00250                                          const char * configId)
00251 {
00252   beginService("MeshJobManager_i::initialize");
00253   std::cerr << "##################################### initialize" << std::endl;
00254   std::cerr << "#####################################" << std::endl;
00255 
00256   //
00257   // We first analyse the CORBA sequence to store data in C++ vectors
00258   //
00259   std::vector<MESHJOB::MeshJobParameter> listConcreteMesh;
00260   std::vector<MESHJOB::MeshJobParameter> listSteelBarMesh;
00261   for(CORBA::ULong i=0; i<meshJobParameterList.length(); i++) {
00262     MESHJOB::MeshJobParameter currentMesh = meshJobParameterList[i];
00263     switch ( currentMesh.file_type ) {
00264     case MESHJOB::MED_CONCRETE:
00265       listConcreteMesh.push_back(currentMesh);
00266       break;
00267     case MESHJOB::MED_STEELBAR:
00268       listSteelBarMesh.push_back(currentMesh);
00269       break;
00270     default:
00271       LOG("The type of the file is not recognized");
00272       return JOBID_UNDEFINED;
00273     }
00274   }
00275   
00276   if ( listConcreteMesh.size() != 1 ) {
00277     // Not consistent with the specification
00278     LOG("You specify more than one concrete mesh");
00279     return JOBID_UNDEFINED;
00280   }
00281   
00282   LOG("Nb. concrete mesh = " << listConcreteMesh.size());
00283   LOG("Nb. steelbar mesh = " << listSteelBarMesh.size());
00284 
00285   // We initiate here a datetime to tag the files and folder
00286   // associated to this job.
00287 #ifdef WIN32
00288   DWORD jobDatetimeTag = timeGetTime();
00289 #else
00290   long jobDatetimeTag = timetag();
00291 #endif
00292   // And a MESHJOB::MeshJobPaths structure to hold the directories
00293   // where to find data
00294   MESHJOB::MeshJobPaths * jobPaths = new MESHJOB::MeshJobPaths();
00295   jobPaths->local_inputdir  = LOCAL_INPUTDIR.c_str();
00296   jobPaths->local_resultdir = (LOCAL_RESULTDIR + "." + ToString(jobDatetimeTag)).c_str();
00297   jobPaths->remote_workdir  = (REMOTE_WORKDIR + "." + ToString(jobDatetimeTag)).c_str();  
00298 
00299   //
00300   // Then, we have to create the padder input data file. This input
00301   // data is a text file containing the list of file names and group
00302   // names.
00303   //
00304   const char * dataFilename = this->_writeDataFile(listConcreteMesh, listSteelBarMesh);
00305   LOG("dataFilename = " << dataFilename);
00306   const char * scriptFilename = this->_writeScriptFile(dataFilename, configId);
00307   LOG("scriptFilename = " << scriptFilename);
00308 
00309   //
00310   // Then, the following instructions consists in preparing the job
00311   // parameters to request the SALOME launcher for creating a new
00312   // job.
00313   //
00314   Engines::JobParameters_var jobParameters = new Engines::JobParameters;
00315   jobParameters->job_type = CORBA::string_dup("command");
00316   // CAUTION: the job_file must be a single filename specifying a
00317   // self-consistent script to be executed without any argument on the
00318   // remote host.
00319   jobParameters->job_file = CORBA::string_dup(scriptFilename);
00320 
00321   //
00322   // Specification of the working spaces:
00323   //
00324   // - local_directory: can be used to specify where to find the input
00325   //   files on the local resource. It's optionnal if you specify the
00326   //   absolute path name of input files.
00327   //
00328   // - result_directory: must be used to specify where to download the
00329   //   output files on the local resources
00330   //
00331   // - work_directory: must be used to specify the remote directory
00332   //   where to put all the stuff to run the job. Note that the job
00333   //   will be executed from within this directory, i.e. a change
00334   //   directory toward this working directory is done by the batch
00335   //   system before running the specified job script.
00336   //
00337   jobParameters->local_directory  = CORBA::string_dup("");
00338   jobParameters->result_directory = CORBA::string_dup(jobPaths->local_resultdir);
00339   jobParameters->work_directory   = CORBA::string_dup(jobPaths->remote_workdir);
00340 
00341   // We specify the input files that are required to execute the
00342   // job_file. If basenames are specified, then the files are supposed
00343   // to be located in local_directory.
00344   int nbFiles = listSteelBarMesh.size()+2;
00345   // The number of input file is: 
00346   //   (nb. of steelbar meshfile)
00347   // + (1 concrete meshfile)
00348   // + (1 padder input file)
00349   // = nb steelbar meshfile + 2
00350   jobParameters->in_files.length(nbFiles);
00351   jobParameters->in_files[0] = CORBA::string_dup(listConcreteMesh[0].file_name);
00352   for (int i=0; i<listSteelBarMesh.size(); i++) {
00353     jobParameters->in_files[1+i] = CORBA::string_dup(listSteelBarMesh[i].file_name);
00354   }
00355   jobParameters->in_files[1+listSteelBarMesh.size()] = CORBA::string_dup(dataFilename);
00356   // Note that all these input files will be copied in the
00357   // REMOTE_WORKDIR on the remote host
00358   
00359   // Then, we have to specify the existance of an output
00360   // filenames. The path is supposed to be a path on the remote
00361   // resource, i.e. where the job is executed.
00362   jobParameters->out_files.length(1);
00363   std::string outputfile_name = std::string(jobPaths->remote_workdir)+"/"+OUTPUTFILE;
00364   jobParameters->out_files[0] = CORBA::string_dup(outputfile_name.c_str());
00365 
00366   // CAUTION: the maximum duration has to be set with a format like "hh:mm"
00367   jobParameters->maximum_duration = CORBA::string_dup("01:00");
00368   jobParameters->queue = CORBA::string_dup("");
00369 
00370   // Setting resource and additionnal properties (if needed)
00371   // The resource parameters can be initiated from scratch, for
00372   // example by specifying the values in hard coding:
00373   // >>>
00374   //jobParameters->resource_required.name = CORBA::string_dup("localhost");
00375   //jobParameters->resource_required.hostname = CORBA::string_dup("localhost");
00376   //jobParameters->resource_required.mem_mb = 1024 * 10;
00377   //jobParameters->resource_required.nb_proc = 1;
00378   // <<<
00379   // But it's better to initiate these parameters from a resource
00380   // definition known by the resource manager. This ensures that the
00381   // resource will be available:
00382   //const char * resourceName = "localhost";
00383   //const char * resourceName = "boulant@claui2p1";
00384   //const char * resourceName = "nepal@nepal";
00385   const char * resourceName = _configMap[configId].resname;
00386   Engines::ResourceDefinition * resourceDefinition = _resourcesManager->GetResourceDefinition(resourceName);
00387   // CAUTION: This resource should have been defined in the
00388   // CatalogResource.xml associated to the SALOME application.
00389   //
00390   // Then, the values can be used to initiate the resource parameters
00391   // of the job:
00392   jobParameters->resource_required.name     = CORBA::string_dup(resourceDefinition->name.in());
00393   // CAUTION: the additionnal two following parameters MUST be
00394   // specified explicitly, because they are not provided by the
00395   // resource definition:
00396   jobParameters->resource_required.mem_mb   = resourceDefinition->mem_mb;
00397   jobParameters->resource_required.nb_proc  = resourceDefinition->nb_proc_per_node;
00398   // CAUTION: the parameter mem_mb specifies the maximum memory value
00399   // that could be allocated for executing the job. This takes into
00400   // account not only the data that could be loaded by the batch
00401   // process but also the linked dynamic library.
00402   //
00403   // A possible problem, for exemple in the case where you use the ssh
00404   // emulation of a batch system, is to get an error message as below
00405   // when libBatch try to run the ssh command:
00406   //
00407   // ## /usr/bin/ssh: error while loading shared libraries: libcrypto.so.0.9.8: failed
00408   // ## to map segment from shared object: Cannot allocate memory
00409   //
00410   // In this exemple, the mem_mb was set to 1MB, value that is not
00411   // sufficient to load the dynamic libraries linked to the ssh
00412   // executable (libcrypto.so in the error message).
00413   //
00414   // So, even in the case of a simple test shell script, you should
00415   // set this value at least to a standard threshold as 500MB
00416 
00417   int jobId = JOBID_UNDEFINED;
00418   try {
00419     std::cerr << "#####################################" << std::endl;
00420     std::cerr << "#####################################" << std::endl;
00421     std::cerr << "jobUndef = " << JOBID_UNDEFINED << std::endl;
00422     jobId = _salomeLauncher->createJob(jobParameters);
00423     std::cerr << "#####################################" << std::endl;
00424     std::cerr << "#####################################" << std::endl;
00425     std::cerr << "#####################################" << std::endl;
00426     std::cerr << "jobId = " << jobId << std::endl;
00427     // We register the datetime tag of this job
00428     _jobDateTimeMap[jobId]=jobDatetimeTag;
00429     _jobPathsMap[jobId] = jobPaths;
00430   }
00431   catch (const SALOME::SALOME_Exception & ex) {
00432     LOG("SALOME Exception in createJob !" <<ex.details.text.in());
00433     //LOG(ex.details.text.in());
00434     return JOBID_UNDEFINED;
00435   }
00436   catch (const CORBA::SystemException& ex) {
00437     LOG("Receive SALOME System Exception: "<<ex);
00438     LOG("Check SALOME servers...");
00439     return JOBID_UNDEFINED;
00440   }
00441   
00442   endService("MeshJobManager_i::initialize");
00443   return jobId;
00444 }
00445 
00447 bool MeshJobManager_i::start(CORBA::Long jobId) {
00448   beginService("MeshJobManager_i::start");
00449 
00450   try {
00451     _salomeLauncher->launchJob(jobId);
00452   }
00453   catch (const SALOME::SALOME_Exception & ex) {
00454     LOG("SALOME Exception in launchjob !" <<ex.details.text.in());
00455     //LOG(ex.details.text.in());
00456     return false;
00457   }
00458   catch (const CORBA::SystemException& ex) {
00459     LOG("Receive SALOME System Exception: "<<ex);
00460     LOG("Check SALOME servers...");
00461     return false;
00462   }
00463 
00464   endService("MeshJobManager_i::initialize");
00465   return true;
00466 }
00467 
00469 char* MeshJobManager_i::getState(CORBA::Long jobId) {
00470   beginService("MeshJobManager_i::getState");
00471 
00472   std::string state;
00473   try
00474   {
00475     state = _salomeLauncher->getJobState(jobId);
00476   }
00477   catch (const SALOME::SALOME_Exception & ex)
00478   {
00479     LOG("SALOME Exception in getJobState !");
00480     state = ex.details.text;
00481   }
00482   catch (const CORBA::SystemException& ex)
00483   {
00484     LOG("Receive SALOME System Exception: " << ex);
00485     state="SALOME System Exception - see logs";
00486   }
00487   LOG("jobId="<<ToString(jobId)<<" state="<<state);
00488   endService("MeshJobManager_i::getState");
00489   return CORBA::string_dup(state.c_str());
00490 }
00491 
00492 MESHJOB::MeshJobPaths * MeshJobManager_i::getPaths(CORBA::Long jobId) {
00493 
00494   MESHJOB::MeshJobPaths * jobPaths = _jobPathsMap[jobId];
00495   if ( jobPaths == NULL ) {
00496     LOG("You request the working paths for an undefined job (jobId="<<ToString(jobId)<<")");
00497     return NULL; // Maybe raise an exception?
00498   }
00499   return jobPaths;
00500 }
00501 
00502 
00503 MESHJOB::MeshJobResults * MeshJobManager_i::finalize(CORBA::Long jobId) {
00504   beginService("MeshJobManager_i::getResults");
00505   MESHJOB::MeshJobResults * result = new MESHJOB::MeshJobResults();
00506 
00507   MESHJOB::MeshJobPaths * jobPaths = this->getPaths(jobId);
00508   std::string local_resultdir(jobPaths->local_resultdir);
00509   result->results_dirname = local_resultdir.c_str();  
00510   try
00511   {
00512     _salomeLauncher->getJobResults(jobId, local_resultdir.c_str());
00513  
00514     // __BUG__: to prevent from a bug of the MED driver (SALOME
00515     // 5.1.5), we change the basename of the output file to force the
00516     // complete reloading of data by the med driver.
00517     long jobDatetimeTag = _jobDateTimeMap[jobId];
00518     std::string outputFileName = "output"+ToString(jobDatetimeTag)+".med";
00519     rename((local_resultdir+"/"+OUTPUTFILE).c_str(), (local_resultdir+"/"+outputFileName).c_str());
00520 
00521     result->outputmesh_filename = outputFileName.c_str();
00522     result->status = "OK";
00523  }
00524   catch (const SALOME::SALOME_Exception & ex)
00525   {
00526     LOG("SALOME Exception in getResults !");
00527     result->status = "SALOME Exception in getResults !";
00528   }
00529   catch (const CORBA::SystemException& ex)
00530   {
00531     LOG("Receive CORBA System Exception: " << ex);
00532     result->status = "Receive CORBA System Exception: see log";
00533   }
00534   endService("MeshJobManager_i::getResults");
00535   return result;
00536 }
00537 
00538 
00540 bool MeshJobManager_i::clean(CORBA::Long jobId) {
00541   beginService("MeshJobManager_i::clean");
00542   
00543   // __GBO__ WORK IN PROGRESS: we just clean the temporary local
00544   // directories. The remote working directories are tag with the
00545   // execution datetime and the we prevent the task from conflict
00546   // with files of another task.
00547   MESHJOB::MeshJobPaths * jobPaths = this->getPaths(jobId);
00548   if ( jobPaths == NULL ) return false;
00549 
00550   // WARN: !!!!!
00551   // For safety reason (and prevent from bug that could erase the
00552   // filesystem), we cancel the operation in the case where the
00553   // directories to delete are not in the /tmp folder.
00554   std::string shell_command("rm -rf ");
00555   std::string inputdir(jobPaths->local_inputdir);
00556   std::string resultdir(jobPaths->local_resultdir);
00557   if ( !myStartsWith(inputdir,"/tmp/") )  {
00558     LOG("WRN: The directory "<<inputdir<<" is not in /tmp. NO DELETE is done");
00559   } else {
00560     shell_command+=inputdir+" ";
00561   }
00562   if ( !myStartsWith(resultdir,"/tmp/"))  {
00563     LOG("WRN: The directory "<<resultdir<<" is not in /tmp. NO DELETE is done");
00564   } else {
00565     shell_command+=resultdir;
00566   }
00567 
00568   LOG("DBG: clean shell command = "<<shell_command);
00569 
00570   bool cleanOk = false;
00571   int error = system(shell_command.c_str());
00572   if (error == 0) cleanOk = true;
00573 
00574   endService("MeshJobManager_i::clean");
00575   return cleanOk;
00576 }
00577 
00578 
00579 std::vector<std::string> * MeshJobManager_i::_getResourceNames() {
00580 
00581   //
00582   // These part is just to control the available resources
00583   //
00584   Engines::ResourceParameters params;
00585   KERNEL::getLifeCycleCORBA()->preSet(params);
00586 
00587   Engines::ResourceList * resourceList = _resourcesManager->GetFittingResources(params);
00588   Engines::ResourceDefinition * resourceDefinition = NULL;
00589   LOG("### resource list:");
00590   std::vector<std::string>* resourceNames = new std::vector<std::string>();
00591   if (resourceList) {
00592     for (int i = 0; i < resourceList->length(); i++) {
00593       const char* aResourceName = (*resourceList)[i];
00594       resourceNames->push_back(std::string(aResourceName));
00595       LOG("resource["<<i<<"] = "<<aResourceName);
00596       resourceDefinition = _resourcesManager->GetResourceDefinition(aResourceName);
00597       LOG("protocol["<<i<<"] = "<<resourceDefinition->protocol);
00598     }
00599   }
00600 
00601   // Note: a ResourceDefinition is used to create a batch configuration
00602   // in the Launcher. This operation is done at Launcher startup from
00603   // the configuration file CatalogResources.xml provided by the
00604   // SALOME application.
00605   // In the code instructions, you just have to choose a resource
00606   // configuration by its name and then define the ResourceParameters
00607   // that specify additionnal properties for a specific job submission
00608   // (use the attribute resource_required of the JobParameters).
00609 
00610   return resourceNames;
00611 }
00612 
00613 
00614 //
00615 // ==========================================================================
00616 // Factory services
00617 // ==========================================================================
00618 //
00619 extern "C"
00620 {
00621   PortableServer::ObjectId * MeshJobManagerEngine_factory( CORBA::ORB_ptr orb,
00622                                                            PortableServer::POA_ptr poa,
00623                                                            PortableServer::ObjectId * contId,
00624                                                            const char *instanceName,
00625                                                            const char *interfaceName)
00626   {
00627     LOG("PortableServer::ObjectId * MeshJobManagerEngine_factory()");
00628     MeshJobManager_i * myEngine = new MeshJobManager_i(orb, poa, contId, instanceName, interfaceName);
00629     return myEngine->getId() ;
00630   }
00631 }