CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/IORawData/CSCCommissioning/src/CSCFileReader.cc

Go to the documentation of this file.
00001 #include "CSCFileReader.h"
00002 
00003 //#include <iostream.h>
00004 
00005 #include <errno.h>
00006 #include <stdlib.h>
00007 #include <cstring>
00008 
00009 #include <DataFormats/FEDRawData/interface/FEDHeader.h>
00010 #include <DataFormats/FEDRawData/interface/FEDTrailer.h>
00011 #include <DataFormats/FEDRawData/interface/FEDNumbering.h>
00012 #include <DataFormats/Provenance/interface/EventID.h>
00013 #include <DataFormats/Provenance/interface/Timestamp.h>
00014 #include <DataFormats/FEDRawData/interface/FEDRawData.h>
00015 #include <DataFormats/FEDRawData/interface/FEDRawDataCollection.h>
00016 
00017 #include <FWCore/ParameterSet/interface/ParameterSet.h>
00018 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00019 
00020 #include <vector>
00021 #include <string>
00022 #include <iosfwd>
00023 #include <sstream>
00024 #include <iostream>
00025 #include <algorithm>
00026 
00027 #define nRUIs 40
00028 #define nFUs  4
00029 
00030 CSCFileReader::CSCFileReader(const edm::ParameterSet& pset):DaqBaseReader(){
00031         LogDebug("CSCFileReader|ctor")<<"Started ...";
00032         // Below some data members are recycled for both cases: RUIs and FUs
00033         //  this is ok as long as eighter of RUI or FU are are provided in .cfg (not both)
00034         nActiveRUIs = 0;
00035         nActiveFUs  = 0;
00036         for(int unit=0; unit<nRUIs; unit++){
00037                 std::ostringstream ruiName, fuName;
00038                 ruiName<<"RUI"<<(unit<10?"0":"")<<unit<<std::ends;
00039                 fuName <<"FU" <<unit<<std::ends;
00040                 std::vector<std::string> ruiFiles = pset.getUntrackedParameter< std::vector<std::string> >(ruiName.str().c_str(),std::vector<std::string>(0));
00041                 std::vector<std::string> fuFiles  = pset.getUntrackedParameter< std::vector<std::string> >(fuName.str().c_str(),std::vector<std::string>(0));
00042                 if( ruiFiles.begin() != ruiFiles.end() ) nActiveRUIs++;
00043                 if( fuFiles.begin()  != fuFiles.end()  ) nActiveFUs++;
00044         }
00045         if( nActiveFUs && nActiveRUIs )
00046                 throw cms::Exception("CSCFileReader|configuration")<<"RUIs and FUs in conflict: either RUI or FU may be defined at a time, not both";
00047         if( !nActiveFUs && !nActiveRUIs )
00048                 throw cms::Exception("CSCFileReader|configuration")<<"Module lacks configuration";
00049 
00050 
00051         // Get list of RUI input files from .cfg file
00052         for(int rui=0; rui<nRUIs && !nActiveFUs; rui++){
00053                 std::ostringstream name;
00054                 name<<"RUI"<<(rui<10?"0":"")<<rui<<std::ends;
00055 
00056                 // Obtain list of files associated with current RUI
00057                 fileNames[rui] = pset.getUntrackedParameter< std::vector<std::string> >(name.str().c_str(),std::vector<std::string>(0));
00058                 currentFile[rui] = fileNames[rui].begin();
00059 
00060                 // If list of files is not empty, open first file
00061                 if( currentFile[rui] != fileNames[rui].end() ){
00062                         try {
00063                                 RUI[rui].open(currentFile[rui]->c_str());
00064                         } catch ( std::runtime_error err ){
00065                                 throw cms::Exception("CSCFileReader")<<"InputFileMissing: "<<err.what()<<" (errno="<<errno<<")";
00066                         }
00067                         nActiveRUIs++;
00068                 }
00069 
00070                 // Filter out possible corruptions
00071                 RUI[rui].reject(FileReaderDDU::DDUoversize|FileReaderDDU::FFFF|FileReaderDDU::Unknown);
00072                 // Do not select anything in particular
00073                 RUI[rui].select(0);
00074 
00075                 currentL1A[rui] = -1;
00076         }
00077 
00078         // Get list of FU input files from .cfg file
00079         for(int fu=0; fu<nFUs && !nActiveRUIs; fu++){
00080                 std::ostringstream name;
00081                 name<<"FU"<<fu<<std::ends;
00082 
00083                 // Obtain list of files associated with current FU
00084                 fileNames[fu] = pset.getUntrackedParameter< std::vector<std::string> >(name.str().c_str(),std::vector<std::string>(0));
00085                 currentFile[fu] = fileNames[fu].begin();
00086 
00087                 // If list of files is not empty, open first file
00088                 if( currentFile[fu] != fileNames[fu].end() ){
00089                         try {
00090                                 FU[fu].open(currentFile[fu]->c_str());
00091                         } catch ( std::runtime_error err ){
00092                                 throw cms::Exception("CSCFileReader")<<"InputFileMissing: "<<err.what()<<" (errno="<<errno<<")";
00093                         }
00094                         nActiveFUs++;
00095                 }
00096 
00097                 // Filter out possible corruptions
00098                 FU[fu].reject(FileReaderDCC::DCCoversize|FileReaderDCC::FFFF|FileReaderDCC::Unknown);
00099                 // Do not select anything in particular
00100                 FU[fu].select(0);
00101 
00102                 currentL1A[fu] = -1;
00103         }
00104 
00105         if( nActiveRUIs && !nActiveFUs ){
00106                 // Assign RUIs to FEDs
00107                 for(int fed=FEDNumbering::MINCSCFEDID; fed<=FEDNumbering::MAXCSCFEDID; fed++){
00108                         std::ostringstream name;
00109                         name<<"FED"<<fed<<std::ends;
00110                         std::vector<std::string> rui_list = pset.getUntrackedParameter< std::vector<std::string> >(name.str().c_str(),std::vector<std::string>(0));
00111                         for(std::vector<std::string>::const_iterator rui=rui_list.begin(); rui!=rui_list.end(); rui++)
00112                                 FED[fed].push_back((unsigned int)atoi(rui->c_str()+rui->length()-2));
00113                 }
00114                 // Do the same for Track-Finder FED
00115                 for(int fed=FEDNumbering::MINCSCTFFEDID; fed<=FEDNumbering::MAXCSCTFFEDID; fed++){
00116                         std::ostringstream name;
00117                         name<<"FED"<<fed<<std::ends;
00118                         std::vector<std::string> rui_list = pset.getUntrackedParameter< std::vector<std::string> >(name.str().c_str(),std::vector<std::string>(0));
00119                         for(std::vector<std::string>::const_iterator rui=rui_list.begin(); rui!=rui_list.end(); rui++)
00120                                 FED[fed].push_back((unsigned int)atoi(rui->c_str()+rui->length()-2));
00121                 }
00122         }
00123         // Starting point
00124         firstEvent = pset.getUntrackedParameter<int>("firstEvent",0);
00125         nEvents = 0;
00126         expectedNextL1A = -1;
00127 
00128         // If Track-Finder was in readout specify its position in the record or set -1 otherwise
00129         //  Current agriment is that if there is a TF event it is first DDU record
00130         tfDDUnumber = pset.getUntrackedParameter<int>("tfDDUnumber",-1);
00131 
00132         // For efficiency reasons create this big chunk of data only once
00133         tmpBuf = new unsigned short[200000*nRUIs+4*4];
00134         // Event buffer and its length for every FU
00135         fuEvent[0]=0; fuEventSize[0]=0;
00136         fuEvent[1]=0; fuEventSize[1]=0;
00137         fuEvent[2]=0; fuEventSize[2]=0;
00138         fuEvent[3]=0; fuEventSize[3]=0;
00139         // Event buffer and its length for every RU
00140         for(int rui=0; rui<nRUIs; rui++){
00141                 ruBuf[rui] = 0;
00142                 ruBufSize[rui] = 0;
00143         }
00144         LogDebug("CSCFileReader|ctor")<<"... and finished";
00145 }
00146 
00147 CSCFileReader::~CSCFileReader(void){ if(tmpBuf) delete [] tmpBuf; }
00148 
00149 int CSCFileReader::readRUI(int rui, const unsigned short* &buf, size_t &length){
00150         if( currentFile[rui] == fileNames[rui].end() ) return -1;
00151         do {
00152                 try {
00153                         length = RUI[rui].next(buf);
00154                 } catch ( std::runtime_error err ){
00155                         throw cms::Exception("CSCFileReader|reading")<<"EndOfStream: "<<err.what()<<" (errno="<<errno<<")";
00156                 }
00157                 if( length==0 ){ // end of file, try next one
00158                         if( ++currentFile[rui] != fileNames[rui].end() ){
00159                                 try {
00160                                         RUI[rui].open(currentFile[rui]->c_str());
00161                                 } catch ( std::runtime_error err ){
00162                                         throw cms::Exception("CSCFileReader|reading")<<"InputFileMissing: "<<err.what()<<" (errno="<<errno<<")";
00163                                 }
00164                         } else return -1;
00165                 }
00166         } while( length==0 );
00167         return buf[2]|((buf[3]&0xFF)<<16);
00168 }
00169 
00170 int CSCFileReader::readFU(int fu, const unsigned short* &buf, size_t &length){
00171         if( currentFile[fu] == fileNames[fu].end() ) return -1;
00172         do {
00173                 try {
00174                         length = FU[fu].next(buf);
00175                 } catch ( std::runtime_error err ){
00176                         throw cms::Exception("CSCFileReader|reading")<<"EndOfStream: "<<err.what()<<" (errno="<<errno<<")";
00177                 }
00178                 if( length==0 ){ // end of file, try next one
00179                         if( ++currentFile[fu] != fileNames[fu].end() ){
00180                                 try {
00181                                         FU[fu].open(currentFile[fu]->c_str());
00182                                 } catch ( std::runtime_error err ){
00183                                         throw cms::Exception("CSCFileReader|reading")<<"InputFileMissing: "<<err.what()<<" (errno="<<errno<<")";
00184                                 }
00185                         } else return -1;
00186                 }
00187         } while( length==0 );
00188         // Take L1A from first DDU header in the DCC record (shift=8)
00189         return buf[2+8]|((buf[3+8]&0xFF)<<16);
00190 }
00191 
00192 int CSCFileReader::buildEventFromRUIs(FEDRawDataCollection *data){
00193         int eventNumber =-1; // Will determine below
00194 
00195         do {
00196                 // Read next event from RUIs
00197                 for(int rui=0; rui<nRUIs; rui++){
00198                         // read event from the RUI only in two cases:
00199                         //     1) it is readable (currentL1A>0) and we expect next event from the RUI
00200                         //     2) it is first time (expectedNextL1A<0)
00201                         if((currentL1A[rui]>0 && currentL1A[rui]<expectedNextL1A) || expectedNextL1A<0 )
00202                                 currentL1A[rui] = readRUI(rui,ruBuf[rui],ruBufSize[rui]);
00203                 }
00204                 eventNumber =-1;
00205 
00206                 // Select lowest L1A from all RUIs and don't expect next event from RUIs that currently hold higher L1A
00207                 for(int rui=0; rui<nRUIs; rui++)
00208                         if( currentL1A[rui]>=0 && (eventNumber>currentL1A[rui] || eventNumber==-1) ) eventNumber=currentL1A[rui];
00209                 // No readable RUIs => fall out
00210                 if( eventNumber<0 ) return -1;
00211                 // Expect next event to be incremented by 1 wrt. to the current event
00212                 expectedNextL1A = eventNumber+1;
00213 
00214         } while(nEvents++<firstEvent);
00215 
00216         for(std::map<unsigned int,std::list<unsigned int> >::const_iterator fed=FED.begin(); fed!=FED.end(); fed++)
00217                 if( fed->first<(unsigned int)FEDNumbering::MINCSCTFFEDID ){
00218                         // Now let's pretend that DDU data were wrapped with DCC Header (2 64-bit words) and Trailer (2 64-bit words):
00219                         unsigned short *dccBuf=tmpBuf, *dccCur=dccBuf;
00220                         dccCur[3] = 0x5000; dccCur[2] = 0x0000; dccCur[1] = 0x0000; dccCur[0] = 0x005F; // Fake DCC Header 1
00221                         dccCur[7] = 0xD900; dccCur[6] = 0x0000; dccCur[5] = 0x0000; dccCur[4] = 0x0017; // Fake DCC Header 2
00222                         dccCur += 8;
00223 
00224                         for(std::list<unsigned int>::const_iterator rui=fed->second.begin(); rui!=fed->second.end(); rui++){
00225 //cout<<"Event:"<<eventNumber<<"  FED:"<<fed->first<<"  RUI:"<<*(fed->second.begin())<<" currL1A:"<<currentL1A[*rui]<<endl;
00226                                 if( currentL1A[*rui]==eventNumber ){
00227                                         if(dccCur-dccBuf+ruBufSize[*rui]>=200000*nRUIs+8) throw cms::Exception("CSCFileReader|eventBuffer")<<"OutOfBuffer: Event size exceeds maximal size allowed!";
00228                                         memcpy(dccCur,ruBuf[*rui],ruBufSize[*rui]*sizeof(unsigned short));
00229                                         dccCur += ruBufSize[*rui];
00230                                 }
00231                         }
00232                         dccCur[3] = 0xEF00; dccCur[2] = 0x0000; dccCur[1] = 0x0000; dccCur[0] = 0x0000; // Fake DCC Trailer 2
00233                         dccCur[7] = 0xAF00; dccCur[6] = 0x0000; dccCur[5] = 0x0000; dccCur[4] = 0x0007; // Fake DCC Trailer 2
00234                         dccCur += 8;
00235 
00236                         FEDRawData& fedRawData = data->FEDData(fed->first);
00237                         fedRawData.resize((dccCur-dccBuf)*sizeof(unsigned short));
00238                         std::copy((unsigned char*)dccBuf,(unsigned char*)dccCur,fedRawData.data());
00239                 } else {
00240                         for(std::list<unsigned int>::const_iterator rui=fed->second.begin(); rui!=fed->second.end(); rui++){
00241                                 FEDRawData& fedRawData = data->FEDData(fed->first);
00242                                 fedRawData.resize(ruBufSize[*rui]*sizeof(unsigned short));
00243                                 std::copy((unsigned char*)ruBuf[*rui],(unsigned char*)(ruBuf[*rui]+ruBufSize[*rui]),fedRawData.data());
00244                         }
00245                 }
00246 
00247         return eventNumber;
00248 }
00249 
00250 int CSCFileReader::nextEventFromFUs(FEDRawDataCollection *data){
00251         int eventNumber =-1; // Will determine below
00252 
00253         // If this is a first time - read one event from each FU
00254         if( expectedNextL1A<0 )
00255                 for(int fu=0; fu<nFUs; fu++)
00256                         currentL1A[fu] = readFU(fu,fuEvent[fu],fuEventSize[fu]);
00257 
00258         // Keep buffers for every FU ready at all times
00259         // When buffer from some FU is ready to go as the next event,
00260         //  release it, but read next one
00261         int readyToGo = -1;
00262         for(int fu=0; fu<nFUs; fu++){
00263                 // If FU is readable and (first loop of this cycle or current FU holds smallest L1A)
00264                 if(currentL1A[fu]>=0 && (eventNumber<0 || currentL1A[fu]<eventNumber)){
00265                         readyToGo   = fu;
00266                         eventNumber = currentL1A[fu];
00267                 }
00268         }
00269         // No readable FUs => fall out
00270         if( readyToGo<0 ) return -1;
00271 
00272         expectedNextL1A = eventNumber + 1;
00273 
00274         // Compose event from DDC record striped of Track-Finder DDU and a separate TF DDU event
00275         unsigned long long *start = (unsigned long long *)fuEvent[readyToGo];
00276         unsigned long long *end   = 0;
00277         enum {Header=1,Trailer=2};
00278         unsigned int eventStatus  = 0;
00279         for(int dduRecord=0; dduRecord<=tfDDUnumber; dduRecord++){
00280                 unsigned long long word_0=0, word_1=0, word_2=0;
00281                 size_t dduWordCount = 0;
00282                 while( !end && dduWordCount<fuEventSize[readyToGo] ){
00283                         unsigned long long *dduWord = start;
00284 
00285                         while( dduWordCount<fuEventSize[readyToGo] ){
00286                                 word_0 =  word_1; // delay by 2 DDU words
00287                                 word_1 =  word_2; // delay by 1 DDU word
00288                                 word_2 = *dduWord;// current DDU word
00289                                 if( (word_2&0xFFFFFFFFFFFF0000LL)==0x8000000180000000LL ){
00290                                         if( eventStatus&Header ){ // Second header
00291                                                 word_2 = word_1;
00292                                                 end = dduWord;
00293                                                 break;
00294                                         }
00295                                         start = dduWord;
00296                                 }
00297                                 if( (word_0&0xFFFFFFFFFFFF0000LL)==0x8000FFFF80000000LL ){
00298                                         eventStatus |= Trailer;
00299                                         end = ++dduWord;
00300                                         break;
00301                                 }
00302                                 // Increase counters by one DDU word
00303                                 dduWord++;
00304                                 dduWordCount++;
00305                         }
00306                 }
00307                 // If reach max length
00308                 if( dduWordCount==fuEventSize[readyToGo] ){
00309                         end = (unsigned long long *)(fuEvent[readyToGo]+fuEventSize[readyToGo]);
00310                         break;
00311                 }
00312         }
00313         // Include 0x5xxx preHeader if exists
00314         if( start>(unsigned long long *)fuEvent[readyToGo] && (*(start-1)&0xF000000000000000LL)==0x5000000000000000LL ) start--;
00315 
00316         // If Track-Finder DDU was in readout
00317         if( tfDDUnumber>=0 ){
00318         // Cut out Track-Finder DDU from the buffer
00319                 if( !end ) throw cms::Exception("CSCFileReader|lookingForTF")<<" Sanity check failed (end==0)! Should never happen";
00320 
00321                 FEDRawData& tfRawData = data->FEDData(FEDNumbering::MINCSCTFFEDID);
00322                 tfRawData.resize((end-start)*sizeof(unsigned long long));
00323                 std::copy((unsigned char*)start,(unsigned char*)end,tfRawData.data());
00324 
00325                 // Create a new buffer from everything before and after TF DDU
00326                 unsigned short *event = tmpBuf;
00327                 memcpy(event,fuEvent[readyToGo],((unsigned short*)start-fuEvent[readyToGo])*sizeof(unsigned short));
00328                 event += ((unsigned short*)start-fuEvent[readyToGo]);
00329                 memcpy(event,end,(fuEvent[readyToGo]+fuEventSize[readyToGo]-(unsigned short*)end)*sizeof(unsigned short));
00330                 event += fuEvent[readyToGo]+fuEventSize[readyToGo]-(unsigned short*)end;
00331                 FEDRawData& fedRawData = data->FEDData(FEDNumbering::MINCSCFEDID);
00332                 fedRawData.resize((fuEventSize[readyToGo]-((unsigned short*)end-(unsigned short*)start))*sizeof(unsigned short));
00333                 std::copy((unsigned char*)tmpBuf,(unsigned char*)event,fedRawData.data());
00334         } else {
00335                 FEDRawData& fedRawData = data->FEDData(FEDNumbering::MINCSCFEDID);
00336                 fedRawData.resize((fuEventSize[readyToGo])*sizeof(unsigned short));
00337                 std::copy((unsigned char*)fuEvent[readyToGo],(unsigned char*)(fuEvent[readyToGo]+fuEventSize[readyToGo]),fedRawData.data());
00338         }
00339 
00340         currentL1A[readyToGo] = readFU(readyToGo,fuEvent[readyToGo],fuEventSize[readyToGo]);
00341 
00342         return eventNumber;
00343 }
00344 
00345 int CSCFileReader::fillRawData(edm::EventID& eID, edm::Timestamp& tstamp, FEDRawDataCollection *& data){
00346         data = new FEDRawDataCollection();
00347 
00348         int runNumber   = 0; // Unknown at the level of EMu local DAQ
00349         int eventNumber =-1; // Will determine below
00350 
00351         if( !nActiveFUs && nActiveRUIs ){
00352                 eventNumber = buildEventFromRUIs(data);
00353         } else {
00354                 eventNumber = nextEventFromFUs(data);
00355         }
00356 
00357         if( eventNumber<0 ) return false;
00358 
00359         eID = edm::EventID(runNumber,1U,eventNumber);
00360 
00361         return true;
00362 }
00363 
00364 #undef nRUIs
00365 #undef nFUs