StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
EventReader.cxx
1 /***************************************************************************
2  * $Id: EventReader.cxx,v 1.66 2014/06/25 15:33:16 jeromel Exp $
3  * Author: M.J. LeVine
4  ***************************************************************************
5  * Description: Event reader code common to all DAQ detectors
6  *
7  *
8  * change log
9  * 06-Jun-99 MJL implement EventReader::getEventInfo()
10  * 06-Jun-99 MJL implement EventReader::printEventInfo()
11  * 23-Jun-99 MJL add verbose flag and setVerbose() method
12  * 23-Jun-99 MJL turn off all printf, cout when verbose=0
13  * 24-Jun-99 MJL navigation now reads DATAP without prior
14  * knowledge of DATAP length
15  * 20-Jul-99 MJL added EventReader::fprintError()
16  * 20-Jul-99 MJL add alternate constructor for EventReader with name of logfile
17  * 20-Jul-99 MJL add alternate getEventReader with name of logfile
18  * 20-Jul-99 MJL add overloaded printEventInfo(FILE *)
19  * 29-Aug-99 MJL if((MMAPP = (char *) mmap(0, ... for HP platform
20  * 28-Dec-99 MJL add alternate InitEventReaders, mapped and unmapped
21  * 31-Jan-00 MJL set runnum (mapped version)
22  * 27-Jun-00 MJL change EventInfo access functions
23  *
24  ***************************************************************************
25  * $Log: EventReader.cxx,v $
26  * Revision 1.66 2014/06/25 15:33:16 jeromel
27  * Code not used but erradicated use of flush
28  *
29  * Revision 1.65 2012/11/20 21:25:34 fisyak
30  * Make aware that SSD old format fix is valid only till end of 2007
31  *
32  * Revision 1.64 2012/11/06 21:25:41 fisyak
33  * Jeff's fix for SSD
34  *
35  * Revision 1.63 2012/06/11 16:38:35 fisyak
36  * std namespace, remove clash with rtsSystems.h
37  *
38  * Revision 1.62 2010/01/15 19:51:25 fine
39  * RT #1803 Fix side effect for DAT files
40  *
41  * Revision 1.61 2010/01/13 21:50:45 fine
42  * Rt #1803. treat zero DAQ time as error. Print error message
43  *
44  * Revision 1.60 2009/08/24 20:27:10 jml
45  * fixed typos
46  *
47  * Revision 1.59 2009/08/24 20:17:20 jml
48  * remove 1.57, install correct handling of detectors present
49  *
50  * Revision 1.57 2009/07/22 20:23:57 fine
51  * generate the EventInfo from the daqReader rather from the DATAP structure
52  *
53  * Revision 1.56 2009/01/08 23:49:23 fine
54  * Adjust the EventInfo error message
55  *
56  * Revision 1.55 2009/01/06 02:55:50 fine
57  * Protection against of crash for the new DAQ files withno DATAP structure
58  *
59  * Revision 1.54 2008/02/01 21:18:08 fine
60  * add strerror() to show the system erro messages. Thanx Matthew Walker
61  *
62  * Revision 1.53 2008/02/01 19:27:13 fine
63  * Replace printf with LOG. Thankx Matthew Walker
64  *
65  * Revision 1.52 2007/12/27 21:46:40 perev
66  * TRG as a part EMC (Pibero)
67  *
68  * Revision 1.51 2007/12/24 06:04:17 fine
69  * introduce OLDEVP namespace to allow ole and new EVP library concurrently
70  *
71  * Revision 1.50 2007/05/24 20:56:38 jeromel
72  * (Pointer to) method returns FALSE instead of NULL fixed (+ one debug statement to remove later)
73  *
74  * Revision 1.49 2004/09/10 22:08:01 perev
75  * more defence agains corrupted DAQ data
76  *
77  * Revision 1.48 2004/03/01 18:05:47 fisyak
78  * Account for new place for rts.h, add osf
79  *
80  * Revision 1.47 2004/02/18 20:31:14 ward
81  * There was a big mess. I am trying to fix it.
82  *
83  * Revision 1.45 2003/12/24 21:55:57 perev
84  * Cleanup
85  *
86  * Revision 1.44 2003/10/02 19:39:22 ward
87  * Swap header only of DATAP, so Insure++ does not complain about uninitialized data.
88  *
89  * Revision 1.43 2003/09/02 17:55:31 perev
90  * gcc 3.2 updates + WarnOff
91  *
92  * Revision 1.42 2003/07/16 19:58:30 perev
93  * Cleanup of StTriggerData2003 at all
94  *
95  * Revision 1.41 2003/01/29 21:09:31 ward
96  * Accomodate nominally zero data words in TOFP.
97  *
98  * Revision 1.40 2003/01/22 18:13:29 ward
99  * Bug in TOF online code, disable corruption check for this bank.
100  *
101  * Revision 1.39 2002/12/09 18:54:23 ward
102  * EMC stuff from Subhassis.
103  *
104  * Revision 1.38 2002/10/13 20:43:37 ward
105  * Support for decoding DAQ100 data and writing it into a table.
106  *
107  * Revision 1.37 2002/10/10 22:13:58 ward
108  * Silence error msg about missing banks in WhereAreThePointers.
109  *
110  * Revision 1.36 2002/01/17 18:29:54 jeromel
111  * After I looked at the code, corrections from Akio (pass2).
112  *
113  * Revision 1.35 2002/01/17 17:29:26 jeromel
114  *
115  * Files: CVS: DetectorReader.cxx EventReader.cxx EventReader.hh CVS: RecHeaderFormats.hh CVS: ----------------------------------------------------------------------
116  * Modifications for FPD support
117  *
118  * Revision 1.34 2001/12/30 23:53:42 ward
119  * Fixed FTPC pointer errors, and other cleanup.
120  *
121  * Revision 1.33 2001/12/29 22:04:31 ward
122  * Disabled corruption checks of all FTP banks.
123  *
124  * Revision 1.32 2001/10/04 19:22:17 ward
125  * Disabled corruption check for the EMCP bank and all banks under it.
126  *
127  * Revision 1.31 2001/07/10 18:12:47 jeromel
128  * Changes commited for Frank Geurts (TOF) after approval from Herb Ward
129  * on Tue, 10 Jul 2001 11:19:48 and review by Victor.
130  * Changes implements TOF DAQ Reader.
131  *
132  * Revision 1.30 2001/06/26 18:07:38 jcs
133  * remove temporary code to skip corruption check for FTPC banks
134  *
135  * Revision 1.29 2001/06/19 21:07:23 jeromel
136  * add FTPC implementation (Janet S.)
137  *
138  * Revision 1.28 2001/05/14 16:25:58 ward
139  * Temporary code to skip corruption check for FTPC banks.
140  *
141  * Revision 1.27 2000/09/15 21:21:00 fisyak
142  * No ulong on HP
143  *
144  * Revision 1.26 2000/09/12 19:19:06 ward
145  * Fixed bug in bank name extraction, added SVTSECP SVTRBP to bank list.
146  *
147  * Revision 1.25 2000/08/29 17:08:51 ward
148  * In corruption detector, temporarily remove L3_P (no doc), and add SVTP.
149  *
150  * Revision 1.24 2000/08/28 22:19:12 ward
151  * Skip corrupted events. StDaqLib/GENERIC/EventReader.cxx & StDAQMaker/StDAQReader.cxx.
152  *
153  * Revision 1.23 2000/06/27 07:28:07 levine
154  * changed EventInfo access functions to fill in, print Token
155  *
156  * Revision 1.22 2000/06/15 23:05:06 jml
157  * I set the number of pointers in DATAP hardcoded to 10.
158  * The algorithm for determinining this has been broken by the
159  * addition of the trigger data at the end of this bank.
160  *
161  * Revision 1.21 2000/06/08 12:44:37 jml
162  * Added <assert.h> to fix compile error in offline
163  *
164  * Revision 1.20 2000/06/07 15:06:08 jml
165  * Changed exit() calls to assert(0) to aid in debugging
166  *
167  * Revision 1.19 2000/01/31 19:26:11 levine
168  * restore run number to memory-mapped version
169  *
170  * Revision 1.18 2000/01/11 22:04:40 levine
171  * EventReader.hh // change the header file to include std::string
172  * EventReader.cxx // convert string to char* via c_str() member
173  * (changes from Brian Lasiuk)
174  *
175  * Revision 1.17 2000/01/04 20:54:46 levine
176  * Implemented memory-mapped file access in EventReader.cxx. Old method
177  * (via seeks) is still possible by setting mmapp=0 in
178  *
179  * getEventReader(fd,offset,(const char *)logfile,mmapp);
180  *
181  *
182  * but memory-mapped access is much more effective.
183  *
184  * Revision 1.16 1999/12/07 23:10:30 levine
185  * changes to silence the gcc compiler warnings
186  *
187  * Revision 1.15 1999/12/07 20:24:45 levine
188  * add #include <time.h> to make compile warning go away
189  *
190  * Revision 1.14 1999/12/06 22:53:20 levine
191  * Cleaned up information generated on failure to initialize EventReader
192  *
193  * Revision 1.13 1999/12/03 21:39:22 levine
194  * ON encountering end of file, issue INFO message instead of ERROR
195  *
196  * Revision 1.12 1999/12/02 16:40:23 levine
197  * change test on ret value for read (line 230) to prevent looping behavior
198  * at end of file
199  *
200  * Revision 1.11 1999/11/20 00:13:09 fisyak
201  * Micheal LeVine update
202  *
203  * Revision 1.9 1999/07/28 16:08:23 levine
204  * modify EventReader so that ENDR does not cause error exit
205  *
206  * Revision 1.8 1999/07/21 21:33:09 levine
207  *
208  *
209  * changes to include error logging to file.
210  *
211  * There are now 2 constructors for EventReader:
212  *
213  * EventReader();
214  * EventReader(const char *logfilename);
215  *
216  * Constructed with no argument, there is no error logging. Supplying a file name
217  * sends all diagnostic output to the named file (N.B. opens in append mode)
218  *
219  * See example in client.cxx for constructing a log file name based on the
220  * datafile name.
221  *
222  * It is strongly advised to use the log file capability. You can grep it for
223  * instances of "ERROR:" to trap anything noteworthy (i.e., corrupted data files).
224  *
225  * Revision 1.7 1999/07/10 21:31:17 levine
226  * Detectors RICH, EMC, TRG now have their own (defined by each detector) interfaces.
227  * Existing user code will not have to change any calls to TPC-like detector
228  * readers.
229  *
230  * Revision 1.6 1999/07/04 01:47:58 levine
231  * minor changes to make solaris CC compiler happy
232  *
233  * Revision 1.5 1999/07/02 04:37:41 levine
234  * Many changes - see change logs in individual programs
235  *
236  **************************************************************************/
237 
238 #include <sys/types.h>
239 #include <sys/stat.h>
240 #include <sys/mman.h>
241 #include <time.h>
242 #include <fcntl.h>
243 #include <stdlib.h>
244 #include <sys/uio.h>
245 #include <unistd.h>
246 #include "EventReader.hh"
247 #include <assert.h>
248 #include <errno.h>
249 #include "StMessMgr.h"
250 //#include "RTS/src/DAQ_READER/daqReader.h"
251 
252 using namespace OLDEVP;
253 
254 void EventInfo::printEventInfo(FILE * fd)
255 {
256 static const char *detnams[] =
257 {"TPC ","SVT ","TOF ","BTOW","FPD ","FTPC","EXT ","RICH","TRG ","L3 "
258 ,"SC ","EXT2","PMD ","SSD ","ETOW","DAQ ","FP2 ","PP ","BSMD","ESMD"
259 ,"EMC"};
260 
261  char ts[128] ;
262 
263  sprintf(ts,"%s",ctime((const time_t *)&UnixTime)) ;
264  ts[24] = 0 ;
265  LOG_INFO<<"=============== Event # "<<EventSeqNo<<" ============="<<endm;
266  LOG_INFO<<"Ev len (wds) "<<EventLength<<endm;
267  LOG_INFO<<"Creation Time: "<<ts<<endm;
268  LOG_INFO<<"Trigger word "<< std::hex << (void *)TrigWord<<
269  "\t\tTrigger Input word "<< std::hex << (void *)TrigInputWord<<endm;
270  LOG_INFO<<"Token: "<<Token<<endm;
271  LOG_INFO<<"Detectors present: ";
272  unsigned const char* p=0; int i=0;
273  for (p=&TPCPresent,i=0; p<=&EMCPresent;p++,i++) {
274  if (*p) {
275  LOG_INFO<<detnams[i]<<" ";
276  }
277  }
278  LOG_INFO<<endm;
279  LOG_INFO<<"==========================================="<<endm;
280 }
281 EventReader *getEventReader(int fd, long offset, int MMap)
282 {
283  EventReader *er = new EventReader();
284  if (MMap) {
285  er->InitEventReader(fd, offset, MMap); // invoke the mapped version
286  if(er->errorNo())
287  {
288  LOG_ERROR << er->errstr().c_str() << endm;
289  LOG_ERROR << (er->err_string[er->errorNo()-1]) << endm;
290  delete er;
291  return NULL;
292  }
293  }
294  else {
295  er->InitEventReader(fd, offset); // invoke the unmapped version
296  if(er->errorNo())
297  {
298  LOG_ERROR << er->errstr().c_str() << endm;
299  LOG_ERROR << (er->err_string[er->errorNo()-1]) << endm;
300  delete er;
301  return NULL;
302  }
303  }
304 
305 
306  return er;
307 }
308 
309 EventReader *getEventReader(int fd, long offset, const char *logfile, int MMap)
310 {
311  EventReader *er = new EventReader(logfile);
312  if (MMap) {
313  er->InitEventReader(fd, offset, MMap);
314  }
315  else {
316  er->InitEventReader(fd, offset);
317  }
318  if(er->errorNo())
319  {
320  LOG_ERROR << er->errstr().c_str() << endm;
321  LOG_ERROR << (er->err_string[er->errorNo()-1]) << endm;
322  delete er;
323  return NULL;
324  }
325  er->printEventInfo(er->logfd); // print the event information to the log file
326  return er;
327 }
328 
329 EventReader *getEventReader(char *event)
330 {
331  EventReader *er = new EventReader();
332  er->InitEventReader(event);
333  if(er->errorNo())
334  {
335  LOG_ERROR << er->errstr().c_str() << endm;
336  LOG_ERROR << (er->err_string[er->errorNo()-1]) << endm;
337  delete er;
338  return NULL;
339  }
340 
341  return er;
342 }
343 
344 EventReader::EventReader()
345 {
346  DATAP = NULL;
347  MMAPP = NULL;
348  errnum = 0;
349  runnum = 0;
350  memset(errstr0, '\0', sizeof(errstr0));
351  event_size = 0;
352  fd = -1;
353  next_event_offset = -1;
354  verbose = 0;
355  logfd = NULL; //no error logging
356 }
357 EventReader::EventReader(const char *logfile) //pass a string with name of logfile
358 {
359  DATAP = NULL;
360  MMAPP = NULL;
361  errnum = 0;
362  runnum = 0;
363  memset(errstr0, '\0', sizeof(errstr0));
364  event_size = 0;
365  fd = -1;
366  next_event_offset = -1;
367  verbose = 0;
368  logfd = fopen(logfile,"a");
369  if (logfd==NULL) {
370  LOG_ERROR<<"EventReader::EventReader() logfile failure"<<endm;
371  LOG_ERROR << strerror(errno) << ": " << logfile<< " !!!!!!!"<<endm;;
372  assert(0);
373  }
374  LOG_INFO<<"opening logfile..."<<endm;
375 }
376 
377 //Memory mapped version
378 void EventReader::InitEventReader(int fdes, long offset, int MMap)
379 {//InitER
380 #define MX_MAP_SIZE 0x20000000
381 
382  off_t FileLength;
383 
384  if (verbose) {
385  LOG_INFO<< "Initializing EventReader with a MAPPED file" << endm;
386  }
387 
388  //initialize the error strings
389  strcpy(err_string[0],"ERROR: FILE");
390  strcpy(err_string[1],"ERROR: CRC");
391  strcpy(err_string[2],"ERROR: SWAP");
392  strcpy(err_string[3],"ERROR: BANK");
393  strcpy(err_string[4],"ERROR: MEM");
394  strcpy(err_string[5],"ERROR: NOT DATA BANK");
395  strcpy(err_string[6],"ERROR: BAD ARG");
396  strcpy(err_string[7],"ERROR: ENDR ENCOUNTERED");
397  strcpy(err_string[8],"ERROR: BAD HEADER");
398  strcpy(err_string[9],"INFO: MISSING BANK");
399  strcpy(err_string[10],"INFO: END OF FILE");
400 
401 
402  fd = fdes;
403  struct stat buf;
404 
405  if (fstat(fd,&buf)<0){
406  LOG_ERROR << "DaqOpenTag"<< strerror(errno) <<endm;
407  ERROR(ERR_FILE);
408  }
409  FileLength = buf.st_size;
410 
411  next_event_offset = 0;
412  Logical_Record lr;
413 
414  // Calculate the mmap offset - must be aligned to pagesize
415  long pagesize = sysconf(_SC_PAGESIZE);
416  if (verbose){
417  LOG_INFO<<"pagesize = "<<(int)pagesize<<endm;;
418  }
419  int mmap_offset = (offset/pagesize)*pagesize;
420 
421  if(mmap_offset < 0) ERROR(ERR_FILE);
422 
423  int mapsize = buf.st_size - offset + pagesize;
424  //round up to the next page boundary
425  if (mapsize<=0) {// <0 means previous event size exceeded file length
426  if (verbose) {
427  LOG_ERROR<<"end of file encountered"<<endm;
428  }
429  ERROR(INFO_END_FILE) ;
430  }
431  if (mapsize>MX_MAP_SIZE) mapsize = MX_MAP_SIZE;
432  event_size = mapsize ; //needed for munmap() in destructor
433 
434  DATAP = NULL;
435  // map to a file
436  if((MMAPP = (char *)mmap(0, mapsize, PROT_READ | PROT_WRITE,
437  MAP_PRIVATE, fd, mmap_offset)) == (caddr_t) -1) {
438  LOG_ERROR<<strerror(errno)<<"mapping file request "
439  <<std::hex<<(void*)mapsize<<" bytes"<<endm;
440  ERROR(ERR_MEM);
441  }
442 
443  // Set DATAP to the real value
444  DATAP = MMAPP + (offset-mmap_offset);
445 
446  if (offset>=buf.st_size) {
447  ERROR(ERR_FILE) ;
448  }
449 
450  while (strncmp(DATAP,"LRHD", 4) == 0) {
451  // copy the logical record into local struct lr
452  if (!memcpy(&lr,DATAP,sizeof(lr))) {
453  LOG_ERROR<< strerror(errno)<<": error in memcpy"<<endm;
454  }
455  // check the CRC
456  if (!lr.test_CRC()) ERROR(ERR_CRC);
457  // swap bytes
458  if (lr.swap() < 0) ERROR(ERR_SWAP);
459  // zero CRC
460  lr.header.CRC = 0;
461 
462  char lcopy[10];
463 
464  strncpy(lcopy,lr.RecordType,8);
465  lcopy[8] = 0;
466  if (verbose) {
467  LOG_INFO<<"lr.RecordType: "<<lcopy<<endm;
468  }
469 
470  if(strncmp(lr.RecordType, "DATA", 4) != 0) { //not DATA
471  //skip over this record
472  next_event_offset += 4 * lr.RecordLength;
473  if (verbose) {
474  LOG_INFO<<"....skipping "<<(unsigned int)next_event_offset<<" bytes"<<endm;
475  }
476  DATAP += next_event_offset;
477 
478  //DATAP now points to beginning of next RECORD
479  }
480  else { // DATA record. Skip LR
481 
482  // save run number
483  runnum = lr.header.RunNumber;
484 
485  DATAP += sizeof(lr);
486  next_event_offset += sizeof(lr);
487  break; //no need to loop any further
488  }
489  } // while (strncmp(DATAP,"LRHD", 4) == 0)
490 
491  // We should now be positioned at DATAP
492 
493  if(strncmp(DATAP,"DATAP", 5) != 0)
494  {
495  if (verbose) {
496  LOG_ERROR<<"failed to find DATAP at offset 0x"<<(unsigned int)next_event_offset<<endm;
497  }
498  ERROR(ERR_BANK);
499  }
500 
501  // read the datap bank
502  Bank_DATAP *datap = (Bank_DATAP *)DATAP;
503 
504  // check CRC, swap
505  if (!datap->test_CRC()) ERROR(ERR_CRC);
506  if (datap->swap() < 0) ERROR(ERR_SWAP);
507 
508  if (offset + 4*datap->EventLength > buf.st_size) {
509  LOG_ERROR<<"event #"<<datap->EventNumber<<" continues beyond file boundary"<<endm;
510  ERROR(ERR_FILE) ;
511  }
512 
513  // printf("======= Event number: %d ============\n",datap.EventNumber);
514  next_event_offset += 4*datap->EventLength; // needed for nextEventOffset()
515  next_event_offset += offset; // now consistent with unmapped behavior
516  // 29-Dec-99 MJL
517 }
518 
519 // unmapped version
520 void EventReader::InitEventReader(int fdes, long offset)
521 {//InitER
522  long c_offset = offset;
523  if (verbose) {
524  LOG_INFO<< "Initializing EventReader with a file" << endm;
525  }
526 
527  //initialize the error strings
528  strcpy(err_string[0],"ERROR: FILE");
529  strcpy(err_string[1],"ERROR: CRC");
530  strcpy(err_string[2],"ERROR: SWAP");
531  strcpy(err_string[3],"ERROR: BANK");
532  strcpy(err_string[4],"ERROR: MEM");
533  strcpy(err_string[5],"ERROR: NOT DATA BANK");
534  strcpy(err_string[6],"ERROR: BAD ARG");
535  strcpy(err_string[7],"ERROR: ENDR ENCOUNTERED");
536  strcpy(err_string[8],"ERROR: BAD HEADER");
537  strcpy(err_string[9],"INFO: MISSING BANK");
538  strcpy(err_string[10],"INFO: END OF FILE");
539 
540 
541  fd = fdes;
542  int DATAPEVENTLENGTH=0; // hack, the event length is not yet in datap
543 
544  char bank[9];
545  memset(bank,'\0',sizeof(bank));
546 
547  int ret = lseek(fd, offset, SEEK_SET);
548  if(ret < 0) ERROR(ERR_FILE);
549 
550  ret = read(fd,bank,8);
551  if(ret < 0) ERROR(ERR_FILE);
552 
553  ret = lseek(fd, offset, SEEK_SET); // set pointer back to top of bank
554  if(ret < 0) ERROR(ERR_FILE);
555 // printf("%s::%d offset=0x%x BANK %s\n",__FILE__,__LINE__,offset,bank);
556 
557  Logical_Record lr;
558 
559  while (strncmp(bank,"LRHD", 4) == 0) {
560 
561  // read the logical record
562  ret = read(fd,&lr,sizeof(lr));
563  if(ret < 0) ERROR(ERR_FILE);
564  c_offset += sizeof(lr);
565 // printf("%s::%d c_offset=0x%x \n",__FILE__,__LINE__,c_offset);
566 // lr.print();
567 
568  // check the CRC
569  // swap bytes
570  // zero CRC
571  if (!lr.test_CRC()) ERROR(ERR_CRC);
572  if (lr.swap() < 0) ERROR(ERR_SWAP);
573  lr.header.CRC = 0;
574 
575 
576  // get event length
577  DATAPEVENTLENGTH = lr.RecordLength - sizeof(lr)/4; // Hack for event len
578  // save run number
579  runnum = lr.header.RunNumber;
580 
581  // Check version (someday)
582 
583  // Check record type
584 // printf("%s::%d c_offset=0x%x \n",__FILE__,__LINE__,c_offset);
585 // lr.print();
586  char lcopy[10];
587  int offset = 0;
588  strncpy(lcopy,lr.RecordType,8);
589  lcopy[8] = 0;
590  if (verbose) {
591  LOG_INFO<<"lr.RecordType: "<<lcopy<<endm;
592  }
593 // if (strncmp(lr.RecordType, "ENDR", 4)==0) { // check for ENDR record
594 // if (verbose)
595 // printf("ENDR encountered. Processing terminated\n");
596 // next_event_offset = -1;
597 // ERROR(ERR_ENDR_ENCOUNTERED);
598 // }
599  if(strncmp(lr.RecordType, "DATA", 4) != 0) { //not DATA
600  //skip over this record
601  offset = 4*lr.RecordLength-sizeof(lr);
602 // printf("%s::%d c_offset=0x%x \n",__FILE__,__LINE__,c_offset);
603  if (verbose) {
604  LOG_INFO<<"....skipping "<<offset<<" bytes"<<endm;
605  }
606  lseek(fd,offset,SEEK_CUR);
607  c_offset += offset;
608 
609  ret = read(fd,bank,8);
610  lseek(fd,-8,SEEK_CUR); //backspace over BANK TYPE
611 // printf("%s::%d c_offset=0x%x BANK %s\n",__FILE__,__LINE__,c_offset,bank);
612  if(ret < 0) ERROR(ERR_FILE);
613  // if(ret == 0) ERROR(ERR_FILE);
614  if(ret == 0) ERROR(INFO_END_FILE);
615  }
616  else { // DATA record. Skip LR
617 // printf("%s::%d c_offset=0x%x \n",__FILE__,__LINE__,c_offset);
618 
619  ret = read(fd,bank,8);
620  lseek(fd,-8,SEEK_CUR); //backspace over BANK TYPE
621 // printf("%s::%d c_offset=0x%x BANK %s\n",__FILE__,__LINE__,c_offset,bank);
622  break; //no need to loop any further
623  }
624 
625  }
626  // We are now Positioned at DATAP
627  memset(bank,'\0',sizeof(bank));
628  ret = read(fd,bank,8);
629  if(ret < 0) ERROR(ERR_FILE);
630 // printf("%s::%d c_offset=0x%x BANK %s\n",__FILE__,__LINE__,c_offset,bank);
631 
632  ret = lseek(fd,-8,SEEK_CUR);// backspace to beginning of Bank
633 
634  offset += sizeof(lr); // I want offset to point at DATAP
635 // printf("%s::%d c_offset=0x%x BANK %s\n",__FILE__,__LINE__,c_offset,bank);
636 
637  if(strncmp(bank,"DATAP", 5) != 0)
638  {
639  ERROR(ERR_BANK);
640  }
641 
642  // read the datap bank then seek back to start of it
643  Bank_DATAP datap;
644  ret = read(fd,&datap,sizeof(Bank_Header));
645  if (datap.header.swap() < 0) ERROR(ERR_SWAP); // There is no data in the body. Swapping it causes
646  // Insure++ to complain. So we swap only the header.
647  int len = 4*datap.header.BankLength;
648  // if (len>sizeof(datap)) ERROR(ERR_BANK);
649  // why is sizeof(datap) 548 when it should be 138*4 ??
650  // according to the RecHeaderFormats.hh declaration??
651  ret = lseek(fd,-sizeof(Bank_Header),SEEK_CUR);
652  if(ret < 0) ERROR(ERR_FILE);
653  ret = read(fd,&datap,len);
654  if(ret < 0) ERROR(ERR_FILE);
655  ret = lseek(fd,-len,SEEK_CUR);
656  if(ret < 0) ERROR(ERR_FILE);
657 
658  // check CRC, swap
659  if (!datap.test_CRC()) ERROR(ERR_CRC);
660  if (datap.swap() < 0) ERROR(ERR_SWAP);
661 
662  if(datap.EventLength < DATAPEVENTLENGTH)
663  datap.EventLength = DATAPEVENTLENGTH; // hack
664 
665  next_event_offset = c_offset + datap.EventLength * 4;
666 // printf("%s::%d c_offset=0x%x datap.EventLength * 4 0x%x\n",__FILE__,__LINE__,c_offset,datap.EventLength * 4);
667 
668  // printf("======= Event number: %d ============\n",datap.EventNumber);
669  // check that the file contains the entire event
670  struct stat statbuf;
671  if(fstat(fd, &statbuf) < 0) ERROR(ERR_FILE);
672  // assert(!(datap.EventLength > (statbuf.st_size - offset)/4)); // ERROR(ERR_FILE);
673  //if(datap.EventLength > (statbuf.st_size - offset)/4) ERROR(ERR_FILE);
674  // mmap or read the file
675 
676  DATAP = (char *)malloc(datap.EventLength * 4);
677  if(!DATAP) ERROR(ERR_MEM);
678 
679  ret = read(fd, DATAP, datap.EventLength*4);
680  if(ret < 0) ERROR(ERR_FILE);
681  // check CRC, swap
682  if (!((Bank_DATAP *)DATAP)->test_CRC()) ERROR(ERR_CRC);
683  if (((Bank_DATAP *)DATAP)->swap() < 0) ERROR(ERR_SWAP);
684 
685 
686  datap.EventLength = DATAPEVENTLENGTH; // hack!
687 
688  event_size = datap.EventLength;
689 
690 }
691 
692 void EventReader::InitEventReader(void *event)
693 {
694  if (verbose){
695  LOG_INFO << "Creating EventReader with a pointer" << endm;
696  }
697 
698  if(strncmp((char *)event,"LRHD",4) == 0)
699  {
700  Logical_Record *lr=(Logical_Record *)event;
701 
702  // check CRC, swap, zero CRC
703  if (!lr->test_CRC()) ERROR(ERR_CRC);
704  if (lr->swap() < 0) ERROR(ERR_SWAP);
705  lr->CRC = 0;
706 
707  // save run number
708  runnum = lr->header.RunNumber;
709 
710  // Check version (someday)
711 
712  // Check Record Type
713  if(strncmp(lr->RecordType, "DATA", 4) != 0) ERROR(ERR_NOT_DATA_BANK);
714 
715  // position at start of DATAP
716  event = (void *)((char *)event + sizeof(Logical_Record));
717  }
718 
719  if(strncmp((char *)event,"DATAP", 5) != 0) ERROR(ERR_BANK);
720  Bank_DATAP *datap = (Bank_DATAP *)event;
721 
722  // CRC, swap, zero CRC
723  if (!datap->test_CRC()) ERROR(ERR_CRC);
724  if (datap->swap() < 0) ERROR(ERR_SWAP);
725  datap->header.CRC = 0;
726 
727  // save event length, DATAP
728  DATAP = (char *)datap;
729  event_size = datap->EventLength * 4;
730 }
731 
732 EventReader::~EventReader()
733 {
734  // cout << "Destroying event reader" << endl;
735 
736  if(fd == -1) // Pointer construction ... their data
737  {
738  // Nothing needs done
739  }
740  else if(MMAPP != NULL) // Memory Mapped file
741  {
742  // Unmap memory
743  munmap(MMAPP,event_size); //unmap
744  }
745  else // file buffer
746  {
747  // free my malloc
748  free(DATAP);
749  }
750  if (logfd!=NULL) fclose(logfd);
751 }
752 
753 int EventReader::system_present(Bank_DATAP *datap, int sys)
754 {
755  Pointer *pointer;
756  datap->swap();
757 
758  if(sys >= 10) {
759  pointer = &datap->EXTY_ID;
760  if((pointer->offset == 0) || (pointer->length == 0)) {
761  return 0;
762  }
763 
764  Bank_DATAPX *datapx = (Bank_DATAPX *)(((INT32 *)datap) + (pointer->offset));
765  datapx->swap();
766 
767  pointer = &datapx->EXT_DET[sys-10];
768  if((pointer->offset == 0) || (pointer->length == 0)) {
769  return 0;
770  }
771  }
772  else {
773  pointer = &datap->TPC;
774  pointer += sys;
775  if((pointer->offset == 0) || (pointer->length == 0)) {
776  return 0;
777  }
778  }
779  return 1;
780 }
781 
782 EventInfo EventReader::getEventInfo()
783 {
784  enum {
785  TPC_SYSTEM = 0
786  ,SVT_SYSTEM = 1
787  ,TOF_SYSTEM = 2
788  ,BTOW_SYSTEM = 3 //EMC Barrel Tower
789  ,FPD_SYSTEM = 4
790  ,FTP_SYSTEM = 5
791  ,EXT_SYSTEM = 6 // ignore
792  ,RIC_SYSTEM = 7
793  ,TRG_SYSTEM = 8
794  ,L3_SYSTEM = 9
795  ,SC_SYSTEM = 10 // reserved for Slow Controls
796  ,EXT2_SYSTEM = 11 // ignore
797  ,PMD_SYSTEM = 12
798  ,SSD_SYSTEM = 13
799  ,ETOW_SYSTEM = 14 //EMC EndCup Tower
800  ,DAQ_SYSTEM = 15 // ignore
801  ,FP2_SYSTEM = 16 // reserved for future FPD
802  ,PP_SYSTEM = 17 // ignore
803  ,BSMD_SYSTEM = 18 //EMC Barrel Shower
804  ,ESMD_SYSTEM = 19 //EMC Endcup Shower
805  };
806 
807  //cout << "Getting event info" << endl;
808  EventInfo ei;
809  memset(&ei,0,sizeof(EventInfo));
810  Bank_DATAP *dp = (Bank_DATAP *)DATAP;
811  if (dp) {
812  ei.Token = dp->header.Token;
813  ei.EventLength = dp->EventLength;
814  ei.UnixTime = dp->Time;
815  ei.EventSeqNo = dp->EventNumber;
816  ei.TrigWord = dp->TriggerWord;
817  ei.TrigInputWord = dp->TriggerInWord;
818  int detpre = dp->DetectorPresence;
819  //?yf ei.UnixTime = -1;// special case: time was not defined (=0 means : now() )
820  ei.EventLength = -1;// special case: time was not defined (=0 means : now() )
821  LOG_INFO<<"EventReader::getEventInfo detector presence = "<<detpre<<endm;
822 
823  int sys = 0;
824  for (unsigned char *p = &ei.TPCPresent; p<=&ei.ESMDPresent;p++) {
825  *p = 0;
826  if(system_present(dp, sys) ||
827  (ei.UnixTime < 1197676800 && (detpre & (1<<sys))) // Dec 15 00:00:00 2007 fix for SSD
828  ) *p = 1;
829  sys++;
830  }
831  ei.EMCPresent = (ei.BTOWPresent|ei.ETOWPresent|ei.BSMDPresent|ei.ESMDPresent|ei.TRGPresent);
832  } else {
833  LOG_ERROR << "EventReader::getEventInfo: No DATAP exists" << endm;
834  }
835  return ei;
836 }
837 
838 void EventReader::printEventInfo(FILE * fd)
839 {
840  EventInfo ei = getEventInfo();
841  ei.printEventInfo(fd);
842 }
843 
844 long EventReader::NextEventOffset()
845 {
846  return next_event_offset;
847 }
848 
849 int EventReader::MemUsed()
850 {
851  return event_size;
852 }
853 
854 void EventReader::setVerbose(int v)
855 {
856  verbose = v;
857 }
858 
859 char * EventReader::findBank(const char *bankid)
860 {
861  // Fix up DATAP
862  Bank_DATAP *pBankDATAP = (Bank_DATAP *)getDATAP();
863  if (!pBankDATAP) {
864  LOG_ERROR<<"DATAP not found: "<<__FILE__<<" "<<__LINE__<<endm;
865  return NULL;
866  }
867  if (!pBankDATAP->test_CRC()) {
868  LOG_ERROR<<"CRC error in DATAP: "<<__FILE__<<" "<<__LINE__<<endm;
869  return NULL;
870  }
871  if (pBankDATAP->swap() < 0){
872  LOG_ERROR<<"swap error in DATAP: "<<__FILE__<<" "<<__LINE__<<endm;
873  return NULL;
874  }
875  pBankDATAP->header.CRC = 0;
876 
877 // position independent pointers to lower banks, variable DATAP length
878 // int len = pBankDATAP->header.BankLength - sizeof(Bank_Header)/4;
879 // len -= ((INT32 )&pBankDATAP->TPC - (INT32 )&pBankDATAP->EventLength)/4;
880 // len /= sizeof(Pointer)/4;
881  // JML - the length is now hard coded again as DATAP now contains
882  // non-pointer data after the pointer data
883  int len = 10;
884  int ext_len=22; // For Extended Detector ( e.g PMD ) ; Added by Susanta on 6th Nov, 2002
885 
886  Pointer *ptr = &pBankDATAP->TPC;
887 
888  Bank_Header *pBank=0;
889  Bank_DATAPX *pBankDATAPX=0; // Added by Susanta for PMD on 6th Nov, 2002
890 
891  int i,j=0;
892 
893  for (i=0; i<len; i++, ptr++) {
894  if (ptr->length==0) continue;//invalid entry
895  if ((unsigned int)ptr->length== 0xfeedf00d) continue; // EVB fills DATAP with this
896  pBank = (Bank_Header *)(((INT32 *)pBankDATAP)+ (ptr->offset)); // the INT32 cast has
897  // the effect of multiplying the offset by 4
898 
899  // staff Added by Susanta for PMD on 6th Nov, 2002.--- BEGIN
900  if(!strncmp("DATAPX",pBank->BankType,6)){
901  pBankDATAPX = (Bank_DATAPX *)(((INT32 *)pBankDATAP)+ (ptr->offset));
902  pBankDATAPX->swap();
903  Pointer *ptr1 = &pBankDATAPX->EXT_DET[0];
904  for(j=0; j < ext_len; j++, ptr1++){
905  if (ptr1->length==0) continue;//invalid entry
906  pBank = (Bank_Header *)(((INT32 *)pBankDATAPX)+ ptr1->offset); // To find Extended Detector ID
907  if(!strncmp(bankid,pBank->BankType,4)) break;
908  }
909  }
910  // ---ENDS
911  if(!strncmp(bankid,pBank->BankType,4)) break;
912  }
913  if (i==len) return NULL;
914  if (!pBank) return NULL;
915 
916  if(strncmp(pBank->BankType,bankid,4)) {
917  LOG_ERROR<<"detector "<<bankid<<" not found in DATAP"<<endm;
918  return NULL;
919  }
920  return (char *)pBank;
921 
922 }
923 
924 void EventReader::fprintError(int err, const char *file, int line, const char *userstring)
925 {
926  if (logfd==NULL) return; //no file designated
927  if (err<0 || err>MX_MESSAGE) return; //protect against bad error code
928  fprintf(logfd,"%s %s::%d %s\n",err_string[err-1],file,line,userstring);
929  fflush(logfd);
930 }
931 
934 #define PP printf(
935 char EventReader::eventIsCorrupted(int herbFd,long offset) {
936  char returnValue;
937  offset+=60; // Skip the LRHD, and go directly to DATAP.
938  strcpy(mLastBank,"???"); mWordIndex=-1;
939  returnValue = BankOrItsDescendentsIsBad(herbFd,offset);
940  if(returnValue) {
941  PP"StDaqLib/EventReader::eventIsCorrupted: bank pointed to by data word %d of bank %s.\n",mWordIndex+1,mLastBank);
942  }
943  return returnValue;
944 }
945 char *EventReader::ConvertToString(unsigned long *input) {
946  static char rv[20];
947  char *cc,*dd;
948  cc=(char*)input;
949  dd=rv;
950  while(isupper(*cc)||isdigit(*cc)||*cc=='_') *(dd++)=*(cc++); *dd=0;
951  if(strlen(rv)>8) rv[8]=0; // Max len of a bank name is 8 chars (2 words = 8 bytes)
952  return rv;
953 }
954 void EventReader::WhereAreThePointers(int *beg,int *end,char *xx) {
955  *beg=-123; *end=-123;
956  assert(strcmp(xx, "TPCMZP"));
957 
958  // Dec 30 2001. The FTP pointers were messed up. If you want to correct them, use
959  // either ~ward/corruptionDetector/corrDet.c or the code in StDaqLib/FTPC. In the
960  // meantime, the line below disables all FTPC checks.
961  if(xx[0]=='F'&&xx[1]=='T'&&xx[2]=='P') { *beg=0; *end= 0; return; }
962 
963  if(!strcmp(xx, "DATAP")) { *beg=7; *end=26; }
964  if(!strcmp(xx, "RICP")) { *beg=1; *end=36; }
965  if(!strcmp(xx,"RICCRAMP")) { *beg=1; *end=16; }
966  if(!strcmp(xx, "TRGP")) { *beg=1; *end= 2; }
967  if(!strcmp(xx, "TPCP")) { *beg=1; *end=48; }
968  if(!strcmp(xx, "TPCSECP")) { *beg=1; *end=24; }
969  if(!strcmp(xx, "TPCRBP")) { *beg=1; *end= 6; }
970  if(!strcmp(xx,"L3_SECTP")) { *beg=9; *end=14; }
971  if(!strcmp(xx, "L3_SECP")) { *beg=6; *end=11; }
972  if(!strcmp(xx, "L3_P")) { *beg=0; *end= 0; return; } // I don't have good doc for L3_P yet.
973  if(!strcmp(xx, "SVTP")) { *beg=1; *end= 8; }
974  if(!strcmp(xx, "SVTSECP")) { *beg=1; *end=24; }
975  if(!strcmp(xx, "SVTRBP")) { *beg=1; *end= 6; }
976  assert(strcmp(xx, "FTPMZP"));
977  if(!strcmp(xx, "FTPP")) { *beg=1; *end=4; } // Changed from 48 to 4, Dec 30 2001 by H Ward.
978  if(!strcmp(xx, "FTPSECP")) { *beg=1; *end= 24; }
979  if(!strcmp(xx, "FTPRBP")) { *beg=1; *end=6; }
980  // There is a bug in TOF online code. if(!strcmp(xx, "TOFP")) { *beg=1; *end=8; }
981  if(!strcmp(xx, "FPDP")) { *beg=0; *end=0; } // This is for chekcing data corruptions. Skip for now
982  (*beg)--; (*end)--;
983  if((*beg)<0||(*end)<0) {
984  // printf("Please add code to WhereAreThePointers for '%s'.\n",xx); Commented Oct 10 2002.
985  *beg=0; *end=0; return;
986  }
987  if(*beg>=*end) assert(0);
988  if((*end-*beg)%2!=1) assert(0);
989 }
990 void EventReader::Swap4(unsigned long *data) {
991  char *hh,temp[4];
992  hh=(char*)data;
993  temp[0]=hh[3]; temp[1]=hh[2]; temp[2]=hh[1]; temp[3]=hh[0];
994  *data=*((unsigned long*)temp);
995 }
996 #define DATA 400 /* number of words */
997 /* comment 12c It is not a pointer bank. We've already looked at the header, that's all we can do
998 for a generic bank. */
999 char EventReader::BankOrItsDescendentsIsBad(int herbFd,long currentOffset) { // Boolean value.
1000  unsigned long header[10],data[DATA];
1001  char doTheByteSwap=FALSE,lastletter,bankname[25];
1002  int i,beg,end,numberOfDataWords,bytesRead;
1003 
1004 
1005 
1006  if(lseek(herbFd,currentOffset,SEEK_SET)!=currentOffset) return TRUE;
1007 
1008  bytesRead=read(herbFd,header,10*sizeof(unsigned long));
1009 
1010  if(bytesRead!=10*sizeof(unsigned long)) return TRUE;
1011 
1012 
1013  strcpy(bankname,ConvertToString(header));
1014  // PP"BBB bankname = %s\n",bankname);
1015  if(strlen(bankname)<3) return TRUE;
1016  lastletter=bankname[strlen(bankname)-1];
1017 
1018  if(header[5]==0x01020304) doTheByteSwap=TRUE; else if(header[5]!=0x04030201) return TRUE;
1019 
1020  /* KEEP ALL CHECKS OF THE HEADER ABOVE THIS LINE. see comment 12c */
1021 
1022  if(lastletter!='P') return FALSE; /* see comment 12c */
1023 
1024  if(doTheByteSwap) for(i=0;i<10;i++) Swap4(header+i);
1025  assert(header[5]==0x04030201); /* We have enought corruption checks above that this shouldn't happen. */
1026 
1027  numberOfDataWords=header[2]-10;
1028  if(numberOfDataWords>DATA) { LOG_INFO<<numberOfDataWords<<" "<<DATA<<", bankname="<<bankname<<endm; }
1029  assert(numberOfDataWords<=DATA);
1030  if(!strcmp(bankname,"TPCMZP")) { beg=0; end=numberOfDataWords-1; }
1031  else if(!strcmp(bankname,"EMCP")) { beg=0; end=0; }
1032  else if(!strcmp(bankname,"PMDP")) { beg=0; end=0; }
1033  else WhereAreThePointers(&beg,&end,bankname);
1034  if(end>=numberOfDataWords&&numberOfDataWords>0) {//29jan03 numberOfDataWords>0 because of bank errs
1035  PP"end=%d, numberOfDataWords=%d, bankname=%s.\n",end,numberOfDataWords,bankname);
1036  assert(end<numberOfDataWords);
1037  }
1038 
1039  bytesRead=read(herbFd,data,numberOfDataWords*sizeof(unsigned long));
1040  if(bytesRead!=int(numberOfDataWords*sizeof(unsigned long))) return TRUE;
1041  if(doTheByteSwap) for(i=0;i<numberOfDataWords;i++) Swap4(data+i);
1042 
1043  if(!strcmp(bankname,"TPCMZP")||!strcmp(bankname,"FTPMZP")) {
1044  if(data[5]!=0&&(data[1]==0||data[3]==0)) return TRUE; /* TPCADCX should be present only if SEQD & ADCD are too. */
1045  }
1046 
1047  for(i=beg;i<end;i+=2) {
1048  if(data[i+1]==0) continue; /* len is 0 */
1049  if(data[i]==0) {
1050  PP"Bank '%s' (at offset %ld bytes in the .daq file) points to itself (data word %d counting from 1).\n",
1051  bankname,currentOffset,i+1);
1052  return TRUE;
1053  }
1054  strncpy(mLastBank,bankname,25);
1055  mWordIndex=i; // mWordIndex is 1 off from the DAQ Data Format document (starts from 0 instead of 1).
1056  if(BankOrItsDescendentsIsBad(herbFd,4*data[i]+currentOffset)) return TRUE;
1057  }
1058  return FALSE;
1059 }