ATLAS Offline Software
Loading...
Searching...
No Matches
EL::PrunDriver Class Referencefinal

a Driver to submit jobs via prun More...

#include <PrunDriver.h>

Inheritance diagram for EL::PrunDriver:
Collaboration diagram for EL::PrunDriver:

Public Member Functions

 PrunDriver ()
void testInvariant () const
SH::MetaObjectoptions ()
 the list of options to jobs with this driver
const SH::MetaObjectoptions () const
std::string submit (const Job &job, const std::string &location) const
 submit the given job with the given output location and wait for it to finish
std::string submitOnly (const Job &job, const std::string &location) const
 submit the given job with the given output location and return immediately

Static Public Member Functions

static void status (const std::string &location)
static void setState (const std::string &location, const std::string &task, const std::string &state)
static void resubmit (const std::string &location, const std::string &option)
 resubmit all failed sub-jobs for the job in the given location
static bool retrieve (const std::string &location)
 retrieve all the output for the job in the given location
static bool wait (const std::string &location, unsigned time=60)
 retrieve all the output for the job in the given location and wait until it is finished completely.
static void updateLocation (const std::string &location)
 update the internal location of files, after moving the submission directory
static void mergedOutputSave (Detail::ManagerData &data)
 create and save a sample handler assuming we created all the merged files at the requested locations
static void diskOutputSave (Detail::ManagerData &data)
 make the output sample handler for the given job or stream from the information stored in the histogram files.

Protected Member Functions

virtual::StatusCode doManagerStep (Detail::ManagerData &data) const override

Static Protected Attributes

static bool abortRetrieve
 this flag is set to true when the wait() function is running and a SIGINT is caught, meaning that control should be returned to the user as soon as possible.

Private Member Functions

::StatusCode doRetrieve (Detail::ManagerData &data) const
 ClassDef (EL::PrunDriver, 1)

Private Attributes

SH::MetaObject m_options
 members directly corresponding to accessors

Detailed Description

a Driver to submit jobs via prun

Definition at line 19 of file PrunDriver.h.

Constructor & Destructor Documentation

◆ PrunDriver()

EL::PrunDriver::PrunDriver ( )

Definition at line 591 of file PrunDriver.cxx.

592{
593 RCU_NEW_INVARIANT(this);
594}
#define RCU_NEW_INVARIANT(x)
Definition Assert.h:221

Member Function Documentation

◆ ClassDef()

EL::PrunDriver::ClassDef ( EL::PrunDriver ,
1  )
private

◆ diskOutputSave()

void EL::Driver::diskOutputSave ( Detail::ManagerData & data)
staticinherited

make the output sample handler for the given job or stream from the information stored in the histogram files.

This is optional, but it is convenient for drivers that use (conventional) writers

Guarantee
basic
Failures
out of memory II
i/o errors

◆ doManagerStep()

StatusCode EL::PrunDriver::doManagerStep ( Detail::ManagerData & data) const
overrideprotected

Definition at line 596 of file PrunDriver.cxx.

