Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:45:52

0001 #include "EventFilter/Utilities/plugins/FRDOutputModule.h"
0002 
0003 // system headers
0004 #include <unistd.h>
0005 #include <sys/types.h>
0006 #include <sys/stat.h>
0007 #include <fcntl.h>
0008 
0009 // C++ headers
0010 #include <cstdio>
0011 #include <fstream>
0012 #include <memory>
0013 #include <vector>
0014 
0015 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0016 #include "FWCore/Utilities/interface/EDGetToken.h"
0017 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0018 #include "FWCore/Utilities/interface/Adler32Calculator.h"
0019 #include "DataFormats/Common/interface/Handle.h"
0020 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
0021 #include "IOPool/Streamer/interface/FRDEventMessage.h"
0022 #include "IOPool/Streamer/interface/FRDFileHeader.h"
0023 #include "EventFilter/Utilities/interface/crc32c.h"
0024 
0025 FRDOutputModule::FRDOutputModule(edm::ParameterSet const& ps)
0026     : edm::one::OutputModuleBase::OutputModuleBase(ps),
0027       edm::one::OutputModule<edm::one::WatchLuminosityBlocks>(ps),
0028       token_(consumes<FEDRawDataCollection>(ps.getParameter<edm::InputTag>("source"))),
0029       frdVersion_(ps.getUntrackedParameter<unsigned int>("frdVersion")),
0030       frdFileVersion_(ps.getUntrackedParameter<unsigned int>("frdFileVersion")),
0031       filePrefix_(ps.getUntrackedParameter<std::string>("filePrefix")),
0032       fileName_(ps.getUntrackedParameter<std::string>("fileName")) {}
0033 
0034 FRDOutputModule::~FRDOutputModule() {}
0035 
0036 void FRDOutputModule::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0037   edm::ParameterSetDescription desc;
0038   desc.add<edm::InputTag>("source", edm::InputTag("rawDataCollector"));
0039   desc.addUntracked<unsigned int>("frdFileVersion", 1), desc.addUntracked<unsigned int>("frdVersion", 6);
0040   desc.addUntracked<std::string>("filePrefix", "");
0041   desc.addUntracked<std::string>("fileName", "");
0042   descriptions.addWithDefaultLabel(desc);
0043 }
0044 
0045 void FRDOutputModule::write(edm::EventForOutput const& e) {
0046   // serialize the FEDRawDataCollection into the format that we expect for
0047   // FRDEventMsgView objects (may be better ways to do this)
0048   edm::Handle<FEDRawDataCollection> fedBuffers;
0049   e.getByToken(token_, fedBuffers);
0050 
0051   // determine the expected size of the FRDEvent IN BYTES !!!!!
0052   assert(frdVersion_ <= FRDHeaderMaxVersion);
0053   int headerSize = FRDHeaderVersionSize[frdVersion_];
0054   int expectedSize = headerSize;
0055   int nFeds = frdVersion_ < 3 ? 1024 : FEDNumbering::lastFEDId() + 1;
0056 
0057   for (int idx = 0; idx < nFeds; ++idx) {
0058     FEDRawData singleFED = fedBuffers->FEDData(idx);
0059     expectedSize += singleFED.size();
0060   }
0061 
0062   // build the FRDEvent into a temporary buffer
0063   std::unique_ptr<std::vector<unsigned char>> workBuffer(
0064       std::make_unique<std::vector<unsigned char>>(expectedSize + 256));
0065   uint32* bufPtr = (uint32*)(workBuffer.get()->data());
0066   if (frdVersion_ <= 5) {
0067     *bufPtr++ = (uint32)frdVersion_;  // version number only
0068   } else {
0069     uint16 flags = 0;
0070     if (!e.eventAuxiliary().isRealData())
0071       flags |= FRDEVENT_MASK_ISGENDATA;
0072     *(uint16*)bufPtr = (uint16)(frdVersion_ & 0xffff);
0073     *((uint16*)bufPtr + 1) = flags;
0074     bufPtr++;
0075   }
0076   *bufPtr++ = (uint32)e.id().run();
0077   *bufPtr++ = (uint32)e.luminosityBlock();
0078   *bufPtr++ = (uint32)e.id().event();
0079   if (frdVersion_ == 4)
0080     *bufPtr++ = 0;  //64-bit event id high part
0081 
0082   if (frdVersion_ < 3) {
0083     uint32 fedsize[1024];
0084     for (int idx = 0; idx < 1024; ++idx) {
0085       FEDRawData singleFED = fedBuffers->FEDData(idx);
0086       fedsize[idx] = singleFED.size();
0087       //std::cout << "fed size " << singleFED.size()<< std::endl;
0088     }
0089     memcpy(bufPtr, fedsize, 1024 * sizeof(uint32));
0090     bufPtr += 1024;
0091   } else {
0092     *bufPtr++ = expectedSize - headerSize;
0093     *bufPtr++ = 0;
0094     if (frdVersion_ <= 4)
0095       *bufPtr++ = 0;
0096   }
0097   uint32* payloadPtr = bufPtr;
0098   for (int idx = 0; idx < nFeds; ++idx) {
0099     FEDRawData singleFED = fedBuffers->FEDData(idx);
0100     if (singleFED.size() > 0) {
0101       memcpy(bufPtr, singleFED.data(), singleFED.size());
0102       bufPtr += singleFED.size() / 4;
0103     }
0104   }
0105   if (frdVersion_ > 4) {
0106     //crc32c checksum
0107     uint32_t crc = 0;
0108     *(payloadPtr - 1) = crc32c(crc, (const unsigned char*)payloadPtr, expectedSize - headerSize);
0109   } else if (frdVersion_ >= 3) {
0110     //adler32 checksum
0111     uint32 adlera = 1;
0112     uint32 adlerb = 0;
0113     cms::Adler32((const char*)payloadPtr, expectedSize - headerSize, adlera, adlerb);
0114     *(payloadPtr - 1) = (adlerb << 16) | adlera;
0115   }
0116 
0117   // create the FRDEventMsgView and use the template consumer to write it out
0118   FRDEventMsgView msg(workBuffer.get()->data());
0119 
0120   //write
0121   ssize_t retval = ::write(outfd_, (void*)msg.startAddress(), msg.size());
0122 
0123   if ((unsigned)retval != msg.size()) {
0124     throw cms::Exception("FRDOutputModule", "write")
0125         << "Error writing FED Raw Data event data to " << fileName_ << ".  Possibly the output disk "
0126         << "is full?" << std::endl;
0127   }
0128 
0129   perFileEventCount_++;
0130   perFileSize_ += msg.size();
0131 }
0132 
0133 void FRDOutputModule::beginLuminosityBlock(edm::LuminosityBlockForOutput const& lumiBlock) {
0134   int ls = lumiBlock.id().luminosityBlock();
0135 
0136   if (outfd_ != -1)
0137     finishFileWrite(lumiBlock.run(), ls);
0138 
0139   if (fileWritten_)
0140     throw cms::Exception("RawEventFileWriterForBU", "beginLuminosityBlock")
0141         << "Multiple lumisections not supported in the same FRD file!";
0142 
0143   std::string fileName;
0144   if (fileName_.empty()) {
0145     std::stringstream ss;
0146     ss << (filePrefix_.empty() ? "" : filePrefix_ + "_") << "run" << std::setfill('0') << std::setw(6)
0147        << lumiBlock.run() << "_ls" << std::setfill('0') << std::setw(4) << ls << "_index000000.raw";
0148     fileName = ss.str();
0149   } else {
0150     //use exact filename (will be overwritten by last LS content if input contains multiple lumisections)
0151     fileName = fileName_;
0152   }
0153 
0154   outfd_ = open(fileName.c_str(), O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
0155   ftruncate(outfd_, 0);
0156 
0157   if (outfd_ < 0) {  //attention here... it may happen that outfd_ is *not* set (e.g. missing initialize call...)
0158     throw cms::Exception("RawEventFileWriterForBU", "beginLuminosityBlock")
0159         << "Error opening FED Raw Data event output file: " << fileName << ": " << strerror(errno) << "\n";
0160   }
0161   edm::LogInfo("RawEventFileWriterForBU") << " Opened " << fileName;
0162 
0163   perFileEventCount_ = 0;
0164   perFileSize_ = 0;
0165 
0166   adlera_ = 1;
0167   adlerb_ = 0;
0168 
0169   if (frdFileVersion_ == 1) {
0170     //reserve space for file header
0171     ftruncate(outfd_, sizeof(FRDFileHeader_v1));
0172     lseek(outfd_, sizeof(FRDFileHeader_v1), SEEK_SET);
0173     perFileSize_ = sizeof(FRDFileHeader_v1);
0174   } else if (frdFileVersion_ == 2) {
0175     ftruncate(outfd_, sizeof(FRDFileHeader_v2));
0176     lseek(outfd_, sizeof(FRDFileHeader_v2), SEEK_SET);
0177     perFileSize_ = sizeof(FRDFileHeader_v2);
0178   } else
0179     throw cms::Exception("RawEventFileWriterForBU", "beginLuminosityBlock")
0180         << "Unsupported FRD version " << frdFileVersion_;
0181 }
0182 
0183 void FRDOutputModule::endLuminosityBlock(edm::LuminosityBlockForOutput const& lumiBlock) {
0184   finishFileWrite(lumiBlock.run(), lumiBlock.id().luminosityBlock());
0185 }
0186 
0187 void FRDOutputModule::finishFileWrite(unsigned int run, int ls) {
0188   if (outfd_ == -1)
0189     return;
0190 
0191   if (frdFileVersion_ == 1) {
0192     //rewind
0193     lseek(outfd_, 0, SEEK_SET);
0194     FRDFileHeader_v1 frdFileHeader(perFileEventCount_, (uint32_t)ls, perFileSize_);
0195     ::write(outfd_, (char*)&frdFileHeader, sizeof(FRDFileHeader_v1));
0196   } else if (frdFileVersion_ == 2) {
0197     lseek(outfd_, 0, SEEK_SET);
0198     FRDFileHeader_v2 frdFileHeader(0, perFileEventCount_, (uint32_t)run, (uint32_t)ls, perFileSize_);
0199     ::write(outfd_, (char*)&frdFileHeader, sizeof(FRDFileHeader_v2));
0200   }
0201   close(outfd_);
0202   outfd_ = -1;
0203   if (!fileName_.empty())
0204     fileWritten_ = true;
0205 
0206   edm::LogInfo("FRDOutputModule") << "closed RAW input file";
0207 }