Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:03:11

0001 ///////////////////////////////////////////////////////////////////////
0002 ///
0003 /// Module to write trigger bit mappings (AlCaRecoTriggerBits) to DB.
0004 /// Can be configured to read an old one and update this by
0005 /// - removing old entries
0006 /// - adding new ones
0007 ///
0008 ///////////////////////////////////////////////////////////////////////
0009 
0010 #include <string>
0011 #include <map>
0012 #include <vector>
0013 #include <algorithm>
0014 #include <set>
0015 
0016 // Framework
0017 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0018 #include "FWCore/ServiceRegistry/interface/Service.h"
0019 #include "FWCore/Framework/interface/EventSetup.h"
0020 #include "FWCore/Framework/interface/one/EDAnalyzer.h"
0021 #include "FWCore/Framework/interface/MakerMacros.h"
0022 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0023 
0024 // Database
0025 #include "CondCore/DBOutputService/interface/PoolDBOutputService.h"
0026 
0027 // What I want to write:
0028 #include "CondFormats/HLTObjects/interface/AlCaRecoTriggerBits.h"
0029 // Rcd for reading old one:
0030 #include "CondFormats/DataRecord/interface/AlCaRecoTriggerBitsRcd.h"
0031 
0032 class AlCaRecoTriggerBitsRcdUpdate : public edm::one::EDAnalyzer<> {
0033 public:
0034   explicit AlCaRecoTriggerBitsRcdUpdate(const edm::ParameterSet &cfg);
0035   ~AlCaRecoTriggerBitsRcdUpdate() override = default;
0036 
0037   void analyze(const edm::Event &evt, const edm::EventSetup &evtSetup) override;
0038   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions);
0039 
0040 private:
0041   typedef std::map<std::string, std::string> TriggerMap;
0042   bool removeKeysFromMap(const std::vector<std::string> &keys, TriggerMap &triggerMap) const;
0043   bool replaceKeysFromMap(const std::vector<edm::ParameterSet> &alcarecoReplace, TriggerMap &triggerMap) const;
0044   bool addTriggerLists(const std::vector<edm::ParameterSet> &triggerListsAdd, AlCaRecoTriggerBits &bits) const;
0045   bool addPathsFromMap(const std::vector<edm::ParameterSet> &pathsToAdd, AlCaRecoTriggerBits &bits) const;
0046   bool removePathsFromMap(const std::vector<edm::ParameterSet> &pathsToRemove, AlCaRecoTriggerBits &bits) const;
0047   void writeBitsToDB(const AlCaRecoTriggerBits &bitsToWrite) const;
0048 
0049   const edm::ESGetToken<AlCaRecoTriggerBits, AlCaRecoTriggerBitsRcd> triggerBitsToken_;
0050   unsigned int nEventCalls_;
0051   const unsigned int firstRunIOV_;
0052   const int lastRunIOV_;
0053   const bool startEmpty_;
0054   const std::vector<std::string> listNamesRemove_;
0055   const std::vector<edm::ParameterSet> triggerListsAdd_;
0056   const std::vector<edm::ParameterSet> alcarecoReplace_;
0057   const std::vector<edm::ParameterSet> pathsToAdd_;
0058   const std::vector<edm::ParameterSet> pathsToRemove_;
0059 };
0060 
0061 ///////////////////////////////////////////////////////////////////////
0062 void AlCaRecoTriggerBitsRcdUpdate::fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0063   edm::ParameterSetDescription desc;
0064   desc.setComment("Plugin to write payloads of type AlCaRecoTriggerBits");
0065   desc.add<unsigned int>("firstRunIOV", 1);
0066   desc.add<int>("lastRunIOV", -1);
0067   desc.add<bool>("startEmpty", true);
0068   desc.add<std::vector<std::string>>("listNamesRemove", {});
0069 
0070   edm::ParameterSetDescription desc_triggeListsToAdd;
0071   desc_triggeListsToAdd.add<std::string>("listName");
0072   desc_triggeListsToAdd.add<std::vector<std::string>>("hltPaths");
0073   std::vector<edm::ParameterSet> default_triggerListsToAdd;
0074   desc.addVPSet("triggerListsAdd", desc_triggeListsToAdd, default_triggerListsToAdd);
0075 
0076   edm::ParameterSetDescription desc_alcarecoToReplace;
0077   desc_alcarecoToReplace.add<std::string>("oldKey");
0078   desc_alcarecoToReplace.add<std::string>("newKey");
0079   std::vector<edm::ParameterSet> default_alcarecoToReplace;
0080   desc.addVPSet("alcarecoToReplace", desc_alcarecoToReplace, default_alcarecoToReplace);
0081 
0082   edm::ParameterSetDescription desc_pathsToAdd;
0083   desc_pathsToAdd.add<std::string>("listName");
0084   desc_pathsToAdd.add<std::vector<std::string>>("hltPaths");
0085   std::vector<edm::ParameterSet> default_pathsToAdd;
0086   desc.addVPSet("pathsToAdd", desc_pathsToAdd, default_pathsToAdd);
0087 
0088   edm::ParameterSetDescription desc_pathsToRemove;
0089   desc_pathsToRemove.add<std::string>("listName");
0090   desc_pathsToRemove.add<std::vector<std::string>>("hltPaths");
0091   std::vector<edm::ParameterSet> default_pathsToRemove;
0092   desc.addVPSet("pathsToRemove", desc_pathsToRemove, default_pathsToRemove);
0093 
0094   descriptions.addWithDefaultLabel(desc);
0095 }
0096 
0097 ///////////////////////////////////////////////////////////////////////
0098 AlCaRecoTriggerBitsRcdUpdate::AlCaRecoTriggerBitsRcdUpdate(const edm::ParameterSet &cfg)
0099     : triggerBitsToken_(esConsumes()),
0100       nEventCalls_(0),
0101       firstRunIOV_(cfg.getParameter<unsigned int>("firstRunIOV")),
0102       lastRunIOV_(cfg.getParameter<int>("lastRunIOV")),
0103       startEmpty_(cfg.getParameter<bool>("startEmpty")),
0104       listNamesRemove_(cfg.getParameter<std::vector<std::string>>("listNamesRemove")),
0105       triggerListsAdd_(cfg.getParameter<std::vector<edm::ParameterSet>>("triggerListsAdd")),
0106       alcarecoReplace_(cfg.getParameter<std::vector<edm::ParameterSet>>("alcarecoToReplace")),
0107       pathsToAdd_(cfg.getParameter<std::vector<edm::ParameterSet>>("pathsToAdd")),
0108       pathsToRemove_(cfg.getParameter<std::vector<edm::ParameterSet>>("pathsToRemove")) {}
0109 
0110 ///////////////////////////////////////////////////////////////////////
0111 void AlCaRecoTriggerBitsRcdUpdate::analyze(const edm::Event &evt, const edm::EventSetup &iSetup) {
0112   if (nEventCalls_++ > 0) {  // postfix increment!
0113     edm::LogWarning("BadConfig") << "@SUB=analyze"
0114                                  << "Writing to DB to be done only once, set\n"
0115                                  << "'process.maxEvents = cms.untracked.PSet(input = cms.untracked.int32(1))'\n"
0116                                  << " next time. But your writing is fine.)";
0117     return;
0118   }
0119 
0120   // create what to write - starting from empty or existing list
0121   std::unique_ptr<AlCaRecoTriggerBits> bitsToWrite;
0122   if (startEmpty_) {
0123     bitsToWrite = std::make_unique<AlCaRecoTriggerBits>();
0124   } else {
0125     bitsToWrite = std::make_unique<AlCaRecoTriggerBits>(iSetup.getData(triggerBitsToken_));
0126   }
0127 
0128   // remove some existing entries in map
0129   this->removeKeysFromMap(listNamesRemove_, bitsToWrite->m_alcarecoToTrig);
0130 
0131   // now add new entries
0132   this->addTriggerLists(triggerListsAdd_, *bitsToWrite);
0133 
0134   // now replace keys
0135   this->replaceKeysFromMap(alcarecoReplace_, bitsToWrite->m_alcarecoToTrig);
0136 
0137   // add paths to the existing key
0138   this->addPathsFromMap(pathsToAdd_, *bitsToWrite);
0139 
0140   // remove paths from the existing key
0141   this->removePathsFromMap(pathsToRemove_, *bitsToWrite);
0142 
0143   // finally write to DB
0144   this->writeBitsToDB(*bitsToWrite);
0145 }
0146 
0147 ///////////////////////////////////////////////////////////////////////
0148 bool AlCaRecoTriggerBitsRcdUpdate::removeKeysFromMap(const std::vector<std::string> &keys,
0149                                                      TriggerMap &triggerMap) const {
0150   for (std::vector<std::string>::const_iterator iKey = keys.begin(), endKey = keys.end(); iKey != endKey; ++iKey) {
0151     if (triggerMap.find(*iKey) != triggerMap.end()) {
0152       triggerMap.erase(*iKey);
0153     } else {  // not in list ==> misconfiguartion!
0154       throw cms::Exception("BadConfig") << "[AlCaRecoTriggerBitsRcdUpdate::removeKeysFromMap] "
0155                                         << "Cannot remove key '" << *iKey << "' since not in "
0156                                         << "list - typo in configuration?\n";
0157       return false;
0158     }
0159   }
0160   return true;
0161 }
0162 
0163 ///////////////////////////////////////////////////////////////////////
0164 bool AlCaRecoTriggerBitsRcdUpdate::replaceKeysFromMap(const std::vector<edm::ParameterSet> &alcarecoReplace,
0165                                                       TriggerMap &triggerMap) const {
0166   std::vector<std::pair<std::string, std::string>> keyPairs;
0167   keyPairs.reserve(alcarecoReplace.size());
0168 
0169   for (auto &iSet : alcarecoReplace) {
0170     const std::string oldKey(iSet.getParameter<std::string>("oldKey"));
0171     const std::string newKey(iSet.getParameter<std::string>("newKey"));
0172     keyPairs.push_back(std::make_pair(oldKey, newKey));
0173   }
0174 
0175   for (auto &iKey : keyPairs) {
0176     if (triggerMap.find(iKey.first) != triggerMap.end()) {
0177       std::string bitsToReplace = triggerMap[iKey.first];
0178       triggerMap.erase(iKey.first);
0179       triggerMap[iKey.second] = bitsToReplace;
0180     } else {  // not in list ==> misconfiguration!
0181       edm::LogWarning("AlCaRecoTriggerBitsRcdUpdate")
0182           << "[AlCaRecoTriggerBitsRcdUpdate::replaceKeysFromMap] "
0183           << "Cannot replace key '" << iKey.first << "with " << iKey.second << " since not in "
0184           << "list - typo in configuration?\n";
0185       return false;
0186     }
0187   }
0188   return true;
0189 }
0190 
0191 ///////////////////////////////////////////////////////////////////////
0192 bool AlCaRecoTriggerBitsRcdUpdate::addTriggerLists(const std::vector<edm::ParameterSet> &triggerListsAdd,
0193                                                    AlCaRecoTriggerBits &bits) const {
0194   TriggerMap &triggerMap = bits.m_alcarecoToTrig;
0195 
0196   // loop on PSets, each containing the key (filter name) and a vstring with triggers
0197   for (const auto &iSet : triggerListsAdd) {
0198     const std::vector<std::string> paths(iSet.getParameter<std::vector<std::string>>("hltPaths"));
0199     // We must avoid a map<string,vector<string> > in DB for performance reason,
0200     // so we have to merge the paths into one string that will be decoded when needed:
0201     const std::string mergedPaths = bits.compose(paths);
0202 
0203     const std::string filter(iSet.getParameter<std::string>("listName"));
0204     if (triggerMap.find(filter) != triggerMap.end()) {
0205       throw cms::Exception("BadConfig") << "List name '" << filter << "' already in map, either "
0206                                         << "remove from 'triggerListsAdd' or "
0207                                         << " add to 'listNamesRemove'.\n";
0208     }
0209     triggerMap[filter] = mergedPaths;
0210   }
0211 
0212   return true;
0213 }
0214 
0215 ///////////////////////////////////////////////////////////////////////
0216 bool AlCaRecoTriggerBitsRcdUpdate::addPathsFromMap(const std::vector<edm::ParameterSet> &pathsToAdd,
0217                                                    AlCaRecoTriggerBits &bits) const {
0218   TriggerMap &triggerMap = bits.m_alcarecoToTrig;  //read from the condition tag
0219 
0220   // loop on PSets, each containing the key (filter name) and a vstring with triggers
0221   for (const auto &iSet : pathsToAdd) {
0222     const std::string filter(iSet.getParameter<std::string>("listName"));
0223     std::string mergedPathsInKey;
0224 
0225     for (const auto &imap : triggerMap) {
0226       if (imap.first == filter)
0227         mergedPathsInKey = imap.second;  //paths in the condition tag
0228     }
0229 
0230     if (mergedPathsInKey.empty()) {
0231       throw cms::Exception("BadConfig") << "List name '" << filter << "' not found in the map, "
0232                                         << "if you want to add new key/paths, please use 'addTriggerLists'.\n";
0233     }
0234 
0235     auto const &pathsInKey = bits.decompose(mergedPathsInKey);
0236     auto const &paths = iSet.getParameter<std::vector<std::string>>("hltPaths");  //paths to add; from the configuration
0237 
0238     if (paths.empty()) {  // nothing to add ==> misconfiguration!
0239       throw cms::Exception("BadConfig") << "Didn't set any path to add!";
0240     }
0241 
0242     std::set<std::string> pathsSet{pathsInKey.begin(), pathsInKey.end()};
0243     std::copy(paths.begin(), paths.end(), std::inserter(pathsSet, pathsSet.end()));
0244     std::vector<std::string> const newPathsInKey{pathsSet.begin(), pathsSet.end()};
0245 
0246     // We must avoid a map<string,vector<string> > in DB for performance reason,
0247     // so we have to merge the paths into one string that will be decoded when needed:
0248     triggerMap[filter] = bits.compose(newPathsInKey);
0249   }
0250 
0251   return true;
0252 }
0253 
0254 ///////////////////////////////////////////////////////////////////////
0255 bool AlCaRecoTriggerBitsRcdUpdate::removePathsFromMap(const std::vector<edm::ParameterSet> &pathsToRemove,
0256                                                       AlCaRecoTriggerBits &bits) const {
0257   TriggerMap &triggerMap = bits.m_alcarecoToTrig;  //read from the condition tag
0258 
0259   // loop on PSets, each containing the key (filter name) and a vstring with triggers
0260   for (const auto &iSet : pathsToRemove) {
0261     const std::string filter(iSet.getParameter<std::string>("listName"));
0262     std::string mergedPathsInKey;
0263 
0264     for (const auto &imap : triggerMap) {
0265       if (imap.first == filter)
0266         mergedPathsInKey = imap.second;  //paths in the condition tag
0267     }
0268 
0269     if (mergedPathsInKey.empty()) {
0270       throw cms::Exception("BadConfig") << "List name '" << filter << "' not found in the map";
0271     }
0272 
0273     auto PathsInKey = bits.decompose(mergedPathsInKey);
0274     auto const paths(
0275         iSet.getParameter<std::vector<std::string>>("hltPaths"));  //paths to remove; from the configuration
0276 
0277     if (paths.empty()) {  // nothing to remove ==> misconfiguration!
0278       throw cms::Exception("BadConfig") << "Didn't set any path to remove!";
0279     }
0280 
0281     for (auto const &path : paths) {
0282       PathsInKey.erase(std::remove(PathsInKey.begin(), PathsInKey.end(), path), PathsInKey.end());
0283     }
0284 
0285     // We must avoid a map<string,vector<string> > in DB for performance reason,
0286     // so we have to merge the paths into one string that will be decoded when needed:
0287     triggerMap[filter] = bits.compose(PathsInKey);
0288   }
0289 
0290   return true;
0291 }
0292 
0293 ///////////////////////////////////////////////////////////////////////
0294 void AlCaRecoTriggerBitsRcdUpdate::writeBitsToDB(const AlCaRecoTriggerBits &bitsToWrite) const {
0295   edm::LogInfo("AlCaRecoTriggerBitsRcdUpdate") << "Uploading to the database...";
0296 
0297   edm::Service<cond::service::PoolDBOutputService> poolDbService;
0298   if (!poolDbService.isAvailable()) {
0299     throw cms::Exception("NotAvailable") << "PoolDBOutputService not available.\n";
0300   }
0301 
0302   const std::string recordName("AlCaRecoTriggerBitsRcd");
0303 
0304   // when updating existing tag, compare payload hashs and skip appending new hash if it's same with last iov's
0305   poolDbService->startTransaction();
0306   auto newHash = poolDbService->session().storePayload(bitsToWrite);
0307   cond::TagInfo_t tag_info;
0308 
0309   if (poolDbService->tagInfo(recordName, tag_info)) {
0310     if (newHash != tag_info.lastInterval.payloadId) {
0311       edm::LogInfo("AlCaRecoTriggerBitsRcdUpdate") << "## Appending to existing tag...";
0312       poolDbService->forceInit();
0313       poolDbService->appendSinceTime(newHash, firstRunIOV_, recordName);
0314     } else {
0315       edm::LogInfo("AlCaRecoTriggerBitsRcdUpdate") << "## Skipping update since hash is the same...";
0316     }
0317 
0318   } else {
0319     edm::LogInfo("AlCaRecoTriggerBitsRcdUpdate") << "## Creating new tag...";
0320     poolDbService->forceInit();
0321     poolDbService->createNewIOV(newHash, firstRunIOV_, recordName);
0322   }
0323   poolDbService->commitTransaction();
0324 
0325   edm::LogInfo("AlCaRecoTriggerBitsRcdUpdate")
0326       << "...done for runs " << firstRunIOV_ << " to " << lastRunIOV_ << " (< 0 meaning infinity)!";
0327 }
0328 
0329 //define this as a plug-in
0330 DEFINE_FWK_MODULE(AlCaRecoTriggerBitsRcdUpdate);