Adding support for raw data events without subevent header
[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 kFileSizeErrorLevel   = 1900000000;
231
232   UInt_t currentFileSize = GetTotalSize();
233   if(currentFileSize > kFileSizeErrorLevel) {
234     Error("ProcessEvent", "file size (%u) exceeds the limit "
235           , currentFileSize);
236     return kErrFileSize;
237   }
238
239   Int_t status;
240   char* data = (char*) event;
241   if (isIovecArray) data = (char*) ((iovec*) event)[0].iov_base;
242
243   // Shortcut for easy header access
244   AliRawEventHeader &header = *fEvent->GetHeader();
245
246   // Read event header
247   if ((status = ReadHeader(header, data)) != header.HeaderSize()) {
248     return kErrHeader;
249   }
250
251   if (AliDebugLevel() > 2) ToAliDebug(3, header.Dump(););
252
253   // Check event type and skip "Start of Run", "End of Run",
254   // "Start of Run Files" and "End of Run Files"
255   Int_t size = header.GetEventSize() - header.HeaderSize();
256   switch (header.GetType()) {
257   case AliRawEventHeader::kStartOfRun:
258   case AliRawEventHeader::kEndOfRun:
259   case AliRawEventHeader::kStartOfRunFiles:
260   case AliRawEventHeader::kEndOfRunFiles:
261     {
262       AliDebug(1, Form("Skipping %s (%d bytes)", header.GetTypeName(), size));
263       return kErrStartEndRun;
264     }
265   default:
266     {
267       AliDebug(1, Form("Processing %s (%d bytes)", header.GetTypeName(), size));
268     }
269   }
270
271   // Amount of data left to read for this event
272   Int_t toRead = size;
273
274   // If there is less data for this event than the next sub-event
275   // header, something is wrong. Skip to next event...
276   if (toRead < header.HeaderSize()) {
277     Error("ProcessEvent", "header size (%d) exceeds number of bytes "
278           "to read (%d)", header.HeaderSize(), toRead);
279     if (AliDebugLevel() > 0) ToAliDebug(1, header.Dump(););
280     return kErrHeaderSize;
281   }
282   
283   // Loop over all sub-events... (LDCs)
284   Int_t nsub = 1;
285   while (toRead > 0) {
286     if (isIovecArray) data = (char*) ((iovec*) event)[nsub].iov_base;
287
288     AliDebug(1, Form("reading LDC %d", nsub));
289
290     AliRawEvent *subEvent = fEvent->NextSubEvent();
291
292     // Read sub-event header
293     AliRawEventHeader &subHeader = *subEvent->GetHeader();
294     if ((status = ReadHeader(subHeader, data)) != subHeader.HeaderSize()) {
295       return kErrSubHeader;
296     }
297
298     if (AliDebugLevel() > 2) ToAliDebug(3, subHeader.Dump(););
299
300     toRead -= subHeader.HeaderSize();
301
302     Int_t rawSize = subHeader.GetEventSize() - subHeader.HeaderSize();
303
304     // Make sure raw data less than left over bytes for current event
305     if (rawSize > toRead) {
306       Warning("ProcessEvent", "raw data size (%d) exceeds number of "
307               "bytes to read (%d)\n", rawSize, toRead);
308       if (AliDebugLevel() > 0) ToAliDebug(1, subHeader.Dump(););
309       return kErrDataSize;
310     }
311
312     // Read Equipment Headers (in case of physics or calibration event)
313     if (header.GetType() == AliRawEventHeader::kPhysicsEvent ||
314         header.GetType() == AliRawEventHeader::kCalibrationEvent) {
315       while (rawSize > 0) {
316         AliRawEquipment &equipment = *subEvent->NextEquipment();
317         AliRawEquipmentHeader &equipmentHeader = 
318           *equipment.GetEquipmentHeader();
319         Int_t equipHeaderSize = equipmentHeader.HeaderSize();
320         if ((status = ReadEquipmentHeader(equipmentHeader, header.DataIsSwapped(),
321                                           data)) != equipHeaderSize) {
322           return kErrEquipmentHeader;
323         }
324         toRead  -= equipHeaderSize;
325         rawSize -= equipHeaderSize;
326
327         // Read equipment raw data
328         AliRawData &subRaw = *equipment.GetRawData();
329
330         Int_t eqSize = equipmentHeader.GetEquipmentSize() - equipHeaderSize;
331         if ((status = ReadRawData(subRaw, eqSize, data)) != eqSize) {
332           return kErrEquipment;
333         }
334         toRead  -= eqSize;
335         rawSize -= eqSize;
336
337       }
338
339     } else {  // Read only raw data but no equipment header
340       AliRawEquipment &equipment = *subEvent->NextEquipment();
341       AliRawData &subRaw = *equipment.GetRawData();
342       if ((status = ReadRawData(subRaw, rawSize, data)) != rawSize) {
343         return kErrEquipment;
344       }
345       toRead  -= rawSize;
346
347     }
348
349     nsub++;
350   }
351
352   // High Level Event Filter
353   if (fFilterMode != kFilterOff) {
354     if (header.GetType() == AliRawEventHeader::kPhysicsEvent ||
355         header.GetType() == AliRawEventHeader::kCalibrationEvent) {
356       Bool_t result = kFALSE;
357       for (Int_t iFilter = 0; iFilter < fFilters.GetEntriesFast(); iFilter++) {
358         AliFilter* filter = (AliFilter*) fFilters[iFilter];
359         if (!filter) continue;
360         if (filter->Filter(fEvent, fESD)) result = kTRUE;
361       }
362       if ((fFilterMode == kFilterOn) && !result) return kFilterReject;
363     }
364   }
365
366   // Set stat info for first event of this file
367   if (fRawDB->GetEvents() == 0)
368     fStats->SetFirstId(header.GetRunNumber(), header.GetEventInRun());
369
370   // Store raw event in tree
371   Int_t nBytes = fRawDB->Fill();
372
373   // Store header in tree
374   if (fTagDB) fTagDB->Fill();
375
376   // Make top event object ready for next event data
377   fEvent->Reset();
378   // Clean up HLT ESD for the next event
379   if (fESD) fESD->Reset();
380
381   return nBytes;
382 }
383
384 //______________________________________________________________________________
385 Int_t AliMDC::GetTotalSize()
386 {
387 // return the total current raw DB file size
388
389   if (!fRawDB) return -1;
390
391   return fRawDB->GetTotalSize();
392 }
393
394 //______________________________________________________________________________
395 Int_t AliMDC::Close()
396 {
397 // close the current raw DB file
398
399   if (!fRawDB) return 1;
400
401   fRawDB->WriteStats(fStats);
402   fRunDB->Update(fStats);
403   delete fRawDB;
404   fRawDB = NULL;
405   delete fStats;
406   fStats = NULL;
407   return 0;
408 }
409
410 //______________________________________________________________________________
411 Int_t AliMDC::Run(const char* inputFile, Bool_t loop,
412                   EWriteMode mode, Double_t maxFileSize, 
413                   const char* fs1, const char* fs2)
414 {
415   // Run the MDC processor. Read from the input stream and only return
416   // when the input gave and EOF or a fatal error occured. On success 0
417   // is returned, 1 in case of a fatality.
418   // inputFile is the name of the DATE input file; if NULL the input will
419   // be taken from the event builder.
420   // If loop is set the same input file will be reused in an infinite loop.
421   // mode specifies the type of the raw DB.
422   // maxFileSize is the maximal size of the raw DB.
423   // fs1 and fs2 are the file system locations of the raw DB.
424
425   Info("Run", "input = %s, rawdb size = %f, filter = %s, "
426        "looping = %s, compression = %d, delete files = %s",
427        inputFile ? inputFile : "event builder", maxFileSize,
428        fFilterMode == kFilterOff ? "off" : 
429        (fFilterMode == kFilterOn ? "on" : "transparent"), 
430        loop ? "yes" : "no", fCompress, fDeleteFiles ? "yes" : "no");
431
432   // Open the input file
433   Int_t fd = -1;
434   if (inputFile) {
435     if ((fd = open(inputFile, O_RDONLY)) == -1) {
436       Error("Run", "cannot open input file %s", inputFile);
437       return 1;
438     }
439   }
440
441   // Used for statistics
442   TStopwatch timer;
443   timer.Start();
444   Double_t told = 0, tnew = 0;
445   Float_t  chunkSize = maxFileSize/100, nextChunk = chunkSize;
446
447   // Create new raw DB.
448   if (fRawDB) Close();
449   if (mode == kRFIO) {
450     fRawDB = new AliRawRFIODB(fEvent, fESD, fCompress, NULL);
451   } else if (mode == kROOTD) {
452     fRawDB = new AliRawRootdDB(fEvent, fESD, fCompress, NULL);
453   } else if (mode == kCASTOR) {
454     fRawDB = new AliRawCastorDB(fEvent, fESD, fCompress, NULL);
455   } else if (mode == kDEVNULL) {
456     fRawDB = new AliRawNullDB(fEvent, fESD, fCompress, NULL);
457   } else {
458     fRawDB = new AliRawDB(fEvent, fESD, fCompress, NULL);
459   }
460   fRawDB->SetMaxSize(maxFileSize);
461   fRawDB->SetFS(fs1, fs2);
462   fRawDB->SetDeleteFiles(fDeleteFiles);
463   fRawDB->Create();
464
465   if (fRawDB->IsZombie()) {
466     delete fRawDB;
467     fRawDB = NULL;
468     return 1;
469   }
470   printf("Filling raw DB %s\n", fRawDB->GetDBName());
471
472   // Create AliStats object
473   fStats = new AliStats(fRawDB->GetDBName(), fCompress, 
474                         fFilterMode != kFilterOff);
475
476   // Process input stream
477 #ifdef USE_EB
478   Int_t eorFlag = 0;
479 #endif
480   char* event = NULL;
481   UInt_t eventSize = 0;
482   Int_t numEvents = 0;
483
484   while (kTRUE) {
485
486     // If we were in looping mode stop directly after a SIGUSR1 signal
487     if (fStop) {
488       Info("Run", "Stopping loop, processed %d events", numEvents);
489       break;
490     }
491
492     if (!inputFile) {  // get data from event builder
493 #ifdef USE_EB
494       if ((eorFlag = ebEor())) break;
495       if ((event = (char*)ebGetNextEvent()) == (char*)-1) {
496         Error("Run", "error getting next event (%s)", ebGetLastError());
497         break;
498       }
499       if (event == 0) {
500         // no event, sleep for 1 second and try again
501         gSystem->Sleep(1000);
502         continue;
503       }
504 #else
505       Error("Run", "AliMDC was compiled without event builder support");
506       delete fRawDB;
507       fRawDB = NULL;
508       delete fStats;
509       fStats = NULL;
510       return 1;
511 #endif
512
513     } else {  // get data from a file
514       AliRawEventHeader header;
515       Int_t nrecv;
516       if ((nrecv = Read(fd, header.HeaderBegin(), header.HeaderSize())) !=
517           header.HeaderSize()) {
518         if (nrecv == 0) {  // eof
519           if (loop) {
520             ::lseek(fd, 0, SEEK_SET);
521             continue;
522           } else {
523             break;
524           }
525         } else {
526           Error("Run", "error reading header");
527           Close();
528           delete[] event;
529           return 1;
530         }
531       }
532       if (eventSize < header.GetEventSize()) {
533         delete[] event;
534         eventSize = 2 * header.GetEventSize();
535         event = new char[eventSize];
536       }
537       memcpy(event, header.HeaderBegin(), header.HeaderSize());
538       Int_t size = header.GetEventSize() - header.HeaderSize();
539       if (Read(fd, event + header.HeaderSize(), size) != size) {
540         Error("Run", "error reading data");
541         Close();
542         delete[] event;
543         return 1;
544       }
545     }
546
547     Int_t result = ProcessEvent(event, !inputFile);
548
549     if (result >= 0) {
550       numEvents++;
551       if (!(numEvents%10))
552         printf("Processed event %d (%d)\n", numEvents, fRawDB->GetEvents());
553     }
554
555     if (result > 0) {
556       // Filling time statistics
557       if (fRawDB->GetBytesWritten() > nextChunk) {
558         tnew = timer.RealTime();
559         fStats->Fill(tnew-told);
560         told = tnew;
561         timer.Continue();
562         nextChunk += chunkSize;
563       }
564
565       // Check size of raw db. If bigger than maxFileSize, close file
566       // and continue with new file.
567       if (fRawDB->GetBytesWritten() > maxFileSize) {
568
569         printf("Written raw DB at a rate of %.1f MB/s\n",
570                fRawDB->GetBytesWritten() / timer.RealTime() / 1000000.);
571
572         // Write stats object to raw db, run db, MySQL and AliEn
573         fRawDB->WriteStats(fStats);
574         if (fRunDB) fRunDB->Update(fStats);
575         delete fStats;
576         fStats = NULL;
577
578         if (!fRawDB->NextFile()) {
579           Error("Run", "error opening next raw data file");
580           Close();
581           if (inputFile) delete[] event;
582           return 1;
583         }
584
585         printf("Filling raw DB %s\n", fRawDB->GetDBName());
586         fStats = new AliStats(fRawDB->GetDBName(), fCompress, 
587                               fFilterMode != kFilterOff);
588
589         timer.Start();
590         told = 0, tnew = 0;
591         nextChunk = chunkSize;
592       }
593
594       // Check size of tag db
595       if (fTagDB && fTagDB->FileFull()) {
596         if (!fTagDB->NextFile()) {
597           delete fTagDB;
598           fTagDB = 0;
599         } else {
600           printf("Filling tag DB %s\n", fTagDB->GetDBName());
601         }
602       }
603     }
604
605     // Make top event object ready for next event data
606     //printf("Event %d has %d sub-events\n", numEvents, fEvent->GetNSubEvents());
607     //    fEvent->Reset();
608     // Clean up HLT ESD for the next event
609     //    if (fESD) fESD->Reset();
610
611     if (!inputFile) {
612 #ifdef USE_EB
613       if (!ebReleaseEvent((iovec*)event)) {
614         Error("Run", "problem releasing event (%s)", ebGetLastError());
615         break;
616       }
617 #endif
618     }
619   }
620
621   printf("Written raw DB at a rate of %.1f MB/s\n",
622          fRawDB->GetBytesWritten() / timer.RealTime() / 1000000.);
623
624   // Write stats to raw db and run db and delete stats object
625   Close();
626
627   if (!inputFile) {
628 #ifdef USE_EB
629     // Print eor flag
630     if (eorFlag) {
631       Info("Run", "event builder reported end of run (%d)", eorFlag);
632     }
633 #endif
634   } else {
635     // Close input source
636     close(fd);
637   }
638
639   return 0;
640 }
641
642 //______________________________________________________________________________
643 Int_t AliMDC::Read(Int_t fd, void *buffer, Int_t length)
644 {
645    // Read exactly length bytes into buffer. Returns number of bytes
646    // received, returns -1 in case of error and 0 for EOF.
647
648    errno = 0;
649
650    if (fd < 0) return -1;
651
652    Int_t n, nrecv = 0;
653    char *buf = (char *)buffer;
654
655    for (n = 0; n < length; n += nrecv) {
656       if ((nrecv = read(fd, buf+n, length-n)) <= 0) {
657          if (nrecv == 0)
658             break;        // EOF
659          if (errno != EINTR)
660             SysError("Read", "read");
661          return -1;
662       }
663    }
664    return n;
665 }
666
667 //______________________________________________________________________________
668 Int_t AliMDC::ReadHeader(AliRawEventHeader &header, char*& data)
669 {
670   // Read header info from DATE data stream. Returns bytes read (i.e.
671   // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
672
673   memcpy(header.HeaderBegin(), data, header.HeaderSize());
674   data += header.HeaderSize();
675
676   // Swap header data if needed
677   if (header.IsSwapped())
678     header.Swap();
679
680   // Is header valid...
681   if (!header.IsValid()) {
682     Error("ReadHeader", "invalid header format");
683     // try recovery... how?
684     return -1;
685   }
686   if (header.GetEventSize() < (UInt_t)header.HeaderSize()) {
687     Error("ReadHeader", "invalid header size");
688     // try recovery... how?
689     return -1;
690   }
691
692   return header.HeaderSize();
693 }
694
695 //______________________________________________________________________________
696 Int_t AliMDC::ReadEquipmentHeader(AliRawEquipmentHeader &header,
697                                   Bool_t isSwapped, char*& data)
698 {
699   // Read equipment header info from DATE data stream. Returns bytes read
700   // (i.e. AliRawEquipmentHeader::HeaderSize()), -1 in case of error and
701   // 0 for EOF. If isSwapped is kTRUE the event data is byte swapped
702   // and we will swap the header to host format.
703
704   memcpy(header.HeaderBegin(), data, header.HeaderSize());
705   data += header.HeaderSize();
706
707   // Swap equipment header data if needed
708   if (isSwapped)
709     header.Swap();
710
711   if (header.GetEquipmentSize() < (UInt_t)header.HeaderSize()) {
712     Error("ReadEquipmentHeader", "invalid equipment header size");
713     // try recovery... how?
714     return -1;
715   }
716
717   return header.HeaderSize();
718 }
719
720 //______________________________________________________________________________
721 Int_t AliMDC::ReadRawData(AliRawData &raw, Int_t size, char*& data)
722 {
723   // Read raw data from DATE data stream. Returns bytes read (i.e.
724   // size), -1 in case of error and 0 for EOF.
725
726   raw.SetBuffer(data, size);
727   data += size;
728
729   return size;
730 }
731
732 //______________________________________________________________________________
733 void AliMDC::Stop()
734 {
735   // Stop the event loop
736  
737   fStop = kTRUE; 
738   if (fRawDB) fRawDB->Stop(); 
739 }
740
741
742 //______________________________________________________________________________
743 AliMDC::AliMDCInterruptHandler::AliMDCInterruptHandler(const 
744                                                        AliMDCInterruptHandler&
745                                                        handler): 
746   TSignalHandler(handler) 
747 {
748 // copy constructor
749
750   Fatal("AliMDCInterruptHandler", "copy constructor not implemented");
751 }
752
753 //______________________________________________________________________________
754 AliMDC::AliMDCInterruptHandler& 
755   AliMDC::AliMDCInterruptHandler::operator = (const AliMDCInterruptHandler& 
756                                               /*handler*/)
757 {
758 // assignment operator
759
760   Fatal("operator =", "assignment operator not implemented");
761   return *this;
762 }