CMS 3D CMS Logo

Classes | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes

ExternalLHEProducer Class Reference

#include <Example/ExternalLHEProducer/src/ExternalLHEProducer.cc>

Inheritance diagram for ExternalLHEProducer:
edm::EDProducer edm::ProducerBase edm::ProductRegistryHelper

List of all members.

Classes

class  FileCloseSentry

Public Member Functions

 ExternalLHEProducer (const edm::ParameterSet &iConfig)
 ~ExternalLHEProducer ()

Static Public Member Functions

static void fillDescriptions (edm::ConfigurationDescriptions &descriptions)

Private Member Functions

virtual void beginJob ()
virtual void beginLuminosityBlock (edm::LuminosityBlock &, edm::EventSetup const &)
virtual void beginRun (edm::Run &run, edm::EventSetup const &es)
int closeDescriptors (int preserve)
virtual void endJob ()
virtual void endLuminosityBlock (edm::LuminosityBlock &, edm::EventSetup const &)
virtual void endRun (edm::Run &, edm::EventSetup const &)
void executeScript ()
virtual void nextEvent ()
virtual void produce (edm::Event &, const edm::EventSetup &)
std::auto_ptr< std::string > readOutput ()

Private Attributes

std::vector< std::string > args_
uint32_t nEvents_
std::string outputContents_
std::string outputFile_
boost::shared_ptr< lhef::LHEEventpartonLevel
std::auto_ptr< lhef::LHEReaderreader_
boost::shared_ptr
< lhef::LHERunInfo
runInfo
boost::shared_ptr
< lhef::LHERunInfo
runInfoLast
boost::ptr_deque
< LHERunInfoProduct
runInfoProducts
std::string scriptName_
bool wasMerged

Detailed Description

Description: [one line class summary]

Implementation: [Notes on implementation]

Definition at line 63 of file ExternalLHEProducer.cc.


Constructor & Destructor Documentation

ExternalLHEProducer::ExternalLHEProducer ( const edm::ParameterSet iConfig) [explicit]

Definition at line 126 of file ExternalLHEProducer.cc.

                                                                       :
  scriptName_((iConfig.getParameter<edm::FileInPath>("scriptName")).fullPath().c_str()),
  outputFile_(iConfig.getParameter<std::string>("outputFile")),
  args_(iConfig.getParameter<std::vector<std::string> >("args")),
  nEvents_(iConfig.getParameter<uint32_t>("nEvents"))
{
  produces<std::string, edm::InRun>("LHEScriptOutput"); 

  produces<LHEEventProduct>();
  produces<LHERunInfoProduct, edm::InRun>();
}
ExternalLHEProducer::~ExternalLHEProducer ( )

Definition at line 139 of file ExternalLHEProducer.cc.

{
}

Member Function Documentation

void ExternalLHEProducer::beginJob ( void  ) [private, virtual]

Reimplemented from edm::EDProducer.

Definition at line 195 of file ExternalLHEProducer.cc.

{
}
void ExternalLHEProducer::beginLuminosityBlock ( edm::LuminosityBlock lumi,
edm::EventSetup const &   
) [private, virtual]

Reimplemented from edm::EDProducer.

Definition at line 439 of file ExternalLHEProducer.cc.

{
}
void ExternalLHEProducer::beginRun ( edm::Run run,
edm::EventSetup const &  es 
) [private, virtual]

Reimplemented from edm::EDProducer.

Definition at line 209 of file ExternalLHEProducer.cc.

References LHERunInfoProduct::addComment(), LHERunInfoProduct::addHeader(), args_, Exception, executeScript(), edm::Service< T >::isAvailable(), LogDebug, nEvents_, nextEvent(), outputContents_, edm::Run::put(), reader_, readOutput(), runInfo, runInfoLast, runInfoProducts, createPayload::skip, and wasMerged.

