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