598{
599 using namespace msgEventLoop;
601 switch (data.step)
602 {
604 {
605 const std::string jobELGDir = data.submitDir + "/elg";
606 const std::string runShFile = jobELGDir + "/runjob.sh";
607 const std::string mergeShFile = jobELGDir + "/elg_merge";
608 const std::string runShOrig = PathResolverFindCalibFile("EventLoopGrid/runjob.sh");
609 const std::string mergeShOrig = PathResolverFindCalibFile("EventLoopGrid/elg_merge");
610
611 const std::string jobDefFile = jobELGDir + "/jobdef.root";
612
613 namespace fs = std::filesystem;
614 std::error_code ec;
615 fs::create_directories(jobELGDir, ec);
616 if (ec) {
617 ANA_MSG_ERROR("could not create directory " << jobELGDir << ": " << ec.message());
618 return StatusCode::FAILURE;
619 }
620 // Copy the grid scripts into the submission directory and make them
621 // executable, aborting submission if either step fails.
622 const auto copyExecutable =
623 [&] (const std::string& from, const std::string& to) -> StatusCode {
624 std::error_code ec2;
625 fs::copy_file(from, to, fs::copy_options::overwrite_existing, ec2);
626 if (ec2) {
627 ANA_MSG_ERROR("could not copy " << from << " to " << to << ": " << ec2.message());
628 return StatusCode::FAILURE;
629 }
630 fs::permissions(to, fs::perms::owner_exec | fs::perms::group_exec |
631 fs::perms::others_exec, fs::perm_options::add, ec2);
632 if (ec2) {
633 ANA_MSG_ERROR("could not make " << to << " executable: " << ec2.message());
634 return StatusCode::FAILURE;
635 }
636 return StatusCode::SUCCESS;
637 };
638 ANA_CHECK(copyExecutable(runShOrig, runShFile));
639 ANA_CHECK(copyExecutable(mergeShOrig, mergeShFile));
640
641 // create symbolic links for additionnal files/directories if any to ship to the grid
642 std::string listToShipToGrid = data.options.castString(EL::Job::optGridPrunShipAdditionalFilesOrDirs, "");
643 // parse the list of comma separated files and/or directories to ship to the grid
644 if (listToShipToGrid.size()){
646 "Creating symbolic links for additional files or directories to be sent to grid.\n"
647 "For root or heavy files you should also add their name (not the full path) to EL::Job::optUserFiles.\n"
648 "Otherwise prun ignores those files."
649 );
650
651 std::vector<std::string> vect_filesOrDirToShip;
652 for (auto&& part : std::views::split(listToShipToGrid, ',')) vect_filesOrDirToShip.emplace_back(part.begin(), part.end());
653 // Create symbolic links of files or directories to the submission directory
654 for (const std::string & fileOrDirToShip: vect_filesOrDirToShip){
655 ANA_MSG_INFO (("Creating symbolic link for: " +fileOrDirToShip).c_str());
656 const fs::path linkPath =
657 fs::path(jobELGDir) / fs::path(fileOrDirToShip).filename();
658 // emulate `ln -sf`: replace any pre-existing link/file
659 fs::remove(linkPath, ec);
660 fs::create_symlink(fileOrDirToShip, linkPath, ec);
661 if (ec) {
662 ANA_MSG_ERROR("could not create symbolic link " << linkPath.string()
663 << " -> " << fileOrDirToShip << ": " << ec.message());
664 return StatusCode::FAILURE;
665 }
666 }
667 ANA_MSG_INFO ("Finished creation of symbolic links");
668 }
669
670 const SH::SampleHandler& sh = data.job->sampleHandler();
671
672 for (SH::Sample* const sample : sh) {
673 SH::MetaObject& meta = *sample->meta();
674 meta.fetchDefaults(data.options);
676 meta.setString("nc_outputs", outputFileNames(*data.job));
677 std::string outputSampleName = meta.castString("nc_outputSampleName");
678 if (outputSampleName.empty()) {
679 outputSampleName = "user.%nickname%.%in:name%";
680 }
681 meta.setString("nc_outDS", formatOutputName(meta, outputSampleName));
682 meta.setString("nc_inDS", meta.castString("nc_grid", sample->name()));
683 meta.setString("nc_writeInputToTxt", "IN:input.txt");
684 meta.setString("nc_match", meta.castString("nc_grid_filter"));
685 const std::string execstr = "runjob.sh " + sample->name();
686 meta.setString("nc_exec", execstr);
687 meta.setString("nc_framework", "EventLoopGrid");
688 }
689
690 saveJobDef(jobDefFile, *data.job, sh);
691
692 for (EL::Job::outputIter out = data.job->outputBegin();
693 out != data.job->outputEnd(); ++out) {
694 SH::SampleHandler shOut = outputSH(sh, out->label());
695 shOut.save(data.submitDir + "/output-" + out->label());
696 }
697 SH::SampleHandler shHist = outputSH(sh, "hist-output");
698 shHist.save(data.submitDir + "/output-hist");
699
700 TmpCd keepDir(jobELGDir);
701
702 processAllInState(sh, JobState::INIT, 0);
703
704 sh.save(data.submitDir + "/input");
705 data.submitted = true;
706 }
707 break;
708
710 {
711 ANA_CHECK (doRetrieve (data));
712 }
713 break;
714
715 default:
716 (void) true; // safe to do nothing
717 }
718 return ::StatusCode::SUCCESS;
719}
#define ANA_MSG_ERROR(xmsg,...)
Macro printing error messages.
#define ANA_MSG_INFO(xmsg,...)
Macro printing info messages.
#define ANA_CHECK(EXP)
check whether the given expression was successful
static Double_t fs
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
static SH::MetaObject defaultOpts()
static void processAllInState(const SH::SampleHandler &sh, JobState::Enum state, const size_t nThreads)
static std::string outputFileNames(const EL::Job &job)
static std::string formatOutputName(const SH::MetaObject &sampleMeta, const std::string &pattern)
static void saveJobDef(const std::string &fileName, const EL::Job &job, const SH::SampleHandler &sh)
static SH::SampleHandler outputSH(const SH::SampleHandler &in, const std::string &outputLabel)
virtual::StatusCode doManagerStep(Detail::ManagerData &data) const
const OutputStream * outputIter
Definition Job.h:139
static const std::string optGridPrunShipAdditionalFilesOrDirs
Enables to ship additional files to the tarbal sent to the grid Should be a list of comma separated p...
Definition Job.h:473
::StatusCode doRetrieve(Detail::ManagerData &data) const
void fetchDefaults(const MetaObject &source)
fetch the meta-data from the given sample not present in this sample.
void setString(const std::string &name, const std::string &value)
set the meta-data string with the given name
std::string castString(const std::string &name, const std::string &def_val="", CastMode mode=CAST_ERROR_THROW) const
the meta-data string with the given name
void save(const std::string &directory) const
save the list of samples to the given directory
CONT to(RANGE &&r)
Definition ranges.h:39
@ doRetrieve
call the actual doRetrieve method
@ submitJob
do the actual job submission
Definition ManagerStep.h:92
::StatusCode StatusCode
StatusCode definition for legacy code.

