File indexing completed on 2023-10-25 09:45:52
0001 #include "EventFilter/Utilities/plugins/FRDOutputModule.h"
0002
0003
0004 #include <unistd.h>
0005 #include <sys/types.h>
0006 #include <sys/stat.h>
0007 #include <fcntl.h>
0008
0009
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
0047
0048 edm::Handle<FEDRawDataCollection> fedBuffers;
0049 e.getByToken(token_, fedBuffers);
0050
0051
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
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_;
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;
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
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
0107 uint32_t crc = 0;
0108 *(payloadPtr - 1) = crc32c(crc, (const unsigned char*)payloadPtr, expectedSize - headerSize);
0109 } else if (frdVersion_ >= 3) {
0110
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
0118 FRDEventMsgView msg(workBuffer.get()->data());
0119
0120
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
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) {
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
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
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 }