File indexing completed on 2024-04-06 11:57:58
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "CalibCalorimetry/EcalLaserSorting/interface/LaserSorter.h"
0010 #include "CalibCalorimetry/EcalLaserSorting/src/Majority.h"
0011
0012 #include <iostream>
0013 #include <iomanip>
0014 #include <algorithm>
0015 #include <sys/stat.h>
0016 #include <sys/types.h>
0017 #include <unistd.h>
0018 #include <cerrno>
0019
0020 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0021 #include "FWCore/Framework/interface/Event.h"
0022 #include "FWCore/Framework/interface/EventSetup.h"
0023 #include "FWCore/Framework/interface/Run.h"
0024 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0025 #include "DataFormats/Provenance/interface/EventID.h"
0026 #include "DataFormats/FEDRawData/interface/FEDRawData.h"
0027 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
0028 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
0029 #include "DataFormats/Provenance/interface/LuminosityBlockID.h"
0030 #include "DataFormats/Provenance/interface/Timestamp.h"
0031 #include "EventFilter/EcalRawToDigi/interface/MatacqRawEvent.h"
0032
0033 using namespace std;
0034
0035 const int LaserSorter::ecalDccFedIdMin_ = 601;
0036 const int LaserSorter::ecalDccFedIdMax_ = 654;
0037
0038 const size_t LaserSorter::OutStreamRecord::indexReserve_ = 2000;
0039
0040 static const struct timeval nullTime = {0, 0};
0041
0042 static const char* const detailedTrigNames[] = {
0043 "Inv0",
0044 "Inv1",
0045 "Inv2",
0046 "Inv3",
0047 "Las",
0048 "Led",
0049 "TP",
0050 "Ped"
0051 };
0052
0053 static const char* const colorNames[] = {"Blue", "Green", "Red", "IR"};
0054
0055 const LaserSorter::stats_t LaserSorter::stats_init = {0, 0, 0, 0, 0};
0056 const int LaserSorter::indexOffset32_ = 1;
0057
0058 static std::string now() {
0059 struct timeval t;
0060 gettimeofday(&t, nullptr);
0061
0062 char buf[256];
0063 strftime(buf, sizeof(buf), "%F %R %S s", localtime(&t.tv_sec));
0064 buf[sizeof(buf) - 1] = 0;
0065
0066 stringstream buf2;
0067 buf2 << buf << " " << ((t.tv_usec + 500) / 1000) << " ms";
0068
0069 return buf2.str();
0070 }
0071
0072 LaserSorter::LaserSorter(const edm::ParameterSet& pset)
0073 : lumiBlock_(0),
0074 lumiBlockPrev_(0),
0075 formatVersion_(5),
0076 outputDir_(pset.getParameter<std::string>("outputDir")),
0077 fedSubDirs_(pset.getParameter<std::vector<std::string> >("fedSubDirs")),
0078 timeLogFile_(pset.getUntrackedParameter<std::string>("timeLogFile", "")),
0079 disableOutput_(pset.getUntrackedParameter<bool>("disableOutput", false)),
0080 runNumber_(0),
0081 outputListFile_(pset.getUntrackedParameter<string>("outputListFile", "")),
0082 doOutputList_(false),
0083 verbosity_(pset.getUntrackedParameter<int>("verbosity", 0)),
0084 iNoFullReadoutDccError_(0),
0085 maxFullReadoutDccError_(pset.getParameter<int>("maxFullReadoutDccError")),
0086 iNoEcalDataMess_(0),
0087 maxNoEcalDataMess_(pset.getParameter<int>("maxNoEcalDataMess")),
0088 lumiBlockSpan_(pset.getParameter<int>("lumiBlockSpan")),
0089 fedRawDataCollectionTag_(pset.getParameter<edm::InputTag>("fedRawDataCollectionTag")),
0090 stats_(stats_init),
0091 overWriteLumiBlockId_(pset.getParameter<bool>("overWriteLumiBlockId")),
0092 orbitCountInALumiBlock_(pset.getParameter<int>("orbitCountInALumiBlock")),
0093 orbit_(-1),
0094 orbitZeroTime_(nullTime) {
0095 gettimeofday(&timer_, nullptr);
0096 logFile_.open("eventSelect.log", ios::app | ios::out);
0097
0098 const unsigned nEcalFeds = 54;
0099 if (fedSubDirs_.size() != nEcalFeds + 1) {
0100 throw cms::Exception("LaserSorter") << "Configuration error: "
0101 << "fedSubDirs parameter must be a vector "
0102 << " of " << nEcalFeds << " strings"
0103 << " (subdirectory for unknown triggered FED followed by "
0104 "subdirectories for FED ID 601 "
0105 "to FED ID 654 in increasing FED ID order)";
0106 }
0107
0108 fedRawDataCollectionToken_ = consumes<FEDRawDataCollection>(fedRawDataCollectionTag_);
0109
0110 if (!outputListFile_.empty()) {
0111 outputList_.open(outputListFile_.c_str(), ios::app);
0112 if (outputList_.bad()) {
0113 throw cms::Exception("FileOpen") << "Failed to open file '" << outputListFile_
0114 << "' for logging of output file path list.";
0115 }
0116 doOutputList_ = true;
0117 }
0118
0119 if (!timeLogFile_.empty()) {
0120 timeLog_.open(timeLogFile_.c_str());
0121 if (timeLog_.fail()) {
0122 cout << "[LaserSorter " << now() << "] "
0123 << "Failed to open file " << timeLogFile_ << " to log timing.\n";
0124 timing_ = false;
0125 } else {
0126 timing_ = true;
0127 }
0128 }
0129
0130 struct stat fileStat;
0131 if (0 == stat(outputDir_.c_str(), &fileStat)) {
0132 if (!S_ISDIR(fileStat.st_mode)) {
0133 throw cms::Exception("[LaserSorter]") << "File " << outputDir_ << " exists but is not a directory "
0134 << " as expected.";
0135 }
0136 } else {
0137 if (0 != mkdir(outputDir_.c_str(), 0755)) {
0138 throw cms::Exception("[LaserSorter]") << "Failed to create directory " << outputDir_ << " for writing data.";
0139 }
0140 }
0141
0142 logFile_ << "# "
0143 "run\t"
0144 "LB\t"
0145 "event\t"
0146 "trigType\t"
0147 "FED\t"
0148 "side\t"
0149 "LB out\t"
0150 "Written\t"
0151 "ECAL data\n";
0152 }
0153
0154 LaserSorter::~LaserSorter() {
0155 logFile_ << "Summary. Event count: " << stats_.nRead << " processed, " << stats_.nWritten << " written, "
0156 << stats_.nInvalidDccStrict << " with errors in DCC ID values, " << stats_.nInvalidDccWeak
0157 << " with unusable DCC ID values, " << stats_.nRestoredDcc << " restored DCC ID based on DCC block size\n";
0158 }
0159
0160
0161 void LaserSorter::analyze(const edm::Event& event, const edm::EventSetup& es) {
0162 if (timing_) {
0163 timeval t;
0164 gettimeofday(&t, nullptr);
0165 timeLog_ << t.tv_sec << "." << setfill('0') << setw(3) << (t.tv_usec + 500) / 1000 << setfill(' ') << "\t"
0166 << (t.tv_usec - timer_.tv_usec) * 1. + (t.tv_sec - timer_.tv_sec) * 1.e6 << "\t";
0167 timer_ = t;
0168 }
0169
0170 ++stats_.nRead;
0171
0172 if (event.id().run() != runNumber_) {
0173
0174 closeAllStreams();
0175 runNumber_ = event.id().run();
0176 iNoFullReadoutDccError_ = 0;
0177 iNoEcalDataMess_ = 0;
0178 lumiBlockPrev_ = 0;
0179 lumiBlock_ = 0;
0180 }
0181
0182 edm::Handle<FEDRawDataCollection> rawdata;
0183 event.getByToken(fedRawDataCollectionToken_, rawdata);
0184
0185
0186
0187
0188 #if 0
0189 orbit_ = event.orbitNumber();
0190 #else
0191 orbit_ = -1;
0192 #endif
0193
0194
0195
0196 if (orbit_ < 0) {
0197
0198 orbit_ = getOrbitFromDcc(rawdata);
0199 }
0200
0201
0202 double dttProba = 0;
0203 int dtt = getDetailedTriggerType(rawdata, &dttProba);
0204
0205 if (overWriteLumiBlockId_) {
0206 edm::LuminosityBlockNumber_t lb = lumiBlock_;
0207 lumiBlock_ = orbit_ / orbitCountInALumiBlock_;
0208 if (lb != lumiBlock_) {
0209 std::cout << "[LaserSorter " << now() << "] Overwrite LB mode. LB number changed from: " << lb << " to "
0210 << lumiBlock_ << "\n";
0211 }
0212 } else {
0213 edm::LuminosityBlockNumber_t lb = lumiBlock_;
0214 lumiBlock_ = event.luminosityBlock();
0215 if (lb != lumiBlock_) {
0216 std::cout << "[LaserSorter " << now() << "] Standard LB mode. LB number changed from: " << lb << " to "
0217 << lumiBlock_ << "\n";
0218 }
0219 }
0220
0221 detailedTrigType_ = dtt;
0222 const int trigType = (detailedTrigType_ >> 8) & 0x7;
0223 const int color = (detailedTrigType_ >> 6) & 0x3;
0224 const int dccId = (detailedTrigType_ >> 0) & 0x3F;
0225 int triggeredFedId = (detailedTrigType_ == -2) ? -1 : (600 + dccId);
0226 const int side = (detailedTrigType_ >> 11) & 0x1;
0227
0228
0229
0230 if (detailedTrigType_ > -2) {
0231 if (dttProba < 1. || triggeredFedId < ecalDccFedIdMin_ || triggeredFedId > ecalDccFedIdMax_) {
0232 ++stats_.nInvalidDccStrict;
0233 }
0234
0235 if (triggeredFedId < ecalDccFedIdMin_ || triggeredFedId > ecalDccFedIdMax_) {
0236 if (verbosity_)
0237 cout << "[LaserSorter " << now() << "] "
0238 << "DCC ID (" << dccId << ") found in trigger type is out of range.";
0239 ++stats_.nInvalidDccWeak;
0240 vector<int> ids = getFullyReadoutDccs(*rawdata);
0241 if (ids.empty()) {
0242 if (verbosity_ && iNoFullReadoutDccError_ < maxFullReadoutDccError_) {
0243 cout << " No fully read-out DCC found\n";
0244 ++iNoFullReadoutDccError_;
0245 }
0246 } else if (ids.size() == 1) {
0247 triggeredFedId = ids[0];
0248 if (verbosity_)
0249 cout << " ID guessed from DCC payloads\n";
0250 ++stats_.nRestoredDcc;
0251 } else {
0252 if (verbosity_) {
0253 cout << " Several fully read-out Dccs:";
0254 for (unsigned i = 0; i < ids.size(); ++i)
0255 cout << " " << ids[i];
0256 cout << "\n";
0257 }
0258 }
0259 }
0260
0261 if (verbosity_ > 1)
0262 cout << "\n----------------------------------------------------------------------\n"
0263 << "Event id: "
0264 << " " << event.id() << "\n"
0265 << "Lumin block: " << lumiBlock_ << "\n"
0266 << "TrigType: " << detailedTrigNames[trigType & 0x7] << " Color: " << colorNames[color & 0x3]
0267 << " FED: " << triggeredFedId << " side:" << side << "\n"
0268 << "\n----------------------------------------------------------------------\n";
0269
0270 } else {
0271 if (verbosity_ > 1)
0272 cout << "\n----------------------------------------------------------------------\n"
0273 << "Event id: "
0274 << " " << event.id() << "\n"
0275 << "Lumin block: " << lumiBlock_ << "\n"
0276 << "No ECAL data\n"
0277 << "\n----------------------------------------------------------------------\n";
0278 }
0279
0280 logFile_ << event.id().run() << "\t" << lumiBlock_ << "\t" << event.id().event() << "\t" << trigType << "\t"
0281 << triggeredFedId << "\t" << side;
0282
0283 bool written = false;
0284 int assignedLB = -1;
0285
0286 if (lumiBlock_ != lumiBlockPrev_) {
0287
0288 const int lb = lumiBlock_;
0289 closeOldStreams(lb);
0290 int minLumi = lumiBlock_ - lumiBlockSpan_;
0291 int maxLumi = lumiBlock_ + lumiBlockSpan_;
0292 for (int lb1 = minLumi; lb1 <= maxLumi; ++lb1) {
0293 restoreStreamsOfLumiBlock(lb1);
0294 }
0295 }
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306 if (disableOutput_) {
0307
0308 } else {
0309 const auto& out = getStream(triggeredFedId, lumiBlock_);
0310
0311 if (out != nullptr) {
0312 assignedLB = out->startingLumiBlock();
0313 if (out->excludedOrbit().find(orbit_) == out->excludedOrbit().end()) {
0314 if (verbosity_ > 1)
0315 cout << "[LaserSorter " << now() << "] "
0316 << "Writing out event from FED " << triggeredFedId << " LB " << lumiBlock_ << " orbit " << orbit_
0317 << "\n";
0318 int dtt = (detailedTrigType_ >= 0) ? detailedTrigType_ : -1;
0319 written = written || writeEvent(*out, event, dtt, *rawdata);
0320 ++stats_.nWritten;
0321 } else {
0322 if (verbosity_)
0323 cout << "[LaserSorter " << now() << "] "
0324 << "File " << out->finalFileName() << " "
0325 << "already contains calibration event from FED " << triggeredFedId << ", LB = " << lumiBlock_
0326 << " with orbit ID " << orbit_ << ". Event skipped.\n";
0327 }
0328 }
0329 }
0330 lumiBlockPrev_ = lumiBlock_;
0331
0332 logFile_ << "\t";
0333 if (assignedLB >= 0)
0334 logFile_ << assignedLB;
0335 else
0336 logFile_ << "-";
0337 logFile_ << "\t" << (written ? "Y" : "N") << "\n";
0338 logFile_ << "\t" << (detailedTrigType_ == -2 ? "N" : "Y") << "\n";
0339
0340 if (timing_) {
0341 timeval t;
0342 gettimeofday(&t, nullptr);
0343 timeLog_ << (t.tv_usec - timer_.tv_usec) * 1. + (t.tv_sec - timer_.tv_sec) * 1.e6 << "\n";
0344 timer_ = t;
0345 }
0346 }
0347
0348 int LaserSorter::dcc2Lme(int dcc, int side) {
0349 int fedid = (dcc % 600) + 600;
0350 vector<int> lmes;
0351
0352 if (fedid <= 609) {
0353 if (fedid <= 607) {
0354 lmes.push_back(fedid - 601 + 83);
0355 } else if (fedid == 608) {
0356 lmes.push_back(90);
0357 lmes.push_back(91);
0358 } else if (fedid == 609) {
0359 lmes.push_back(92);
0360 }
0361 }
0362 else if (fedid >= 610 && fedid <= 645) {
0363 lmes.push_back(2 * (fedid - 610) + 1);
0364 lmes.push_back(lmes[0] + 1);
0365 }
0366 else if (fedid >= 646) {
0367 if (fedid <= 652) {
0368 lmes.push_back(fedid - 646 + 73);
0369 } else if (fedid == 653) {
0370 lmes.push_back(80);
0371 lmes.push_back(81);
0372 } else if (fedid == 654) {
0373 lmes.push_back(82);
0374 }
0375 }
0376 return lmes.empty() ? -1 : lmes[min(lmes.size(), (size_t)side)];
0377 }
0378
0379 int LaserSorter::getOrbitFromDcc(const edm::Handle<FEDRawDataCollection>& rawdata) const {
0380 const int orbit32 = 6;
0381 for (int id = ecalDccFedIdMin_; id <= ecalDccFedIdMax_; ++id) {
0382 if (!FEDNumbering::inRange(id))
0383 continue;
0384 const FEDRawData& data = rawdata->FEDData(id);
0385 if (data.size() >= 4 * (orbit32 + 1)) {
0386 const uint32_t* pData32 = (const uint32_t*)data.data();
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396 return pData32[orbit32];
0397 }
0398 }
0399 return -1;
0400 }
0401
0402 int LaserSorter::getDetailedTriggerType(const edm::Handle<FEDRawDataCollection>& rawdata, double* proba) {
0403 Majority<int> stat;
0404 bool ecalData = false;
0405 for (int id = ecalDccFedIdMin_; id <= ecalDccFedIdMax_; ++id) {
0406 if (!FEDNumbering::inRange(id))
0407 continue;
0408 const FEDRawData& data = rawdata->FEDData(id);
0409 const int detailedTrigger32 = 5;
0410 if (verbosity_ > 3)
0411 cout << "[LaserSorter " << now() << "] "
0412 << "FED " << id << " data size: " << data.size() << "\n";
0413 if (data.size() >= 4 * (detailedTrigger32 + 1)) {
0414 ecalData = true;
0415 const uint32_t* pData32 = (const uint32_t*)data.data();
0416 int tType = pData32[detailedTrigger32] & 0xFFF;
0417 if (verbosity_ > 3)
0418 cout << "[LaserSorter " << now() << "] "
0419 << "Trigger type " << tType << "\n";
0420 stat.add(tType);
0421 }
0422 }
0423 if (!ecalData)
0424 return -2;
0425 double p;
0426 int tType = stat.result(&p);
0427 if (p < 0) {
0428
0429 if (iNoEcalDataMess_ < maxNoEcalDataMess_) {
0430 edm::LogWarning("NotFound") << "No ECAL DCC data found. "
0431 "(This warning will be disabled for the current run after "
0432 << maxNoEcalDataMess_ << " occurences.)";
0433 ++iNoEcalDataMess_;
0434 }
0435 tType = -1;
0436 } else if (p < .8) {
0437
0438 edm::LogWarning("EventCorruption") << "Inconsitency in detailed trigger type indicated in ECAL DCC data headers\n";
0439 tType = -1;
0440 }
0441 if (proba)
0442 *proba = p;
0443 return tType;
0444 }
0445
0446 void LaserSorter::closeAllStreams() {
0447 for (OutStreamList::iterator it = outStreamList_.begin(); it != outStreamList_.end(); ) {
0448 it = closeOutStream(it);
0449 }
0450 }
0451
0452 void LaserSorter::closeOldStreams(edm::LuminosityBlockNumber_t lumiBlock) {
0453 const edm::LuminosityBlockNumber_t minLumiBlock = lumiBlock - lumiBlockSpan_;
0454 const edm::LuminosityBlockNumber_t maxLumiBlock = lumiBlock + lumiBlockSpan_;
0455
0456
0457 for (OutStreamList::iterator it = outStreamList_.begin(); it != outStreamList_.end();
0458 ) {
0459 if ((*it)->startingLumiBlock() < minLumiBlock || (*it)->startingLumiBlock() > maxLumiBlock) {
0460
0461 if (verbosity_)
0462 cout << "[LaserSorter " << now() << "] "
0463 << "Closing file for "
0464 << "FED " << (*it)->fedId() << " LB " << (*it)->startingLumiBlock() << "\n";
0465 it = closeOutStream(it);
0466 } else {
0467 ++it;
0468 }
0469 }
0470 }
0471
0472 const std::unique_ptr<LaserSorter::OutStreamRecord>& LaserSorter::getStream(int fedId,
0473 edm::LuminosityBlockNumber_t lumiBlock) {
0474 const static std::unique_ptr<LaserSorter::OutStreamRecord> streamNotFound(nullptr);
0475
0476 if ((fedId != -1) && (fedId < ecalDccFedIdMin_ || fedId > ecalDccFedIdMax_))
0477 fedId = -1;
0478
0479 if (verbosity_ > 1)
0480 cout << "[LaserSorter " << now() << "] "
0481 << "Looking for an opened output file for FED " << fedId << " LB " << lumiBlock << "\n";
0482
0483
0484 for (OutStreamList::iterator it = outStreamList_.begin(); it != outStreamList_.end(); ++it) {
0485 if ((*it)->fedId() == fedId && (abs((int)(*it)->startingLumiBlock() - (int)lumiBlock) <= lumiBlockSpan_)) {
0486
0487 return (*it);
0488 }
0489 }
0490
0491
0492 if (verbosity_)
0493 cout << "[LaserSorter " << now() << "] "
0494 << "File not yet opened. Opening it.\n";
0495
0496 OutStreamList::iterator streamRecord = createOutStream(fedId, lumiBlock);
0497 return streamRecord != outStreamList_.end() ? (*streamRecord) : streamNotFound;
0498 }
0499
0500 bool LaserSorter::writeEvent(OutStreamRecord& outRcd,
0501 const edm::Event& event,
0502 int dtt,
0503 const FEDRawDataCollection& data) {
0504 ofstream& out = *outRcd.out();
0505 bool rc = true;
0506 vector<unsigned> fedIds;
0507 getOutputFedList(event, data, fedIds);
0508
0509 out.clear();
0510 uint32_t evtStart = out.tellp();
0511 if (out.bad())
0512 evtStart = 0;
0513 rc &= writeEventHeader(out, event, dtt, fedIds.size());
0514
0515 if (orbitZeroTime_.tv_sec == 0 && data.FEDData(matacqFedId_).size() != 0) {
0516 struct timeval ts = {0, 0};
0517 MatacqRawEvent mre(data.FEDData(matacqFedId_).data(), data.FEDData(matacqFedId_).size());
0518 mre.getTimeStamp(ts);
0519 uint32_t orb = mre.getOrbitId();
0520 if (ts.tv_sec != 0) {
0521 div_t dt = div(orb * 89.1, 1000 * 1000);
0522 orbitZeroTime_.tv_sec = ts.tv_sec - dt.quot;
0523 orbitZeroTime_.tv_usec = ts.tv_usec - dt.rem;
0524 if (orbitZeroTime_.tv_usec < 0) {
0525 orbitZeroTime_.tv_usec += 1000 * 1000;
0526 orbitZeroTime_.tv_sec -= 1;
0527 }
0528 }
0529 }
0530
0531 for (unsigned iFed = 0; iFed < fedIds.size() && rc; ++iFed) {
0532 if (verbosity_ > 3)
0533 cout << "[LaserSorter " << now() << "] "
0534 << "Writing data block of FED " << fedIds[iFed] << ". Data size: " << data.FEDData(fedIds[iFed]).size()
0535 << "\n";
0536 rc &= writeFedBlock(out, data.FEDData(fedIds[iFed]));
0537 }
0538
0539 if (rc) {
0540
0541 vector<IndexRecord>& indices = *outRcd.indices();
0542 if (verbosity_ > 2) {
0543 std::cout << "Event "
0544 << " written successfully. "
0545 << "Orbit: " << orbit_ << "\tFile index: " << evtStart << "\n";
0546 }
0547 IndexRecord indexRcd = {(uint32_t)orbit_, evtStart};
0548 indices.push_back(indexRcd);
0549 }
0550 return rc;
0551 }
0552
0553 bool LaserSorter::writeFedBlock(std::ofstream& out, const FEDRawData& data) {
0554 bool rc = false;
0555 if (data.size() > 4) {
0556 const uint32_t* pData = reinterpret_cast<const uint32_t*>(data.data());
0557
0558 uint32_t dccLen64 = pData[2] & 0x00FFFFFF;
0559
0560 if (data.size() != dccLen64 * sizeof(uint64_t)) {
0561
0562
0563 throw cms::Exception("LaserSorter") << "Mismatch between FED fragment size indicated in header "
0564 << "(" << dccLen64 << "*8 Byte) "
0565 << "and actual size (" << data.size() << " Byte) "
0566 << "for FED ID " << ((pData[0] >> 8) & 0xFFF) << "!\n";
0567 }
0568
0569 if (verbosity_ > 3)
0570 cout << "[LaserSorter " << now() << "] "
0571 << "Event fragment size: " << data.size() << " Byte"
0572 << "\t From Dcc header: " << dccLen64 * 8 << " Byte\n";
0573
0574 const size_t nBytes = data.size();
0575
0576
0577
0578 if (out.fail())
0579 cout << "[LaserSorter " << now() << "] "
0580 << "Problem with stream!\n";
0581 out.write((const char*)data.data(), nBytes);
0582 rc = true;
0583 } else {
0584 throw cms::Exception("Bug") << "Bug found in " << __FILE__ << ":" << __LINE__ << ".\n";
0585 }
0586 return rc;
0587 }
0588
0589 bool LaserSorter::renameAsBackup(const std::string& fileName, std::string& newFileName) {
0590 int i = 0;
0591 int err;
0592
0593 int maxTries = 20;
0594 stringstream newFileName_;
0595 do {
0596 newFileName_.str("");
0597 newFileName_ << fileName << "~";
0598 if (i > 0)
0599 newFileName_ << i;
0600 err = link(fileName.c_str(), newFileName_.str().c_str());
0601 if (err == 0) {
0602 newFileName = newFileName_.str();
0603 err = unlink(fileName.c_str());
0604 }
0605 ++i;
0606 } while ((err != 0) && (errno == EEXIST) && (i < maxTries));
0607 return err == 0;
0608 }
0609
0610 LaserSorter::OutStreamList::iterator LaserSorter::createOutStream(int fedId, edm::LuminosityBlockNumber_t lumiBlock) {
0611 if (verbosity_)
0612 cout << "[LaserSorter " << now() << "] "
0613 << "Creating a stream for FED " << fedId << " lumi block " << lumiBlock << ".\n";
0614 std::string tmpName;
0615 std::string finalName;
0616
0617 streamFileName(fedId, lumiBlock, tmpName, finalName);
0618
0619 errno = 0;
0620
0621
0622 ofstream* out = new ofstream(tmpName.c_str(), ios::out | ios::in);
0623 if (out->is_open()) {
0624 string newName;
0625 if (!renameAsBackup(tmpName, newName)) {
0626 throw cms::Exception("LaserSorter") << "Failed to rename file " << tmpName << " to " << newName << "\n";
0627 }
0628 if (verbosity_)
0629 cout << "[LaserSorter " << now() << "] "
0630 << "Already existing File " << tmpName << " renamed to " << newName << "\n";
0631 out->close();
0632 }
0633
0634 out->clear();
0635 out->open(tmpName.c_str(), ios::out | ios::trunc);
0636
0637 if (out->fail()) {
0638 delete out;
0639 throw cms::Exception("LaserSorter") << "Failed to create file " << tmpName << " for writing event from FED "
0640 << fedId << " lumi block " << lumiBlock << ": " << strerror(errno) << "\n.";
0641 }
0642
0643 ifstream in(finalName.c_str());
0644 bool newFile = true;
0645 if (in.good()) {
0646 if (verbosity_)
0647 cout << "[LaserSorter " << now() << "] "
0648 << "File " << finalName << " already exists. It will be updated if needed.\n";
0649
0650 char buffer[256];
0651 streamsize nread = -1;
0652 int vers = readFormatVersion(in, finalName);
0653 if (vers == -1) {
0654 edm::LogWarning("LaserSorter") << "File " << tmpName.c_str() << " is not an LMF file despite its extension or "
0655 << "it is corrupted.\n";
0656 } else if (vers != formatVersion_) {
0657 edm::LogWarning("LaserSorter") << "Cannot include events already in file " << tmpName.c_str()
0658 << " because of version "
0659 << "mismatch (found version " << (int)vers << " while "
0660 << "only version " << (int)formatVersion_ << " is supported).\n";
0661 } else {
0662 newFile = false;
0663
0664 const int indexTableOffsetPos8 = 1 * sizeof(uint32_t);
0665 uint32_t indexTableOffsetValue = 0;
0666 in.clear();
0667 in.seekg(indexTableOffsetPos8, ios::beg);
0668 in.read((char*)&indexTableOffsetValue, sizeof(indexTableOffsetValue));
0669 if (in.fail()) {
0670 cout << "[LaserSorter " << now() << "] "
0671 << "Failed to read offset of index table "
0672 " in the existing file "
0673 << finalName << "\n";
0674 } else {
0675 if (verbosity_ > 2)
0676 cout << "[LaserSorter " << now() << "] "
0677 << "Index table offset of "
0678 "original file "
0679 << finalName << ": 0x" << hex << setfill('0') << setw(8) << indexTableOffsetValue << dec << setfill(' ')
0680 << "\n";
0681 }
0682 in.clear();
0683 in.seekg(0, ios::beg);
0684
0685
0686 uint32_t toRead = indexTableOffsetValue;
0687 cout << "[LaserSorter " << now() << "] "
0688 << "Copying " << finalName << " to " << tmpName << endl;
0689 while (!in.eof() && (toRead > 0) && (nread = in.readsome(buffer, min(toRead, (uint32_t)sizeof(buffer)))) != 0) {
0690
0691
0692 toRead -= nread;
0693
0694 out->write(buffer, nread);
0695 if (out->bad()) {
0696 throw cms::Exception("LaserSorter")
0697 << "Error while writing to file " << tmpName << ". Check if there is enough "
0698 << "space on the device.\n";
0699 }
0700 }
0701
0702
0703 indexTableOffsetValue = 0;
0704 out->clear();
0705 out->seekp(indexTableOffsetPos8, ios::beg);
0706 out->write((char*)&indexTableOffsetValue, sizeof(uint32_t));
0707 out->clear();
0708 out->seekp(0, ios::end);
0709 }
0710 }
0711
0712 #if 0
0713 out->flush();
0714 cout << "Press enter... file name was " << tmpName << endl;
0715 char c;
0716 cin >> c;
0717 #endif
0718
0719 OutStreamRecord* outRcd = new OutStreamRecord(fedId, lumiBlock, out, tmpName, finalName);
0720
0721 if (newFile) {
0722 writeFileHeader(*out);
0723 } else {
0724 std::string errMsg;
0725 if (!readIndexTable(in, finalName, *outRcd, &errMsg)) {
0726 throw cms::Exception("LaserSorter") << errMsg << "\n";
0727 }
0728 }
0729
0730 return outStreamList_.emplace(outStreamList_.end(), outRcd);
0731 }
0732
0733 void LaserSorter::writeFileHeader(std::ofstream& out) {
0734 out.clear();
0735
0736 uint32_t id = 'L' | ('M' << 8) | ('F' << 16) | (formatVersion_ << 24);
0737
0738 out.write((char*)&id, sizeof(uint32_t));
0739
0740
0741 uint32_t zero = 0;
0742 out.write((char*)&zero, sizeof(uint32_t));
0743
0744 if (out.fail()) {
0745 throw cms::Exception("LaserSorter") << "Failed to write file header.\n";
0746 }
0747 }
0748
0749 bool LaserSorter::writeEventHeader(std::ofstream& out, const edm::Event& evt, int dtt, unsigned nFeds) {
0750 uint32_t data[10];
0751 timeval tt = {0, 0};
0752 if ((evt.time().value() >> 32)) {
0753 tt.tv_usec = evt.time().value() & 0xFFFFFFFF;
0754 tt.tv_sec = evt.time().value() >> 32;
0755 } else if (orbitZeroTime_.tv_sec) {
0756 div_t dt = div(orbit_ * 89.1, 1000 * 1000);
0757 tt.tv_sec = orbitZeroTime_.tv_sec + dt.quot;
0758 tt.tv_usec = orbitZeroTime_.tv_usec + dt.rem;
0759 if (tt.tv_usec > 1000 * 1000) {
0760 tt.tv_usec -= 1000 * 1000;
0761 tt.tv_sec += 1;
0762 }
0763 }
0764
0765 data[0] = tt.tv_usec;
0766 data[1] = tt.tv_sec;
0767 data[2] = evt.luminosityBlock();
0768 data[3] = evt.run();
0769 data[4] = orbit_;
0770 data[5] = evt.bunchCrossing();
0771 data[6] = evt.id().event();
0772 data[7] = dtt;
0773 data[8] = nFeds;
0774 data[9] = 0;
0775
0776 if (verbosity_ > 1) {
0777 cout << "[LaserSorter " << now() << "] "
0778 << "Write header of event: "
0779 << "Time: " << toString(evt.time().value()) << ", LB: " << evt.luminosityBlock() << ", Run: " << evt.run()
0780 << ", Bx: " << evt.bunchCrossing() << ", Event ID: " << evt.id().event() << ", Detailed trigger type: 0x"
0781 << hex << dtt << dec << " (" << detailedTrigNames[(dtt >> 8) & 0x7] << ", " << colorNames[(dtt >> 6) & 0x3]
0782 << ", DCC " << (dtt & 0x3f) << ", side " << ((dtt >> 10) & 0x1) << ")"
0783 << ", number of FEDs: "
0784 << "\n";
0785 }
0786
0787 out.clear();
0788 out.write((char*)data, sizeof(data));
0789 return !out.bad();
0790 }
0791
0792 void LaserSorter::streamFileName(int fedId,
0793 edm::LuminosityBlockNumber_t lumiBlock,
0794 std::string& tmpName,
0795 std::string& finalName) {
0796 int iFed;
0797 if (fedId >= ecalDccFedIdMin_ && fedId <= ecalDccFedIdMax_) {
0798 iFed = fedId - ecalDccFedIdMin_ + 1;
0799 } else if (fedId < 0) {
0800 iFed = -1;
0801 } else {
0802 iFed = 0;
0803 }
0804 if (iFed < -1 || iFed >= (int)fedSubDirs_.size()) {
0805 throw cms::Exception("LaserSorter") << "Bug found at " << __FILE__ << ":" << __LINE__
0806 << ". FED ID is out of index!";
0807 }
0808
0809 struct stat fileStat;
0810
0811 stringstream buf;
0812 buf << outputDir_ << "/" << (iFed < 0 ? "Empty" : fedSubDirs_[iFed]);
0813
0814 string dir = buf.str();
0815 if (0 == stat(dir.c_str(), &fileStat)) {
0816 if (!S_ISDIR(fileStat.st_mode)) {
0817 throw cms::Exception("[LaserSorter]") << "File " << dir << " exists but is not a directory "
0818 << " as expected.";
0819 }
0820 } else {
0821 if (0 != mkdir(dir.c_str(), 0755)) {
0822 throw cms::Exception("[LaserSorter]") << "Failed to create directory " << dir << " for writing data.";
0823 }
0824 }
0825
0826 buf.str("");
0827 buf << "Run" << runNumber_ << "_LB" << setfill('0') << setw(4) << lumiBlock << ".lmf";
0828 string fileName = buf.str();
0829 string tmpFileName = fileName + ".part";
0830
0831 finalName = dir + "/" + fileName;
0832 tmpName = dir + "/" + tmpFileName;
0833
0834 if (verbosity_ > 3)
0835 cout << "[LaserSorter " << now() << "] "
0836 << "File path: " << finalName << "\n";
0837 }
0838
0839 LaserSorter::OutStreamList::iterator LaserSorter::closeOutStream(LaserSorter::OutStreamList::iterator streamRecord) {
0840 if (streamRecord == outStreamList_.end())
0841 return outStreamList_.end();
0842
0843 if (verbosity_)
0844 cout << "[LaserSorter " << now() << "] "
0845 << "Writing Index table of file " << (*streamRecord)->finalFileName() << "\n";
0846 ofstream& out = *(*streamRecord)->out();
0847 out.clear();
0848 if (!writeIndexTable(out, *(*streamRecord)->indices())) {
0849 cout << "Error while writing index table for file " << (*streamRecord)->finalFileName() << ". "
0850 << "Resulting file might be corrupted. "
0851 << "The error can be due to a lack of disk space.";
0852 }
0853
0854 if (verbosity_)
0855 cout << "[LaserSorter " << now() << "] "
0856 << "Closing file " << (*streamRecord)->finalFileName() << ".\n";
0857 out.close();
0858
0859 const std::string& tmpFileName = (*streamRecord)->tmpFileName();
0860 const std::string& finalFileName = (*streamRecord)->finalFileName();
0861
0862 if (verbosity_)
0863 cout << "[LaserSorter " << now() << "] "
0864 << "Renaming " << tmpFileName << " to " << finalFileName << ".\n";
0865
0866 if (0 != rename(tmpFileName.c_str(), finalFileName.c_str())) {
0867 cout << "[LaserSorter " << now() << "] "
0868 << " Failed to rename output file from " << tmpFileName << " to " << finalFileName << ". " << strerror(errno)
0869 << "\n";
0870 }
0871
0872 if (doOutputList_) {
0873 char buf[256];
0874 time_t t = time(nullptr);
0875 strftime(buf, sizeof(buf), "%F %R:%S", localtime(&t));
0876
0877 ifstream f(".watcherfile");
0878 string inputFile;
0879 f >> inputFile;
0880 outputList_ << finalFileName << "\t" << buf << "\t" << inputFile << endl;
0881 }
0882
0883 return outStreamList_.erase(streamRecord);
0884 }
0885
0886 void LaserSorter::endJob() {
0887
0888
0889 closeAllStreams();
0890 }
0891
0892 void LaserSorter::beginJob() {}
0893
0894 bool LaserSorter::isDccEventEmpty(const FEDRawData& data, size_t* dccLen, int* nTowerBlocks) const {
0895 if (nTowerBlocks)
0896 *nTowerBlocks = 0;
0897
0898
0899 bool rc = true;
0900 if (dccLen)
0901 *dccLen = 0;
0902 const unsigned nWord32 = data.size() / sizeof(uint32_t);
0903 if (nWord32 == 0) {
0904
0905 return true;
0906 }
0907 for (unsigned iWord32 = 0; iWord32 < nWord32; iWord32 += 2) {
0908 const uint32_t* data32 = ((const uint32_t*)(data.data())) + iWord32;
0909 int dataType = (data32[1] >> 28) & 0xF;
0910
0911
0912
0913
0914 if (0 == (dataType >> 2)) {
0915 const int dccHeaderId = (data32[1] >> 24) & 0x3F;
0916 if (dccHeaderId == 1) {
0917 if (dccLen)
0918 *dccLen = ((data32[0] >> 0) & 0xFFFFFF);
0919 }
0920 }
0921 if ((dataType >> 2) == 3) {
0922 rc = false;
0923 if (nTowerBlocks) {
0924 ++(*nTowerBlocks);
0925 } else {
0926 break;
0927 }
0928 }
0929 }
0930
0931
0932
0933
0934
0935
0936
0937 return rc;
0938 }
0939
0940 void LaserSorter::getOutputFedList(const edm::Event& event,
0941 const FEDRawDataCollection& data,
0942 std::vector<unsigned>& fedIds) const {
0943 fedIds.erase(fedIds.begin(), fedIds.end());
0944 for (int id = ecalDccFedIdMin_; id <= ecalDccFedIdMax_; ++id) {
0945 size_t dccLen;
0946 const FEDRawData& dccEvent = data.FEDData(id);
0947 if (!isDccEventEmpty(dccEvent, &dccLen)) {
0948 fedIds.push_back(id);
0949 }
0950 if (dccLen * sizeof(uint64_t) != dccEvent.size()) {
0951 edm::LogWarning("LaserSorter") << "Length error in data of FED " << id << " in event " << event.id()
0952 << ", Data of this FED dropped.";
0953 }
0954 }
0955
0956
0957
0958 if (data.FEDData(matacqFedId_).size() > 4) {
0959
0960
0961 fedIds.push_back(matacqFedId_);
0962 }
0963 }
0964
0965 std::vector<int> LaserSorter::getFullyReadoutDccs(const FEDRawDataCollection& data) const {
0966 int nTowers;
0967 vector<int> result;
0968 for (int fed = ecalDccFedIdMin_; fed <= ecalDccFedIdMax_; ++fed) {
0969 const FEDRawData& fedData = data.FEDData(fed);
0970 isDccEventEmpty(fedData, nullptr, &nTowers);
0971 if (nTowers >= 68)
0972 result.push_back(fed);
0973 }
0974 return result;
0975 }
0976
0977 bool LaserSorter::writeIndexTable(std::ofstream& out, std::vector<IndexRecord>& indices) {
0978 uint32_t indexTablePos = out.tellp();
0979 uint32_t nevts = indices.size();
0980
0981 out.clear();
0982 out.write((char*)&nevts, sizeof(nevts));
0983 const uint32_t reserved = 0;
0984 out.write((const char*)&reserved, sizeof(reserved));
0985
0986 if (out.bad())
0987 return false;
0988
0989 sort(indices.begin(), indices.end());
0990
0991 for (unsigned i = 0; i < indices.size(); ++i) {
0992 uint32_t data[2];
0993 data[0] = indices[i].orbit;
0994 data[1] = indices[i].filePos;
0995 out.write((char*)data, sizeof(data));
0996 }
0997
0998 if (out.bad())
0999 return false;
1000
1001
1002
1003 out.clear();
1004 out.seekp(indexOffset32_ * sizeof(uint32_t));
1005
1006
1007 if (!out.bad())
1008 out.write((char*)&indexTablePos, sizeof(uint32_t));
1009
1010 bool rc = !out.bad();
1011
1012
1013 out.seekp(0, ios::end);
1014
1015 return rc;
1016 }
1017
1018
1019 bool LaserSorter::readIndexTable(std::ifstream& in, std::string& inName, OutStreamRecord& outRcd, std::string* err) {
1020 stringstream errMsg;
1021
1022 ifstream* s = ∈
1023
1024
1025 s->clear();
1026 s->seekg(0);
1027
1028 uint32_t fileHeader[2];
1029 s->read((char*)&fileHeader[0], sizeof(fileHeader));
1030 uint32_t indexTablePos = fileHeader[1];
1031
1032 if (s->eof()) {
1033 s->clear();
1034 s->seekg(0);
1035 errMsg << "Failed to read header of file " << inName << ".";
1036 if (err)
1037 *err = errMsg.str();
1038 return false;
1039 }
1040
1041 s->seekg(indexTablePos);
1042
1043 uint32_t nevts = 0;
1044 s->read((char*)&nevts, sizeof(nevts));
1045 s->ignore(4);
1046 if (s->bad()) {
1047 errMsg << "Failed to read index table from file " << inName << ".";
1048 if (err)
1049 *err = errMsg.str();
1050 return false;
1051 }
1052 if (nevts > maxEvents_) {
1053 errMsg << "Number of events indicated in event index of file " << inName << " (" << nevts << ") "
1054 << "is unexpectively large.";
1055 if (err)
1056 *err = errMsg.str();
1057 return false;
1058 }
1059 outRcd.indices()->resize(nevts);
1060 s->read((char*)&(*outRcd.indices())[0], nevts * sizeof(IndexRecord));
1061 if (s->bad()) {
1062 outRcd.indices()->clear();
1063 errMsg << "Failed to read index table from file " << inName << ".";
1064 if (err)
1065 *err = errMsg.str();
1066 return false;
1067 }
1068 if (nevts > maxEvents_) {
1069 errMsg << "Number of events indicated in event index of file " << inName << " is unexpectively large.";
1070 if (err)
1071 *err = errMsg.str();
1072 outRcd.indices()->clear();
1073 return false;
1074 }
1075
1076 if (verbosity_ > 1)
1077 cout << "[LaserSorter " << now() << "] "
1078 << "Orbit IDs of events "
1079 << "already contained in the file " << inName << ":";
1080 for (unsigned i = 0; i < outRcd.indices()->size(); ++i) {
1081 if (verbosity_ > 1) {
1082 cout << " " << setw(9) << (*outRcd.indices())[i].orbit;
1083 }
1084 outRcd.excludedOrbit().insert((*outRcd.indices())[i].orbit);
1085 }
1086 if (verbosity_ > 1)
1087 cout << "\n";
1088
1089 return true;
1090 }
1091
1092 int LaserSorter::readFormatVersion(std::ifstream& in, const std::string& fileName) {
1093 int vers = -1;
1094 streampos p = in.tellg();
1095
1096 uint32_t data;
1097
1098 in.read((char*)&data, sizeof(data));
1099
1100 char magic[4];
1101
1102 magic[0] = data & 0xFF;
1103 magic[1] = (data >> 8) & 0xFF;
1104 magic[2] = (data >> 16) & 0xFF;
1105 magic[3] = 0;
1106
1107 const string lmf = string("LMF");
1108
1109 if (in.good() && lmf == magic) {
1110 vers = (data >> 24) & 0xFF;
1111 }
1112
1113 if (lmf != magic) {
1114 edm::LogWarning("LaserSorter") << "File " << fileName << "is not an LMF file.\n";
1115 }
1116
1117 in.clear();
1118 in.seekg(p);
1119 return vers;
1120 }
1121
1122 std::string LaserSorter::toString(uint64_t t) {
1123 char buf[256];
1124
1125 time_t tsec = t >> 32;
1126
1127 uint32_t tusec = t & 0xFFFFFFFF;
1128 strftime(buf, sizeof(buf), "%F %R %S s", localtime(&tsec));
1129 buf[sizeof(buf) - 1] = 0;
1130
1131 stringstream buf2;
1132 buf2 << (tusec + 500) / 1000;
1133
1134 return string(buf) + " " + buf2.str() + " ms";
1135 }
1136
1137 void LaserSorter::restoreStreamsOfLumiBlock(int lumiBlock) {
1138 string dummy;
1139 string fileName;
1140
1141 for (int fedId = ecalDccFedIdMin_ - 2; fedId <= ecalDccFedIdMax_; ++fedId) {
1142 int fedId_;
1143 if (fedId == ecalDccFedIdMin_ - 2)
1144 fedId_ = -1;
1145 else
1146 fedId_ = fedId;
1147 streamFileName(fedId_, lumiBlock, dummy, fileName);
1148 struct stat s;
1149
1150
1151 if (stat(fileName.c_str(), &s) == 0) {
1152 getStream(fedId_, lumiBlock);
1153 }
1154 }
1155 }
1156
1157 void LaserSorter::beginRun(edm::Run const& run, edm::EventSetup const& es) {}
1158
1159 void LaserSorter::endRun(edm::Run const& run, edm::EventSetup const& es) {}