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