ed929a6c4456470c38156101e5215208151e780f
[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 <TROOT.h>
53 #include <TStopwatch.h>
54
55 #include <sys/uio.h>
56 #ifdef USE_EB
57 #include "libDateEb.h"
58 #endif
59
60 #include <AliLog.h>
61 #include <AliESD.h>
62
63 #include "AliRawEvent.h"
64 #include "AliRawEventHeader.h"
65 #include "AliRawEquipment.h"
66 #include "AliRawEquipmentHeader.h"
67 #include "AliRawData.h"
68 #include "AliStats.h"
69 #include "AliRawDB.h"
70 #include "AliRawRFIODB.h"
71 #include "AliRawCastorDB.h"
72 #include "AliRawRootdDB.h"
73 #include "AliRawNullDB.h"
74 #include "AliTagDB.h"
75 #include "AliRunDB.h"
76 #include "AliFilter.h"
77
78 #include "AliMDC.h"
79
80
81 ClassImp(AliMDC)
82
83
84 // Filter names
85 const char* const AliMDC::fgkFilterName[kNFilters] = {"AliHoughFilter"};
86
87 //______________________________________________________________________________
88 AliMDC::AliMDC(Int_t compress, Bool_t deleteFiles, EFilterMode filterMode, 
89                const char* localRunDB, Bool_t rdbmsRunDB,
90                const char* alienHostRunDB, const char* alienDirRunDB,
91                Double_t maxSizeTagDB, const char* fileNameTagDB) :
92   fEvent(new AliRawEvent),
93   fESD(NULL),
94   fStats(NULL),
95   fRawDB(NULL),
96   fRunDB(new AliRunDB(localRunDB, rdbmsRunDB, alienHostRunDB, alienDirRunDB)),
97   fTagDB(NULL),
98   fCompress(compress),
99   fDeleteFiles(deleteFiles),
100   fFilterMode(filterMode),
101   fFilters(),
102   fStop(kFALSE)
103 {
104   // Create MDC processor object.
105   // compress is the file compression mode.
106   // If deleteFiles is kTRUE the raw data files will be deleted after they
107   // were closed.
108   // If the filterMode if kFilterOff no filter algorithm will be, if it is
109   // kFilterTransparent the algorthims will be run but no events will be
110   // rejected, if it is kFilterOn the filters will be run and the event will
111   // be rejected if all filters return kFALSE.
112   // localRunDB is the file name of the local run DB; if NULL no local run DB
113   // will be created.
114   // The filling of a MySQL run DB can be switch on or off with rdbmsRunDB.
115   // The host and directory name of the alien run DB can be specified by
116   // alienHostRunDB and alienDirRunDB; if NULL no alien DB will be filled.
117   // If maxSizeTagDB is greater than 0 it determines the maximal size of the
118   // tag DB and then fileNameTagDB is the directory name for the tag DB.
119   // Otherwise fileNameTagDB is the file name of the tag DB. If it is NULL
120   // no tag DB will be created.
121  
122
123   if (fFilterMode != kFilterOff) {
124     fESD = new AliESD;
125   }
126
127   if (fileNameTagDB) {
128     if (maxSizeTagDB > 0) {
129       fTagDB = new AliTagDB(fEvent->GetHeader(), NULL);
130       fTagDB->SetMaxSize(maxSizeTagDB);
131       fTagDB->SetFS(fileNameTagDB);
132       fTagDB->Create();
133     } else {
134       fTagDB = new AliTagDB(fEvent->GetHeader(), fileNameTagDB);
135     }
136   }
137
138   // install SIGUSR1 handler to allow clean interrupts
139   gSystem->AddSignalHandler(new AliMDCInterruptHandler(this));
140
141   // create the high level filters
142   if (fFilterMode != kFilterOff) {
143     for (Int_t iFilter = 0; iFilter < kNFilters; iFilter++) {
144       TClass* filterClass = gROOT->GetClass(fgkFilterName[iFilter]);
145       if (!filterClass) {
146         Warning("AliMDC", "no filter class %s found", fgkFilterName[iFilter]);
147         continue;
148       }
149       AliFilter* filter = (AliFilter*) filterClass->New();
150       if (!filter) {
151         Warning("AliMDC", "creation of filter %s failed", fgkFilterName[iFilter]);
152         continue;
153       }
154       fFilters.Add(filter);
155     }
156   }
157 }
158
159 //______________________________________________________________________________
160 AliMDC::~AliMDC()
161 {
162 // destructor
163
164   fFilters.Delete();
165   delete fTagDB;
166   delete fRunDB;
167   delete fRawDB;
168   delete fStats;
169   delete fESD;
170   delete fEvent;
171 }
172  
173 //______________________________________________________________________________
174 AliMDC::AliMDC(const AliMDC& mdc): TObject(mdc)
175 {
176 // copy constructor
177
178   Fatal("AliMDC", "copy constructor not implemented");
179 }
180
181 //______________________________________________________________________________
182 AliMDC& AliMDC::operator = (const AliMDC& /*mdc*/)
183 {
184 // assignment operator
185
186   Fatal("operator =", "assignment operator not implemented");
187   return *this;
188 }
189
190
191 //______________________________________________________________________________
192 Int_t AliMDC::Open(EWriteMode mode, const char* fileName)
193 {
194 // open a new raw DB file
195
196   if (mode == kRFIO)
197     fRawDB = new AliRawRFIODB(fEvent, fESD, fCompress, fileName);
198   else if (mode == kROOTD)
199     fRawDB = new AliRawRootdDB(fEvent, fESD, fCompress, fileName);
200   else if (mode == kCASTOR)
201     fRawDB = new AliRawCastorDB(fEvent, fESD, fCompress, fileName);
202   else if (mode == kDEVNULL)
203     fRawDB = new AliRawNullDB(fEvent, fESD, fCompress, fileName);
204   else
205     fRawDB = new AliRawDB(fEvent, fESD, fCompress, fileName);
206   fRawDB->SetDeleteFiles(fDeleteFiles);
207
208   if (fRawDB->IsZombie()) {
209     delete fRawDB;
210     fRawDB = NULL;
211     return 1;
212   }
213   Info("Open", "Filling raw DB %s\n", fRawDB->GetDBName());
214
215   // Create AliStats object
216   fStats = new AliStats(fRawDB->GetDBName(), fCompress, 
217                         fFilterMode != kFilterOff);
218   return 0;
219 }
220
221 //______________________________________________________________________________
222 Int_t AliMDC::ProcessEvent(void* event, Bool_t isIovecArray)
223 {
224 // Convert the DATE event to an AliRawEvent object and store it in the raw DB,
225 // optionally also run the filter.
226 // event is either a pointer to the streamlined event 
227 // or, if isIovecArray is kTRUE, a pointer to an array of iovecs with one
228 // iovec per subevent (used by the event builder).
229 // The return value is the number of written bytes or an error code
230   const UInt_t kFileSizeWarningLevel = 1800000000;
231   const UInt_t kFileSizeErrorLevel   = 1900000000;
232
233   UInt_t currentFileSize = GetTotalSize();
234   if(currentFileSize > kFileSizeErrorLevel) {
235     Error("ProcessEvent", "file size (%u) exceeds the limit "
236           , currentFileSize);
237     return kErrFileSize;
238   }
239   if(currentFileSize > kFileSizeWarningLevel)
240     Warning("ProcessEvent", "file size (%u) is close to the limit "
241             , currentFileSize);
242
243   Int_t status;
244   char* data = (char*) event;
245   if (isIovecArray) data = (char*) ((iovec*) event)[0].iov_base;
246
247   // Shortcut for easy header access
248   AliRawEventHeader &header = *fEvent->GetHeader();
249
250   // Read event header
251   if ((status = ReadHeader(header, data)) != header.HeaderSize()) {
252     return kErrHeader;
253   }
254
255   if (AliDebugLevel() > 2) ToAliDebug(3, header.Dump(););
256
257   // Check event type and skip "Start of Run", "End of Run",
258   // "Start of Run Files" and "End of Run Files"
259   Int_t size = header.GetEventSize() - header.HeaderSize();
260   switch (header.GetType()) {
261   case AliRawEventHeader::kStartOfRun:
262   case AliRawEventHeader::kEndOfRun:
263   case AliRawEventHeader::kStartOfRunFiles:
264   case AliRawEventHeader::kEndOfRunFiles:
265     {
266       AliDebug(1, Form("Skipping %s (%d bytes)", header.GetTypeName(), size));
267       return kErrStartEndRun;
268     }
269   default:
270     {
271       AliDebug(1, Form("Processing %s (%d bytes)", header.GetTypeName(), size));
272     }
273   }
274
275   // Amount of data left to read for this event
276   Int_t toRead = size;
277
278   // If there is less data for this event than the next sub-event
279   // header, something is wrong. Skip to next event...
280   if (toRead < header.HeaderSize()) {
281     Error("ProcessEvent", "header size (%d) exceeds number of bytes "
282           "to read (%d)", header.HeaderSize(), toRead);
283     if (AliDebugLevel() > 0) ToAliDebug(1, header.Dump(););
284     return kErrHeaderSize;
285   }
286   
287   // Loop over all sub-events... (LDCs)
288   Int_t nsub = 1;
289   while (toRead > 0) {
290     if (isIovecArray) data = (char*) ((iovec*) event)[nsub].iov_base;
291
292     AliDebug(1, Form("reading LDC %d", nsub));
293
294     AliRawEvent *subEvent = fEvent->NextSubEvent();
295
296     // Read sub-event header
297     AliRawEventHeader &subHeader = *subEvent->GetHeader();
298     if ((status = ReadHeader(subHeader, data)) != subHeader.HeaderSize()) {
299       return kErrSubHeader;
300     }
301
302     if (AliDebugLevel() > 2) ToAliDebug(3, subHeader.Dump(););
303
304     toRead -= subHeader.HeaderSize();
305
306     Int_t rawSize = subHeader.GetEventSize() - subHeader.HeaderSize();
307
308     // Make sure raw data less than left over bytes for current event
309     if (rawSize > toRead) {
310       Warning("ProcessEvent", "raw data size (%d) exceeds number of "
311               "bytes to read (%d)\n", rawSize, toRead);
312       if (AliDebugLevel() > 0) ToAliDebug(1, subHeader.Dump(););
313       return kErrDataSize;
314     }
315
316     // Read Equipment Headers (in case of physics or calibration event)
317     if (header.GetType() == AliRawEventHeader::kPhysicsEvent ||
318         header.GetType() == AliRawEventHeader::kCalibrationEvent) {
319       while (rawSize > 0) {
320         AliRawEquipment &equipment = *subEvent->NextEquipment();
321         AliRawEquipmentHeader &equipmentHeader = 
322           *equipment.GetEquipmentHeader();
323         Int_t equipHeaderSize = equipmentHeader.HeaderSize();
324         if ((status = ReadEquipmentHeader(equipmentHeader, header.DataIsSwapped(),
325                                           data)) != equipHeaderSize) {
326           return kErrEquipmentHeader;
327         }
328         toRead  -= equipHeaderSize;
329         rawSize -= equipHeaderSize;
330
331         // Read equipment raw data
332         AliRawData &subRaw = *equipment.GetRawData();
333
334         Int_t eqSize = equipmentHeader.GetEquipmentSize() - equipHeaderSize;
335         if ((status = ReadRawData(subRaw, eqSize, data)) != eqSize) {
336           return kErrEquipment;
337         }
338         toRead  -= eqSize;
339         rawSize -= eqSize;
340
341       }
342
343     } else {  // Read only raw data but no equipment header
344       AliRawEquipment &equipment = *subEvent->NextEquipment();
345       AliRawData &subRaw = *equipment.GetRawData();
346       if ((status = ReadRawData(subRaw, rawSize, data)) != rawSize) {
347         return kErrEquipment;
348       }
349       toRead  -= rawSize;
350
351     }
352
353     nsub++;
354   }
355
356   // High Level Event Filter
357   if (fFilterMode != kFilterOff) {
358     if (header.GetType() == AliRawEventHeader::kPhysicsEvent ||
359         header.GetType() == AliRawEventHeader::kCalibrationEvent) {
360       Bool_t result = kFALSE;
361       for (Int_t iFilter = 0; iFilter < fFilters.GetEntriesFast(); iFilter++) {
362         AliFilter* filter = (AliFilter*) fFilters[iFilter];
363         if (!filter) continue;
364         if (filter->Filter(fEvent, fESD)) result = kTRUE;
365       }
366       if ((fFilterMode == kFilterOn) && !result) return kFilterReject;
367     }
368   }
369
370   // Set stat info for first event of this file
371   if (fRawDB->GetEvents() == 0)
372     fStats->SetFirstId(header.GetRunNumber(), header.GetEventInRun());
373
374   // Store raw event in tree
375   Int_t nBytes = fRawDB->Fill();
376
377   // Store header in tree
378   if (fTagDB) fTagDB->Fill();
379
380   // Make top event object ready for next event data
381   fEvent->Reset();
382   // Clean up HLT ESD for the next event
383   if (fESD) fESD->Reset();
384
385   return nBytes;
386 }
387
388 //______________________________________________________________________________
389 Int_t AliMDC::GetTotalSize()
390 {
391 // return the total current raw DB file size
392
393   if (!fRawDB) return -1;
394
395   return fRawDB->GetTotalSize();
396 }
397
398 //______________________________________________________________________________
399 Int_t AliMDC::Close()
400 {
401 // close the current raw DB file
402
403   if (!fRawDB) return 1;
404
405   fRawDB->WriteStats(fStats);
406   fRunDB->Update(fStats);
407   delete fRawDB;
408   fRawDB = NULL;
409   delete fStats;
410   fStats = NULL;
411   return 0;
412 }
413
414 //______________________________________________________________________________
415 Int_t AliMDC::Run(const char* inputFile, Bool_t loop,
416                   EWriteMode mode, Double_t maxFileSize, 
417                   const char* fs1, const char* fs2)
418 {
419   // Run the MDC processor. Read from the input stream and only return
420   // when the input gave and EOF or a fatal error occured. On success 0
421   // is returned, 1 in case of a fatality.
422   // inputFile is the name of the DATE input file; if NULL the input will
423   // be taken from the event builder.
424   // If loop is set the same input file will be reused in an infinite loop.
425   // mode specifies the type of the raw DB.
426   // maxFileSize is the maximal size of the raw DB.
427   // fs1 and fs2 are the file system locations of the raw DB.
428
429   Info("Run", "input = %s, rawdb size = %f, filter = %s, "
430        "looping = %s, compression = %d, delete files = %s",
431        inputFile ? inputFile : "event builder", maxFileSize,
432        fFilterMode == kFilterOff ? "off" : 
433        (fFilterMode == kFilterOn ? "on" : "transparent"), 
434        loop ? "yes" : "no", fCompress, fDeleteFiles ? "yes" : "no");
435
436   // Open the input file
437   Int_t fd = -1;
438   if (inputFile) {
439     if ((fd = open(inputFile, O_RDONLY)) == -1) {
440       Error("Run", "cannot open input file %s", inputFile);
441       return 1;
442     }
443   }
444
445   // Used for statistics
446   TStopwatch timer;
447   timer.Start();
448   Double_t told = 0, tnew = 0;
449   Float_t  chunkSize = maxFileSize/100, nextChunk = chunkSize;
450
451   // Create new raw DB.
452   if (fRawDB) Close();
453   if (mode == kRFIO) {
454     fRawDB = new AliRawRFIODB(fEvent, fESD, fCompress, NULL);
455   } else if (mode == kROOTD) {
456     fRawDB = new AliRawRootdDB(fEvent, fESD, fCompress, NULL);
457   } else if (mode == kCASTOR) {
458     fRawDB = new AliRawCastorDB(fEvent, fESD, fCompress, NULL);
459   } else if (mode == kDEVNULL) {
460     fRawDB = new AliRawNullDB(fEvent, fESD, fCompress, NULL);
461   } else {
462     fRawDB = new AliRawDB(fEvent, fESD, fCompress, NULL);
463   }
464   fRawDB->SetMaxSize(maxFileSize);
465   fRawDB->SetFS(fs1, fs2);
466   fRawDB->SetDeleteFiles(fDeleteFiles);
467   fRawDB->Create();
468
469   if (fRawDB->IsZombie()) {
470     delete fRawDB;
471     fRawDB = NULL;
472     return 1;
473   }
474   printf("Filling raw DB %s\n", fRawDB->GetDBName());
475
476   // Create AliStats object
477   fStats = new AliStats(fRawDB->GetDBName(), fCompress, 
478                         fFilterMode != kFilterOff);
479
480   // Process input stream
481 #ifdef USE_EB
482   Int_t eorFlag = 0;
483 #endif
484   char* event = NULL;
485   UInt_t eventSize = 0;
486   Int_t numEvents = 0;
487
488   while (kTRUE) {
489
490     // If we were in looping mode stop directly after a SIGUSR1 signal
491     if (fStop) {
492       Info("Run", "Stopping loop, processed %d events", numEvents);
493       break;
494     }
495
496     if (!inputFile) {  // get data from event builder
497 #ifdef USE_EB
498       if ((eorFlag = ebEor())) break;
499       if ((event = (char*)ebGetNextEvent()) == (char*)-1) {
500         Error("Run", "error getting next event (%s)", ebGetLastError());
501         break;
502       }
503       if (event == 0) {
504         // no event, sleep for 1 second and try again
505         gSystem->Sleep(1000);
506         continue;
507       }
508 #else
509       Error("Run", "AliMDC was compiled without event builder support");
510       delete fRawDB;
511       fRawDB = NULL;
512       delete fStats;
513       fStats = NULL;
514       return 1;
515 #endif
516
517     } else {  // get data from a file
518       AliRawEventHeader header;
519       Int_t nrecv;
520       if ((nrecv = Read(fd, header.HeaderBegin(), header.HeaderSize())) !=
521           header.HeaderSize()) {
522         if (nrecv == 0) {  // eof
523           if (loop) {
524             ::lseek(fd, 0, SEEK_SET);
525             continue;
526           } else {
527             break;
528           }
529         } else {
530           Error("Run", "error reading header");
531           Close();
532           delete[] event;
533           return 1;
534         }
535       }
536       if (eventSize < header.GetEventSize()) {
537         delete[] event;
538         eventSize = 2 * header.GetEventSize();
539         event = new char[eventSize];
540       }
541       memcpy(event, header.HeaderBegin(), header.HeaderSize());
542       Int_t size = header.GetEventSize() - header.HeaderSize();
543       if (Read(fd, event + header.HeaderSize(), size) != size) {
544         Error("Run", "error reading data");
545         Close();
546         delete[] event;
547         return 1;
548       }
549     }
550
551     Int_t result = ProcessEvent(event, !inputFile);
552
553     if (result >= 0) {
554       numEvents++;
555       if (!(numEvents%10))
556         printf("Processed event %d (%d)\n", numEvents, fRawDB->GetEvents());
557     }
558
559     if (result > 0) {
560       // Filling time statistics
561       if (fRawDB->GetBytesWritten() > nextChunk) {
562         tnew = timer.RealTime();
563         fStats->Fill(tnew-told);
564         told = tnew;
565         timer.Continue();
566         nextChunk += chunkSize;
567       }
568
569       // Check size of raw db. If bigger than maxFileSize, close file
570       // and continue with new file.
571       if (fRawDB->GetBytesWritten() > maxFileSize) {
572
573         printf("Written raw DB at a rate of %.1f MB/s\n",
574                fRawDB->GetBytesWritten() / timer.RealTime() / 1000000.);
575
576         // Write stats object to raw db, run db, MySQL and AliEn
577         fRawDB->WriteStats(fStats);
578         if (fRunDB) fRunDB->Update(fStats);
579         delete fStats;
580         fStats = NULL;
581
582         if (!fRawDB->NextFile()) {
583           Error("Run", "error opening next raw data file");
584           Close();
585           if (inputFile) delete[] event;
586           return 1;
587         }
588
589         printf("Filling raw DB %s\n", fRawDB->GetDBName());
590         fStats = new AliStats(fRawDB->GetDBName(), fCompress, 
591                               fFilterMode != kFilterOff);
592
593         timer.Start();
594         told = 0, tnew = 0;
595         nextChunk = chunkSize;
596       }
597
598       // Check size of tag db
599       if (fTagDB && fTagDB->FileFull()) {
600         if (!fTagDB->NextFile()) {
601           delete fTagDB;
602           fTagDB = 0;
603         } else {
604           printf("Filling tag DB %s\n", fTagDB->GetDBName());
605         }
606       }
607     }
608
609     // Make top event object ready for next event data
610     //printf("Event %d has %d sub-events\n", numEvents, fEvent->GetNSubEvents());
611     //    fEvent->Reset();
612     // Clean up HLT ESD for the next event
613     //    if (fESD) fESD->Reset();
614
615     if (!inputFile) {
616 #ifdef USE_EB
617       if (!ebReleaseEvent((iovec*)event)) {
618         Error("Run", "problem releasing event (%s)", ebGetLastError());
619         break;
620       }
621 #endif
622     }
623   }
624
625   printf("Written raw DB at a rate of %.1f MB/s\n",
626          fRawDB->GetBytesWritten() / timer.RealTime() / 1000000.);
627
628   // Write stats to raw db and run db and delete stats object
629   Close();
630
631   if (!inputFile) {
632 #ifdef USE_EB
633     // Print eor flag
634     if (eorFlag) {
635       Info("Run", "event builder reported end of run (%d)", eorFlag);
636     }
637 #endif
638   } else {
639     // Close input source
640     close(fd);
641   }
642
643   return 0;
644 }
645
646 //______________________________________________________________________________
647 Int_t AliMDC::Read(Int_t fd, void *buffer, Int_t length)
648 {
649    // Read exactly length bytes into buffer. Returns number of bytes
650    // received, returns -1 in case of error and 0 for EOF.
651
652    errno = 0;
653
654    if (fd < 0) return -1;
655
656    Int_t n, nrecv = 0;
657    char *buf = (char *)buffer;
658
659    for (n = 0; n < length; n += nrecv) {
660       if ((nrecv = read(fd, buf+n, length-n)) <= 0) {
661          if (nrecv == 0)
662             break;        // EOF
663          if (errno != EINTR)
664             SysError("Read", "read");
665          return -1;
666       }
667    }
668    return n;
669 }
670
671 //______________________________________________________________________________
672 Int_t AliMDC::ReadHeader(AliRawEventHeader &header, char*& data)
673 {
674   // Read header info from DATE data stream. Returns bytes read (i.e.
675   // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
676
677   memcpy(header.HeaderBegin(), data, header.HeaderSize());
678   data += header.HeaderSize();
679
680   // Swap header data if needed
681   if (header.IsSwapped())
682     header.Swap();
683
684   // Is header valid...
685   if (!header.IsValid()) {
686     Error("ReadHeader", "invalid header format");
687     // try recovery... how?
688     return -1;
689   }
690   if (header.GetEventSize() < (UInt_t)header.HeaderSize()) {
691     Error("ReadHeader", "invalid header size");
692     // try recovery... how?
693     return -1;
694   }
695
696   return header.HeaderSize();
697 }
698
699 //______________________________________________________________________________
700 Int_t AliMDC::ReadEquipmentHeader(AliRawEquipmentHeader &header,
701                                   Bool_t isSwapped, char*& data)
702 {
703   // Read equipment header info from DATE data stream. Returns bytes read
704   // (i.e. AliRawEquipmentHeader::HeaderSize()), -1 in case of error and
705   // 0 for EOF. If isSwapped is kTRUE the event data is byte swapped
706   // and we will swap the header to host format.
707
708   memcpy(header.HeaderBegin(), data, header.HeaderSize());
709   data += header.HeaderSize();
710
711   // Swap equipment header data if needed
712   if (isSwapped)
713     header.Swap();
714
715   if (header.GetEquipmentSize() < (UInt_t)header.HeaderSize()) {
716     Error("ReadEquipmentHeader", "invalid equipment header size");
717     // try recovery... how?
718     return -1;
719   }
720
721   return header.HeaderSize();
722 }
723
724 //______________________________________________________________________________
725 Int_t AliMDC::ReadRawData(AliRawData &raw, Int_t size, char*& data)
726 {
727   // Read raw data from DATE data stream. Returns bytes read (i.e.
728   // size), -1 in case of error and 0 for EOF.
729
730   raw.SetBuffer(data, size);
731   data += size;
732
733   return size;
734 }
735
736 //______________________________________________________________________________
737 void AliMDC::Stop()
738 {
739   // Stop the event loop
740  
741   fStop = kTRUE; 
742   if (fRawDB) fRawDB->Stop(); 
743 }
744
745
746 //______________________________________________________________________________
747 AliMDC::AliMDCInterruptHandler::AliMDCInterruptHandler(const 
748                                                        AliMDCInterruptHandler&
749                                                        handler): 
750   TSignalHandler(handler) 
751 {
752 // copy constructor
753
754   Fatal("AliMDCInterruptHandler", "copy constructor not implemented");
755 }
756
757 //______________________________________________________________________________
758 AliMDC::AliMDCInterruptHandler& 
759   AliMDC::AliMDCInterruptHandler::operator = (const AliMDCInterruptHandler& 
760                                               /*handler*/)
761 {
762 // assignment operator
763
764   Fatal("operator =", "assignment operator not implemented");
765   return *this;
766 }