{

  // pass the number of events as previous to last argument
  
  std::ostringstream eventStream;
  eventStream << nEvents_;
  args_.push_back(eventStream.str());

  // pass the random number generator seed as last argument

  edm::Service<edm::RandomNumberGenerator> rng;

  if ( ! rng.isAvailable()) {
    throw cms::Exception("Configuration")
      << "The ExternalLHEProducer module requires the RandomNumberGeneratorService\n"
      "which is not present in the configuration file.  You must add the service\n"
      "in the configuration file if you want to run ExternalLHEProducer";
  }
  std::ostringstream randomStream;
  randomStream << rng->mySeed(); 
  args_.push_back(randomStream.str());

  for ( unsigned int iArg = 0; iArg < args_.size() ; iArg++ ) {
    LogDebug("LHEInputArgs") << "arg [" << iArg << "] = " << args_[iArg];
  }

  executeScript();
  std::auto_ptr<std::string> localContents = readOutput();
  outputContents_ = *localContents;

  run.put(localContents, "LHEScriptOutput");

  // LHE C++ classes translation

  unsigned int skip = 0;
  std::auto_ptr<lhef::LHEReader> thisRead( new lhef::LHEReader(outputContents_, skip ) );
  reader_ = thisRead;

  nextEvent();
  if (runInfoLast) {
    runInfo = runInfoLast;
  
    std::auto_ptr<LHERunInfoProduct> product(new LHERunInfoProduct(*runInfo->getHEPRUP()));
    std::for_each(runInfo->getHeaders().begin(),
                  runInfo->getHeaders().end(),
                  boost::bind(&LHERunInfoProduct::addHeader,
                              product.get(), _1));
    std::for_each(runInfo->getComments().begin(),
                  runInfo->getComments().end(),
                  boost::bind(&LHERunInfoProduct::addComment,
                              product.get(), _1));
  
    // keep a copy around in case of merging
    runInfoProducts.push_back(new LHERunInfoProduct(*product));
    wasMerged = false;
  
    run.put(product);
  
    runInfo.reset();
  }

}
int ExternalLHEProducer::closeDescriptors ( int  preserve) [private]

Definition at line 287 of file ExternalLHEProducer.cc.

References linker::DIR, dir, and NULL.

Referenced by executeScript().

{
  int maxfd = 1024;
  int fd;
#ifdef __linux__
  DIR * dir;
  struct dirent *dp;
  maxfd = preserve;
  if ((dir = opendir("/proc/self/fd"))) {
    errno = 0;
    while ((dp = readdir (dir)) != NULL) {
      if ((strcmp(dp->d_name, ".") == 0)  || (strcmp(dp->d_name, "..") == 0)) {
        continue;
      }
      if (sscanf(dp->d_name, "%d", &fd) != 1) {
        //throw cms::Exception("closeDescriptors") << "Found unexpected filename in /proc/self/fd: " << dp->d_name;
        return -1;
      }
      if (fd > maxfd) {
        maxfd = fd;
      }
    }
    if (errno) {
      //throw cms::Exception("closeDescriptors") << "Unable to determine the number of fd (errno=" << errno << ", " << strerror(errno) << ").";
      return errno;
    }
    closedir(dir);
  }
#endif
  // TODO: assert for an unreasonable number of fds?
  for (fd=3; fd<maxfd+1; fd++) {
    if (fd != preserve)
      close(fd);
  }
  return 0;
}
void ExternalLHEProducer::endJob ( void  ) [private, virtual]

Reimplemented from edm::EDProducer.

Definition at line 201 of file ExternalLHEProducer.cc.

References reader_.

                            {

  reader_.reset();

}
void ExternalLHEProducer::endLuminosityBlock ( edm::LuminosityBlock ,
edm::EventSetup const &   
) [private, virtual]

Reimplemented from edm::EDProducer.

Definition at line 445 of file ExternalLHEProducer.cc.

{
}
void ExternalLHEProducer::endRun ( edm::Run run,
edm::EventSetup const &  es 
) [private, virtual]

Reimplemented from edm::EDProducer.

Definition at line 275 of file ExternalLHEProducer.cc.

References edm::Run::put(), and runInfoProducts.

{

  if (!runInfoProducts.empty()) {
    std::auto_ptr<LHERunInfoProduct> product(runInfoProducts.pop_front().release());
    run.put(product);
  }

}
void ExternalLHEProducer::executeScript ( ) [private]

Definition at line 326 of file ExternalLHEProducer.cc.

References args_, closeDescriptors(), Exception, i, NULL, evf::utils::pid, testRegParams::pipe, SiPixelLorentzAngle_cfi::read, scriptName_, ntuplemaker::status, and TablePrint::write.

Referenced by beginRun().

