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