397159c578c778f01de50495a39be0af7688ec72
[u/mrichter/AliRoot.git] / RAW / AliMDC.cxx
1 // @(#)alimdc:$Name$:$Id$
2 // Author: Fons Rademakers  26/11/99
3 // Updated: Dario Favretto  15/04/2003
4
5 /**************************************************************************
6  * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
7  *                                                                        *
8  * Author: The ALICE Off-line Project.                                    *
9  * Contributors are mentioned in the code where appropriate.              *
10  *                                                                        *
11  * Permission to use, copy, modify and distribute this software and its   *
12  * documentation strictly for non-commercial purposes is hereby granted   *
13  * without fee, provided that the above copyright notice appears in all   *
14  * copies and that both the copyright notice and this permission notice   *
15  * appear in the supporting documentation. The authors make no claims     *
16  * about the suitability of this software for any purpose. It is          *
17  * provided "as is" without express or implied warranty.                  *
18  **************************************************************************/
19
20 //////////////////////////////////////////////////////////////////////////
21 //                                                                      //
22 // AliMDC                                                               //
23 //                                                                      //
24 // Set of classes defining the ALICE RAW event format. The AliRawEvent  //
25 // class defines a RAW event. It consists of an AliEventHeader object   //
26 // an AliEquipmentHeader object, an AliRawData object and an array of   //
27 // sub-events, themselves also being AliRawEvents. The number of        //
28 // sub-events depends on the number of DATE LDC's.                      //
29 // The AliRawEvent objects are written to a ROOT file using different   //
30 // technologies, i.e. to local disk via AliRawDB or via rfiod using     //
31 // AliRawRFIODB or via rootd using AliRawRootdDB or to CASTOR via       //
32 // rootd using AliRawCastorDB (and for performance testing there is     //
33 // also AliRawNullDB).                                                  //
34 // The AliRunDB class provides the interface to the run and file        //
35 // catalogues (AliEn or plain MySQL).                                   //
36 // The AliStats class provides statics information that is added as     //
37 // a single keyed object to each raw file.                              //
38 // The AliTagDB provides an interface to a TAG database.                //
39 // The AliMDC class is usid by the "alimdc" stand-alone program         //
40 // that reads data directly from DATE.                                  //
41 //                                                                      //
42 //////////////////////////////////////////////////////////////////////////
43
44 #include <errno.h>
45
46 #include <TSystem.h>
47 #include <TError.h>
48 #include <TStopwatch.h>
49
50 #ifdef ALI_DATE
51 #include "event.h"
52 #endif
53 #ifdef USE_EB
54 #include "libDateEb.h"
55 #endif
56
57 #include "AliRawEvent.h"
58 #include "AliRawEventHeader.h"
59 #include "AliRawEquipmentHeader.h"
60 #include "AliRawData.h"
61 #include "AliStats.h"
62 #include "AliRawDB.h"
63 #include "AliRawRFIODB.h"
64 #include "AliRawCastorDB.h"
65 #include "AliRawRootdDB.h"
66 #include "AliRawNullDB.h"
67 #include "AliTagDB.h"
68
69 #include "AliMDC.h"
70
71
72 ClassImp(AliMDC)
73
74
75 #define ALIDEBUG(level) \
76    if (AliMDC::Instance() && (AliMDC::Instance()->GetDebugLevel() >= (level)))
77
78
79 // Fixed file system locations for the different DB's
80 #ifdef USE_RDM
81 const char* const AliMDC::fgkFifo       = "/tmp/alimdc.fifo";
82 const char* const AliMDC::fgkRawDBFS[2] = { "/tmp/mdc1", "/tmp/mdc2" };
83 const char* const AliMDC::fgkTagDBFS    = "/tmp/mdc1/tags";
84 const char* const AliMDC::fgkRunDBFS    = "/tmp/mdc1/meta";
85 const char* const AliMDC::fgkRFIOFS     = "rfio:/castor/cern.ch/user/r/rdm";
86 const char* const AliMDC::fgkCastorFS   = "castor:/castor/cern.ch/user/r/rdm";
87 const char* const AliMDC::fgkRootdFS    = "root://localhost//tmp/mdc1";
88 const char* const AliMDC::fgkAlienHost  = "alien://aliens7.cern.ch:15000/?direct";
89 const char* const AliMDC::fgkAlienDir   = "/alice_mdc/DC";
90 #else
91 const char* const AliMDC::fgkFifo       = "/tmp/alimdc.fifo";
92 const char* const AliMDC::fgkRawDBFS[2] = { "/data1/mdc", "/data2/mdc" };
93 const char* const AliMDC::fgkTagDBFS    = "/data1/mdc/tags";
94 const char* const AliMDC::fgkRunDBFS    = "/data1/mdc/meta";
95 const char* const AliMDC::fgkRFIOFS     = "rfio:/castor/cern.ch/lcg/dc5";
96 const char* const AliMDC::fgkCastorFS   = "castor:/castor/cern.ch/lcg/dc5";
97 const char* const AliMDC::fgkRootdFS    = "root://localhost//tmp/mdc1";
98 const char* const AliMDC::fgkAlienHost  = "alien://aliens7.cern.ch:15000/?direct";
99 const char* const AliMDC::fgkAlienDir   = "/alice_mdc/DC";
100 #endif
101
102 // Maximum size of tag db files
103 const Double_t AliMDC::fgkMaxTagFileSize = 2.5e8;    // 250MB
104
105 Bool_t AliMDC::fgDeleteFiles = kFALSE;
106 AliMDC* AliMDC::fgInstance = NULL;
107
108
109 //______________________________________________________________________________
110 AliMDC::AliMDC(Int_t fd, Int_t compress, Double_t maxFileSize, Bool_t useFilter,
111                EWriteMode mode, Bool_t useLoop, Bool_t delFiles)
112 {
113    // Create MDC processor object.
114
115    fFd           = fd;
116    fCompress     = compress;
117    fMaxFileSize  = maxFileSize;
118    fUseFilter    = useFilter;
119    fWriteMode    = mode;
120    fUseLoop      = useLoop;
121    fUseFifo      = kFALSE;
122    fUseEb        = kFALSE;
123    fStopLoop     = kFALSE;
124    fNumEvents    = 0;
125    fDebugLevel   = 0;
126    fgDeleteFiles = delFiles;
127
128    if (fFd == -1) {
129 #ifdef USE_EB
130      if (!ebRegister()) {
131         Error("AliMDC", "cannot register with the event builder (%s)",
132               ebGetLastError());
133         return;
134      }
135      fUseEb = kTRUE;
136 #else
137      if ((mkfifo(fgkFifo, 0644) < 0) && (errno != EEXIST)) {
138          Error("AliMDC", "cannot create fifo %s", fgkFifo);
139          return;
140       }
141       if ((chmod(fgkFifo, 0666) == -1) && (errno != EPERM)) {
142          Error("AliMDC", "cannot change permission of fifo %s", fgkFifo);
143          return;
144       }
145       if ((fFd = open(fgkFifo, O_RDONLY)) == -1) {
146          Error("AliMDC", "cannot open input file %s", fgkFifo);
147          return;
148       }
149       fUseFifo = kTRUE;
150 #endif
151       fUseLoop = kFALSE;
152    }
153
154    printf("<AliMDC::AliMDC>: input = %s, rawdb size = %f, filter = %s, "
155           "looping = %s, compression = %d, delete files = %s",
156           fUseFifo ? "fifo" : (fUseEb ? "eb" : "file"), fMaxFileSize,
157           fUseFilter ? "on" : "off", fUseLoop ? "yes" : "no", fCompress,
158           fgDeleteFiles ? "yes" : "no");
159    if (fWriteMode == kRFIO)
160       printf(", use RFIO\n");
161    else if (fWriteMode == kROOTD)
162       printf(", use rootd\n");
163    else if (fWriteMode == kCASTOR)
164       printf(", use CASTOR/rootd\n");
165    else if (fWriteMode == kDEVNULL)
166       printf(", write raw data to /dev/null\n");
167    else
168       printf("\n");
169
170    // install SIGUSR1 handler to allow clean interrupts
171    gSystem->AddSignalHandler(new AliMDCInterruptHandler(this));
172
173    fgInstance = this;
174 }
175
176 //______________________________________________________________________________
177 AliMDC::AliMDC(const AliMDC& mdc): TObject(mdc)
178 {
179 // copy constructor
180
181   Fatal("AliMDC", "copy constructor not implemented");
182 }
183
184 //______________________________________________________________________________
185 AliMDC& AliMDC::operator = (const AliMDC& /*mdc*/)
186 {
187 // assignment operator
188
189   Fatal("operator =", "assignment operator not implemented");
190   return *this;
191 }
192
193 //______________________________________________________________________________
194 Int_t AliMDC::Run()
195 {
196    // Run the MDC processor. Read from the input stream and only return
197    // when the input gave and EOF or a fatal error occured. On success 0
198    // is returned, 1 in case of a fatality.
199
200    TStopwatch timer;
201    Int_t status;
202
203    // Make sure needed directories exist
204    const char *dirs[4];
205    dirs[0] = fgkRawDBFS[0];
206    dirs[1] = fgkRawDBFS[1];
207    dirs[2] = fgkTagDBFS;
208    dirs[3] = fgkRunDBFS;
209    for (int idir = 0; idir < 4; idir++) {
210       gSystem->ResetErrno();
211       gSystem->MakeDirectory(dirs[idir]);
212       if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
213          SysError("Run", "mkdir %s", dirs[idir]);
214          return 1;
215       }
216    }
217
218    // Used for statistics
219    timer.Start();
220    Double_t told = 0, tnew = 0;
221    Float_t  chunkSize = fMaxFileSize/100, nextChunk = chunkSize;
222
223    // Event object used to store event data.
224    AliRawEvent *event = new AliRawEvent;
225
226    // Create new raw DB.
227    AliRawDB *rawdb;
228    if (fWriteMode == kRFIO)
229       rawdb = new AliRawRFIODB(event, fMaxFileSize, fCompress);
230    else if (fWriteMode == kROOTD)
231       rawdb = new AliRawRootdDB(event, fMaxFileSize, fCompress);
232    else if (fWriteMode == kCASTOR)
233       rawdb = new AliRawCastorDB(event, fMaxFileSize, fCompress);
234    else if (fWriteMode == kDEVNULL)
235       rawdb = new AliRawNullDB(event, fMaxFileSize, fCompress);
236    else
237       rawdb = new AliRawDB(event, fMaxFileSize, fCompress);
238
239    if (rawdb->IsZombie()) return 1;
240    printf("Filling raw DB %s\n", rawdb->GetDBName());
241
242    // Create new tag DB.
243    AliTagDB *tagdb = 0;
244 #if 0
245    // no tagdb for the time being to get maximum speed
246    if (fWriteMode == fgkDEVNULL)
247       tagdb = new AliTagNullDB(event->GetHeader(), fgkMaxTagFileSize);
248    else
249       tagdb = new AliTagDB(event->GetHeader(), fgkMaxTagFileSize);
250    if (tagdb->IsZombie())
251       tagdb = 0;
252    else
253       printf("Filling tag DB %s\n", tagdb->GetDBName());
254 #endif
255
256    // Create AliStats object
257    AliStats *stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter);
258
259    // Shortcut for easy header access
260    AliRawEventHeader &header = *event->GetHeader();
261
262    // Process input stream
263 #ifdef USE_EB
264    Int_t eorFlag = 0;
265    while (!(eorFlag = ebEor())) {
266       struct iovec *ebvec;
267       if ((ebvec = ebGetNextEvent()) == (void *)-1) {
268          Error("Run", "error getting next event (%s)", ebGetLastError());
269          break;
270       }
271       if (ebvec == 0) {
272          // no event, sleep for 1 second and try again
273          gSystem->Sleep(1000);
274          continue;
275       }
276       char *ebdata = (char *) ebvec[0].iov_base;
277 #else
278    while (1) {
279       char *ebdata = 0;
280 #endif
281
282       // Read event header
283       if ((status = ReadHeader(header, ebdata)) != header.HeaderSize()) {
284          if (status == 0) {
285             if (fUseLoop) {
286 #ifndef USE_EB
287                ::lseek(fFd, 0, SEEK_SET);
288 #endif
289                continue;
290             }
291             printf("<AliMDC::Run>: EOF, processed %d events\n", fNumEvents);
292             break;
293          }
294          return 1;
295       }
296       ALIDEBUG(3)
297          header.Dump();
298
299       // If we were in looping mode stop directly after a SIGUSR1 signal
300       if (StopLoop()) {
301          Info("Run", "Stopping loop, processed %d events", fNumEvents);
302          break;
303       }
304
305       // Check if event has any hard track flagged
306       Bool_t callFilter = kFALSE;
307       // This needs to be re-engineered for the next ADC...
308       //if (fUseFilter && TEST_USER_ATTRIBUTE(header.GetTypeAttribute(), 0))
309       //   callFilter = kTRUE;
310
311       // Check event type and skip "Start of Run", "End of Run",
312       // "Start of Run Files" and "End of Run Files"
313       switch (header.GetType()) {
314          case AliRawEventHeader::kStartOfRun:
315          case AliRawEventHeader::kEndOfRun:
316          case AliRawEventHeader::kStartOfRunFiles:
317          case AliRawEventHeader::kEndOfRunFiles:
318             {
319                Int_t skip = header.GetEventSize() - header.HeaderSize();
320 #ifndef USE_EB
321                ::lseek(fFd, skip, SEEK_CUR);
322 #endif
323                ALIDEBUG(1)
324                   Info("Run", "Skipping %s (%d bytes)", header.GetTypeName(), skip);
325                continue;
326             }
327          default:
328             ALIDEBUG(1) {
329                Int_t s = header.GetEventSize() - header.HeaderSize();
330                Info("Run", "Processing %s (%d bytes)", header.GetTypeName(), s);
331             }
332       }
333
334       // Amount of data left to read for this event
335       Int_t toRead = header.GetEventSize() - header.HeaderSize();
336
337       // If there is less data for this event than the next sub-event
338       // header, something is wrong. Skip to next event...
339       if (toRead < header.HeaderSize()) {
340          ALIDEBUG(1) {
341             Warning("Run",
342                     "header size (%d) exceeds number of bytes to read (%d)\n",
343                     header.HeaderSize(), toRead);
344             header.Dump();
345          }
346          if ((status = DumpEvent(toRead)) != toRead) {
347             if (status == 0)
348                break;
349             return 1;
350          }
351          Error("Run", "discarding event %d (too little data for header)", fNumEvents);
352          continue;
353       }
354
355       // Loop over all sub-events... (LDCs)
356       Int_t nsub = 1;
357       while (toRead > 0) {
358 #ifdef USE_EB
359          ebdata = (char *)ebvec[nsub].iov_base;
360 #endif
361
362          ALIDEBUG(1)
363             Info("Run", "reading LDC %d", nsub);
364
365          AliRawEvent *subEvent = event->NextSubEvent();
366
367          // Read sub-event header
368          AliRawEventHeader &subHeader = *subEvent->GetHeader();
369          if ((status = ReadHeader(subHeader, ebdata)) != subHeader.HeaderSize()) {
370             if (status == 0) {
371                Error("Run", "unexpected EOF reading sub-event header");
372                break;
373             }
374             return 1;
375          }
376
377          ALIDEBUG(3)
378             subHeader.Dump();
379
380          toRead -= subHeader.HeaderSize();
381
382 #ifdef USE_EB
383          ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize();
384 #endif
385
386          Int_t rawSize = subHeader.GetEventSize() - subHeader.HeaderSize();
387
388          // Read Equipment Header (in case of physics or calibration event)
389          if (header.GetType() == AliRawEventHeader::kPhysicsEvent ||
390              header.GetType() == AliRawEventHeader::kCalibrationEvent) {
391             AliRawEquipmentHeader &equipment = *subEvent->GetEquipmentHeader();
392             Int_t equipHeaderSize = equipment.HeaderSize();
393             if ((status = ReadEquipmentHeader(equipment, header.DataIsSwapped(),
394                                               ebdata)) != equipHeaderSize) {
395                if (status == 0) {
396                   Error("Run", "unexpected EOF reading equipment-header");
397                   break;
398                }
399                return 1;
400             }
401             toRead  -= equipHeaderSize;
402             rawSize -= equipHeaderSize;
403 #ifdef USE_EB
404             ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize() +
405                      equipHeaderSize;
406 #endif
407          }
408
409          // Make sure raw data less than left over bytes for current event
410          if (rawSize > toRead) {
411             ALIDEBUG(1) {
412                Warning("Run", "raw data size (%d) exceeds number of bytes "
413                        "to read (%d)\n", rawSize, toRead);
414                subHeader.Dump();
415             }
416             if ((status = DumpEvent(toRead)) != toRead) {
417                if (status == 0)
418                   break;
419                return 1;
420             }
421             Error("Run", "discarding event %d (too much data)", fNumEvents);
422             continue;
423          }
424
425          // Read sub-event raw data
426          AliRawData &subRaw = *subEvent->GetRawData();
427          if ((status = ReadRawData(subRaw, rawSize, ebdata)) != rawSize) {
428             if (status == 0) {
429                Error("Run", "unexpected EOF reading sub-event raw data");
430                break;
431             }
432             return 1;
433          }
434
435          if (callFilter) {
436 #ifdef ALI_DATE
437             if (TEST_USER_ATTRIBUTE(subHeader.GetTypeAttribute(), 0))
438                Filter(subRaw);
439             else {
440                // set size of all sectors without hard track flag to 0
441                subRaw.SetSize(0);
442             }
443 #endif
444          }
445
446          toRead -= rawSize;
447          nsub++;
448       }
449
450       // Set stat info for first event of this file
451       if (rawdb->GetEvents() == 0)
452          stats->SetFirstId(header.GetRunNumber(), header.GetEventInRun());
453
454       // Store raw event in tree
455       rawdb->Fill();
456
457       // Store header in tree
458       if (tagdb) tagdb->Fill();
459
460       fNumEvents++;
461
462       if (!(fNumEvents%10))
463          printf("Processed event %d (%d)\n", fNumEvents, rawdb->GetEvents());
464
465       // Filling time statistics
466       if (rawdb->GetBytesWritten() > nextChunk) {
467          tnew = timer.RealTime();
468          stats->Fill(tnew-told);
469          told = tnew;
470          timer.Continue();
471          nextChunk += chunkSize;
472       }
473
474       // Check size of raw db. If bigger than maxFileSize, close file
475       // and continue with new file.
476       if (rawdb->FileFull()) {
477
478          printf("Written raw DB at a rate of %.1f MB/s\n",
479                 rawdb->GetBytesWritten() / timer.RealTime() / 1000000.);
480
481          // Write stats object to raw db, run db, MySQL and AliEn
482          stats->WriteToDB(rawdb);
483          delete stats;
484
485          if (!rawdb->NextFile()) {
486             Error("Run", "error opening next raw data file");
487             return 1;
488          }
489
490          printf("Filling raw DB %s\n", rawdb->GetDBName());
491          stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter);
492
493          timer.Start();
494          told = 0, tnew = 0;
495          nextChunk = chunkSize;
496       }
497
498       // Check size of tag db
499       if (tagdb && tagdb->FileFull()) {
500          if (!tagdb->NextFile())
501             tagdb = 0;
502          else
503             printf("Filling tag DB %s\n", tagdb->GetDBName());
504       }
505
506       // Make top event object ready for next event data
507       //printf("Event %d has %d sub-events\n", fNumEvents, event->GetNSubEvents());
508       event->Reset();
509
510 #ifdef USE_EB
511       if (!ebReleaseEvent(ebvec)) {
512          Error("Run", "problem releasing event (%s)", ebGetLastError());
513          break;
514       }
515 #endif
516    }
517
518    printf("Written raw DB at a rate of %.1f MB/s\n",
519           rawdb->GetBytesWritten() / timer.RealTime() / 1000000.);
520
521    // Write stats to raw db and run db and delete stats object
522    stats->WriteToDB(rawdb);
523    delete stats;
524
525    // Close the raw DB
526    delete rawdb;
527
528    // Close the tag DB
529    delete tagdb;
530
531    // Close input source
532    close(fFd);
533
534 #if 0
535    // Cleanup fifo
536    if (fUseFifo && ::unlink(fgkFifo) == -1) {
537       SysError("Run", "unlink");
538       return 1;
539    }
540 #endif
541
542 #ifdef USE_EB
543    // Print eor flag
544    if (eorFlag) {
545       Info("Run", "event builder reported end of run (%d)", eorFlag);
546    }
547 #endif
548
549    return 0;
550 }
551
552 //______________________________________________________________________________
553 Int_t AliMDC::Read(void *buffer, Int_t length)
554 {
555    // Read exactly length bytes into buffer. Returns number of bytes
556    // received, returns -1 in case of error and 0 for EOF.
557
558    errno = 0;
559
560    if (fFd < 0) return -1;
561
562    Int_t n, nrecv = 0;
563    char *buf = (char *)buffer;
564
565    for (n = 0; n < length; n += nrecv) {
566       if ((nrecv = read(fFd, buf+n, length-n)) <= 0) {
567          if (nrecv == 0)
568             break;        // EOF
569          if (errno != EINTR)
570             SysError("Read", "read");
571          return -1;
572       }
573    }
574    return n;
575 }
576
577 //______________________________________________________________________________
578 Int_t AliMDC::ReadHeader(AliRawEventHeader &header, void *eb)
579 {
580    // Read header info from DATE data stream. Returns bytes read (i.e.
581    // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
582
583    Int_t nrecv;
584
585    if (eb) {
586       // read from event builder memory area
587       memcpy(header.HeaderBegin(), eb, header.HeaderSize());
588       nrecv = header.HeaderSize();
589    } else {
590       // read from fifo or file
591       if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) !=
592            header.HeaderSize()) {
593          if (nrecv == 0)
594             return 0;
595          return -1;
596       }
597    }
598
599    // Swap header data if needed
600    if (header.IsSwapped())
601       header.Swap();
602
603    // Is header valid...
604    if (!header.IsValid()) {
605       Error("ReadHeader", "invalid header format");
606       // try recovery... how?
607       return -1;
608    }
609    if (header.GetEventSize() < (UInt_t)header.HeaderSize()) {
610       Error("ReadHeader", "invalid header size");
611       // try recovery... how?
612       return -1;
613    }
614
615    return nrecv;
616 }
617
618 //______________________________________________________________________________
619 Int_t AliMDC::ReadEquipmentHeader(AliRawEquipmentHeader &header,
620                                   Bool_t isSwapped, void *eb)
621 {
622    // Read equipment header info from DATE data stream. Returns bytes read
623    // (i.e. AliRawEquipmentHeader::HeaderSize()), -1 in case of error and
624    // 0 for EOF. If isSwapped is kTRUE the event data is byte swapped
625    // and we will swap the header to host format.
626
627    Int_t nrecv;
628
629    if (eb) {
630       // read from event builder memory area
631       memcpy(header.HeaderBegin(), eb, header.HeaderSize());
632       nrecv = header.HeaderSize();
633    } else {
634       // read from fifo or file
635       if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) !=
636            header.HeaderSize()) {
637          if (nrecv == 0)
638             return 0;
639          return -1;
640       }
641    }
642
643    // Swap equipment header data if needed
644    if (isSwapped)
645       header.Swap();
646
647    if (header.GetEquipmentSize() < (UInt_t)header.HeaderSize()) {
648       Error("ReadEquipmentHeader", "invalid equipment header size");
649       // try recovery... how?
650       return -1;
651    }
652
653    return nrecv;
654 }
655
656 //______________________________________________________________________________
657 Int_t AliMDC::ReadRawData(AliRawData &raw, Int_t size, void *eb)
658 {
659    // Read raw data from DATE data stream. Returns bytes read (i.e.
660    // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
661
662    Int_t nrecv;
663
664    if (eb) {
665       // read from event builder memory area
666       raw.SetBuffer(eb, size);
667       nrecv = size;
668    } else {
669       // read from fifo or file
670       raw.SetSize(size);
671       if ((nrecv = Read(raw.GetBuffer(), size)) != size) {
672          if (nrecv == 0) {
673             Error("ReadRawData", "unexpected EOF");
674             return 0;
675          }
676          return -1;
677       }
678    }
679
680    return nrecv;
681 }
682
683 //______________________________________________________________________________
684 Int_t AliMDC::DumpEvent(Int_t toRead)
685 {
686    // This case should not happen, but if it does try to handle it
687    // gracefully by reading the rest of the event and discarding it.
688    // Returns bytes read, -1 in case of fatal error and 0 for EOF.
689
690    Error("DumpEvent", "dumping %d bytes of event %d", toRead, fNumEvents);
691
692    Int_t nrecv;
693    char *tbuf = new char[toRead];
694    if ((nrecv = Read(tbuf, toRead)) != toRead) {
695       if (nrecv == 0) {
696          Error("DumpEvent", "unexpected EOF");
697          return 0;
698       }
699       return -1;
700    }
701    delete [] tbuf;
702
703    return nrecv;
704 }
705
706 //______________________________________________________________________________
707 Int_t AliMDC::Filter(AliRawData &raw)
708 {
709    // Call 3rd level filter for this raw data segment.
710
711 #ifdef USE_HLT
712
713    // Add HLT code here
714
715 #else
716
717    raw.GetSize();
718    printf("Filter called for event %d\n", fNumEvents);
719
720 #endif
721
722    return 0;
723 }
724
725 //______________________________________________________________________________
726 AliMDC::AliMDCInterruptHandler::AliMDCInterruptHandler(const 
727                                                        AliMDCInterruptHandler&
728                                                        handler): 
729   TSignalHandler(handler) 
730 {
731 // copy constructor
732
733   Fatal("AliMDCInterruptHandler", "copy constructor not implemented");
734 }
735
736 //______________________________________________________________________________
737 AliMDC::AliMDCInterruptHandler& 
738   AliMDC::AliMDCInterruptHandler::operator = (const AliMDCInterruptHandler& 
739                                               /*handler*/)
740 {
741 // assignment operator
742
743   Fatal("operator =", "assignment operator not implemented");
744   return *this;
745 }