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