Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-06-29 22:57:59

0001 #ifndef IOPool_Streamer_interface_RawEventOutputModuleForBU_h
0002 #define IOPool_Streamer_interface_RawEventOutputModuleForBU_h
0003 
0004 #include <memory>
0005 #include <vector>
0006 
0007 #include "DataFormats/Common/interface/Handle.h"
0008 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
0009 #include "DataFormats/FEDRawData/interface/RawDataBuffer.h"
0010 #include "EventFilter/Utilities/interface/EvFDaqDirector.h"
0011 #include "EventFilter/Utilities/interface/crc32c.h"
0012 #include "EventFilter/Utilities/plugins/EvFBuildingThrottle.h"
0013 #include "FWCore/Framework/interface/EventForOutput.h"
0014 #include "FWCore/Framework/interface/LuminosityBlockForOutput.h"
0015 #include "FWCore/Framework/interface/one/OutputModule.h"
0016 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0017 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0018 #include "FWCore/ServiceRegistry/interface/ModuleCallingContext.h"
0019 #include "FWCore/ServiceRegistry/interface/Service.h"
0020 #include "FWCore/Utilities/interface/Adler32Calculator.h"
0021 #include "FWCore/Utilities/interface/EDGetToken.h"
0022 #include "IOPool/Streamer/interface/FRDEventMessage.h"
0023 
0024 template <class Consumer>
0025 class RawEventOutputModuleForBU : public edm::one::OutputModule<edm::one::WatchRuns, edm::one::WatchLuminosityBlocks> {
0026   /**
0027    * Consumers are suppose to provide:
0028    *   void doOutputEvent(const FRDEventMsgView& msg)
0029    *   void start()
0030    *   void stop()
0031    */
0032 
0033 public:
0034   explicit RawEventOutputModuleForBU(edm::ParameterSet const& ps);
0035   ~RawEventOutputModuleForBU() override;
0036 
0037   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0038 
0039 private:
0040   void write(edm::EventForOutput const& e) override;
0041   void beginRun(edm::RunForOutput const&) override;
0042   void endRun(edm::RunForOutput const&) override;
0043   void writeRun(const edm::RunForOutput&) override {}
0044   void writeLuminosityBlock(const edm::LuminosityBlockForOutput&) override {}
0045 
0046   void beginLuminosityBlock(edm::LuminosityBlockForOutput const&) override;
0047   void endLuminosityBlock(edm::LuminosityBlockForOutput const&) override;
0048 
0049   std::unique_ptr<Consumer> templateConsumer_;
0050   const edm::EDGetTokenT<FEDRawDataCollection> tokenFRD_;
0051   const edm::EDGetTokenT<RawDataBuffer> token_;
0052   const unsigned int numEventsPerFile_;
0053   const unsigned int frdVersion_;
0054   std::string rawProductName_;
0055   unsigned int rawProductType_ = 0;
0056   std::vector<unsigned int> sourceIdList_;
0057   unsigned int totevents_ = 0;
0058   unsigned int index_ = 0;
0059 };
0060 
0061 template <class Consumer>
0062 RawEventOutputModuleForBU<Consumer>::RawEventOutputModuleForBU(edm::ParameterSet const& ps)
0063     : edm::one::OutputModuleBase::OutputModuleBase(ps),
0064       edm::one::OutputModule<edm::one::WatchRuns, edm::one::WatchLuminosityBlocks>(ps),
0065       templateConsumer_(new Consumer(ps)),
0066       tokenFRD_(consumes<FEDRawDataCollection>(ps.getParameter<edm::InputTag>("source"))),
0067       token_(consumes<RawDataBuffer>(ps.getParameter<edm::InputTag>("source"))),
0068       numEventsPerFile_(ps.getParameter<unsigned int>("numEventsPerFile")),
0069       frdVersion_(ps.getParameter<unsigned int>("frdVersion")),
0070       rawProductName_(ps.getUntrackedParameter<std::string>("rawProductName")),
0071       sourceIdList_(ps.getUntrackedParameter<std::vector<unsigned int>>("sourceIdList", std::vector<unsigned int>())) {
0072   if (rawProductName_ == "FEDRawDataCollection")
0073     rawProductType_ = 1;
0074   else if (rawProductName_ == "RawDataBuffer")
0075     rawProductType_ = 2;
0076   else
0077     throw cms::Exception("RawEventOutputModuleForBU") << "Unknown raw product specified";
0078   if (frdVersion_ > 0 && frdVersion_ < 5)
0079     throw cms::Exception("RawEventOutputModuleForBU")
0080         << "Generating data with FRD version " << frdVersion_ << " is no longer supported";
0081   else if (frdVersion_ > edm::streamer::FRDHeaderMaxVersion)
0082     throw cms::Exception("RawEventOutputModuleForBU") << "Unknown FRD version " << frdVersion_;
0083 }
0084 
0085 template <class Consumer>
0086 RawEventOutputModuleForBU<Consumer>::~RawEventOutputModuleForBU() {}
0087 
0088 template <class Consumer>
0089 void RawEventOutputModuleForBU<Consumer>::write(edm::EventForOutput const& e) {
0090   //using namespace edm::streamer;
0091 
0092   if (totevents_ > 0 && totevents_ % numEventsPerFile_ == 0) {
0093     index_++;
0094     unsigned int ls = e.luminosityBlock();
0095     std::string filename = edm::Service<evf::EvFDaqDirector>()->getOpenRawFilePath(ls, index_);
0096     std::string destinationDir = edm::Service<evf::EvFDaqDirector>()->buBaseRunDir();
0097     int run = edm::Service<evf::EvFDaqDirector>()->getRunNumber();
0098     templateConsumer_->initialize(destinationDir, filename, run, ls);
0099   }
0100   totevents_++;
0101   // serialize the FEDRawDataCollection into the format that we expect for
0102   // FRDEventMsgView objects (may be better ways to do this)
0103   edm::Handle<FEDRawDataCollection> fedBuffers;
0104   edm::Handle<RawDataBuffer> fedBuffer;
0105 
0106   unsigned int usedRawType = 0;
0107   if (rawProductType_ == 1) {
0108     e.getByToken(tokenFRD_, fedBuffers);
0109     usedRawType = 1;
0110   } else if (rawProductType_ == 2) {
0111     e.getByToken(token_, fedBuffer);
0112     usedRawType = 2;
0113   }
0114   assert(usedRawType);
0115 
0116   // determine the expected size of the FRDEvent IN bytes
0117   int headerSize = edm::streamer::FRDHeaderVersionSize[frdVersion_];
0118   int expectedSize = headerSize;
0119   //for FEDRawDataCollection
0120   int nFeds = FEDNumbering::lastFEDId() + 1;
0121 
0122   if (usedRawType == 1) {
0123     if (!sourceIdList_.empty()) {
0124       for (int idx : sourceIdList_) {
0125         auto singleFED = fedBuffers->FEDData(idx);
0126         expectedSize += singleFED.size();
0127       }
0128     } else {
0129       for (int idx = 0; idx < nFeds; ++idx) {
0130         auto singleFED = fedBuffers->FEDData(idx);
0131         expectedSize += singleFED.size();
0132       }
0133     }
0134   } else if (usedRawType == 2) {
0135     if (!sourceIdList_.empty()) {
0136       for (int idx : sourceIdList_) {
0137         auto singleFED = fedBuffer->fragmentData(idx);
0138         expectedSize += singleFED.size();
0139       }
0140     } else {
0141       //for (int idx = 0; idx < nFeds; ++idx) {
0142       for (auto it = fedBuffer->map().begin(); it != fedBuffer->map().end(); it++) {
0143         auto singleFED = fedBuffer->fragmentData(it);
0144         expectedSize += singleFED.size();
0145       }
0146     }
0147   }
0148 
0149   // build the FRDEvent into a temporary buffer
0150   std::unique_ptr<std::vector<unsigned char>> workBuffer(
0151       std::make_unique<std::vector<unsigned char>>(expectedSize + 256));
0152   uint32_t* bufPtr = (uint32_t*)(workBuffer.get()->data());
0153 
0154   if (frdVersion_) {
0155     if (frdVersion_ <= 5) {
0156       //32-bits version field
0157       *bufPtr++ = (uint32_t)frdVersion_;
0158     } else {
0159       //16 bits version and 16 bits flags
0160       uint16_t flags = 0;
0161       if (!e.eventAuxiliary().isRealData())
0162         flags |= edm::streamer::FRDEVENT_MASK_ISGENDATA;
0163       *(uint16_t*)bufPtr = (uint16_t)(frdVersion_ & 0xffff);
0164       *((uint16_t*)bufPtr + 1) = flags;
0165       bufPtr++;
0166     }
0167     *bufPtr++ = (uint32_t)e.id().run();
0168     *bufPtr++ = (uint32_t)e.luminosityBlock();
0169     *bufPtr++ = (uint32_t)e.id().event();
0170     *bufPtr++ = expectedSize - headerSize;
0171     *bufPtr++ = 0;
0172   }
0173   uint32_t* payloadPtr = bufPtr;
0174   if (usedRawType == 1) {
0175     if (!sourceIdList_.empty()) {
0176       for (int idx : sourceIdList_) {
0177         FEDRawData singleFED = fedBuffers->FEDData(idx);
0178         if (singleFED.size() > 0) {
0179           memcpy(bufPtr, singleFED.data(), singleFED.size());
0180           bufPtr += singleFED.size() / 4;
0181         }
0182       }
0183     } else {
0184       for (int idx = 0; idx < nFeds; ++idx) {
0185         FEDRawData singleFED = fedBuffers->FEDData(idx);
0186         if (singleFED.size() > 0) {
0187           memcpy(bufPtr, singleFED.data(), singleFED.size());
0188           bufPtr += singleFED.size() / 4;
0189         }
0190       }
0191     }
0192   } else if (usedRawType == 2) {
0193     if (!sourceIdList_.empty()) {
0194       for (int idx : sourceIdList_) {
0195         auto singleFED = fedBuffer->fragmentData(idx);
0196         memcpy(bufPtr, &singleFED.data()[0], singleFED.size());
0197         bufPtr += singleFED.size() / 4;
0198       }
0199     } else {
0200       for (auto it = fedBuffer->map().begin(); it != fedBuffer->map().end(); it++) {
0201         auto singleFED = fedBuffer->fragmentData(it);
0202         memcpy(bufPtr, &singleFED.data()[0], singleFED.size());
0203         bufPtr += singleFED.size() / 4;
0204       }
0205     }
0206   }
0207   if (frdVersion_) {
0208     //crc32c checksum
0209     uint32_t crc = 0;
0210     *(payloadPtr - 1) = crc32c(crc, (const unsigned char*)payloadPtr, expectedSize - headerSize);
0211 
0212     // create the FRDEventMsgView and use the template consumer to write it out
0213     edm::streamer::FRDEventMsgView msg(workBuffer.get()->data());
0214     templateConsumer_->doOutputEvent(msg);
0215   } else {
0216     //write only raw FEDs
0217     templateConsumer_->doOutputEvent((void*)workBuffer.get()->data(), expectedSize);
0218   }
0219 }
0220 
0221 template <class Consumer>
0222 void RawEventOutputModuleForBU<Consumer>::beginRun(edm::RunForOutput const&) {
0223   // edm::Service<evf::EvFDaqDirector>()->updateBuLock(1);
0224   templateConsumer_->start();
0225 }
0226 
0227 template <class Consumer>
0228 void RawEventOutputModuleForBU<Consumer>::endRun(edm::RunForOutput const&) {
0229   templateConsumer_->stop();
0230 }
0231 
0232 template <class Consumer>
0233 void RawEventOutputModuleForBU<Consumer>::beginLuminosityBlock(edm::LuminosityBlockForOutput const& ls) {
0234   index_ = 0;
0235   std::string filename = edm::Service<evf::EvFDaqDirector>()->getOpenRawFilePath(ls.id().luminosityBlock(), index_);
0236   std::string destinationDir = edm::Service<evf::EvFDaqDirector>()->buBaseRunDir();
0237   int run = edm::Service<evf::EvFDaqDirector>()->getRunNumber();
0238   std::cout << " writing to destination dir " << destinationDir << " name: " << filename << std::endl;
0239   totevents_ = 0;
0240   templateConsumer_->initialize(destinationDir, filename, run, ls.id().luminosityBlock());
0241 }
0242 
0243 template <class Consumer>
0244 void RawEventOutputModuleForBU<Consumer>::endLuminosityBlock(edm::LuminosityBlockForOutput const& ls) {
0245   //  templateConsumer_->touchlock(ls.id().luminosityBlock(),basedir);
0246   templateConsumer_->endOfLS(ls.id().luminosityBlock());
0247 }
0248 
0249 template <class Consumer>
0250 void RawEventOutputModuleForBU<Consumer>::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0251   edm::ParameterSetDescription desc;
0252   desc.add<edm::InputTag>("source", edm::InputTag("rawDataCollector"));
0253   desc.add<unsigned int>("numEventsPerFile", 100);
0254   desc.add<unsigned int>("frdVersion", 6);
0255   desc.addUntracked<std::string>("rawProductName", "FEDRawDataCollection")
0256       ->setComment("FEDRawDataCollection or RawDataBuffer");
0257   desc.addUntracked<std::vector<unsigned int>>("sourceIdList", std::vector<unsigned int>());
0258   Consumer::extendDescription(desc);
0259 
0260   descriptions.addWithDefaultLabel(desc);
0261 }
0262 
0263 #endif  // IOPool_Streamer_interface_RawEventOutputModuleForBU_h