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