CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_2_9_HLT1_bphpatch4/src/CalibCalorimetry/EcalLaserSorting/src/LmfSource.cc

Go to the documentation of this file.
00001 /*
00002  *  $Date: 2010/02/12 17:34:05 $
00003  *  $Revision: 1.7 $
00004  *  \author Philippe Gras CEA/Saclay
00005  */
00006 
00007 #include <iostream>
00008 #include <iomanip>
00009 #include "CalibCalorimetry/EcalLaserSorting/interface/LmfSource.h"
00010 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00011 #include "FWCore/Framework/interface/Event.h"
00012 #include "FWCore/Framework/interface/EventSetup.h"
00013 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00014 #include "DataFormats/FEDRawData/interface/FEDRawData.h"
00015 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
00016 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
00017 
00018 using namespace edm;
00019 using namespace std;
00020 
00021 unsigned char LmfSource::minDataFormatVersion_ = 4;
00022 unsigned char LmfSource::maxDataFormatVersion_ = 5;
00023 unsigned LmfSource::fileHeaderSize = 2;
00024 
00025 
00026 LmfSource::LmfSource(const ParameterSet& pset,
00027                      const InputSourceDescription& desc) :
00028   ConfigurableInputSource(pset, desc),
00029   fileNames_(pset.getParameter<vector<string> >("fileNames")),
00030   iFile_ (-1),
00031   fedId_(-1),
00032   fileHeader_(fileHeaderSize),
00033   dataFormatVers_(5),
00034   rcRead_(false),
00035   preScale_(pset.getParameter<unsigned>("preScale")),
00036   iEvent_(0),
00037   iEventInFile_(0),
00038   indexTablePos_(0),
00039   orderedRead_(pset.getParameter<bool>("orderedRead")),
00040   watchFileList_(pset.getParameter<bool>("watchFileList")),
00041   fileListName_(pset.getParameter<std::string>("fileListName")),
00042   inputDir_(pset.getParameter<std::string>("inputDir")),
00043   nSecondsToSleep_(pset.getParameter<int>("nSecondsToSleep")),
00044   verbosity_(pset.getUntrackedParameter<int>("verbosity"))
00045 {
00046   if(preScale_==0) preScale_ = 1;
00047   produces<FEDRawDataCollection>();
00048   // open fileListName
00049   if (watchFileList_) {
00050     fileList_.open( fileListName_.c_str() );
00051     if (fileList_.fail()) {
00052       throw cms::Exception("FileListOpenError")
00053         << "Failed to open input file " << fileListName_ << "\n";
00054     }
00055   } else {
00056   //throws a cms exception if error in fileNames parameter
00057   checkFileNames();
00058   }
00059 }
00060 
00061 bool LmfSource::readFileHeader(){
00062   if(iFile_==-1) return false; //no file open
00063 
00064   if(verbosity_) cout << "[LmfSource]"
00065                    << "Opening file #" << (iFile_+1) << " '"
00066                    << currentFileName_ << "'\n";
00067   
00068   in_.read((char*)&fileHeader_[0], fileHeaderSize*sizeof(uint32_t));
00069 
00070   if(in_.eof()) return false;
00071   
00072   if(verbosity_){
00073     cout << "[LmfSource]"
00074          << "File header (in hex):" << hex;
00075     for(unsigned i=0; i < fileHeaderSize; ++i){ 
00076       if(i%8==0) cout << "\n";
00077       cout << setw(8) << fileHeader_[i] << " ";
00078     }
00079     cout << dec << "\n";
00080   }
00081 
00082 
00083   char id[4];
00084 
00085   id[0] = fileHeader_[0] & 0xFF;
00086   id[1] = (fileHeader_[0] >>8) & 0xFF;
00087   id[2] = (fileHeader_[0] >>16) & 0xFF;
00088   id[3] = (fileHeader_[0] >>24) & 0xFF;
00089   
00090   if(!(id[0]=='L' && id[1] == 'M'
00091        && id[2] == 'F')){
00092     throw cms::Exception("FileReadError")
00093       << currentFileName_ << " is not a file in LMF format!";
00094   }
00095   dataFormatVers_ = id[3];
00096   if(verbosity_) cout << "[LmfSource]"
00097                    << "LMF format: " << (int)dataFormatVers_ << "\n";
00098   
00099   if(dataFormatVers_ > maxDataFormatVersion_
00100      || dataFormatVers_ < minDataFormatVersion_){
00101     throw cms::Exception("FileReadError")
00102       << currentFileName_ << ": LMF format version " << (int) dataFormatVers_
00103       << " is not supported by this release of LmfSource module";
00104   }
00105 
00106   indexTablePos_ = fileHeader_[1];
00107 
00108   if(verbosity_) cout << "[LmfSource] File position of index table: 0x"
00109                    << setfill('0') << hex << setw(8) << indexTablePos_
00110                    << setfill(' ') << dec << "\n";
00111   
00112   if(dataFormatVers_ < 5){
00113     in_.ignore(4);
00114   }
00115     
00116   return true;
00117 }
00118 
00119 bool LmfSource::produce(edm::Event& evt){
00120   //   bool rc;
00121   //   while(!((rc = readFileHeader()) & readEventPayload())){
00122   //     if(openFile(++iFile_)==false){//no more files
00123   //       if(verbosity_) cout << "[LmfSource]"
00124   //                   << "No more input file";
00125   //       return false;
00126   //     }
00127   //   }
00128   if(rcRead_){//readout succeeded
00129     auto_ptr<FEDRawDataCollection> coll(new FEDRawDataCollection);
00130     coll->swap(fedColl_);
00131     if(verbosity_) cout << "[LmfSource] Putting FEDRawDataCollection in event\n";
00132     evt.put(coll);
00133   }
00134   return rcRead_;
00135 }
00136 
00137 bool LmfSource::openFile(int iFile){
00138   iEventInFile_ = 0;
00139   if(watchFileList_) {
00140     for ( ;; ) {
00141       // read the first field of the line, which must be the filename
00142       fileList_ >> currentFileName_;
00143       currentFileName_ = inputDir_ + "/" + currentFileName_;
00144       if (!fileList_.fail()) {
00145         // skip the rest of the line
00146         std::string tmp_buffer;
00147         std::getline(fileList_, tmp_buffer);
00148         if(verbosity_) cout << "[LmfSource]"
00149           << "Opening file " << currentFileName_ << "\n";
00150         in_.open(currentFileName_.c_str());
00151         if (!in_.fail()) {
00152           // file was successfully open
00153           return true;
00154         } else {
00155           // skip file
00156           edm::LogError("FileOpenError")
00157             << "Failed to open input file " << currentFileName_ << ". Skipping file\n";
00158           in_.close();
00159           in_.clear();
00160         }
00161       }
00162       // if here, no new file is available: sleep and retry later
00163       if (verbosity_) std::cout << "[LmfSource]"
00164         << " going to sleep 5 seconds\n";
00165       sleep(nSecondsToSleep_);
00166       fileList_.clear();
00167     }
00168   } else {
00169     if(iFile > (int)fileNames_.size()-1) return false;
00170     currentFileName_ = fileNames_[iFile];
00171     if(verbosity_) cout << "[LmfSource]"
00172       << "Opening file " << currentFileName_ << "\n";
00173     in_.open(currentFileName_.c_str());
00174     if(in_.fail()){
00175       throw cms::Exception("FileOpenError")
00176         << "Failed to open input file " << currentFileName_ << "\n";
00177     }
00178   }
00179   return true;
00180 }
00181 
00182 bool LmfSource::nextEventWithinFile(){
00183   if(iFile_<0) return false; //no file opened.
00184   if(orderedRead_){
00185     if(iEventInFile_>=indexTable_.size()) return false;
00186     if(verbosity_){
00187       cout << "[LmfSource] move to event with orbit Id "
00188            << indexTable_[iEventInFile_].orbit
00189            << " at file position 0x"
00190            << hex << setfill('0')
00191            << setw(8) << indexTable_[iEventInFile_].filePos
00192            << setfill(' ') << dec << "\n";
00193     }
00194     const streampos pos = indexTable_[iEventInFile_].filePos;
00195     in_.clear();
00196     in_.seekg(pos);
00197     if(in_.bad()){
00198       cout << "[LmfSource] Problem while reading file "
00199            << currentFileName_ << ". Problem with event index table?\n";
00200       return false;
00201     }
00202     ++iEventInFile_;
00203     return true;
00204   } else{
00205     return true;
00206   }
00207 }
00208                
00209 bool LmfSource::readEvent(bool doSkip){
00210   while(!(nextEventWithinFile() && readEventWithinFile(doSkip))){
00211     //failed to read event. Let's look for next file:
00212     in_.close();
00213     in_.clear();
00214     bool rcOpen = openFile(++iFile_);
00215     if(rcOpen==false){//no more files
00216       if(verbosity_) cout << "[LmfSource]"
00217                        << "No more input file";
00218       rcRead_ = false;
00219       return rcRead_;
00220     }
00221     rcRead_ = readFileHeader();
00222     if(verbosity_) cout << "File header readout "
00223                      << (rcRead_?"succeeded":"failed") << "\n";
00224     if(rcRead_ && orderedRead_) readIndexTable();
00225   }
00226   return rcRead_;
00227 }
00228  
00229 void LmfSource::setRunAndEventInfo(){
00230   //empties collection:
00231   if(fedId_>0){
00232     fedColl_.FEDData(fedId_).resize(0);
00233   }
00234   if(verbosity_) cout << "[LmfSource]"
00235                    << "About to read event...\n";
00236 
00237   bool rc;
00238   for(;;){
00239     if(filter()){//event to read
00240       rc = readEvent();
00241       break;    //either event is read or no more event
00242     } else { //event to skip
00243       rc = readEvent(true);
00244       if(rc==false){//no more events
00245         break;
00246       }
00247     }
00248   }
00249 
00250   if(!rc) return; //event readout failed
00251     
00252   if(verbosity_) cout << "[LmfSource]"
00253                    << "Setting event time to "
00254                    << /*toString(*/timeStamp_/*)*/ << ", "
00255                    << "Run number to " << runNum_ << ","
00256                    << "Event number to " << eventNum_ << "\n";
00257 
00258   setTime(timeStamp_);
00259   setRunNumber(runNum_);
00260   setEventNumber(eventNum_);
00261   setLuminosityBlockNumber_t(lumiBlock_);
00262 }
00263 
00264 bool LmfSource::readEventWithinFile(bool doSkip){
00265   if(iFile_==-1 || !rcRead_) return false; //no file open
00266   //                                         or header reading failed
00267   //number of 32-bit word to read first to get the event size
00268   //field
00269   const int timeStamp32[]      = {0, 0}; //timestamp is 64-bit long
00270   const int lumiBlock32[]      = {2, 2};
00271   const int runNum32[]         = {3, 3};
00272   const int orbitNum32[]       = {4, 4};
00273   const int bx32[]             = {5, 5};
00274   const int eventNum32[]       = {6, 6};
00275   const int activeFedId32[]    = {7,-1};
00276   const int calibTrig32[]      = {-1,7};
00277   const int nFeds32[]          = {-1,8};
00278   // const int reserved32[]       = {-1,9};
00279   const int evtHeadSize32[]    = {8,10};
00280   
00281   const unsigned char iv = dataFormatVers_-minDataFormatVersion_;
00282   assert(iv<=sizeof(timeStamp32)/sizeof(timeStamp32[0]));
00283   
00284   if((int)header_.size() < evtHeadSize32[iv]) header_.resize(evtHeadSize32[iv]);
00285 
00286 
00287   if(verbosity_) cout << "[LmfSource]"
00288                    << "Reading event header\n";
00289 
00290   in_.read((char*)&header_[0], evtHeadSize32[iv]*4);
00291   if(in_.bad()){//reading error other than eof
00292     throw cms::Exception("FileReadError")
00293       << "Error while reading from file " << currentFileName_;
00294   }
00295   if(in_.eof()) return false;
00296 
00297   if(verbosity_){
00298     cout << "[LmfSource]"
00299          << "Event header (in hex):" << hex << setfill('0');
00300     for(int i=0; i < evtHeadSize32[iv]; ++i){ 
00301       if(i%8==0) cout << "\n";
00302       cout << setw(8) << header_[i] << " ";
00303     }
00304     cout << dec << setfill(' ') << "\n";
00305   }
00306   
00307   timeStamp_   = *(uint64_t*)&header_[timeStamp32[iv]];
00308   lumiBlock_   = header_[lumiBlock32[iv]];
00309   runNum_      = header_[runNum32[iv]];
00310   orbitNum_    = header_[orbitNum32[iv]];
00311   eventNum_    = header_[eventNum32[iv]];
00312   bx_          = header_[bx32[iv]];
00313   calibTrig_   = calibTrig32[iv]>=0?header_[calibTrig32[iv]]:0;
00314   int activeFedId = activeFedId32[iv]>=0?
00315     header_[activeFedId32[iv]]:
00316     ((calibTrig_ & 0x3F) + 600);
00317   nFeds_       = nFeds32<0?1:header_[nFeds32[iv]];
00318   
00319   if(verbosity_){
00320     cout << "[LmfSource] "
00321          << "timeStamp:          " << /*toString(timeStamp_)*/ timeStamp_ << "\n"
00322          << "lumiBlock:          " << lumiBlock_ << "\n"
00323          << "runNum:             " << runNum_ << "\n"
00324          << "orbitNum:           " << orbitNum_ << "\n"
00325          << "eventNum:           " << eventNum_ << "\n"
00326          << "bx:                 " << bx_ << "\n"
00327          << "activeFedId:        " << activeFedId << "\n"
00328          << "Calib trigger type: " << ((calibTrig_ >>8) & 0x3) << "\n"
00329          << "Color:              " << ((calibTrig_ >>6) & 0x3) << "\n"
00330          << "nFeds:              " << nFeds_ << "\n";
00331   }
00332 
00333   const int dccLenOffset32 = 2;
00334   const int fedIdOffset32  = 0; 
00335   const int nPreRead32     = 3;
00336   vector<int32_t> buf(nPreRead32);
00337   for(int iFed = 0; iFed < nFeds_; ++iFed){  
00338     in_.read((char*) &buf[0], nPreRead32*sizeof(uint32_t));
00339 
00340     if(verbosity_){
00341       cout << "[LmfSource] " << nPreRead32 << " first 32-bit words of "
00342            << "FED block: " << hex << setfill('0');
00343       for(unsigned i = 0; i< buf.size(); ++i){
00344         cout << "0x" << setw(8) << buf[i] << " ";
00345       }
00346       cout << dec << setfill(' ');
00347     }
00348         
00349     
00350     if(in_.bad()) return false;
00351     
00352     const unsigned eventSize64 = buf[dccLenOffset32] &  0x00FFFFFF;
00353     const unsigned eventSize32 = eventSize64*2;
00354     const unsigned eventSize8  = eventSize64*8;
00355     const unsigned fedId_      = (buf[fedIdOffset32] >>8) & 0xFFF;
00356 
00357     if(eventSize8 > maxEventSize_){
00358       throw cms::Exception("FileReadError")
00359         << "Size of event fragment (FED block) read from "
00360         << " data of file " << currentFileName_
00361         << "is unexpctively large (" << (eventSize8 >>10)
00362         << " kByte). "
00363         << "This must be an error (corrupted file?)\n";
00364     }
00365     
00366     if(!FEDNumbering::inRange(fedId_)){
00367       throw cms::Exception("FileReadError")
00368         << "Invalid FED number read from data file.";
00369     }
00370 
00371     int32_t toRead8 = (eventSize32-nPreRead32)*sizeof(int32_t);
00372 
00373     if(toRead8<0){
00374       throw cms::Exception("FileReadError")
00375         << "Event size error while reading an event from file "
00376         << currentFileName_ << "\n";
00377     }
00378     
00379     if(doSkip){//event to skip
00380       if(verbosity_) cout << "[LmfSource] "
00381                        << "Skipping on event. Move file pointer "
00382                        << toRead8 << " ahead.\n";
00383       in_.seekg(toRead8, ios::cur);
00384       if(in_.bad()){//reading error other than eof
00385         throw cms::Exception("FileReadError")
00386           << "Error while reading from file " << currentFileName_;
00387       }
00388     } else{
00389       //reads FED data:
00390       FEDRawData& data_ = fedColl_.FEDData(fedId_);
00391       data_.resize(eventSize8);
00392       
00393       //copy already read data:
00394       copy(buf.begin(), buf.end(), (int32_t*)data_.data());
00395       
00396       in_.read((char*)(data_.data()) + nPreRead32*4,
00397                toRead8);
00398       
00399       if(in_.bad()){//reading error other than eof
00400         throw cms::Exception("FileReadError")
00401           << "Error while reading from file " << currentFileName_;
00402       }
00403     
00404       if(verbosity_ && data_.size()>16){
00405         cout << "[LmfSource]"
00406              << "Head of DCC data (in hex):" << hex;
00407         for(int i=0; i < 16; ++i){ 
00408           if(i%8==0) cout << "\n";
00409           cout << setw(8) << ((uint32_t*)data_.data())[i] << " ";
00410         }
00411         cout << dec << "\n";
00412       }
00413 
00414       if(dataFormatVers_<=4){//calib trigger in not in event header.
00415         //                    gets it from DCC block
00416         calibTrig_ = (((uint32_t*)data_.data())[5] & 0xFC0)
00417           | ((activeFedId-600) &  0x3F);
00418         if(verbosity_){
00419           cout << "[LmfSource] Old data format. "
00420             "Uses information read from FED block to retrieve calibration "
00421             "trigger type. Value is: 0x"
00422                << hex << setfill('0') << setw(3) << calibTrig_
00423                << setfill(' ') << dec << "\n";
00424         }
00425       }
00426     }
00427     if(in_.eof()) return false;
00428   }
00429   ++iEvent_;
00430   return true;
00431 }
00432 
00433 bool LmfSource::filter() const{
00434   return (iEvent_%preScale_==0);
00435 }
00436             
00437 std::string LmfSource::toString(TimeValue_t& t) const{
00438   char buf[256];
00439   const int secTousec = 1000*1000;
00440   time_t tsec = t/secTousec;
00441   uint32_t tusec = (uint32_t)(t-tsec);
00442   strftime(buf, sizeof(buf), "%F %R %S s", localtime(&tsec));
00443   buf[sizeof(buf)-1] = 0;
00444   stringstream buf2;
00445   buf2 << (tusec+500)/1000;
00446   return string(buf) + " " + buf2.str() + " ms";
00447 }
00448 
00449 void LmfSource::checkFileNames(){
00450   for(unsigned i = 0; i < fileNames_.size(); ++i){
00451     std::string& fileName = fileNames_[i];
00452     const char s[] = "file:";
00453     if(fileName.compare(0, sizeof(s)-1, s)==0){ //file: prefix => to strip
00454       fileName.erase(fileName.begin(),
00455                      fileName.begin() + sizeof(s)-1);
00456     }
00457     if(fileName.find_first_of(":")!=string::npos){
00458       throw cms::Exception("LmfSource")
00459         << "Character ':' is not allowed in paths specified fileNames "
00460         << "parameter. Please note only local file (or NFS, AFS)"
00461         << " is supported (no rfio, no /store)";
00462     }
00463     const char s1[] = "/store";
00464     if(fileName.compare(0, sizeof(s1)-1, s1)==0){
00465       throw cms::Exception("LmfSource")
00466         << "CMSSW /store not supported by LmfSource. Only local file "
00467         << "(or NFS/AFS) allowed. Path starting with /store not permitted";
00468     }
00469   }
00470 }
00471 
00472 void LmfSource::readIndexTable(){
00473 
00474   stringstream errMsg;
00475   errMsg << "Error while reading event index table of file "
00476          << currentFileName_ << ". Try to read it with "
00477          << "option orderedRead disabled.\n";
00478 
00479   if(indexTablePos_==0) throw cms::Exception("LmfSource") << errMsg.str();
00480 
00481   streampos pos = in_.tellg();
00482   in_.clear();
00483   in_.seekg(indexTablePos_);
00484 
00485   uint32_t nevts = 0;
00486   in_.read((char*)&nevts, sizeof(nevts));
00487   in_.ignore(4);
00488   if(nevts>maxEvents_){
00489     throw cms::Exception("LmfSource")
00490       << "Number of events indicated in event index of file "
00491       << currentFileName_ << " is unexpectively large. File cannot be "
00492       << "read in time-ordered event mode. See orderedRead parmater of "
00493       << "LmfSource module.\n";
00494   }
00495   //if(in_.bad()) throw cms::Exception("LmfSource") << errMsg.str();
00496   if(in_.bad()) throw cms::Exception("LmfSource") << errMsg.str();
00497   indexTable_.resize(nevts);
00498   in_.read((char*)&indexTable_[0], nevts*sizeof(IndexRecord));
00499 }