Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:19:14

0001 #include "FileReaderDDU.h"
0002 #include <cerrno>       // errno
0003 #include <cstdlib>      // exit
0004 #include <cstring>      // bzero, memcpy
0005 #include <fcntl.h>      // open
0006 #include <iostream>     // cerr
0007 #include <sys/stat.h>   // open
0008 #include <sys/types.h>  // open
0009 #include <unistd.h>     // read, close
0010 
0011 #ifndef O_LARGEFILE  //for OSX
0012 #define O_LARGEFILE 0
0013 #endif
0014 
0015 FileReaderDDU::FileReaderDDU(void) {
0016   if (sizeof(unsigned long long) != 8 || sizeof(unsigned short) != 2)
0017     throw std::runtime_error(std::string("Wrong platform: sizeof(unsigned long long)!=8 || sizeof(unsigned short)!=2"));
0018   end = (file_buffer_end = file_buffer + sizeof(file_buffer) / sizeof(unsigned long long));
0019   bzero(raw_event, sizeof(raw_event));
0020   bzero(file_buffer, sizeof(file_buffer));
0021   word_0 = 0;
0022   word_1 = 0;
0023   word_2 = 0;
0024   eventStatus = 0;
0025   selectCriteria = Header | Trailer;
0026   rejectCriteria = DDUoversize | FFFF | Unknown;
0027   acceptCriteria = 0x3F;  // Everything
0028   fd = 0;
0029 }
0030 
0031 FileReaderDDU::~FileReaderDDU(void) {
0032   if (fd)
0033     close(fd);
0034 }
0035 
0036 int FileReaderDDU::open(const char *filename) {
0037   if (fd)
0038     close(fd);
0039   fd = ::open(filename, O_RDONLY | O_LARGEFILE);
0040   if (fd == -1)
0041     throw(std::runtime_error(std::string("Error opening ").append(filename).append(" data file.")));
0042   return fd;
0043 }
0044 
0045 size_t FileReaderDDU::read(const unsigned short *&buf) {
0046   // Check for ubnormal situation
0047   if (end > file_buffer_end || end < file_buffer)
0048     throw(std::runtime_error("Error of reading"));
0049   if (!fd)
0050     throw(std::runtime_error("Open some file first"));
0051 
0052   unsigned long long *start = end;
0053   unsigned short *event = raw_event;
0054 
0055   eventStatus = 0;
0056   size_t dduWordCount = 0;
0057   end = nullptr;
0058 
0059   while (!end && dduWordCount < 50000) {
0060     unsigned long long *dduWord = start;
0061     unsigned long long preHeader = 0;
0062 
0063     // Did we reach end of current buffer and want to read next block?
0064     // If it was first time and we don't have file buffer then we won't get inside
0065     while (dduWord < file_buffer_end && dduWordCount < 50000) {
0066       word_0 = word_1;    // delay by 2 DDU words
0067       word_1 = word_2;    // delay by 1 DDU word
0068       word_2 = *dduWord;  // current DDU word
0069       if ((word_2 & 0xFFFFFFFFFFFF0000LL) == 0x8000000180000000LL) {
0070         if (eventStatus & Header)  // Second header
0071         {
0072           word_2 = word_1;  // Fall back to get rigth preHeader next time
0073           end = dduWord;    // Even if we end with preHeader of next evet put it to the end of this event too
0074           break;
0075         }
0076         if (dduWordCount > 1)  // Extra words between trailer and header
0077         {
0078           if ((word_0 & 0xFFFFFFFFFFFF0000LL) == 0xFFFFFFFFFFFF0000LL)
0079             eventStatus |= FFFF;
0080           word_2 = word_1;  // Fall back to get rigth preHeader next time
0081           end = dduWord;
0082           break;
0083         }
0084         eventStatus |= Header;
0085         if (event == raw_event)
0086           preHeader = word_1;  // If preHeader not yet in event then put it there
0087         start = dduWord;
0088       }
0089       if ((word_0 & 0xFFFFFFFFFFFF0000LL) == 0x8000FFFF80000000LL) {
0090         eventStatus |= Trailer;
0091         end = ++dduWord;
0092         break;
0093       }
0094       // Increase counters by one DDU word
0095       dduWord++;
0096       dduWordCount++;
0097     }
0098 
0099     // If have DDU Header
0100     if (preHeader) {
0101       // Need to account first word of DDU Header
0102       memcpy(event, &preHeader, sizeof(preHeader));
0103       event += sizeof(preHeader) / sizeof(unsigned short);
0104     }
0105 
0106     // Take care of the rest
0107     memcpy(event, start, (dduWord - start) * sizeof(unsigned long long));
0108     event += (dduWord - start) * sizeof(unsigned long long) / sizeof(unsigned short);
0109 
0110     // If reach max length
0111     if (dduWordCount == 50000) {
0112       end = dduWord;
0113       break;
0114     }
0115 
0116     if (!end) {
0117       // Need to read next block for the rest of this event
0118       ssize_t length = ::read(fd, file_buffer, sizeof(file_buffer));
0119       if (length == -1)
0120         throw(std::runtime_error("Error of reading"));
0121       if (length == 0) {
0122         eventStatus |= EndOfStream;
0123         end = (file_buffer_end = file_buffer + sizeof(file_buffer) / sizeof(unsigned long long));
0124         break;
0125       }
0126       file_buffer_end = file_buffer + length / sizeof(unsigned long long);
0127 
0128       // Will start from the beginning of new buffer next time we read it
0129       start = file_buffer;
0130     }
0131   }
0132 
0133   if (!end)
0134     eventStatus |= DDUoversize;
0135   if (!(eventStatus & Header) && !(eventStatus & Trailer) && !(eventStatus & FFFF))
0136     eventStatus |= Unknown;
0137 
0138   buf = (const unsigned short *)raw_event;
0139   return (eventStatus & FFFF ? event - raw_event - 4 : event - raw_event);
0140 }
0141 
0142 size_t FileReaderDDU::next(const unsigned short *&buf, int prescaling) {
0143   size_t size = 0;
0144   for (int i = 0; i < prescaling; i++) {
0145     do {
0146       if ((size = read(buf)) == 0)
0147         break;
0148     } while (rejectCriteria & eventStatus || !(acceptCriteria & eventStatus) ||
0149              (selectCriteria ? selectCriteria != eventStatus : 0));
0150   }
0151   return size;
0152 }