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