◆ doRetrieve()

StatusCode EL::PrunDriver::doRetrieve ( Detail::ManagerData & data) const
private

Definition at line 721 of file PrunDriver.cxx.

722{
723 RCU_READ_INVARIANT(this);
724 RCU_REQUIRE(not data.submitDir.empty());
725
726 TmpCd tmpDir(data.submitDir);
727
728 SH::SampleHandler sh;
729 sh.load("input");
730 RCU_ASSERT(sh.size());
731
732 const size_t nRunThreads = options()->castDouble("nc_run_threads", 0);
733 const size_t nDlThreads = options()->castDouble("nc_download_threads", 0);
734 processAllInState(sh, JobState::INIT, 0);
735 processAllInState(sh, JobState::RUN, nRunThreads);
736 processAllInState(sh, JobState::DOWNLOAD, nDlThreads);
737 processAllInState(sh, JobState::MERGE, 0);
738
739 sh.save("input");
740
741 std::cout << std::endl;
742
743 bool allDone = true;
744 for (SH::Sample* const sample : sh) {
745 JobState::Enum state = sampleState(sample);
746 std::string details = sample->meta()->castString("nc_ELG_state_details", "", SH::MetaObject::CAST_NOCAST_DEFAULT);
747 if (not details.empty()) { details = '(' + details + ')'; }
748
749 std::cout << sample->name() << "\t";
750 switch (state) {
751 case JobState::INIT:
752 case JobState::RUN:
753 case JobState::DOWNLOAD:
754 case JobState::MERGE:
755 std::cout << JobState::name[state] << "\t";
756 break;
757 case JobState::FINISHED:
758 std::cout << "\033[1;32m" << JobState::name[state] << "\033[0m\t";
759 break;
760 case JobState::FAILED:
761 std::cout << "\033[1;31m" << JobState::name[state] << "\033[0m\t";
762 break;
763 }
764 std::cout << details << std::endl;
765
766 allDone &= (state == JobState::FINISHED || state == JobState::FAILED);
767 }
768
769 std::cout << std::endl;
770
771 data.retrieved = true;
772 data.completed = allDone;
773 return ::StatusCode::SUCCESS;
774}
#define RCU_ASSERT(x)
Definition Assert.h:210
#define RCU_REQUIRE(x)
Definition Assert.h:196
#define RCU_READ_INVARIANT(x)
Definition Assert.h:217
static JobState::Enum sampleState(SH::Sample *sample)
SH::MetaObject * options()
the list of options to jobs with this driver
double castDouble(const std::string &name, double def_val=0, CastMode mode=CAST_ERROR_THROW) const
the meta-data double with the given name
@ CAST_NOCAST_DEFAULT
cast and return the default value if the input has the wrong type
Definition MetaObject.h:70

◆ mergedOutputSave()

void EL::Driver::mergedOutputSave ( Detail::ManagerData & data)
staticinherited

create and save a sample handler assuming we created all the merged files at the requested locations

This is optional, but it is convenient for drivers that want to keep their outputs locally.

Guarantee
basic
Failures
out of memory II
i/o errors

◆ options() [1/2]

SH::MetaObject * EL::Driver::options ( )
inherited

the list of options to jobs with this driver

Guarantee
no-fail
Postcondition
result != 0

◆ options() [2/2]

const SH::MetaObject * EL::Driver::options ( ) const
inherited

◆ resubmit()

void EL::Driver::resubmit ( const std::string & location,
const std::string & option )
staticinherited

resubmit all failed sub-jobs for the job in the given location

\parm option driver-specific option string selecting which jobs to resubmit (and how)

