00001
00002
00003
00004
00005 #include "FWCore/Framework/interface/OutputModule.h"
00006
00007 #include "DataFormats/Common/interface/Handle.h"
00008 #include "DataFormats/Provenance/interface/BranchDescription.h"
00009 #include "DataFormats/Provenance/interface/BranchKey.h"
00010 #include "DataFormats/Provenance/interface/ParentageRegistry.h"
00011 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00012 #include "FWCore/Framework/interface/CurrentProcessingContext.h"
00013 #include "FWCore/Framework/interface/Event.h"
00014 #include "FWCore/Framework/interface/EventPrincipal.h"
00015 #include "FWCore/Framework/interface/OutputModuleDescription.h"
00016 #include "FWCore/Framework/interface/TriggerNamesService.h"
00017 #include "FWCore/Framework/src/CPCSentry.h"
00018 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00019 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00020 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00021 #include "FWCore/ServiceRegistry/interface/Service.h"
00022 #include "FWCore/Utilities/interface/DebugMacros.h"
00023
00024 #include <cassert>
00025
00026 namespace edm {
00027
00028 std::vector<std::string> const& getAllTriggerNames() {
00029 Service<service::TriggerNamesService> tns;
00030 return tns->getTrigPaths();
00031 }
00032 }
00033
00034 namespace {
00035
00036
00037 void remove_whitespace(std::string& s) {
00038 s.erase(std::remove(s.begin(), s.end(), ' '), s.end());
00039 s.erase(std::remove(s.begin(), s.end(), '\t'), s.end());
00040 }
00041
00042 void test_remove_whitespace() {
00043 std::string a("noblanks");
00044 std::string b("\t no blanks \t");
00045
00046 remove_whitespace(b);
00047 assert(a == b);
00048 }
00049
00050
00051
00052
00053
00054 typedef std::pair<std::string, std::string> parsed_path_spec_t;
00055 void parse_path_spec(std::string const& path_spec,
00056 parsed_path_spec_t& output) {
00057 std::string trimmed_path_spec(path_spec);
00058 remove_whitespace(trimmed_path_spec);
00059
00060 std::string::size_type colon = trimmed_path_spec.find(":");
00061 if(colon == std::string::npos) {
00062 output.first = trimmed_path_spec;
00063 } else {
00064 output.first = trimmed_path_spec.substr(0, colon);
00065 output.second = trimmed_path_spec.substr(colon + 1,
00066 trimmed_path_spec.size());
00067 }
00068 }
00069
00070 void test_parse_path_spec() {
00071 std::vector<std::string> paths;
00072 paths.push_back("a:p1");
00073 paths.push_back("b:p2");
00074 paths.push_back(" c");
00075 paths.push_back("ddd\t:p3");
00076 paths.push_back("eee: p4 ");
00077
00078 std::vector<parsed_path_spec_t> parsed(paths.size());
00079 for(size_t i = 0; i < paths.size(); ++i) {
00080 parse_path_spec(paths[i], parsed[i]);
00081 }
00082
00083 assert(parsed[0].first == "a");
00084 assert(parsed[0].second == "p1");
00085 assert(parsed[1].first == "b");
00086 assert(parsed[1].second == "p2");
00087 assert(parsed[2].first == "c");
00088 assert(parsed[2].second == "");
00089 assert(parsed[3].first == "ddd");
00090 assert(parsed[3].second == "p3");
00091 assert(parsed[4].first == "eee");
00092 assert(parsed[4].second == "p4");
00093 }
00094 }
00095
00096 namespace edm {
00097 namespace test {
00098 void run_all_output_module_tests() {
00099 test_remove_whitespace();
00100 test_parse_path_spec();
00101 }
00102 }
00103
00104
00105 OutputModule::OutputModule(ParameterSet const& pset) :
00106 maxEvents_(-1),
00107 remainingEvents_(maxEvents_),
00108 keptProducts_(),
00109 hasNewlyDroppedBranch_(),
00110 process_name_(),
00111 productSelectorRules_(pset, "outputCommands", "OutputModule"),
00112 productSelector_(),
00113 moduleDescription_(),
00114 current_context_(nullptr),
00115 prodsValid_(false),
00116 wantAllEvents_(false),
00117 selectors_(),
00118 selector_config_id_(),
00119 droppedBranchIDToKeptBranchID_(),
00120 branchIDLists_(new BranchIDLists),
00121 origBranchIDLists_(nullptr),
00122 branchParents_(),
00123 branchChildren_() {
00124
00125 hasNewlyDroppedBranch_.fill(false);
00126
00127 Service<service::TriggerNamesService> tns;
00128 process_name_ = tns->getProcessName();
00129
00130 ParameterSet selectevents =
00131 pset.getUntrackedParameterSet("SelectEvents", ParameterSet());
00132
00133 selectevents.registerIt();
00134
00135 selector_config_id_ = selectevents.id();
00136
00137
00138
00139
00140 if(selectevents.empty()) {
00141 wantAllEvents_ = true;
00142 selectors_.setupDefault(getAllTriggerNames());
00143 return;
00144 }
00145
00146 std::vector<std::string> path_specs =
00147 selectevents.getParameter<std::vector<std::string> >("SelectEvents");
00148
00149 if(path_specs.empty()) {
00150 wantAllEvents_ = true;
00151 selectors_.setupDefault(getAllTriggerNames());
00152 return;
00153 }
00154
00155
00156
00157 std::vector<parsed_path_spec_t> parsed_paths(path_specs.size());
00158 for(size_t i = 0; i < path_specs.size(); ++i) {
00159 parse_path_spec(path_specs[i], parsed_paths[i]);
00160 }
00161 selectors_.setup(parsed_paths, getAllTriggerNames(), process_name_);
00162 }
00163
00164 void OutputModule::configure(OutputModuleDescription const& desc) {
00165 remainingEvents_ = maxEvents_ = desc.maxEvents_;
00166 origBranchIDLists_ = desc.branchIDLists_;
00167 }
00168
00169 void OutputModule::selectProducts(ProductRegistry const& preg) {
00170 if(productSelector_.initialized()) return;
00171 productSelector_.initialize(productSelectorRules_, preg.allBranchDescriptions());
00172
00173
00174
00175
00176
00177 std::map<BranchID, BranchDescription const*> trueBranchIDToKeptBranchDesc;
00178
00179 for(auto const& it : preg.productList()) {
00180 BranchDescription const& desc = it.second;
00181 if(desc.transient()) {
00182
00183 } else if(!desc.present() && !desc.produced()) {
00184
00185
00186 } else if(selected(desc)) {
00187
00188 if(desc.produced()) {
00189
00190
00191 BranchID const& trueBranchID = desc.originalBranchID();
00192 std::map<BranchID, BranchDescription const*>::const_iterator iter = trueBranchIDToKeptBranchDesc.find(trueBranchID);
00193 if(iter != trueBranchIDToKeptBranchDesc.end()) {
00194 throw edm::Exception(errors::Configuration, "Duplicate Output Selection")
00195 << "Two (or more) equivalent branches have been selected for output.\n"
00196 << "#1: " << BranchKey(desc) << "\n"
00197 << "#2: " << BranchKey(*iter->second) << "\n"
00198 << "Please drop at least one of them.\n";
00199 }
00200 trueBranchIDToKeptBranchDesc.insert(std::make_pair(trueBranchID, &desc));
00201 }
00202 switch (desc.branchType()) {
00203 case InEvent:
00204 {
00205 consumes(TypeToGet{desc.unwrappedTypeID(),PRODUCT_TYPE},
00206 InputTag{desc.moduleLabel(),
00207 desc.productInstanceName(),
00208 desc.processName()});
00209 break;
00210 }
00211 case InLumi:
00212 {
00213 consumes<InLumi>(TypeToGet{desc.unwrappedTypeID(),PRODUCT_TYPE},
00214 InputTag(desc.moduleLabel(),
00215 desc.productInstanceName(),
00216 desc.processName()));
00217 break;
00218 }
00219 case InRun:
00220 {
00221 consumes<InRun>(TypeToGet{desc.unwrappedTypeID(),PRODUCT_TYPE},
00222 InputTag(desc.moduleLabel(),
00223 desc.productInstanceName(),
00224 desc.processName()));
00225 break;
00226 }
00227 default:
00228 assert(false);
00229 break;
00230 }
00231
00232 keptProducts_[desc.branchType()].push_back(&desc);
00233 } else {
00234
00235
00236 hasNewlyDroppedBranch_[desc.branchType()] = true;
00237 }
00238 }
00239
00240 for(auto const& it : preg.productList()) {
00241 BranchDescription const& desc = it.second;
00242 if(!desc.produced() || desc.isAlias()) continue;
00243 BranchID const& branchID = desc.branchID();
00244 std::map<BranchID, BranchDescription const*>::const_iterator iter = trueBranchIDToKeptBranchDesc.find(branchID);
00245 if(iter != trueBranchIDToKeptBranchDesc.end()) {
00246
00247 BranchID const& keptBranchID = iter->second->branchID();
00248 if(keptBranchID != branchID) {
00249
00250 droppedBranchIDToKeptBranchID_.insert(std::make_pair(branchID.id(), keptBranchID.id()));
00251 }
00252 }
00253 }
00254 }
00255
00256 OutputModule::~OutputModule() { }
00257
00258 void OutputModule::doBeginJob() {
00259 this->beginJob();
00260 }
00261
00262 void OutputModule::doEndJob() {
00263 endJob();
00264 }
00265
00266
00267 Trig OutputModule::getTriggerResults(Event const& ev) const {
00268 return selectors_.getOneTriggerResults(ev);
00269 }
00270
00271 Trig OutputModule::getTriggerResults(EventPrincipal const& ep) const {
00272
00273
00274
00275
00276 Event ev(const_cast<EventPrincipal&>(ep),
00277 *current_context_->moduleDescription());
00278 return getTriggerResults(ev);
00279 }
00280
00281 namespace {
00282 class PVSentry {
00283 public:
00284 PVSentry(detail::CachedProducts& prods, bool& valid) : p(prods), v(valid) {}
00285 ~PVSentry() {
00286 p.clear();
00287 v = false;
00288 }
00289 private:
00290 detail::CachedProducts& p;
00291 bool& v;
00292
00293 PVSentry(PVSentry const&);
00294 PVSentry& operator=(PVSentry const&);
00295 };
00296 }
00297
00298 bool
00299 OutputModule::doEvent(EventPrincipal const& ep,
00300 EventSetup const&,
00301 CurrentProcessingContext const* cpc) {
00302 detail::CPCSentry sentry(current_context_, cpc);
00303 PVSentry products_sentry(selectors_, prodsValid_);
00304
00305 FDEBUG(2) << "writeEvent called\n";
00306
00307 if(!wantAllEvents_) {
00308
00309
00310 Event e(const_cast<EventPrincipal&>(ep), moduleDescription_);
00311 if(!selectors_.wantEvent(e)) {
00312 return true;
00313 }
00314 }
00315 write(ep);
00316 updateBranchParents(ep);
00317 if(remainingEvents_ > 0) {
00318 --remainingEvents_;
00319 }
00320 return true;
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 bool
00340 OutputModule::doBeginRun(RunPrincipal const& rp,
00341 EventSetup const&,
00342 CurrentProcessingContext const* cpc) {
00343 detail::CPCSentry sentry(current_context_, cpc);
00344 FDEBUG(2) << "beginRun called\n";
00345 beginRun(rp);
00346 return true;
00347 }
00348
00349 bool
00350 OutputModule::doEndRun(RunPrincipal const& rp,
00351 EventSetup const&,
00352 CurrentProcessingContext const* cpc) {
00353 detail::CPCSentry sentry(current_context_, cpc);
00354 FDEBUG(2) << "endRun called\n";
00355 endRun(rp);
00356 return true;
00357 }
00358
00359 void
00360 OutputModule::doWriteRun(RunPrincipal const& rp) {
00361 FDEBUG(2) << "writeRun called\n";
00362 writeRun(rp);
00363 }
00364
00365 bool
00366 OutputModule::doBeginLuminosityBlock(LuminosityBlockPrincipal const& lbp,
00367 EventSetup const&,
00368 CurrentProcessingContext const* cpc) {
00369 detail::CPCSentry sentry(current_context_, cpc);
00370 FDEBUG(2) << "beginLuminosityBlock called\n";
00371 beginLuminosityBlock(lbp);
00372 return true;
00373 }
00374
00375 bool
00376 OutputModule::doEndLuminosityBlock(LuminosityBlockPrincipal const& lbp,
00377 EventSetup const&,
00378 CurrentProcessingContext const* cpc) {
00379 detail::CPCSentry sentry(current_context_, cpc);
00380 FDEBUG(2) << "endLuminosityBlock called\n";
00381 endLuminosityBlock(lbp);
00382 return true;
00383 }
00384
00385 void OutputModule::doWriteLuminosityBlock(LuminosityBlockPrincipal const& lbp) {
00386 FDEBUG(2) << "writeLuminosityBlock called\n";
00387 writeLuminosityBlock(lbp);
00388 }
00389
00390 void OutputModule::doOpenFile(FileBlock const& fb) {
00391 openFile(fb);
00392 }
00393
00394 void OutputModule::doRespondToOpenInputFile(FileBlock const& fb) {
00395 respondToOpenInputFile(fb);
00396 }
00397
00398 void OutputModule::doRespondToCloseInputFile(FileBlock const& fb) {
00399 respondToCloseInputFile(fb);
00400 }
00401
00402 void OutputModule::doRespondToOpenOutputFiles(FileBlock const& fb) {
00403 respondToOpenOutputFiles(fb);
00404 }
00405
00406 void OutputModule::doRespondToCloseOutputFiles(FileBlock const& fb) {
00407 respondToCloseOutputFiles(fb);
00408 }
00409
00410 void
00411 OutputModule::doPreForkReleaseResources() {
00412 preForkReleaseResources();
00413 }
00414
00415 void
00416 OutputModule::doPostForkReacquireResources(unsigned int iChildIndex, unsigned int iNumberOfChildren) {
00417 postForkReacquireResources(iChildIndex, iNumberOfChildren);
00418 }
00419
00420 void OutputModule::maybeOpenFile() {
00421 if(!isFileOpen()) doOpenFile();
00422 }
00423
00424 void OutputModule::doCloseFile() {
00425 if(isFileOpen()) reallyCloseFile();
00426 }
00427
00428 void OutputModule::reallyCloseFile() {
00429 fillDependencyGraph();
00430 startEndFile();
00431 writeFileFormatVersion();
00432 writeFileIdentifier();
00433 writeIndexIntoFile();
00434 writeProcessConfigurationRegistry();
00435 writeProcessHistoryRegistry();
00436 writeParameterSetRegistry();
00437 writeProductDescriptionRegistry();
00438 writeParentageRegistry();
00439 writeBranchIDListRegistry();
00440 writeProductDependencies();
00441 writeBranchMapper();
00442 finishEndFile();
00443 branchParents_.clear();
00444 branchChildren_.clear();
00445 }
00446
00447 BranchIDLists const*
00448 OutputModule::branchIDLists() const {
00449 if(!droppedBranchIDToKeptBranchID_.empty()) {
00450
00451 *branchIDLists_ = *origBranchIDLists_;
00452
00453 for(BranchIDList& branchIDList : *branchIDLists_) {
00454 for(BranchID::value_type& branchID : branchIDList) {
00455
00456 std::map<BranchID::value_type, BranchID::value_type>::const_iterator iter = droppedBranchIDToKeptBranchID_.find(branchID);
00457 if(iter != droppedBranchIDToKeptBranchID_.end()) {
00458 branchID = iter->second;
00459 }
00460 }
00461 }
00462 return branchIDLists_.get();
00463 }
00464 return origBranchIDLists_;
00465 }
00466
00467 CurrentProcessingContext const*
00468 OutputModule::currentContext() const {
00469 return current_context_;
00470 }
00471
00472 ModuleDescription const&
00473 OutputModule::description() const {
00474 return moduleDescription_;
00475 }
00476
00477 bool
00478 OutputModule::selected(BranchDescription const& desc) const {
00479 return productSelector_.selected(desc);
00480 }
00481
00482 void
00483 OutputModule::fillDescriptions(ConfigurationDescriptions& descriptions) {
00484 ParameterSetDescription desc;
00485 desc.setUnknown();
00486 descriptions.addDefault(desc);
00487 }
00488
00489 void
00490 OutputModule::fillDescription(ParameterSetDescription& desc) {
00491 ProductSelectorRules::fillDescription(desc, "outputCommands");
00492 EventSelector::fillDescription(desc);
00493 }
00494
00495 void
00496 OutputModule::prevalidate(ConfigurationDescriptions& ) {
00497 }
00498
00499
00500 static const std::string kBaseType("OutputModule");
00501 const std::string&
00502 OutputModule::baseType() {
00503 return kBaseType;
00504 }
00505
00506 void
00507 OutputModule::setEventSelectionInfo(std::map<std::string, std::vector<std::pair<std::string, int> > > const& outputModulePathPositions,
00508 bool anyProductProduced) {
00509
00510 ParameterSet selectEventsInfo;
00511 selectEventsInfo.copyForModify(getParameterSet(selector_config_id_));
00512 selectEventsInfo.addParameter<bool>("InProcessHistory", anyProductProduced);
00513 std::string const& label = description().moduleLabel();
00514 std::vector<std::string> endPaths;
00515 std::vector<int> endPathPositions;
00516
00517
00518
00519 if (!label.empty()) {
00520 std::map<std::string, std::vector<std::pair<std::string, int> > >::const_iterator iter = outputModulePathPositions.find(label);
00521 assert(iter != outputModulePathPositions.end());
00522 for (std::vector<std::pair<std::string, int> >::const_iterator i = iter->second.begin(), e = iter->second.end();
00523 i != e; ++i) {
00524 endPaths.push_back(i->first);
00525 endPathPositions.push_back(i->second);
00526 }
00527 }
00528 selectEventsInfo.addParameter<std::vector<std::string> >("EndPaths", endPaths);
00529 selectEventsInfo.addParameter<std::vector<int> >("EndPathPositions", endPathPositions);
00530 if (!selectEventsInfo.exists("SelectEvents")) {
00531 selectEventsInfo.addParameter<std::vector<std::string> >("SelectEvents", std::vector<std::string>());
00532 }
00533 selectEventsInfo.registerIt();
00534
00535 selector_config_id_ = selectEventsInfo.id();
00536 }
00537
00538 void
00539 OutputModule::updateBranchParents(EventPrincipal const& ep) {
00540 for(EventPrincipal::const_iterator i = ep.begin(), iEnd = ep.end(); i != iEnd; ++i) {
00541 if((*i) && (*i)->productProvenancePtr() != 0) {
00542 BranchID const& bid = (*i)->branchDescription().branchID();
00543 BranchParents::iterator it = branchParents_.find(bid);
00544 if(it == branchParents_.end()) {
00545 it = branchParents_.insert(std::make_pair(bid, std::set<ParentageID>())).first;
00546 }
00547 it->second.insert((*i)->productProvenancePtr()->parentageID());
00548 branchChildren_.insertEmpty(bid);
00549 }
00550 }
00551 }
00552
00553 void
00554 OutputModule::fillDependencyGraph() {
00555 for(BranchParents::const_iterator i = branchParents_.begin(), iEnd = branchParents_.end();
00556 i != iEnd; ++i) {
00557 BranchID const& child = i->first;
00558 std::set<ParentageID> const& eIds = i->second;
00559 for(std::set<ParentageID>::const_iterator it = eIds.begin(), itEnd = eIds.end();
00560 it != itEnd; ++it) {
00561 Parentage entryDesc;
00562 ParentageRegistry::instance()->getMapped(*it, entryDesc);
00563 std::vector<BranchID> const& parents = entryDesc.parents();
00564 for(std::vector<BranchID>::const_iterator j = parents.begin(), jEnd = parents.end();
00565 j != jEnd; ++j) {
00566 branchChildren_.insertChild(*j, child);
00567 }
00568 }
00569 }
00570 }
00571 }