1 // Copyright (C) 2011-2024 CEA, EDF
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // Authors : Guillaume Boulant (EDF) - 01/03/2011
29 #include "MeshJobManager_i.hxx"
31 #include <SALOMEconfig.h>
32 #include CORBA_SERVER_HEADER(SALOME_Exception)
35 #include "Basics_Utils.hxx" // For standard logging
37 #include "SALOME_KernelServices.hxx" // For CORBA logging
43 // ====================================================================
44 // General purpose helper functions (to put elsewhere at least)
45 // ====================================================================
49 * This function must be used to associate a datetime tag to a job
53 static long timetag() {
56 long tag = tv.tv_usec + tv.tv_sec*1000000;
62 * This function returns true if the string text starts with the string
65 static bool myStartsWith(const std::string& text,const std::string& token){
66 if(text.length() < token.length())
68 return (text.compare(0, token.length(), token) == 0);
72 * This function returns true if the file exists on the local file
77 static bool fexists(const char *filename)
79 std::ifstream ifile(filename);
80 if ((bool)ifile && ifile.good()) {
86 //Engines::EngineComponent_var RetrievePadderMeshJobManagerInstance()
91 // ====================================================================
92 // Constructor/Destructor
93 // ====================================================================
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)
103 LOG("Activating MESHJOB::MeshJobManager object");
105 _id = _poa->activate_object(_thisObj);
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");
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");
119 _lastErrorMessage = "";
122 MeshJobManager_i::~MeshJobManager_i() {
123 LOG("MeshJobManager_i::~MeshJobManager_i()");
127 // ====================================================================
128 // Helper functions to deals with the local and remote file systems
129 // ====================================================================
131 #include <fstream> // to get the file streams
133 #include <stdlib.h> // to get _splitpath
134 #include <direct.h> // to get _mkdir
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
142 #include <stdlib.h> // to get system and getenv
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(" ");
150 static std::string USER(getenv("USERNAME"));
152 static std::string USER(getenv("USER"));
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);
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):
167 * [<concreteMeshFile> <concreteGroupName>]
168 * nbSteelBarMeshes <N>
169 * <steelBarMeshFile_1> <steelBarGroupName_1>
170 * <steelBarMeshFile_2> <steelBarGroupName_2>
172 * <steelBarMeshFile_N> <steelBarGroupName_N>
175 const char * MeshJobManager_i::_writeDataFile(std::vector<MESHJOB::MeshJobFile> listConcreteMesh,
176 std::vector<MESHJOB::MeshJobFile> listSteelBarMesh,
177 const MESHJOB::MeshJobParameterList & meshJobParameterList) {
179 _mkdir(LOCAL_INPUTDIR.c_str());
181 mkdir(LOCAL_INPUTDIR.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
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());
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.
192 // We first specify the concrete mesh data (filename and groupname)
193 if ( listConcreteMesh.size() > 0 ) {
195 char fname[ _MAX_FNAME ];
196 _splitpath( listConcreteMesh[0].file_name, NULL, NULL, fname, NULL );
197 char* bname = &fname[0];
199 char* bname = basename(listConcreteMesh[0].file_name);
201 line = std::string(bname) + " " + std::string(listConcreteMesh[0].group_name);
202 dataFile << line.c_str() << std::endl;
204 // Then, we can specify the steelbar mesh data, starting by the
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++) {
211 char fname[ _MAX_FNAME ];
212 _splitpath( listSteelBarMesh[i].file_name, NULL, NULL, fname, NULL );
213 char* bname = &fname[0];
215 char* bname = basename(listSteelBarMesh[i].file_name);
217 line = std::string(bname) + " " + std::string(listSteelBarMesh[i].group_name);
218 dataFile << line.c_str() << std::endl;
221 // We conclude the list of files with the name of the output file
223 dataFile << line.c_str() << std::endl;
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;
233 return dataFilename->c_str();
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.
242 const char* MeshJobManager_i::_writeScriptFile(const char * dataFileName, const char * configId) {
244 _mkdir(LOCAL_INPUTDIR.c_str());
246 mkdir(LOCAL_INPUTDIR.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
249 // Make it static so that it's allocated once (constant name)
250 static std::string * scriptFilename = new std::string(LOCAL_INPUTDIR+"/"+SCRIPTFILE);
252 char * binpath = _configMap[configId].binpath;
253 char * envpath = _configMap[configId].envpath;
256 char fname[ _MAX_FNAME ];
257 _splitpath( dataFileName, NULL, NULL, fname, NULL );
258 const char* bname = &fname[0];
260 const char* bname = basename(const_cast<char *>(dataFileName));
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.
272 return scriptFilename->c_str();
276 // ====================================================================
277 // Functions to initialize and supervise the mesh computation job
278 // ====================================================================
280 bool MeshJobManager_i::configure(const char *configId,
281 const MESHJOB::ConfigParameter & configParameter)
283 beginService("MeshJobManager_i::configure");
285 _configMap[configId] = configParameter;
287 LOG("Adding configuration for " << configId);
288 LOG("- binpath = " << _configMap[configId].binpath);
289 LOG("- envpath = " << _configMap[configId].envpath);
291 endService("MeshJobManager_i::configure");
295 long MeshJobManager_i::JOBID_UNDEFINED = -1;
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)
302 beginService("MeshJobManager_i::initialize");
304 // We first analyse the CORBA sequence to store data in C++ vectors
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);
314 case MESHJOB::MED_STEELBAR:
315 listSteelBarMesh.push_back(currentMesh);
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;
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;
336 LOG("Nb. concrete mesh = " << listConcreteMesh.size());
337 LOG("Nb. steelbar mesh = " << listSteelBarMesh.size());
339 // We initiate here a datetime to tag the files and folder
340 // associated to this job.
342 DWORD jobDatetimeTag = timeGetTime();
344 long jobDatetimeTag = timetag();
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();
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
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);
364 // Then, the following instructions consists in preparing the job
365 // parameters to request the SALOME launcher for creating a new
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
373 jobParameters->job_file = CORBA::string_dup(scriptFilename);
376 // Specification of the working spaces:
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.
382 // - result_directory: must be used to specify where to download the
383 // output files on the local resources
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.
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);
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);
409 for (int i=0; i<nbsmesh; i++) {
410 jobParameters->in_files[nbcmesh+i] = CORBA::string_dup(listSteelBarMesh[i].file_name);
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
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;
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());
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("");
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:
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;
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;
454 Engines::ResourceDefinition * resourceDefinition;
456 resourceDefinition = _resourcesManager->GetResourceDefinition(resourceName);
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;
464 // CAUTION: This resource should have been defined in the
465 // CatalogResource.xml associated to the SALOME application.
467 // Then, the values can be used to initiate the resource parameters
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.
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:
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
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).
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;
495 jobId = _salomeLauncher->createJob(jobParameters);
496 // We register the datetime tag of this job
497 _jobDateTimeMap[jobId]=jobDatetimeTag;
498 _jobPathsMap[jobId] = jobPaths;
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;
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;
512 endService("MeshJobManager_i::initialize");
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");
521 _salomeLauncher->launchJob(jobId);
523 catch (const SALOME::SALOME_Exception & ex) {
524 LOG("SALOME Exception in launchjob !" <<ex.details.text.in());
525 _lastErrorMessage = ex.details.text.in();
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)";
535 endService("MeshJobManager_i::initialize");
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");
546 state = _salomeLauncher->getJobState(jobId);
548 catch (const SALOME::SALOME_Exception & ex)
550 LOG("SALOME Exception in getJobState !");
551 _lastErrorMessage = ex.details.text.in();
552 state = ex.details.text;
554 catch (const CORBA::SystemException& ex)
556 LOG("Receive SALOME System Exception: " << ex);
557 state="SALOME System Exception - see logs";
559 LOG("jobId="<<ToString(jobId)<<" state="<<state);
560 endService("MeshJobManager_i::getState");
561 return CORBA::string_dup(state.c_str());
564 MESHJOB::MeshJobPaths * MeshJobManager_i::getPaths(CORBA::Long jobId) {
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?
575 MESHJOB::MeshJobResults * MeshJobManager_i::finalize(CORBA::Long jobId) {
576 beginService("MeshJobManager_i::getResults");
577 MESHJOB::MeshJobResults * result = new MESHJOB::MeshJobResults();
579 MESHJOB::MeshJobPaths * jobPaths = this->getPaths(jobId);
580 std::string local_resultdir(jobPaths->local_resultdir);
581 result->results_dirname = local_resultdir.c_str();
584 _salomeLauncher->getJobResults(jobId, local_resultdir.c_str());
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());
593 result->outputmesh_filename = outputFileName.c_str();
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;
602 result->status = true;
605 catch (const SALOME::SALOME_Exception & ex)
607 _lastErrorMessage = ex.details.text.in();
608 LOG(_lastErrorMessage);
609 result->status = false;
611 catch (const CORBA::SystemException& ex)
613 _lastErrorMessage = "The SALOME launcher can not retrieve the result data";
614 LOG(_lastErrorMessage);
615 result->status = false;
617 endService("MeshJobManager_i::getResults");
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");
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;
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");
643 shell_command+=inputdir+" ";
645 if ( !myStartsWith(resultdir,"/tmp/")) {
646 LOG("WRN: The directory "<<resultdir<<" is not in /tmp. NO DELETE is done");
648 shell_command+=resultdir;
651 LOG("DBG: clean shell command = "<<shell_command);
653 bool cleanOk = false;
654 int error = system(shell_command.c_str());
655 if (error == 0) cleanOk = true;
657 endService("MeshJobManager_i::clean");
662 std::vector<std::string> * MeshJobManager_i::_getResourceNames() {
665 // These part is just to control the available resources
667 Engines::ResourceParameters params;
668 KERNEL::getLifeCycleCORBA()->preSet(params);
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>();
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
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).
694 return resourceNames;
697 char* MeshJobManager_i::getLastErrorMessage() {
698 beginService("MeshJobManager_i::getState");
699 endService("MeshJobManager_i::getState");
700 return CORBA::string_dup(_lastErrorMessage.c_str());
704 // ==========================================================================
706 // ==========================================================================
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)
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);
724 myEngine = new MeshJobManager_i(orb, poa, contId, instanceName, interfaceName, true, true);
725 return myEngine->getId() ;