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