Guarantee
basic, may partially resubmit
Failures
out of memory III
job resubmission errors
job can't be read
job was made with different driver

◆ retrieve()

bool EL::Driver::retrieve ( const std::string & location)
staticinherited

retrieve all the output for the job in the given location

While job failures will cause this method to fail you can typically retry it multiple times if you can use partial results.

Returns
whether the job completed successfully
Guarantee
basic, may partially retrieve
Failures
out of memory III
job failures
job can't be read
job was made with different driver

◆ setState()

void EL::PrunDriver::setState ( const std::string & location,
const std::string & task,
const std::string & state )
static

Definition at line 794 of file PrunDriver.cxx.

797{
798 RCU_REQUIRE(not location.empty());
799 RCU_REQUIRE(not task.empty());
800 RCU_REQUIRE(not state.empty());
801 TmpCd tmpDir(location);
802 SH::SampleHandler sh;
803 sh.load("input");
804 RCU_ASSERT(sh.size());
805 if (not sh.get(task)) {
806 std::cout << "Unknown task: " << task << std::endl;
807 std::cout << "Choose one of: " << std::endl;
808 sh.print();
809 return;
810 }
811 JobState::parse(state);
812 sh.get(task)->meta()->setString("nc_ELG_state", state);
813 sh.save("input");
814}

◆ status()

void EL::PrunDriver::status ( const std::string & location)
static

Definition at line 776 of file PrunDriver.cxx.

777{
778 RCU_REQUIRE(not location.empty());
779 TmpCd tmpDir(location);
780 SH::SampleHandler sh;
781 sh.load("input");
782 RCU_ASSERT(sh.size());
783 processAllInState(sh, JobState::RUN, 0);
784 sh.save("input");
785 for (SH::Sample* const sample : sh) {
786 JobState::Enum state = sampleState(sample);
787 std::string details = sample->meta()->castString("nc_ELG_state_details", "", SH::MetaObject::CAST_NOCAST_DEFAULT);
788 if (not details.empty()) { details = '(' + details + ')'; }
789 std::cout << sample->name() << "\t" << JobState::name[state]
790 << "\t" << details << std::endl;
791 }
792}

◆ submit()

std::string EL::Driver::submit ( const Job & job,
const std::string & location ) const
inherited

submit the given job with the given output location and wait for it to finish

This is mostly for small jobs and backward compatibility. For longer jobs use submitOnly instead.

Returns
The actual location of the submit directory, if the job was configured to generate a unique directory.
Guarantee
basic, may partially submit
Failures
out of memory II
Failures
can't create directory at location
submission errors

◆ submitOnly()

std::string EL::Driver::submitOnly ( const Job & job,
const std::string & location ) const
inherited

submit the given job with the given output location and return immediately

This method allows you to submit jobs to your local batch system, log out and at a later point log back in again.

Returns
The actual location of the submit directory, if the job was configured to generate a unique directory.
Guarantee
basic, may partially submit
Failures
out of memory II
can't create directory at location
submission errors \warn not all drivers support this. some will do all their work in the submit function. \warn you normally need to call wait() or retrieve() before you can use the output.

◆ testInvariant()

void EL::PrunDriver::testInvariant ( ) const

Definition at line 588 of file PrunDriver.cxx.

589{}

◆ updateLocation()

void EL::Driver::updateLocation ( const std::string & location)
staticinherited

update the internal location of files, after moving the submission directory

Guarantee
basic, may update partially
Failures
out of memory II \warn only move the submission directory after all your jobs are finished, or the results will be unpredictable

◆ wait()

bool EL::Driver::wait ( const std::string & location,
unsigned time = 60 )
staticinherited

retrieve all the output for the job in the given location and wait until it is finished completely.

poll the output every time seconds.

While job failures will cause this method to fail you can typically retry it multiple times if you can use partial results.

Typically sleeping for 60 seconds is an appropriate interval, but if it doesn't work for you, you can change it here.

Guarantee
basic, may partially retrieve
Failures
out of memory III
job failures
job can't be read
job was made with different driver

Member Data Documentation

◆ abortRetrieve

bool EL::Driver::abortRetrieve
staticprotectedinherited

this flag is set to true when the wait() function is running and a SIGINT is caught, meaning that control should be returned to the user as soon as possible.

drivers can use it to abort long running operations in doRetrieve before completion

Definition at line 212 of file Driver.h.

◆ m_options

SH::MetaObject EL::Driver::m_options
privateinherited

members directly corresponding to accessors

Definition at line 233 of file Driver.h.


The documentation for this class was generated from the following files: