CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/FWCore/MessageLogger/src/JobReport.cc

Go to the documentation of this file.
00001 
00002 // -*- C++ -*-
00003 //
00004 //
00005 // 10/23/07 mf        In an attempt to get clues about (or ene) the
00006 //                does-not-output-branches behavior, changed the
00007 //                generic os<< lines in JobReport::JobReportImpl::writeOutputFile
00008 //                to direct use of LogInfo.
00009 //
00010 // 4/8/08   mf        Encase the logdesc for in <CDATA> ... </CDATA>
00011 //
00012 // 6/19/08  mf        reportMessageInfo()
00013 //
00014 // 24 June 2008   ewv  Correct format for CDATA and for second instance of reportError
00015 
00016 //
00017 // Original Author:  Marc Paterno
00018 //
00019 
00020 #include "FWCore/MessageLogger/interface/JobReport.h"
00021 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00022 #include "FWCore/Utilities/interface/Map.h"
00023 #include "FWCore/Utilities/interface/EDMException.h"
00024 
00025 #include "FWCore/Utilities/interface/tinyxml.h"
00026 
00027 #include <fstream>
00028 #include <iomanip>
00029 #include <iostream>
00030 #include <sstream>
00031 
00032 namespace edm {
00033   /*
00034    * Note that output formatting is spattered across these classes
00035    * If something outside these classes requires access to the
00036    * same formatting then we need to refactor it into a common library
00037    */
00038   template <typename S, typename T>
00039   S& formatFile(T const& f, S& os) {
00040 
00041     if(f.fileHasBeenClosed) {
00042       os << "\n<State  Value=\"closed\"/>";
00043     } else {
00044       os << "\n<State  Value=\"open\"/>";
00045     }
00046 
00047     os << "\n<LFN>" << TiXmlText(f.logicalFileName) << "</LFN>";
00048     os << "\n<PFN>" << TiXmlText(f.physicalFileName) << "</PFN>";
00049     os << "\n<Catalog>" << TiXmlText(f.catalog) << "</Catalog>";
00050     os << "\n<ModuleLabel>" << TiXmlText(f.moduleLabel) << "</ModuleLabel>";
00051     os << "\n<GUID>" << f.guid << "</GUID>";
00052     os << "\n<Branches>";
00053     for(std::vector<std::string>::const_iterator iBranch = f.branchNames.begin(),
00054         iBranchEnd = f.branchNames.end();
00055         iBranch != iBranchEnd;
00056         ++iBranch) {
00057       os << "\n  <Branch>" << TiXmlText(*iBranch) << "</Branch>";
00058     }
00059     os << "\n</Branches>";
00060     return os;
00061   }
00062     /*
00063      * Note that output formatting is spattered across these classes
00064      * If something outside these classes requires access to the
00065      * same formatting then we need to refactor it into a common library
00066      */
00067   template <typename S>
00068     S&
00069     print(S& os, JobReport::InputFile const& f) {
00070 
00071       os << "\n<InputFile>";
00072       formatFile(f, os);
00073       os << "\n<InputType>" << f.inputType << "</InputType>";
00074       os << "\n<InputSourceClass>" << TiXmlText(f.inputSourceClassName)
00075          << "</InputSourceClass>";
00076       os << "\n<EventsRead>" << f.numEventsRead << "</EventsRead>";
00077       return os;
00078     }
00079 
00080   template <typename S>
00081     S&
00082     print(S& os, JobReport::OutputFile const& f) {
00083       formatFile(f, os);
00084       os << "\n<OutputModuleClass>"
00085                         << TiXmlText(f.outputModuleClassName)
00086                         << "</OutputModuleClass>";
00087       os << "\n<TotalEvents>"
00088                         << f.numEventsWritten
00089                         << "</TotalEvents>\n";
00090       os << "\n<DataType>"
00091                         << TiXmlText(f.dataType)
00092                         << "</DataType>\n";
00093       os << "\n<BranchHash>"
00094                         << TiXmlText(f.branchHash)
00095                         << "</BranchHash>\n";
00096 
00097       return os;
00098     }
00099 
00100   template <typename S>
00101     S&
00102     print(S& os,
00103            JobReport::RunReport const& rep) {
00104     os << "\n<Run ID=\""
00105        << rep.runNumber
00106        << "\">\n";
00107 
00108     typedef std::set<unsigned int>::iterator iterator;
00109     for(iterator il = rep.lumiSections.begin(), ilEnd = rep.lumiSections.end(); il != ilEnd; ++il) {
00110       os << "   <LumiSection ID=\"" << *il << "\"/>\n";
00111 
00112     }
00113     os << "</Run>\n";
00114     return os;
00115   }
00116 
00117   std::ostream& operator<< (std::ostream& os, JobReport::InputFile const& f) {
00118     return print(os,f);
00119   }
00120   std::ostream& operator<< (std::ostream& os, JobReport::OutputFile const& f) {
00121     return print(os,f);
00122   }
00123 
00124   std::ostream& operator<< (std::ostream& os, JobReport::RunReport const& f) {
00125     return print(os,f);
00126   }
00127 
00128   //To talk to MessageLogger directly
00129   edm::MessageSender& operator<< (edm::MessageSender& os, JobReport::InputFile const& f) {
00130     return print(os,f);
00131   }
00132   edm::MessageSender& operator<< (edm::MessageSender& os, JobReport::OutputFile const& f) {
00133     return print(os,f);
00134   }
00135   edm::MessageSender& operator<< (edm::MessageSender& os, JobReport::RunReport const& f) {
00136     return print(os,f);
00137   }
00138 //  edm::MessageSender& operator<< (edm::MessageSender& os, JobReport::LumiSectionReport const& rep) {
00139 //    return print(os,rep);
00140 //  }
00141 //
00142 
00143     JobReport::InputFile& JobReport::JobReportImpl::getInputFileForToken(JobReport::Token t) {
00144         if(t >= inputFiles_.size()) {
00145             throw edm::Exception(edm::errors::LogicError)
00146               << "Access reported for input file with token "
00147               << t
00148               << " but no matching input file is found\n";
00149         }
00150 
00151         if(inputFiles_[t].fileHasBeenClosed) {
00152             throw edm::Exception(edm::errors::LogicError)
00153               << "Access reported for input file with token "
00154               << t
00155               << " after this file has been closed.\n"
00156               << "File record follows:\n"
00157               << inputFiles_[t]
00158               << '\n';
00159         }
00160 
00161       return inputFiles_[t];
00162     }
00163 
00164     JobReport::OutputFile& JobReport::JobReportImpl::getOutputFileForToken(JobReport::Token t) {
00165         if(t >= outputFiles_.size()) {
00166             throw edm::Exception(edm::errors::LogicError)
00167               << "Access reported for output file with token "
00168               << t
00169               << " but no matching output file is found\n";
00170         }
00171         if(outputFiles_[t].fileHasBeenClosed) {
00172             throw edm::Exception(edm::errors::LogicError)
00173               << "Access reported for output file with token "
00174               << t
00175               << " after this file has been closed.\n"
00176               << "File record follows:\n"
00177               << outputFiles_[t]
00178               << '\n';
00179         }
00180       return outputFiles_[t];
00181     }
00182 
00183     /*
00184      * Add the input file token provided to every output
00185      * file currently available.
00186      * Used whenever a new input file is opened, it's token
00187      * is added to all open output files as a contributor
00188      */
00189     void JobReport::JobReportImpl::insertInputForOutputs(JobReport::Token t) {
00190         typedef std::vector<JobReport::OutputFile>::iterator iterator;
00191         for(iterator outFile = outputFiles_.begin(), outFileEnd = outputFiles_.end(); outFile != outFileEnd; ++outFile) {
00192           outFile->contributingInputs.push_back(t);
00193         }
00194     }
00195     /*
00196      * get a vector of Tokens for all currently open
00197      * input files.
00198      * Used when a new output file is opened, all currently open
00199      * input file tokens are used to initialize its list of contributors
00200      */
00201     void JobReport::JobReportImpl::openInputFiles(std::vector<JobReport::Token>& result) {
00202         result.reserve(inputFiles_.size());
00203         for(unsigned int i = 0; i < inputFiles_.size(); ++i) {
00204           if(inputFiles_[i].fileHasBeenClosed == false) {
00205             result.push_back(i);
00206           }
00207         }
00208     }
00209 
00210     /*
00211      * get a vector of Tokens for all currently open
00212      * output files.
00213      *
00214      */
00215     void JobReport::JobReportImpl::openOutputFiles(std::vector<JobReport::Token>& result) {
00216         result.reserve(outputFiles_.size());
00217         for(unsigned int i = 0; i < outputFiles_.size(); ++i) {
00218           if(outputFiles_[i].fileHasBeenClosed == false) {
00219             result.push_back(i);
00220           }
00221         }
00222     }
00223 
00224     /*
00225      * Write anJobReport::InputFile object to the Logger
00226      * Generate XML string forJobReport::InputFile instance and dispatch to
00227      * job report via MessageLogger
00228      */
00229     void JobReport::JobReportImpl::writeInputFile(JobReport::InputFile const& f) {
00230       if(ost_) {
00231         *ost_ << f ;
00232         *ost_ << "\n<Runs>";
00233         typedef std::map<JobReport::RunNumber, JobReport::RunReport>::const_iterator const_iterator;
00234         for(const_iterator iRun = f.runReports.begin(), iRunEnd = f.runReports.end(); iRun != iRunEnd; ++iRun) {
00235           *ost_ << iRun->second;
00236         }
00237         *ost_ << "\n</Runs>\n";
00238         *ost_ << "</InputFile>\n";
00239         *ost_ << std::flush;
00240       }
00241         //LogInfo("FwkJob") << f;
00242     }
00243 
00244     /*
00245      * Write an OutputFile object to the Logger
00246      * Generate an XML string for the OutputFile provided and
00247      * dispatch it to the logger
00248      * Contributing input tokens are resolved to the input LFN and PFN
00249      *
00250      * TODO: We have not yet addressed the issue where we cleanup not
00251      * contributing input files.
00252      * Also, it is possible to get fake input to output file mappings
00253      * if an input file is open already when a new output file is opened
00254      * but the input gets closed without contributing events to the
00255      * output file due to filtering etc.
00256      *
00257      */
00258     void JobReport::JobReportImpl::writeOutputFile(JobReport::OutputFile const& f) {
00259       if(ost_) {
00260         *ost_ << "\n<File>";
00261         *ost_ << f;
00262 
00263         *ost_ << "\n<Runs>";
00264         typedef std::map<JobReport::RunNumber, JobReport::RunReport>::const_iterator const_iterator;
00265         for(const_iterator iRun = f.runReports.begin(), iRunEnd = f.runReports.end(); iRun != iRunEnd; ++iRun) {
00266           *ost_ << iRun->second;
00267         }
00268         *ost_ << "\n</Runs>\n";
00269 
00270         *ost_ << "\n<Inputs>";
00271         for(std::vector<JobReport::Token>::const_iterator
00272           iInput = f.contributingInputs.begin(),
00273           iInputEnd = f.contributingInputs.end();
00274           iInput != iInputEnd; ++iInput) {
00275             JobReport::InputFile inpFile = inputFiles_[*iInput];
00276             *ost_ << "\n<Input>";
00277             *ost_ << "\n  <LFN>" << TiXmlText(inpFile.logicalFileName) << "</LFN>";
00278             *ost_ << "\n  <PFN>" << TiXmlText(inpFile.physicalFileName) << "</PFN>";
00279             *ost_ << "\n  <FastCopying>" << findOrDefault(f.fastCopyingInputs, inpFile.physicalFileName) << "</FastCopying>";
00280             *ost_ << "\n</Input>";
00281         }
00282         *ost_ << "\n</Inputs>";
00283         *ost_ << "\n</File>\n";
00284       }
00285     }
00286 
00287     /*
00288      *  Flush all open files to logger in event of a problem.
00289      *  Called from JobReport dtor to flush any remaining open files
00290      */
00291     void JobReport::JobReportImpl::flushFiles(void) {
00292       for(std::vector<JobReport::InputFile>::iterator ipos = inputFiles_.begin(), iposEnd = inputFiles_.end();
00293           ipos != iposEnd; ++ipos) {
00294         if(!(ipos->fileHasBeenClosed)) {
00295           writeInputFile(*ipos);
00296         }
00297       }
00298       for(std::vector<JobReport::OutputFile>::iterator opos = outputFiles_.begin(), oposEnd = outputFiles_.end();
00299           opos != oposEnd; ++opos) {
00300         if(!(opos->fileHasBeenClosed)) {
00301           writeOutputFile(*opos);
00302         }
00303       }
00304     }
00305 
00306   void JobReport::JobReportImpl::addGeneratorInfo(std::string const& name,
00307                                                   std::string const& value) {
00308 
00309     generatorInfo_[name] = value;
00310   }
00311 
00312   void JobReport::JobReportImpl::writeGeneratorInfo(void) {
00313     if(ost_) {
00314       *ost_ << "\n<GeneratorInfo>\n";
00315       for(std::map<std::string, std::string>::iterator pos = generatorInfo_.begin(),
00316           posEnd = generatorInfo_.end();
00317           pos != posEnd;  ++pos) {
00318         std::ostringstream msg;
00319         msg << "\n<Data Name=\"" << pos->first
00320           << "\" Value=\"" << pos->second << "\"/>";
00321         *ost_ << msg.str();
00322       }
00323       *ost_ << "</GeneratorInfo>\n";
00324     }
00325   }
00326 
00327   void JobReport::JobReportImpl::associateRun(unsigned int runNumber) {
00328     std::vector<Token> openFiles;
00329     openOutputFiles(openFiles);
00330     for(std::vector<Token>::iterator iToken = openFiles.begin(), iTokenEnd = openFiles.end(); iToken != iTokenEnd; ++iToken) {
00331       JobReport::OutputFile& theFile = outputFiles_[*iToken];
00332 
00333       //
00334       // check run is known to file
00335       // if not, add a run report for that run
00336       if(theFile.runReports.count(runNumber) == 0) {
00337         JobReport::RunReport newReport = JobReport::RunReport();
00338         newReport.runNumber = runNumber;
00339         theFile.runReports.insert(
00340                  std::make_pair(runNumber, newReport)
00341                 );
00342       }
00343 
00344     }
00345   }
00346 
00347   void JobReport::JobReportImpl::associateInputRun(unsigned int runNumber) {
00348     std::vector<Token> openFiles;
00349     openInputFiles(openFiles);
00350     for(std::vector<Token>::iterator iToken = openFiles.begin(), iTokenEnd = openFiles.end(); iToken != iTokenEnd; ++iToken) {
00351       JobReport::InputFile& theFile = inputFiles_[*iToken];
00352 
00353       //
00354       // check run is known to file
00355       // if not, add a run report for that run
00356       if(theFile.runReports.count(runNumber) == 0) {
00357         JobReport::RunReport newReport = JobReport::RunReport();
00358         newReport.runNumber = runNumber;
00359         theFile.runReports.insert(std::make_pair(runNumber, newReport));
00360       }
00361 
00362     }
00363   }
00364 
00365   void JobReport::JobReportImpl::associateLumiSection(unsigned int runNumber, unsigned int lumiSect) {
00366     std::vector<Token> openFiles;
00367     openOutputFiles(openFiles);
00368     for(std::vector<Token>::iterator iToken = openFiles.begin(), iTokenEnd = openFiles.end(); iToken != iTokenEnd; ++iToken) {
00369       //
00370       // Loop over all open output files
00371       //
00372       JobReport::OutputFile& theFile = outputFiles_[*iToken];
00373 
00374       //
00375       // check run is known to file
00376       // if not, add a run report for that run
00377       if(theFile.runReports.count(runNumber) == 0) {
00378         JobReport::RunReport newReport = JobReport::RunReport();
00379         newReport.runNumber = runNumber;
00380         theFile.runReports.insert(std::make_pair(runNumber, newReport));
00381       }
00382 
00383       //
00384       // Get the run report for this run, now that it either was created
00385       // or already existed
00386       std::map<JobReport::RunNumber, JobReport::RunReport>::iterator finder;
00387       finder = theFile.runReports.find(runNumber);
00388 
00389       //
00390       // add the lumi section to the report, the lumi list is a Set
00391       // so duplicates dont matter
00392       (finder->second).lumiSections.insert(lumiSect);
00393     }
00394   }
00395 
00396   void JobReport::JobReportImpl::associateInputLumiSection(unsigned int runNumber, unsigned int lumiSect) {
00397     std::vector<Token> openFiles;
00398     openInputFiles(openFiles);
00399     for(std::vector<Token>::iterator iToken = openFiles.begin(), iTokenEnd = openFiles.end(); iToken != iTokenEnd; ++iToken) {
00400       //
00401       // Loop over all open input files
00402       //
00403       JobReport::InputFile& theFile = inputFiles_[*iToken];
00404 
00405       //
00406       // check run is known to file
00407       // if not, add a run report for that run
00408       if(theFile.runReports.count(runNumber) == 0) {
00409         JobReport::RunReport newReport = JobReport::RunReport();
00410         newReport.runNumber = runNumber;
00411         theFile.runReports.insert(std::make_pair(runNumber, newReport));
00412       }
00413 
00414       //
00415       // Get the run report for this run, now that it either was created
00416       // or already existed
00417       std::map<JobReport::RunNumber, JobReport::RunReport>::iterator finder;
00418       finder = theFile.runReports.find(runNumber);
00419 
00420       //
00421       // add the lumi section to the report, the lumi list is a Set
00422       // so duplicates dont matter
00423       (finder->second).lumiSections.insert(lumiSect);
00424     }
00425   }
00426 
00427   JobReport::~JobReport() {
00428     impl_->writeGeneratorInfo();
00429     impl_->flushFiles();
00430     if(impl_->ost_) {
00431       *(impl_->ost_) << "</FrameworkJobReport>\n" << std::flush;
00432     }
00433   }
00434 
00435     JobReport::JobReport() :
00436       impl_(new JobReportImpl(0)) {
00437     }
00438 
00439     JobReport::JobReport(std::ostream* iOstream) : impl_(new JobReportImpl(iOstream)) {
00440       if(impl_->ost_) {
00441         *(impl_->ost_) << "<FrameworkJobReport>\n";
00442       }
00443     }
00444 
00445   namespace {
00446     void
00447     toFileName(std::string const& jobReportFile, unsigned int childIndex, unsigned int numberOfChildren, std::ostringstream& ofilename) {
00448       char filler = ofilename.fill();
00449       unsigned int numberOfDigitsInIndex = 0U;
00450       while (numberOfChildren != 0) {
00451         ++numberOfDigitsInIndex;
00452         numberOfChildren /= 10;
00453       }
00454       if(numberOfDigitsInIndex == 0) {
00455         numberOfDigitsInIndex = 3; // Protect against zero numberOfChildren
00456       }
00457       std::string::size_type offset = jobReportFile.rfind('.');
00458       if(offset == std::string::npos) {
00459         ofilename << jobReportFile;
00460         ofilename << '_' << std::setw(numberOfDigitsInIndex) << std::setfill('0') << childIndex << std::setfill(filler);
00461       } else {
00462         ofilename << jobReportFile.substr(0, offset);
00463         ofilename << '_' << std::setw(numberOfDigitsInIndex) << std::setfill('0') << childIndex << std::setfill(filler);
00464         ofilename << jobReportFile.substr(offset);
00465       }
00466     }
00467   }
00468 
00469     void
00470     JobReport::parentBeforeFork(std::string const& jobReportFile, unsigned int numberOfChildren) {
00471       if(impl_->ost_) {
00472         *(impl_->ost_) << "<ChildProcessFiles>\n";
00473         for(unsigned int i = 0; i < numberOfChildren; ++i) {
00474           std::ostringstream ofilename;
00475           toFileName(jobReportFile, i, numberOfChildren, ofilename);
00476           *(impl_->ost_) << "  <ChildProcessFile>" << ofilename.str() << "</ChildProcessFile>\n";
00477         }
00478         *(impl_->ost_) << "</ChildProcessFiles>\n";
00479         *(impl_->ost_) << "</FrameworkJobReport>\n";
00480         std::ofstream* p = dynamic_cast<std::ofstream *>(impl_->ost_);
00481         if(p) {
00482           p->close();
00483         }
00484       }
00485     }
00486 
00487     void
00488     JobReport::parentAfterFork(std::string const& /*jobReportFile*/) {
00489     }
00490 
00491     void
00492     JobReport::childAfterFork(std::string const& jobReportFile, unsigned int childIndex, unsigned int numberOfChildren) {
00493       std::ofstream* p = dynamic_cast<std::ofstream*>(impl_->ost_);
00494       if(!p) return;
00495       std::ostringstream ofilename;
00496       toFileName(jobReportFile, childIndex, numberOfChildren, ofilename);
00497       p->open(ofilename.str().c_str());
00498       *p << "<FrameworkJobReport>\n";
00499     }
00500 
00501     JobReport::Token
00502     JobReport::inputFileOpened(std::string const& physicalFileName,
00503                                std::string const& logicalFileName,
00504                                std::string const& catalog,
00505                                std::string const& inputType,
00506                                std::string const& inputSourceClassName,
00507                                std::string const& moduleLabel,
00508                                std::string const& guid,
00509                                std::vector<std::string> const& branchNames) {
00510       // Do we have to worry about thread safety here? Or is this
00511       // service used in a way to make this safe?
00512       impl_->inputFiles_.push_back(JobReport::InputFile());
00513       JobReport::InputFile& r = impl_->inputFiles_.back();
00514       impl_->fastClonedBranches_ = &r.fastClonedBranches;
00515 
00516       r.logicalFileName      = logicalFileName;
00517       r.physicalFileName     = physicalFileName;
00518       r.catalog              = catalog;
00519       r.inputType            = inputType;
00520       r.inputSourceClassName = inputSourceClassName;
00521       r.moduleLabel          = moduleLabel;
00522       r.guid                 = guid;
00523       // r.runsSeen is not modified
00524       r.numEventsRead        = 0;
00525       r.branchNames          = branchNames;
00526       r.fileHasBeenClosed    = false;
00527 
00528       JobReport::Token newToken = impl_->inputFiles_.size()-1;
00529         //
00530        // Add the new input file token to all output files
00531       //  currently open.
00532       impl_->insertInputForOutputs(newToken);
00533       return newToken;
00534     }
00535 
00536     void
00537     JobReport::eventReadFromFile(JobReport::Token fileToken, unsigned int /*run*/, unsigned int) {
00538       JobReport::InputFile& f = impl_->getInputFileForToken(fileToken);
00539       ++f.numEventsRead;
00540       //f.runsSeen.insert(run);
00541     }
00542 
00543     void
00544     JobReport::reportDataType(Token fileToken, std::string const& dataType) {
00545       JobReport::OutputFile& f = impl_->getOutputFileForToken(fileToken);
00546       f.dataType = dataType;
00547     }
00548 
00549     void
00550     JobReport::inputFileClosed(JobReport::Token fileToken) {
00551       JobReport::InputFile& f = impl_->getInputFileForToken(fileToken);
00552       // Dump information to the MessageLogger's JobSummary
00553       // about this file.
00554       // After setting the file to 'closed', we will no longer be able
00555       // to reference it by ID.
00556       f.fileHasBeenClosed = true;
00557       impl_->writeInputFile(f);
00558     }
00559 
00560     JobReport::Token
00561     JobReport::outputFileOpened(std::string const& physicalFileName,
00562                                 std::string const& logicalFileName,
00563                                 std::string const& catalog,
00564                                 std::string const& outputModuleClassName,
00565                                 std::string const& moduleLabel,
00566                                 std::string const& guid,
00567                                 std::string const& dataType,
00568                                 std::string const& branchHash,
00569                                 std::vector<std::string> const& branchNames) {
00570       impl_->outputFiles_.push_back(JobReport::OutputFile());
00571       JobReport::OutputFile& r = impl_->outputFiles_.back();
00572 
00573       r.logicalFileName       = logicalFileName;
00574       r.physicalFileName      = physicalFileName;
00575       r.catalog               = catalog;
00576       r.outputModuleClassName = outputModuleClassName;
00577       r.moduleLabel           = moduleLabel;
00578       r.guid           = guid;
00579       r.dataType = dataType;
00580       r.branchHash = branchHash;
00581       // r.runsSeen is not modified
00582       r.numEventsWritten      = 0;
00583       r.branchNames           = branchNames;
00584       r.fileHasBeenClosed     = false;
00585         //
00586        // Init list of contributors to list of open input file Tokens
00587       //
00588       impl_->openInputFiles(r.contributingInputs);
00589       return impl_->outputFiles_.size()-1;
00590     }
00591 
00592     void
00593     JobReport::eventWrittenToFile(JobReport::Token fileToken, unsigned int /*run*/, unsigned int) {
00594       JobReport::OutputFile& f = impl_->getOutputFileForToken(fileToken);
00595       ++f.numEventsWritten;
00596       //f.runsSeen.insert(run);
00597     }
00598 
00599     void
00600     JobReport::outputFileClosed(JobReport::Token fileToken) {
00601       JobReport::OutputFile& f = impl_->getOutputFileForToken(fileToken);
00602       // Dump information to the MessageLogger's JobSummary
00603       // about this file.
00604       // After setting the file to 'closed', we will no longer be able
00605       // to reference it by ID.
00606       f.fileHasBeenClosed = true;
00607       impl_->writeOutputFile(f);
00608     }
00609 
00610     void
00611     JobReport:: reportFastCopyingStatus(JobReport::Token fileToken, std::string const& inputFileName, bool fastCopying) {
00612       JobReport::OutputFile& f = impl_->getOutputFileForToken(fileToken);
00613       f.fastCopyingInputs.insert(std::make_pair(inputFileName, fastCopying));
00614     }
00615 
00616     void
00617     JobReport::overrideEventsWritten(Token fileToken, int const eventsWritten) {
00618       // Get the required output file instance using the token
00619       JobReport::OutputFile& f = impl_->getOutputFileForToken(fileToken);
00620       // set the eventsWritten parameter to the provided value
00621       f.numEventsWritten = eventsWritten;
00622     }
00623 
00624     void
00625     JobReport::overrideEventsRead(Token fileToken, int const eventsRead) {
00626       // Get the required input file instance using the token
00627       JobReport::InputFile& f = impl_->getInputFileForToken(fileToken);
00628       // set the events read parameter to the provided value
00629       f.numEventsRead = eventsRead;
00630     }
00631 
00632     void
00633     JobReport::overrideContributingInputs(Token outputToken,
00634                                           std::vector<Token> const& inputTokens) {
00635        // Get the required output file instance using the token
00636       JobReport::OutputFile& f = impl_->getOutputFileForToken(outputToken);
00637       // override its contributing inputs data
00638       f.contributingInputs = inputTokens;
00639     }
00640 
00641     void
00642     JobReport::reportSkippedEvent(unsigned int run, unsigned int event) {
00643       if(impl_->ost_) {
00644         std::ostream& msg = *(impl_->ost_);
00645         msg << "<SkippedEvent Run=\"" << run << "\"";
00646         msg << " Event=\"" << event << "\" />\n";
00647         msg << std::flush;
00648         //LogInfo("FwkJob") << msg.str();
00649       }
00650     }
00651 
00652   void
00653   JobReport::reportLumiSection(unsigned int run, unsigned int lumiSectId) {
00654     impl_->associateLumiSection(run, lumiSectId);
00655   }
00656 
00657   void
00658   JobReport::reportInputLumiSection(unsigned int run, unsigned int lumiSectId) {
00659     impl_->associateInputLumiSection(run, lumiSectId);
00660   }
00661 
00662   void
00663   JobReport::reportRunNumber(unsigned int run) {
00664     impl_->associateRun(run);
00665   }
00666   void
00667   JobReport::reportInputRunNumber(unsigned int run) {
00668     impl_->associateInputRun(run);
00669   }
00670 
00671   void
00672   JobReport::reportError(std::string const& shortDesc,
00673                            std::string const& longDesc) {
00674     if(impl_->ost_) {
00675       std::ostream& msg = *(impl_->ost_);
00676       msg << "<FrameworkError ExitStatus=\"1\" Type=\"" << shortDesc << "\" >\n";
00677       msg << "<![CDATA[\n" << longDesc << "\n]]>\n";
00678       msg << "</FrameworkError>\n";
00679    //LogError("FwkJob") << msg.str();
00680       msg << std::flush;
00681     }
00682   }
00683 
00684   void
00685   JobReport::reportAnalysisFile(std::string const& fileName, std::map<std::string, std::string> const& fileData) {
00686     if(impl_->ost_) {
00687       std::ostream& msg = *(impl_->ost_);
00688       //std::ostringstream msg;
00689       msg << "<AnalysisFile>\n"
00690           << "  <FileName>" << TiXmlText(fileName) << "</FileName>\n";
00691 
00692       typedef std::map<std::string, std::string>::const_iterator const_iterator;
00693       for(const_iterator pos = fileData.begin(), posEnd = fileData.end(); pos != posEnd; ++pos) {
00694         msg <<  "  <" << pos->first
00695             <<  "  Value=\"" << pos->second  << "\" />"
00696             <<  "\n";
00697       }
00698       msg << "</AnalysisFile>\n";
00699       //LogError("FwkJob") << msg.str();
00700       msg << std::flush;
00701     }
00702   }
00703 
00704   void
00705   JobReport::reportError(std::string const& shortDesc,
00706                          std::string const& longDesc,
00707                          int const& exitCode) {
00708     if(impl_->ost_) {
00709       std::ostream& msg = *(impl_->ost_);
00710       //std::ostringstream msg;
00711       msg << "<FrameworkError ExitStatus=\""<< exitCode
00712             << "\" Type=\"" << shortDesc << "\" >\n";
00713       msg << "<![CDATA[\n" << longDesc << "\n]]>\n";
00714       msg << "</FrameworkError>\n";
00715       //LogError("FwkJob") << msg.str();
00716       msg << std::flush;
00717     }
00718   }
00719 
00720   void
00721   JobReport::reportSkippedFile(std::string const& pfn,
00722                                std::string const& lfn) {
00723     if(impl_->ost_) {
00724       std::ostream& msg = *(impl_->ost_);
00725       TiXmlElement skipped("SkippedFile");
00726       skipped.SetAttribute("Pfn", pfn);
00727       skipped.SetAttribute("Lfn", lfn);
00728       msg << skipped << "\n";
00729       msg << std::flush;
00730       //LogInfo("FwkJob") << msg.str();
00731     }
00732   }
00733 
00734   void
00735   JobReport::reportFallbackAttempt(std::string const& pfn, std::string const& lfn, std::string const& err) {
00736     if(impl_->ost_) {
00737       std::ostream& msg = *(impl_->ost_);
00738       TiXmlElement fallback("FallbackAttempt");
00739       fallback.SetAttribute("Pfn", pfn);
00740       fallback.SetAttribute("Lfn", lfn);
00741       msg << fallback << "\n";
00742       msg << "<![CDATA[\n" << err << "\n]]>\n";
00743       msg << std::flush;
00744       //LogInfo("FwkJob") << msg.str();
00745     }
00746   }
00747 
00748   void
00749   JobReport::reportMemoryInfo(std::vector<std::string> const& memoryData) {
00750     if(impl_->ost_) {
00751       std::ostream& msg = *(impl_->ost_);
00752       msg << "<MemoryService>\n";
00753 
00754       typedef std::vector<std::string>::const_iterator const_iterator;
00755       for(const_iterator pos = memoryData.begin(), posEnd = memoryData.end(); pos != posEnd; ++pos) {
00756         msg << *pos << "\n";
00757       }
00758       msg << "</MemoryService>\n";
00759       msg << std::flush;
00760     }
00761   }
00762 
00763   void
00764   JobReport::reportMessageInfo(std::map<std::string, double> const& messageData) {
00765     if(impl_->ost_) {
00766       std::ostream& msg = *(impl_->ost_);
00767       msg << "<MessageSummary>\n";
00768       typedef std::map<std::string, double>::const_iterator const_iterator;
00769       for(const_iterator pos = messageData.begin(), posEnd = messageData.end(); pos != posEnd; ++pos) {
00770         msg <<  "  <" << pos->first
00771         <<  "  Value=\"" << pos->second  << "\" />"
00772         <<  "\n";
00773       }
00774       msg << "</MessageSummary>\n";
00775       msg << std::flush;
00776     }
00777   }
00778 
00779   void
00780   JobReport::reportReadBranches() {
00781     if(impl_->ost_) {
00782       std::ostream& ost = *(impl_->ost_);
00783       ost << "<ReadBranches>\n";
00784       typedef std::map<std::string, long long>::const_iterator const_iterator;
00785       for(const_iterator it = impl_->readBranches_.begin(), itEnd = impl_->readBranches_.end(); it != itEnd; ++it) {
00786         TiXmlElement branch("Branch");
00787         branch.SetAttribute("Name", it->first);
00788         branch.SetAttribute("ReadCount", it->second);
00789         ost << branch << "\n";
00790         // ost << "  <Branch Name=" << '"' << it->first << '"'<<  " ReadCount=" << it->second << ">\n";
00791       }
00792       ost << "</ReadBranches>\n";
00793       ost << std::flush;
00794     }
00795   }
00796 
00797   void
00798   JobReport::reportReadBranch(std::string const& branchName) {
00799     // Fast cloned branches have already been reported.
00800     if(impl_->fastClonedBranches_->find(branchName) == impl_->fastClonedBranches_->end()) {
00801       ++impl_->readBranches_[branchName];
00802     }
00803   }
00804 
00805   void
00806   JobReport::reportFastClonedBranches(std::set<std::string> const& fastClonedBranches, long long nEvents) {
00807     for(std::set<std::string>::const_iterator it = fastClonedBranches.begin(), itEnd = fastClonedBranches.end();
00808         it != itEnd; ++it) {
00809       if(impl_->fastClonedBranches_->insert(*it).second) {
00810         impl_->readBranches_[*it] += nEvents;
00811       }
00812     }
00813   }
00814 
00815   void
00816   JobReport::reportGeneratorInfo(std::string const& name, std::string const& value) {
00817     impl_->addGeneratorInfo(name, value);
00818   }
00819 
00820   void JobReport::reportRandomStateFile(std::string const& name) {
00821     if(impl_->ost_) {
00822       std::ostream& msg = *(impl_->ost_);
00823       msg << "<RandomServiceStateFile>\n"
00824         << TiXmlText(name) << "\n"
00825         <<  "</RandomServiceStateFile>\n";
00826       //LogInfo("FwkJob") << msg.str();
00827       msg << std::flush;
00828     }
00829   }
00830 
00831   void
00832   JobReport::reportPSetHash(std::string const& hashValue) {
00833     if(impl_->ost_) {
00834       std::ostream& msg = *(impl_->ost_);
00835       msg << "<PSetHash>"
00836         <<  hashValue
00837         <<  "</PSetHash>\n";
00838       //LogInfo("FwkJob") << msg.str();
00839       msg << std::flush;
00840     }
00841   }
00842 
00843   void
00844   JobReport::reportPerformanceSummary(std::string const& metricClass,
00845                                       std::map<std::string, std::string> const& metrics) {
00846     if(impl_->ost_) {
00847       std::ostream& msg = *(impl_->ost_);
00848       msg << "<PerformanceReport>\n"
00849         << "  <PerformanceSummary Metric=\"" << metricClass << "\">\n";
00850 
00851       typedef std::map<std::string, std::string>::const_iterator const_iterator;
00852       for(const_iterator iter = metrics.begin(), iterEnd = metrics.end(); iter != iterEnd; ++iter) {
00853         msg << "    <Metric Name=\"" << iter->first << "\" "
00854         << "Value=\"" << iter->second << "\"/>\n";
00855       }
00856 
00857       msg << "  </PerformanceSummary>\n"
00858         << "</PerformanceReport>\n";
00859       msg << std::flush;
00860       //LogInfo("FwkJob") << msg.str();
00861     }
00862   }
00863 
00864   void
00865   JobReport::reportPerformanceForModule(std::string const&  metricClass,
00866                                         std::string const&  moduleName,
00867                                         std::map<std::string, std::string> const& metrics) {
00868     if(impl_->ost_) {
00869       std::ostream& msg = *(impl_->ost_);
00870       msg << "<PerformanceReport>\n"
00871         << "  <PerformanceModule Metric=\"" << metricClass << "\" "
00872         << " Module=\"" << moduleName << "\" >\n";
00873 
00874       typedef std::map<std::string, std::string>::const_iterator const_iterator;
00875       for(const_iterator iter = metrics.begin(), iterEnd = metrics.end(); iter != iterEnd; ++iter) {
00876         msg << "    <Metric Name=\"" << iter->first << "\" "
00877         << "Value=\"" << iter->second << "\"/>\n";
00878       }
00879 
00880       msg << "  </PerformanceModule>\n"
00881         << "</PerformanceReport>\n";
00882       msg << std::flush;
00883       //LogInfo("FwkJob") << msg.str();
00884     }
00885   }
00886 
00887   std::string
00888   JobReport::dumpFiles(void) {
00889     std::ostringstream msg;
00890 
00891     typedef std::vector<JobReport::OutputFile>::iterator iterator;
00892 
00893     for(iterator f = impl_->outputFiles_.begin(), fEnd = impl_->outputFiles_.end(); f != fEnd; ++f) {
00894 
00895       msg << "\n<File>";
00896       msg << *f;
00897 
00898       msg << "\n<LumiSections>";
00899       //typedef std::vector<JobReport::LumiSectionReport>::iterator Iter;
00900       //for(Iter iLumi = f->lumiSections.begin(),
00901       //     iLumiEnd = f->lumiSections.end();
00902       //     iLumi != iLumiEnd;  ++iLumi) {
00903       //  msg << *iLumi;
00904       //}
00905       //msg << "\n</LumiSections>\n";
00906       msg << "\n<Inputs>";
00907       typedef std::vector<JobReport::Token>::iterator iterator;
00908       for(iterator iInput = f->contributingInputs.begin(),
00909           iInputEnd = f->contributingInputs.end();
00910           iInput != iInputEnd; ++iInput) {
00911         JobReport::InputFile inpFile = impl_->inputFiles_[*iInput];
00912         msg << "\n<Input>";
00913         msg << "\n  <LFN>" << TiXmlText(inpFile.logicalFileName) << "</LFN>";
00914         msg << "\n  <PFN>" << TiXmlText(inpFile.physicalFileName) << "</PFN>";
00915         msg << "\n  <FastCopying>" << findOrDefault(f->fastCopyingInputs, inpFile.physicalFileName) << "</FastCopying>";
00916         msg << "\n</Input>";
00917       }
00918       msg << "\n</Inputs>";
00919       msg << "\n</File>";
00920 
00921     }
00922     return msg.str();
00923   }
00924 
00925 } //namspace edm