Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-05-23 23:00:40

0001 #include "FileReaderDCC.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 FileReaderDCC::FileReaderDCC(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   raw_event = new unsigned short[200000 * 40];
0019   end = (file_buffer_end = file_buffer + sizeof(file_buffer) / sizeof(unsigned long long));
0020   bzero(raw_event, sizeof(unsigned short) * 200000 * 40);
0021   bzero(file_buffer, sizeof(file_buffer));
0022   word_0 = 0;
0023   word_1 = 0;
0024   word_2 = 0;
0025   eventStatus = 0;
0026   selectCriteria = Header | Trailer;
0027   rejectCriteria = DCCoversize | FFFF | Unknown;
0028   acceptCriteria = 0x3F;  // Everything
0029   fd = 0;
0030 }
0031 
0032 FileReaderDCC::~FileReaderDCC(void) {
0033   if (fd)
0034     close(fd);
0035 }
0036 
0037 int FileReaderDCC::open(const char *filename) {
0038   if (fd)
0039     close(fd);
0040   fd = ::open(filename, O_RDONLY | O_LARGEFILE);
0041   if (fd == -1)
0042     throw(std::runtime_error(std::string("Error opening ").append(filename).append(" data file.")));
0043   return fd;
0044 }
0045 
0046 size_t FileReaderDCC::read(const unsigned short *&buf) {
0047   // Check for ubnormal situation
0048   if (end > file_buffer_end || end < file_buffer)
0049     throw(std::runtime_error("Error of reading"));
0050   if (!fd)
0051     throw(std::runtime_error("Open some file first"));
0052 
0053   unsigned long long *start = end;
0054   unsigned short *event = raw_event;
0055 
0056   eventStatus = 0;
0057   size_t dccWordCount = 0;
0058   end = nullptr;
0059 
0060   while (!end && dccWordCount < 50000 * 40) {
0061     unsigned long long *dccWord = start;
0062     unsigned long long preHeader = 0;
0063 
0064     // Did we reach end of current buffer and want to read next block?
0065     // If it was first time and we don't have file buffer then we won't get inside
0066     while (dccWord < file_buffer_end && dccWordCount < 50000) {
0067       word_0 = word_1;                                                // delay by 2 DCC words
0068       word_1 = word_2;                                                // delay by 1 DCC word
0069       word_2 = *dccWord;                                              // current DCC word
0070       if ((word_1 & 0xF0000000000000FFLL) == 0x500000000000005FLL &&  // let's call this a preHeader
0071           (word_2 & 0xFF000000000000FFLL) == 0xD900000000000017LL)    // and this is a header
0072       {
0073         if (eventStatus & Header)  // Second header
0074         {
0075           word_2 = word_1;  // Fall back to get rigth preHeader next time
0076           end = dccWord;    // Even if we end with preHeader of next evet put it to the end of this event too
0077           break;
0078         }
0079         if (dccWordCount > 1)  // Extra words between trailer and header
0080         {
0081           if ((word_0 & 0xFFFFFFFFFFFF0000LL) == 0xFFFFFFFFFFFF0000LL)
0082             eventStatus |= FFFF;
0083           word_2 = word_1;  // Fall back to get rigth preHeader next time
0084           end = dccWord;
0085           break;
0086         }
0087         eventStatus |= Header;
0088         if (event == raw_event)
0089           preHeader = word_1;  // If preHeader not yet in event then put it there
0090         start = dccWord;
0091       }
0092       if ((word_1 & 0xFF00000000000000LL) == 0xEF00000000000000LL &&
0093           (word_2 & 0xFF0000000000000FLL) == 0xAF00000000000007LL) {
0094         eventStatus |= Trailer;
0095         end = ++dccWord;
0096         break;
0097       }
0098       // Increase counters by one DCC word
0099       dccWord++;
0100       dccWordCount++;
0101     }
0102 
0103     // If have DCC Header
0104     if (preHeader) {
0105       // Need to account first word of DCC Header
0106       memcpy(event, &preHeader, sizeof(preHeader));
0107       event += sizeof(preHeader) / sizeof(unsigned short);
0108     }
0109 
0110     // Take care of the rest
0111     memcpy(event, start, (dccWord - start) * sizeof(unsigned long long));
0112     event += (dccWord - start) * sizeof(unsigned long long) / sizeof(unsigned short);
0113 
0114     // If reach max length
0115     if (dccWordCount == 50000 * 40) {
0116       end = dccWord;
0117       break;
0118     }
0119 
0120     if (!end) {
0121       // Need to read next block for the rest of this event
0122       ssize_t length = ::read(fd, file_buffer, sizeof(file_buffer));
0123       if (length == -1)
0124         throw(std::runtime_error("Error of reading"));
0125       if (length == 0) {
0126         eventStatus |= EndOfStream;
0127         end = (file_buffer_end = file_buffer + sizeof(file_buffer) / sizeof(unsigned long long));
0128         break;
0129       }
0130       file_buffer_end = file_buffer + length / sizeof(unsigned long long);
0131 
0132       // Will start from the beginning of new buffer next time we read it
0133       start = file_buffer;
0134     }
0135   }
0136 
0137   if (!end)
0138     eventStatus |= DCCoversize;
0139   if (!(eventStatus & Header) && !(eventStatus & Trailer) && !(eventStatus & FFFF))
0140     eventStatus |= Unknown;
0141 
0142   buf = (const unsigned short *)raw_event;
0143   return (eventStatus & FFFF ? event - raw_event - 4 : event - raw_event);
0144 }
0145 
0146 size_t FileReaderDCC::next(const unsigned short *&buf) {
0147   size_t size = 0;
0148   do {
0149     if ((size = read(buf)) == 0)
0150       break;
0151   } while (rejectCriteria & eventStatus || !(acceptCriteria & eventStatus) ||
0152            (selectCriteria ? selectCriteria != eventStatus : 0));
0153   return size;
0154 }