Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:47:02

0001 /*
0002  *  \author Philippe Gras CEA/Saclay
0003  */
0004 
0005 #include <iostream>
0006 #include <iomanip>
0007 #include "CalibCalorimetry/EcalLaserSorting/interface/LmfSource.h"
0008 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0009 #include "FWCore/Framework/interface/Event.h"
0010 #include "FWCore/Framework/interface/EventSetup.h"
0011 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0012 #include "DataFormats/FEDRawData/interface/FEDRawData.h"
0013 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
0014 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
0015 
0016 using namespace edm;
0017 using namespace std;
0018 
0019 const unsigned char LmfSource::minDataFormatVersion_ = 4;
0020 const unsigned char LmfSource::maxDataFormatVersion_ = 5;
0021 const unsigned LmfSource::fileHeaderSize = 2;
0022 
0023 LmfSource::LmfSource(const ParameterSet& pset, const InputSourceDescription& desc)
0024     : ProducerSourceBase(pset, desc, true),
0025       fileNames_(pset.getParameter<vector<string> >("fileNames")),
0026       iFile_(-1),
0027       fedId_(-1),
0028       fileHeader_(fileHeaderSize),
0029       dataFormatVers_(5),
0030       rcRead_(false),
0031       preScale_(pset.getParameter<unsigned>("preScale")),
0032       iEvent_(0),
0033       iEventInFile_(0),
0034       indexTablePos_(0),
0035       orderedRead_(pset.getParameter<bool>("orderedRead")),
0036       watchFileList_(pset.getParameter<bool>("watchFileList")),
0037       fileListName_(pset.getParameter<std::string>("fileListName")),
0038       inputDir_(pset.getParameter<std::string>("inputDir")),
0039       nSecondsToSleep_(pset.getParameter<int>("nSecondsToSleep")),
0040       verbosity_(pset.getUntrackedParameter<int>("verbosity")) {
0041   if (preScale_ == 0)
0042     preScale_ = 1;
0043   produces<FEDRawDataCollection>();
0044   // open fileListName
0045   if (watchFileList_) {
0046     fileList_.open(fileListName_.c_str());
0047     if (fileList_.fail()) {
0048       throw cms::Exception("FileListOpenError") << "Failed to open input file " << fileListName_ << "\n";
0049     }
0050   } else {
0051     //throws a cms exception if error in fileNames parameter
0052     checkFileNames();
0053   }
0054 }
0055 
0056 bool LmfSource::readFileHeader() {
0057   if (iFile_ == -1)
0058     return false;  //no file open
0059 
0060   if (verbosity_)
0061     cout << "[LmfSource]"
0062          << "Opening file #" << (iFile_ + 1) << " '" << currentFileName_ << "'\n";
0063 
0064   in_.read((char*)&fileHeader_[0], fileHeaderSize * sizeof(uint32_t));
0065 
0066   if (in_.eof())
0067     return false;
0068 
0069   if (verbosity_) {
0070     cout << "[LmfSource]"
0071          << "File header (in hex):" << hex;
0072     for (unsigned i = 0; i < fileHeaderSize; ++i) {
0073       if (i % 8 == 0)
0074         cout << "\n";
0075       cout << setw(8) << fileHeader_[i] << " ";
0076     }
0077     cout << dec << "\n";
0078   }
0079 
0080   char id[4];
0081 
0082   id[0] = fileHeader_[0] & 0xFF;
0083   id[1] = (fileHeader_[0] >> 8) & 0xFF;
0084   id[2] = (fileHeader_[0] >> 16) & 0xFF;
0085   id[3] = (fileHeader_[0] >> 24) & 0xFF;
0086 
0087   if (!(id[0] == 'L' && id[1] == 'M' && id[2] == 'F')) {
0088     throw cms::Exception("FileReadError") << currentFileName_ << " is not a file in LMF format!";
0089   }
0090   dataFormatVers_ = id[3];
0091   if (verbosity_)
0092     cout << "[LmfSource]"
0093          << "LMF format: " << (int)dataFormatVers_ << "\n";
0094 
0095   if (dataFormatVers_ > maxDataFormatVersion_ || dataFormatVers_ < minDataFormatVersion_) {
0096     throw cms::Exception("FileReadError") << currentFileName_ << ": LMF format version " << (int)dataFormatVers_
0097                                           << " is not supported by this release of LmfSource module";
0098   }
0099 
0100   indexTablePos_ = fileHeader_[1];
0101 
0102   if (verbosity_)
0103     cout << "[LmfSource] File position of index table: 0x" << setfill('0') << hex << setw(8) << indexTablePos_
0104          << setfill(' ') << dec << "\n";
0105 
0106   if (dataFormatVers_ < 5) {
0107     in_.ignore(4);
0108   }
0109 
0110   return true;
0111 }
0112 
0113 void LmfSource::produce(edm::Event& evt) {
0114   //   bool rc;
0115   //   while(!((rc = readFileHeader()) & readEventPayload())){
0116   //     if(openFile(++iFile_)==false){//no more files
0117   //       if(verbosity_) cout << "[LmfSource]"
0118   //               << "No more input file";
0119   //       return false;
0120   //     }
0121   //   }
0122   auto coll = std::make_unique<FEDRawDataCollection>();
0123   coll->swap(fedColl_);
0124   if (verbosity_)
0125     cout << "[LmfSource] Putting FEDRawDataCollection in event\n";
0126   evt.put(std::move(coll));
0127 }
0128 
0129 bool LmfSource::openFile(int iFile) {
0130   iEventInFile_ = 0;
0131   if (watchFileList_) {
0132     for (;;) {
0133       // read the first field of the line, which must be the filename
0134       fileList_ >> currentFileName_;
0135       currentFileName_ = inputDir_ + "/" + currentFileName_;
0136       if (!fileList_.fail()) {
0137         // skip the rest of the line
0138         std::string tmp_buffer;
0139         std::getline(fileList_, tmp_buffer);
0140         if (verbosity_)
0141           cout << "[LmfSource]"
0142                << "Opening file " << currentFileName_ << "\n";
0143         in_.open(currentFileName_.c_str());
0144         if (!in_.fail()) {
0145           // file was successfully open
0146           return true;
0147         } else {
0148           // skip file
0149           edm::LogError("FileOpenError") << "Failed to open input file " << currentFileName_ << ". Skipping file\n";
0150           in_.close();
0151           in_.clear();
0152         }
0153       }
0154       // if here, no new file is available: sleep and retry later
0155       if (verbosity_)
0156         std::cout << "[LmfSource]"
0157                   << " going to sleep 5 seconds\n";
0158       sleep(nSecondsToSleep_);
0159       fileList_.clear();
0160     }
0161   } else {
0162     if (iFile > (int)fileNames_.size() - 1)
0163       return false;
0164     currentFileName_ = fileNames_[iFile];
0165     if (verbosity_)
0166       cout << "[LmfSource]"
0167            << "Opening file " << currentFileName_ << "\n";
0168     in_.open(currentFileName_.c_str());
0169     if (in_.fail()) {
0170       throw cms::Exception("FileOpenError") << "Failed to open input file " << currentFileName_ << "\n";
0171     }
0172   }
0173   return true;
0174 }
0175 
0176 bool LmfSource::nextEventWithinFile() {
0177   if (iFile_ < 0)
0178     return false;  //no file opened.
0179   if (orderedRead_) {
0180     if (iEventInFile_ >= indexTable_.size())
0181       return false;
0182     if (verbosity_) {
0183       cout << "[LmfSource] move to event with orbit Id " << indexTable_[iEventInFile_].orbit << " at file position 0x"
0184            << hex << setfill('0') << setw(8) << indexTable_[iEventInFile_].filePos << setfill(' ') << dec << "\n";
0185     }
0186     const streampos pos = indexTable_[iEventInFile_].filePos;
0187     in_.clear();
0188     in_.seekg(pos);
0189     if (in_.bad()) {
0190       cout << "[LmfSource] Problem while reading file " << currentFileName_ << ". Problem with event index table?\n";
0191       return false;
0192     }
0193     ++iEventInFile_;
0194     return true;
0195   } else {
0196     return true;
0197   }
0198 }
0199 
0200 bool LmfSource::readEvent(bool doSkip) {
0201   while (!(nextEventWithinFile() && readEventWithinFile(doSkip))) {
0202     //failed to read event. Let's look for next file:
0203     in_.close();
0204     in_.clear();
0205     bool rcOpen = openFile(++iFile_);
0206     if (rcOpen == false) {  //no more files
0207       if (verbosity_)
0208         cout << "[LmfSource]"
0209              << "No more input file";
0210       rcRead_ = false;
0211       return rcRead_;
0212     }
0213     rcRead_ = readFileHeader();
0214     if (verbosity_)
0215       cout << "File header readout " << (rcRead_ ? "succeeded" : "failed") << "\n";
0216     if (rcRead_ && orderedRead_)
0217       readIndexTable();
0218   }
0219   return rcRead_;
0220 }
0221 
0222 bool LmfSource::setRunAndEventInfo(EventID& id, TimeValue_t& time, edm::EventAuxiliary::ExperimentType& eType) {
0223   //empties collection:
0224   if (fedId_ > 0) {
0225     fedColl_.FEDData(fedId_).resize(0);
0226   }
0227   if (verbosity_)
0228     cout << "[LmfSource]"
0229          << "About to read event...\n";
0230 
0231   bool rc;
0232   for (;;) {
0233     if (filter()) {  //event to read
0234       rc = readEvent();
0235       break;  //either event is read or no more event
0236     } else {  //event to skip
0237       rc = readEvent(true);
0238       if (rc == false) {  //no more events
0239         break;
0240       }
0241     }
0242   }
0243 
0244   if (!rc)
0245     return false;  //event readout failed
0246 
0247   if (verbosity_)
0248     cout << "[LmfSource]"
0249          << "Setting event time to " << /*toString(*/ timeStamp_ /*)*/ << ", "
0250          << "Run number to " << runNum_ << ","
0251          << "Event number to " << eventNum_ << "\n";
0252 
0253   time = timeStamp_;
0254   id = EventID(runNum_, lumiBlock_, eventNum_);
0255   return true;
0256 }
0257 
0258 bool LmfSource::readEventWithinFile(bool doSkip) {
0259   if (iFile_ == -1 || !rcRead_)
0260     return false;  //no file open
0261   //                                         or header reading failed
0262   //number of 32-bit word to read first to get the event size
0263   //field
0264   const int timeStamp32[] = {0, 0};  //timestamp is 64-bit long
0265   const int lumiBlock32[] = {2, 2};
0266   const int runNum32[] = {3, 3};
0267   const int orbitNum32[] = {4, 4};
0268   const int bx32[] = {5, 5};
0269   const int eventNum32[] = {6, 6};
0270   const int activeFedId32[] = {7, -1};
0271   const int calibTrig32[] = {-1, 7};
0272   const int nFeds32[] = {-1, 8};
0273   // const int reserved32[]       = {-1,9};
0274   const int evtHeadSize32[] = {8, 10};
0275 
0276   const unsigned char iv = dataFormatVers_ - minDataFormatVersion_;
0277   assert(iv <= sizeof(timeStamp32) / sizeof(timeStamp32[0]));
0278 
0279   if ((int)header_.size() < evtHeadSize32[iv])
0280     header_.resize(evtHeadSize32[iv]);
0281 
0282   if (verbosity_)
0283     cout << "[LmfSource]"
0284          << "Reading event header\n";
0285 
0286   in_.read((char*)&header_[0], evtHeadSize32[iv] * 4);
0287   if (in_.bad()) {  //reading error other than eof
0288     throw cms::Exception("FileReadError") << "Error while reading from file " << currentFileName_;
0289   }
0290   if (in_.eof())
0291     return false;
0292 
0293   if (verbosity_) {
0294     cout << "[LmfSource]"
0295          << "Event header (in hex):" << hex << setfill('0');
0296     for (int i = 0; i < evtHeadSize32[iv]; ++i) {
0297       if (i % 8 == 0)
0298         cout << "\n";
0299       cout << setw(8) << header_[i] << " ";
0300     }
0301     cout << dec << setfill(' ') << "\n";
0302   }
0303 
0304   timeStamp_ = *(uint64_t*)&header_[timeStamp32[iv]];
0305   lumiBlock_ = header_[lumiBlock32[iv]];
0306   runNum_ = header_[runNum32[iv]];
0307   orbitNum_ = header_[orbitNum32[iv]];
0308   eventNum_ = header_[eventNum32[iv]];
0309   bx_ = header_[bx32[iv]];
0310   calibTrig_ = calibTrig32[iv] >= 0 ? header_[calibTrig32[iv]] : 0;
0311   int activeFedId = activeFedId32[iv] >= 0 ? header_[activeFedId32[iv]] : ((calibTrig_ & 0x3F) + 600);
0312   nFeds_ = nFeds32[iv] < 0 ? 1 : header_[nFeds32[iv]];
0313 
0314   if (verbosity_) {
0315     time_t t = time_t(timeStamp_ >> 32);
0316     div_t t_ms_us = div(timeStamp_ & 0xFFFFFFFF, 1000);
0317     char tbuf[256];
0318     strftime(tbuf, sizeof(tbuf), "%F %T", localtime(&t));
0319     tbuf[sizeof(tbuf) - 1] = 0;
0320     cout << "[LmfSource] "
0321          << "timeStamp:          " << /*toString(timeStamp_)*/ timeStamp_ << " (" << tbuf << " " << t_ms_us.quot
0322          << " ms " << t_ms_us.rem << " us)\n"
0323          << "lumiBlock:          " << lumiBlock_ << "\n"
0324          << "runNum:             " << runNum_ << "\n"
0325          << "orbitNum:           " << orbitNum_ << "\n"
0326          << "eventNum:           " << eventNum_ << "\n"
0327          << "bx:                 " << bx_ << "\n"
0328          << "activeFedId:        " << activeFedId << "\n"
0329          << "Calib trigger type: " << ((calibTrig_ >> 8) & 0x3) << "\n"
0330          << "Color:              " << ((calibTrig_ >> 6) & 0x3) << "\n"
0331          << "Side:               " << ((calibTrig_ >> 11) & 0x1) << "\n"
0332          << "nFeds:              " << nFeds_ << "\n";
0333   }
0334 
0335   const int dccLenOffset32 = 2;
0336   const int fedIdOffset32 = 0;
0337   const int nPreRead32 = 3;
0338   vector<int32_t> buf(nPreRead32);
0339   for (int iFed = 0; iFed < nFeds_; ++iFed) {
0340     in_.read((char*)&buf[0], nPreRead32 * sizeof(uint32_t));
0341 
0342     if (verbosity_) {
0343       cout << "[LmfSource] " << nPreRead32 << " first 32-bit words of "
0344            << "FED block: " << hex << setfill('0');
0345       for (unsigned i = 0; i < buf.size(); ++i) {
0346         cout << "0x" << setw(8) << buf[i] << " ";
0347       }
0348       cout << dec << setfill(' ');
0349     }
0350 
0351     if (in_.bad())
0352       return false;
0353 
0354     const unsigned eventSize64 = buf[dccLenOffset32] & 0x00FFFFFF;
0355     const unsigned eventSize32 = eventSize64 * 2;
0356     const unsigned eventSize8 = eventSize64 * 8;
0357     const unsigned fedId_ = (buf[fedIdOffset32] >> 8) & 0xFFF;
0358 
0359     if (eventSize8 > maxEventSize_) {
0360       throw cms::Exception("FileReadError")
0361           << "Size of event fragment (FED block) read from "
0362           << " data of file " << currentFileName_ << "is unexpctively large (" << (eventSize8 >> 10) << " kByte). "
0363           << "This must be an error (corrupted file?)\n";
0364     }
0365 
0366     if (!FEDNumbering::inRange(fedId_)) {
0367       throw cms::Exception("FileReadError") << "Invalid FED number read from data file.";
0368     }
0369 
0370     int32_t toRead8 = (eventSize32 - nPreRead32) * sizeof(int32_t);
0371 
0372     if (toRead8 < 0) {
0373       throw cms::Exception("FileReadError")
0374           << "Event size error while reading an event from file " << currentFileName_ << "\n";
0375     }
0376 
0377     if (doSkip) {  //event to skip
0378       if (verbosity_)
0379         cout << "[LmfSource] "
0380              << "Skipping on event. Move file pointer " << toRead8 << " ahead.\n";
0381       in_.seekg(toRead8, ios::cur);
0382       if (in_.bad()) {  //reading error other than eof
0383         throw cms::Exception("FileReadError") << "Error while reading from file " << currentFileName_;
0384       }
0385     } else {
0386       //reads FED data:
0387       FEDRawData& data_ = fedColl_.FEDData(fedId_);
0388       data_.resize(eventSize8);
0389 
0390       //copy already read data:
0391       copy(buf.begin(), buf.end(), (int32_t*)data_.data());
0392 
0393       in_.read((char*)(data_.data()) + nPreRead32 * 4, toRead8);
0394 
0395       if (in_.bad()) {  //reading error other than eof
0396         throw cms::Exception("FileReadError") << "Error while reading from file " << currentFileName_;
0397       }
0398 
0399       if (verbosity_ && data_.size() > 16) {
0400         cout << "[LmfSource]"
0401              << "Head of DCC data (in hex):" << hex;
0402         for (int i = 0; i < 16; ++i) {
0403           if (i % 8 == 0)
0404             cout << "\n";
0405           cout << setw(8) << ((uint32_t*)data_.data())[i] << " ";
0406         }
0407         cout << dec << "\n";
0408       }
0409 
0410       if (dataFormatVers_ <= 4) {  //calib trigger in not in event header.
0411         //                    gets it from DCC block
0412         calibTrig_ = (((uint32_t*)data_.data())[5] & 0xFC0) | ((activeFedId - 600) & 0x3F);
0413         if (verbosity_) {
0414           cout << "[LmfSource] Old data format. "
0415                   "Uses information read from FED block to retrieve calibration "
0416                   "trigger type. Value is: 0x"
0417                << hex << setfill('0') << setw(3) << calibTrig_ << setfill(' ') << dec << "\n";
0418         }
0419       }
0420     }
0421     if (in_.eof())
0422       return false;
0423   }
0424   ++iEvent_;
0425   return true;
0426 }
0427 
0428 bool LmfSource::filter() const { return (iEvent_ % preScale_ == 0); }
0429 
0430 std::string LmfSource::toString(TimeValue_t& t) const {
0431   char buf[256];
0432   const int secTousec = 1000 * 1000;
0433   time_t tsec = t / secTousec;
0434   uint32_t tusec = (uint32_t)(t - tsec);
0435   strftime(buf, sizeof(buf), "%F %R %S s", localtime(&tsec));
0436   buf[sizeof(buf) - 1] = 0;
0437   stringstream buf2;
0438   buf2 << (tusec + 500) / 1000;
0439   return string(buf) + " " + buf2.str() + " ms";
0440 }
0441 
0442 void LmfSource::checkFileNames() {
0443   for (unsigned i = 0; i < fileNames_.size(); ++i) {
0444     std::string& fileName = fileNames_[i];
0445     const char s[] = "file:";
0446     if (fileName.compare(0, sizeof(s) - 1, s) == 0) {  //file: prefix => to strip
0447       fileName.erase(fileName.begin(), fileName.begin() + sizeof(s) - 1);
0448     }
0449     if (fileName.find_first_of(':') != string::npos) {
0450       throw cms::Exception("LmfSource") << "Character ':' is not allowed in paths specified fileNames "
0451                                         << "parameter. Please note only local file (or NFS, AFS)"
0452                                         << " is supported (no rfio, no /store)";
0453     }
0454     const char s1[] = "/store";
0455     if (fileName.compare(0, sizeof(s1) - 1, s1) == 0) {
0456       throw cms::Exception("LmfSource") << "CMSSW /store not supported by LmfSource. Only local file "
0457                                         << "(or NFS/AFS) allowed. Path starting with /store not permitted";
0458     }
0459   }
0460 }
0461 
0462 void LmfSource::readIndexTable() {
0463   stringstream errMsg;
0464   errMsg << "Error while reading event index table of file " << currentFileName_ << ". Try to read it with "
0465          << "option orderedRead disabled.\n";
0466 
0467   if (indexTablePos_ == 0)
0468     throw cms::Exception("LmfSource") << errMsg.str();
0469 
0470   in_.clear();
0471   in_.seekg(indexTablePos_);
0472 
0473   uint32_t nevts = 0;
0474   in_.read((char*)&nevts, sizeof(nevts));
0475   in_.ignore(4);
0476   if (nevts > maxEvents_) {
0477     throw cms::Exception("LmfSource") << "Number of events indicated in event index of file " << currentFileName_
0478                                       << " is unexpectively large. File cannot be "
0479                                       << "read in time-ordered event mode. See orderedRead parmater of "
0480                                       << "LmfSource module.\n";
0481   }
0482   //if(in_.bad()) throw cms::Exception("LmfSource") << errMsg.str();
0483   if (in_.bad())
0484     throw cms::Exception("LmfSource") << errMsg.str();
0485   indexTable_.resize(nevts);
0486   in_.read((char*)&indexTable_[0], nevts * sizeof(IndexRecord));
0487 }