CMS 3D CMS Logo

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

Go to the documentation of this file.
00001 #include "FileReaderDDU.h"
00002 #include <iostream>    // cerr
00003 #include <errno.h>     // errno
00004 #include <string.h>    // bzero, memcpy
00005 #include <stdlib.h>    // exit
00006 #include <sys/types.h> // open
00007 #include <sys/stat.h>  // open
00008 #include <fcntl.h>     // open
00009 #include <unistd.h>    // read, close
00010 
00011 #ifndef O_LARGEFILE //for OSX
00012 #define O_LARGEFILE 0
00013 #endif
00014 
00015 
00016 FileReaderDDU::FileReaderDDU(void){
00017         if( sizeof(unsigned long long)!=8 || sizeof(unsigned short)!=2 )
00018                 throw std::runtime_error(std::string("Wrong platform: sizeof(unsigned long long)!=8 || sizeof(unsigned short)!=2"));
00019         end = (file_buffer_end = file_buffer + sizeof(file_buffer)/sizeof(unsigned long long));
00020         bzero(raw_event,  sizeof(raw_event)  );
00021         bzero(file_buffer,sizeof(file_buffer));
00022         word_0=0; word_1=0; word_2=0;
00023         eventStatus = 0;
00024         selectCriteria = Header|Trailer;
00025         rejectCriteria = DDUoversize|FFFF|Unknown;
00026         acceptCriteria = 0x3F; // Everything
00027         fd = 0;
00028 }
00029 
00030 FileReaderDDU::~FileReaderDDU(void){ if( fd ) close(fd); }
00031 
00032 int FileReaderDDU::open(const char *filename) throw (std::runtime_error) {
00033         if( fd ) close(fd);
00034         fd = ::open(filename,O_RDONLY|O_LARGEFILE);
00035         if( fd == -1 ) throw ( std::runtime_error(std::string("Error opening ").append(filename).append(" data file.")) );
00036         return fd;
00037 }
00038 
00039 size_t FileReaderDDU::read(const unsigned short* &buf) throw (std::runtime_error) {
00040         // Check for ubnormal situation
00041         if( end>file_buffer_end || end<file_buffer ) throw ( std::runtime_error("Error of reading") );
00042         if( !fd ) throw ( std::runtime_error("Open some file first") );
00043 
00044         unsigned long long *start = end;
00045         unsigned short     *event = raw_event;
00046 
00047         eventStatus = 0;
00048         size_t dduWordCount = 0;
00049         end = 0;
00050 
00051         while( !end && dduWordCount<50000 ){
00052                 unsigned long long *dduWord = start;
00053                 unsigned long long preHeader = 0;
00054 
00055                 // Did we reach end of current buffer and want to read next block?
00056                 // If it was first time and we don't have file buffer then we won't get inside
00057                 while( dduWord<file_buffer_end && dduWordCount<50000 ){
00058                         word_0 =  word_1; // delay by 2 DDU words
00059                         word_1 =  word_2; // delay by 1 DDU word
00060                         word_2 = *dduWord;// current DDU word
00061                         if( (word_2&0xFFFFFFFFFFFF0000LL)==0x8000000180000000LL ){
00062                                 if( eventStatus&Header ){ // Second header
00063                                         word_2 = word_1; // Fall back to get rigth preHeader next time
00064                                         end = dduWord;   // Even if we end with preHeader of next evet put it to the end of this event too
00065                                         break;
00066                                 }
00067                                 if( dduWordCount>1 ){ // Extra words between trailer and header
00068                                         if( (word_0&0xFFFFFFFFFFFF0000LL)==0xFFFFFFFFFFFF0000LL ) eventStatus |= FFFF;
00069                                         word_2 = word_1; // Fall back to get rigth preHeader next time
00070                                         end = dduWord;
00071                                         break;
00072                                 }
00073                                 eventStatus |= Header;
00074                                 if( event==raw_event ) preHeader = word_1; // If preHeader not yet in event then put it there
00075                                 start = dduWord;
00076                         }
00077                         if( (word_0&0xFFFFFFFFFFFF0000LL)==0x8000FFFF80000000LL ){
00078                                 eventStatus |= Trailer;
00079                                 end = ++dduWord;
00080                                 break;
00081                         }
00082                         // Increase counters by one DDU word
00083                         dduWord++;
00084                         dduWordCount++;
00085                 }
00086 
00087                 // If have DDU Header
00088                 if( preHeader ){
00089                         // Need to account first word of DDU Header
00090                         memcpy(event,&preHeader,sizeof(preHeader));
00091                         event += sizeof(preHeader)/sizeof(unsigned short);
00092                 }
00093 
00094                 // Take care of the rest
00095                 memcpy(event,start,(dduWord-start)*sizeof(unsigned long long));
00096                 event += (dduWord-start)*sizeof(unsigned long long)/sizeof(unsigned short);
00097 
00098                 // If reach max length
00099                 if( dduWordCount==50000 ){ end = dduWord; break; }
00100 
00101                 if( !end ){
00102                         // Need to read next block for the rest of this event
00103                         ssize_t length = ::read(fd,file_buffer,sizeof(file_buffer));
00104                         if( length==-1 ) throw ( std::runtime_error("Error of reading") );
00105                         if( length== 0 ){
00106                                 eventStatus |= EndOfStream;
00107                                 end = (file_buffer_end = file_buffer + sizeof(file_buffer)/sizeof(unsigned long long));
00108                                 break;
00109                         }
00110                         file_buffer_end = file_buffer + length/sizeof(unsigned long long);
00111 
00112                         // Will start from the beginning of new buffer next time we read it
00113                         start = file_buffer;
00114                 }
00115         }
00116 
00117         if( !end ) eventStatus |= DDUoversize;
00118         if( !(eventStatus&Header) && !(eventStatus&Trailer) && !(eventStatus&FFFF) ) eventStatus |= Unknown;
00119 
00120         buf = (const unsigned short*)raw_event;
00121         return (eventStatus&FFFF?event-raw_event-4:event-raw_event);
00122 }
00123 
00124 size_t FileReaderDDU::next(const unsigned short* &buf, int prescaling) throw(std::runtime_error) {
00125         size_t size=0;
00126         for(int i=0; i<prescaling; i++){
00127                 do {
00128                         if( (size = read(buf)) == 0 ) break;
00129                 } while( rejectCriteria&eventStatus || !(acceptCriteria&eventStatus) || (selectCriteria?selectCriteria!=eventStatus:0) );
00130         }
00131         return size;
00132 }