{

  // Fork a script, wait until it finishes.

  int rc = 0, rc2 = 0;
  int filedes[2], fd_flags;
  unsigned int argc;

  if (pipe(filedes)) {
    throw cms::Exception("Unable to create a new pipe");
  }
  FileCloseSentry sentry1(filedes[0]), sentry2(filedes[1]);

  if ((fd_flags = fcntl(filedes[1], F_GETFD, NULL)) == -1) {
    throw cms::Exception("ExternalLHEProducer") << "Failed to get pipe file descriptor flags (errno=" << rc << ", " << strerror(rc) << ")";
  }
  if (fcntl(filedes[1], F_SETFD, fd_flags | FD_CLOEXEC) == -1) {
    throw cms::Exception("ExternalLHEProducer") << "Failed to set pipe file descriptor flags (errno=" << rc << ", " << strerror(rc) << ")";
  }

  argc = 1 + args_.size();
  // TODO: assert that we have a reasonable number of arguments
  char **argv = new char *[argc+1];
  argv[0] = strdup(scriptName_.c_str());
  for (unsigned int i=1; i<argc; i++) {
    argv[i] = strdup(args_[i-1].c_str());
  }
  argv[argc] = NULL;

  pid_t pid = fork();
  if (pid == 0) {
    // The child process
    if (!(rc = closeDescriptors(filedes[1]))) {
      execvp(argv[0], argv); // If execv returns, we have an error.
      rc = errno;
    }
    while ((write(filedes[1], &rc, sizeof(int)) == -1) && (errno == EINTR)) {}
    _exit(1);
  }

  // Free the arg vector ASAP
  for (unsigned int i=0; i<args_.size()+1; i++) {
    free(argv[i]);
  }
  delete [] argv;

  if (pid == -1) {
    throw cms::Exception("ForkException") << "Unable to fork a child (errno=" << errno << ", " << strerror(errno) << ")";
  }

  close(filedes[1]);
  // If the exec succeeds, the read will fail.
  while (((rc2 = read(filedes[0], &rc, sizeof(int))) == -1) && (errno == EINTR)) { rc2 = 0; }
  if ((rc2 == sizeof(int)) && rc) {
    throw cms::Exception("ExternalLHEProducer") << "Failed to execute script (errno=" << rc << ", " << strerror(rc) << ")";
  }
  close(filedes[0]);

  int status = 0;
  errno = 0;
  do {
    if (waitpid(pid, &status, 0) < 0) {
      if (errno == EINTR) {
        continue;
      } else {
        throw cms::Exception("ExternalLHEProducer") << "Failed to read child status (errno=" << errno << ", " << strerror(errno) << ")";
      }
    }
    if (WIFSIGNALED(status)) {
      throw cms::Exception("ExternalLHEProducer") << "Child exited due to signal " << WTERMSIG(status) << ".";
    }
    if (WIFEXITED(status)) {
      rc = WEXITSTATUS(status);
      break;
    }
  } while (true);
  if (rc) {
    throw cms::Exception("ExternalLHEProducer") << "Child failed with exit code " << rc << ".";
  }

}
void ExternalLHEProducer::fillDescriptions ( edm::ConfigurationDescriptions descriptions) [static]

Reimplemented from edm::EDProducer.

Definition at line 451 of file ExternalLHEProducer.cc.

References edm::ParameterSetDescription::add(), edm::ConfigurationDescriptions::addDefault(), and edm::ParameterSetDescription::setComment().

                                                                                {
  //The following says we do not know what parameters are allowed so do no validation
  // Please change this to state exactly what you do use, even if it is no parameters
  edm::ParameterSetDescription desc;
  desc.setComment("Executes an external script and places its output file into an EDM collection");

  edm::FileInPath thePath;
  desc.add<edm::FileInPath>("scriptName", thePath);
  desc.add<std::string>("outputFile", "myoutput");
  desc.add<std::vector<std::string> >("args");
  desc.add<uint32_t>("nEvents");

  descriptions.addDefault(desc);
}
void ExternalLHEProducer::nextEvent ( ) [private, virtual]

Definition at line 466 of file ExternalLHEProducer.cc.

References partonLevel, reader_, runInfo, and runInfoLast.

Referenced by beginRun(), and produce().

{

  if (partonLevel)
    return;

  partonLevel = reader_->next();
  if (!partonLevel)
    return;

  boost::shared_ptr<lhef::LHERunInfo> runInfoThis = partonLevel->getRunInfo();
  if (runInfoThis != runInfoLast) {
    runInfo = runInfoThis;
    runInfoLast = runInfoThis;
  }
}
void ExternalLHEProducer::produce ( edm::Event iEvent,
const edm::EventSetup iSetup 
) [private, virtual]

Implements edm::EDProducer.

Definition at line 150 of file ExternalLHEProducer.cc.

References LHERunInfoProduct::addComment(), LHEEventProduct::addComment(), LHERunInfoProduct::addHeader(), nextEvent(), partonLevel, edm::Event::put(), runInfo, runInfoProducts, and wasMerged.

