CMS 3D CMS Logo

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

Go to the documentation of this file.
00001 /*
00002  *  $Date: 2012/11/19 18:34:01 $
00003  *  $Revision: 1.9 $
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   ProducerSourceBase(pset, desc, true),
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 void 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   auto_ptr<FEDRawDataCollection> coll(new FEDRawDataCollection);
00129   coll->swap(fedColl_);
00130   if(verbosity_) cout << "[LmfSource] Putting FEDRawDataCollection in event\n";
00131   evt.put(coll);
00132 }
00133 
00134 bool LmfSource::openFile(int iFile){
00135   iEventInFile_ = 0;
00136   if(watchFileList_) {
00137     for ( ;; ) {
00138       // read the first field of the line, which must be the filename
00139       fileList_ >> currentFileName_;
00140       currentFileName_ = inputDir_ + "/" + currentFileName_;
00141       if (!fileList_.fail()) {
00142         // skip the rest of the line
00143         std::string tmp_buffer;
00144         std::getline(fileList_, tmp_buffer);
00145         if(verbosity_) cout << "[LmfSource]"
00146           << "Opening file " << currentFileName_ << "\n";
00147         in_.open(currentFileName_.c_str());
00148         if (!in_.fail()) {
00149           // file was successfully open
00150           return true;
00151         } else {
00152           // skip file
00153           edm::LogError("FileOpenError")
00154             << "Failed to open input file " << currentFileName_ << ". Skipping file\n";
00155           in_.close();
00156           in_.clear();
00157         }
00158       }
00159       // if here, no new file is available: sleep and retry later
00160       if (verbosity_) std::cout << "[LmfSource]"
00161         << " going to sleep 5 seconds\n";
00162       sleep(nSecondsToSleep_);
00163       fileList_.clear();
00164     }
00165   } else {
00166     if(iFile > (int)fileNames_.size()-1) return false;
00167     currentFileName_ = fileNames_[iFile];
00168     if(verbosity_) cout << "[LmfSource]"
00169       << "Opening file " << currentFileName_ << "\n";
00170     in_.open(currentFileName_.c_str());
00171     if(in_.fail()){
00172       throw cms::Exception("FileOpenError")
00173         << "Failed to open input file " << currentFileName_ << "\n";
00174     }
00175   }
00176   return true;
00177 }
00178 
00179 bool LmfSource::nextEventWithinFile(){
00180   if(iFile_<0) return false; //no file opened.
00181   if(orderedRead_){
00182     if(iEventInFile_>=indexTable_.size()) return false;
00183     if(verbosity_){
00184       cout << "[LmfSource] move to event with orbit Id "
00185            << indexTable_[iEventInFile_].orbit
00186            << " at file position 0x"
00187            << hex << setfill('0')
00188            << setw(8) << indexTable_[iEventInFile_].filePos
00189            << setfill(' ') << dec << "\n";
00190     }
00191     const streampos pos = indexTable_[iEventInFile_].filePos;
00192     in_.clear();
00193     in_.seekg(pos);
00194     if(in_.bad()){
00195       cout << "[LmfSource] Problem while reading file "
00196            << currentFileName_ << ". Problem with event index table?\n";
00197       return false;
00198     }
00199     ++iEventInFile_;
00200     return true;
00201   } else{
00202     return true;
00203   }
00204 }
00205                
00206 bool LmfSource::readEvent(bool doSkip){
00207   while(!(nextEventWithinFile() && readEventWithinFile(doSkip))){
00208     //failed to read event. Let's look for next file:
00209     in_.close();
00210     in_.clear();
00211     bool rcOpen = openFile(++iFile_);
00212     if(rcOpen==false){//no more files
00213       if(verbosity_) cout << "[LmfSource]"
00214                        << "No more input file";
00215       rcRead_ = false;
00216       return rcRead_;
00217     }
00218     rcRead_ = readFileHeader();
00219     if(verbosity_) cout << "File header readout "
00220                      << (rcRead_?"succeeded":"failed") << "\n";
00221     if(rcRead_ && orderedRead_) readIndexTable();
00222   }
00223   return rcRead_;
00224 }
00225  
00226 bool LmfSource::setRunAndEventInfo(EventID& id, TimeValue_t& time){
00227   //empties collection:
00228   if(fedId_>0){
00229     fedColl_.FEDData(fedId_).resize(0);
00230   }
00231   if(verbosity_) cout << "[LmfSource]"
00232                    << "About to read event...\n";
00233 
00234   bool rc;
00235   for(;;){
00236     if(filter()){//event to read
00237       rc = readEvent();
00238       break;    //either event is read or no more event
00239     } else { //event to skip
00240       rc = readEvent(true);
00241       if(rc==false){//no more events
00242         break;
00243       }
00244     }
00245   }
00246 
00247   if(!rc) return false; //event readout failed
00248     
00249   if(verbosity_) cout << "[LmfSource]"
00250                    << "Setting event time to "
00251                    << /*toString(*/timeStamp_/*)*/ << ", "
00252                    << "Run number to " << runNum_ << ","
00253                    << "Event number to " << eventNum_ << "\n";
00254 
00255   time = timeStamp_;
00256   id = EventID(runNum_, lumiBlock_, eventNum_);
00257   return true; 
00258 }
00259 
00260 bool LmfSource::readEventWithinFile(bool doSkip){
00261   if(iFile_==-1 || !rcRead_) return false; //no file open
00262   //                                         or header reading failed
00263   //number of 32-bit word to read first to get the event size
00264   //field
00265   const int timeStamp32[]      = {0, 0}; //timestamp is 64-bit long
00266   const int lumiBlock32[]      = {2, 2};
00267   const int runNum32[]         = {3, 3};
00268   const int orbitNum32[]       = {4, 4};
00269   const int bx32[]             = {5, 5};
00270   const int eventNum32[]       = {6, 6};
00271   const int activeFedId32[]    = {7,-1};
00272   const int calibTrig32[]      = {-1,7};
00273   const int nFeds32[]          = {-1,8};
00274   // const int reserved32[]       = {-1,9};
00275   const int evtHeadSize32[]    = {8,10};
00276   
00277   const unsigned char iv = dataFormatVers_-minDataFormatVersion_;
00278   assert(iv<=sizeof(timeStamp32)/sizeof(timeStamp32[0]));
00279   
00280   if((int)header_.size() < evtHeadSize32[iv]) header_.resize(evtHeadSize32[iv]);
00281 
00282 
00283   if(verbosity_) cout << "[LmfSource]"
00284                    << "Reading event header\n";
00285 
00286   in_.read((char*)&header_[0], evtHeadSize32[iv]*4);
00287   if(in_.bad()){//reading error other than eof
00288     throw cms::Exception("FileReadError")
00289       << "Error while reading from file " << currentFileName_;
00290   }
00291   if(in_.eof()) return false;
00292 
00293   if(verbosity_){
00294     cout << "[LmfSource]"
00295          << "Event header (in hex):" << hex << setfill('0');
00296     for(int i=0; i < evtHeadSize32[iv]; ++i){ 
00297       if(i%8==0) cout << "\n";
00298       cout << setw(8) << header_[i] << " ";
00299     }
00300     cout << dec << setfill(' ') << "\n";
00301   }
00302   
00303   timeStamp_   = *(uint64_t*)&header_[timeStamp32[iv]];
00304   lumiBlock_   = header_[lumiBlock32[iv]];
00305   runNum_      = header_[runNum32[iv]];
00306   orbitNum_    = header_[orbitNum32[iv]];
00307   eventNum_    = header_[eventNum32[iv]];
00308   bx_          = header_[bx32[iv]];
00309   calibTrig_   = calibTrig32[iv]>=0?header_[calibTrig32[iv]]:0;
00310   int activeFedId = activeFedId32[iv]>=0?
00311     header_[activeFedId32[iv]]:
00312     ((calibTrig_ & 0x3F) + 600);
00313   nFeds_       = nFeds32<0?1:header_[nFeds32[iv]];
00314   
00315   if(verbosity_){
00316     cout << "[LmfSource] "
00317          << "timeStamp:          " << /*toString(timeStamp_)*/ timeStamp_ << "\n"
00318          << "lumiBlock:          " << lumiBlock_ << "\n"
00319          << "runNum:             " << runNum_ << "\n"
00320          << "orbitNum:           " << orbitNum_ << "\n"
00321          << "eventNum:           " << eventNum_ << "\n"
00322          << "bx:                 " << bx_ << "\n"
00323          << "activeFedId:        " << activeFedId << "\n"
00324          << "Calib trigger type: " << ((calibTrig_ >>8) & 0x3) << "\n"
00325          << "Color:              " << ((calibTrig_ >>6) & 0x3) << "\n"
00326          << "nFeds:              " << nFeds_ << "\n";
00327   }
00328 
00329   const int dccLenOffset32 = 2;
00330   const int fedIdOffset32  = 0; 
00331   const int nPreRead32     = 3;
00332   vector<int32_t> buf(nPreRead32);
00333   for(int iFed = 0; iFed < nFeds_; ++iFed){  
00334     in_.read((char*) &buf[0], nPreRead32*sizeof(uint32_t));
00335 
00336     if(verbosity_){
00337       cout << "[LmfSource] " << nPreRead32 << " first 32-bit words of "
00338            << "FED block: " << hex << setfill('0');
00339       for(unsigned i = 0; i< buf.size(); ++i){
00340         cout << "0x" << setw(8) << buf[i] << " ";
00341       }
00342       cout << dec << setfill(' ');
00343     }
00344         
00345     
00346     if(in_.bad()) return false;
00347     
00348     const unsigned eventSize64 = buf[dccLenOffset32] &  0x00FFFFFF;
00349     const unsigned eventSize32 = eventSize64*2;
00350     const unsigned eventSize8  = eventSize64*8;
00351     const unsigned fedId_      = (buf[fedIdOffset32] >>8) & 0xFFF;
00352 
00353     if(eventSize8 > maxEventSize_){
00354       throw cms::Exception("FileReadError")
00355         << "Size of event fragment (FED block) read from "
00356         << " data of file " << currentFileName_
00357         << "is unexpctively large (" << (eventSize8 >>10)
00358         << " kByte). "
00359         << "This must be an error (corrupted file?)\n";
00360     }
00361     
00362     if(!FEDNumbering::inRange(fedId_)){
00363       throw cms::Exception("FileReadError")
00364         << "Invalid FED number read from data file.";
00365     }
00366 
00367     int32_t toRead8 = (eventSize32-nPreRead32)*sizeof(int32_t);
00368 
00369     if(toRead8<0){
00370       throw cms::Exception("FileReadError")
00371         << "Event size error while reading an event from file "
00372         << currentFileName_ << "\n";
00373     }
00374     
00375     if(doSkip){//event to skip
00376       if(verbosity_) cout << "[LmfSource] "
00377                        << "Skipping on event. Move file pointer "
00378                        << toRead8 << " ahead.\n";
00379       in_.seekg(toRead8, ios::cur);
00380       if(in_.bad()){//reading error other than eof
00381         throw cms::Exception("FileReadError")
00382           << "Error while reading from file " << currentFileName_;
00383       }
00384     } else{
00385       //reads FED data:
00386       FEDRawData& data_ = fedColl_.FEDData(fedId_);
00387       data_.resize(eventSize8);
00388       
00389       //copy already read data:
00390       copy(buf.begin(), buf.end(), (int32_t*)data_.data());
00391       
00392       in_.read((char*)(data_.data()) + nPreRead32*4,
00393                toRead8);
00394       
00395       if(in_.bad()){//reading error other than eof
00396         throw cms::Exception("FileReadError")
00397           << "Error while reading from file " << currentFileName_;
00398       }
00399     
00400       if(verbosity_ && data_.size()>16){
00401         cout << "[LmfSource]"
00402              << "Head of DCC data (in hex):" << hex;
00403         for(int i=0; i < 16; ++i){ 
00404           if(i%8==0) cout << "\n";
00405           cout << setw(8) << ((uint32_t*)data_.data())[i] << " ";
00406         }
00407         cout << dec << "\n";
00408       }
00409 
00410       if(dataFormatVers_<=4){//calib trigger in not in event header.
00411         //                    gets it from DCC block
00412         calibTrig_ = (((uint32_t*)data_.data())[5] & 0xFC0)
00413           | ((activeFedId-600) &  0x3F);
00414         if(verbosity_){
00415           cout << "[LmfSource] Old data format. "
00416             "Uses information read from FED block to retrieve calibration "
00417             "trigger type. Value is: 0x"
00418                << hex << setfill('0') << setw(3) << calibTrig_
00419                << setfill(' ') << dec << "\n";
00420         }
00421       }
00422     }
00423     if(in_.eof()) return false;
00424   }
00425   ++iEvent_;
00426   return true;
00427 }
00428 
00429 bool LmfSource::filter() const{
00430   return (iEvent_%preScale_==0);
00431 }
00432             
00433 std::string LmfSource::toString(TimeValue_t& t) const{
00434   char buf[256];
00435   const int secTousec = 1000*1000;
00436   time_t tsec = t/secTousec;
00437   uint32_t tusec = (uint32_t)(t-tsec);
00438   strftime(buf, sizeof(buf), "%F %R %S s", localtime(&tsec));
00439   buf[sizeof(buf)-1] = 0;
00440   stringstream buf2;
00441   buf2 << (tusec+500)/1000;
00442   return string(buf) + " " + buf2.str() + " ms";
00443 }
00444 
00445 void LmfSource::checkFileNames(){
00446   for(unsigned i = 0; i < fileNames_.size(); ++i){
00447     std::string& fileName = fileNames_[i];
00448     const char s[] = "file:";
00449     if(fileName.compare(0, sizeof(s)-1, s)==0){ //file: prefix => to strip
00450       fileName.erase(fileName.begin(),
00451                      fileName.begin() + sizeof(s)-1);
00452     }
00453     if(fileName.find_first_of(":")!=string::npos){
00454       throw cms::Exception("LmfSource")
00455         << "Character ':' is not allowed in paths specified fileNames "
00456         << "parameter. Please note only local file (or NFS, AFS)"
00457         << " is supported (no rfio, no /store)";
00458     }
00459     const char s1[] = "/store";
00460     if(fileName.compare(0, sizeof(s1)-1, s1)==0){
00461       throw cms::Exception("LmfSource")
00462         << "CMSSW /store not supported by LmfSource. Only local file "
00463         << "(or NFS/AFS) allowed. Path starting with /store not permitted";
00464     }
00465   }
00466 }
00467 
00468 void LmfSource::readIndexTable(){
00469 
00470   stringstream errMsg;
00471   errMsg << "Error while reading event index table of file "
00472          << currentFileName_ << ". Try to read it with "
00473          << "option orderedRead disabled.\n";
00474 
00475   if(indexTablePos_==0) throw cms::Exception("LmfSource") << errMsg.str();
00476 
00477   in_.clear();
00478   in_.seekg(indexTablePos_);
00479 
00480   uint32_t nevts = 0;
00481   in_.read((char*)&nevts, sizeof(nevts));
00482   in_.ignore(4);
00483   if(nevts>maxEvents_){
00484     throw cms::Exception("LmfSource")
00485       << "Number of events indicated in event index of file "
00486       << currentFileName_ << " is unexpectively large. File cannot be "
00487       << "read in time-ordered event mode. See orderedRead parmater of "
00488       << "LmfSource module.\n";
00489   }
00490   //if(in_.bad()) throw cms::Exception("LmfSource") << errMsg.str();
00491   if(in_.bad()) throw cms::Exception("LmfSource") << errMsg.str();
00492   indexTable_.resize(nevts);
00493   in_.read((char*)&indexTable_[0], nevts*sizeof(IndexRecord));
00494 }