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