{
  nextEvent();
  if (!partonLevel)
    return;

  std::auto_ptr<LHEEventProduct> product(new LHEEventProduct(*partonLevel->getHEPEUP()));
  if (partonLevel->getPDF())
    product->setPDF(*partonLevel->getPDF());
  std::for_each(partonLevel->getComments().begin(),
                partonLevel->getComments().end(),
                boost::bind(&LHEEventProduct::addComment,
                            product.get(), _1));

  iEvent.put(product);

  if (runInfo) {
    std::auto_ptr<LHERunInfoProduct> product(new LHERunInfoProduct(*runInfo->getHEPRUP()));
    std::for_each(runInfo->getHeaders().begin(),
                  runInfo->getHeaders().end(),
                  boost::bind(&LHERunInfoProduct::addHeader,
                              product.get(), _1));
    std::for_each(runInfo->getComments().begin(),
                  runInfo->getComments().end(),
                  boost::bind(&LHERunInfoProduct::addComment,
                              product.get(), _1));
  
    if (!runInfoProducts.empty()) {
      runInfoProducts.front().mergeProduct(*product);
      if (!wasMerged) {
        runInfoProducts.pop_front();
        runInfoProducts.push_front(product);
        wasMerged = true;
      }
    }
  
    runInfo.reset();
  }
  
  partonLevel.reset();
  return; 
}
std::auto_ptr< std::string > ExternalLHEProducer::readOutput ( ) [private]

Definition at line 411 of file ExternalLHEProducer.cc.

References BUFSIZE, Exception, n, outputFile_, and SiPixelLorentzAngle_cfi::read.

Referenced by beginRun().

{
  int fd;
  ssize_t n;
  char buf[BUFSIZE];

  if ((fd = open(outputFile_.c_str(), O_RDONLY)) == -1) {
    throw cms::Exception("OutputOpenError") << "Unable to open script output file " << outputFile_ << " (errno=" << errno << ", " << strerror(errno) << ").";
  }

  std::stringstream ss;
  while ((n = read(fd, buf, BUFSIZE)) > 0 || (n == -1 && errno == EINTR)) {
    if (n > 0)
      ss.write(buf, n);
  }
  if (n == -1) {
    throw cms::Exception("OutputOpenError") << "Unable to read from script output file " << outputFile_ << " (errno=" << errno << ", " << strerror(errno) << ").";
  }

  if (unlink(outputFile_.c_str())) {
    throw cms::Exception("OutputDeleteError") << "Unable to delete original script output file " << outputFile_ << " (errno=" << errno << ", " << strerror(errno) << ").";
  }

  return std::auto_ptr<std::string>(new std::string(ss.str()));
}

Member Data Documentation

std::vector<std::string> ExternalLHEProducer::args_ [private]

Definition at line 90 of file ExternalLHEProducer.cc.

Referenced by beginRun(), and executeScript().

uint32_t ExternalLHEProducer::nEvents_ [private]

Definition at line 91 of file ExternalLHEProducer.cc.

Referenced by beginRun().

std::string ExternalLHEProducer::outputContents_ [private]

Definition at line 92 of file ExternalLHEProducer.cc.

Referenced by beginRun().

std::string ExternalLHEProducer::outputFile_ [private]

Definition at line 89 of file ExternalLHEProducer.cc.

Referenced by readOutput().

boost::shared_ptr<lhef::LHEEvent> ExternalLHEProducer::partonLevel [private]

Definition at line 97 of file ExternalLHEProducer.cc.

Referenced by nextEvent(), and produce().

Definition at line 94 of file ExternalLHEProducer.cc.

Referenced by beginRun(), endJob(), and nextEvent().

boost::shared_ptr<lhef::LHERunInfo> ExternalLHEProducer::runInfo [private]

Definition at line 96 of file ExternalLHEProducer.cc.

Referenced by beginRun(), nextEvent(), and produce().

boost::shared_ptr<lhef::LHERunInfo> ExternalLHEProducer::runInfoLast [private]

Definition at line 95 of file ExternalLHEProducer.cc.

Referenced by beginRun(), and nextEvent().

Definition at line 98 of file ExternalLHEProducer.cc.

Referenced by beginRun(), endRun(), and produce().

std::string ExternalLHEProducer::scriptName_ [private]

Definition at line 88 of file ExternalLHEProducer.cc.

Referenced by executeScript().

Definition at line 99 of file ExternalLHEProducer.cc.

Referenced by beginRun(), and produce().