Updates to RAW package. Used during the Computing DC.
[u/mrichter/AliRoot.git] / RAW / AliMDC.cxx
CommitLineData
a197a4ce 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
8c49c5a5 20/* $Id$ */
21
a197a4ce 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
8c49c5a5 46#include <sys/types.h>
47#include <sys/stat.h>
48
a197a4ce 49#include <errno.h>
50
51#include <TSystem.h>
e10815f1 52#include <TROOT.h>
a197a4ce 53#include <TStopwatch.h>
54
e10815f1 55#include <sys/uio.h>
a197a4ce 56#ifdef USE_EB
57#include "libDateEb.h"
58#endif
59
e10815f1 60#include <AliLog.h>
a109e73e 61#include <AliESD.h>
a109e73e 62
a197a4ce 63#include "AliRawEvent.h"
64#include "AliRawEventHeader.h"
94d918a7 65#include "AliRawEquipment.h"
a197a4ce 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"
b7d09bb3 75#include "AliRunDB.h"
e10815f1 76#include "AliFilter.h"
a197a4ce 77
78#include "AliMDC.h"
79
a197a4ce 80ClassImp(AliMDC)
81
82
e10815f1 83// Filter names
84const char* const AliMDC::fgkFilterName[kNFilters] = {"AliHoughFilter"};
a197a4ce 85
e10815f1 86//______________________________________________________________________________
87AliMDC::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 }
a197a4ce 125
e10815f1 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 }
a197a4ce 136
e10815f1 137 // install SIGUSR1 handler to allow clean interrupts
138 gSystem->AddSignalHandler(new AliMDCInterruptHandler(this));
a197a4ce 139
e10815f1 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;
a197a4ce 147 }
e10815f1 148 AliFilter* filter = (AliFilter*) filterClass->New();
149 if (!filter) {
150 Warning("AliMDC", "creation of filter %s failed", fgkFilterName[iFilter]);
151 continue;
a197a4ce 152 }
e10815f1 153 fFilters.Add(filter);
154 }
155 }
a197a4ce 156}
157
158//______________________________________________________________________________
e10815f1 159AliMDC::~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//______________________________________________________________________________
a197a4ce 173AliMDC::AliMDC(const AliMDC& mdc): TObject(mdc)
174{
175// copy constructor
176
177 Fatal("AliMDC", "copy constructor not implemented");
178}
179
180//______________________________________________________________________________
181AliMDC& AliMDC::operator = (const AliMDC& /*mdc*/)
182{
183// assignment operator
184
185 Fatal("operator =", "assignment operator not implemented");
186 return *this;
187}
188
e10815f1 189
a197a4ce 190//______________________________________________________________________________
e10815f1 191Int_t AliMDC::Open(EWriteMode mode, const char* fileName)
a197a4ce 192{
e10815f1 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;
f07ec911 210 return -1;
e10815f1 211 }
212 Info("Open", "Filling raw DB %s\n", fRawDB->GetDBName());
a197a4ce 213
e10815f1 214 // Create AliStats object
215 fStats = new AliStats(fRawDB->GetDBName(), fCompress,
216 fFilterMode != kFilterOff);
217 return 0;
218}
a109e73e 219
e10815f1 220//______________________________________________________________________________
221Int_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
d21e9888 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 }
e10815f1 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 }
a197a4ce 249
e10815f1 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 }
a197a4ce 269
e10815f1 270 // Amount of data left to read for this event
271 Int_t toRead = size;
a197a4ce 272
e10815f1 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;
a197a4ce 335
a197a4ce 336 }
a197a4ce 337
e10815f1 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;
a197a4ce 343 }
e10815f1 344 toRead -= rawSize;
a197a4ce 345
e10815f1 346 }
a197a4ce 347
e10815f1 348 nsub++;
349 }
a197a4ce 350
e10815f1 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;
a197a4ce 360 }
e10815f1 361 if ((fFilterMode == kFilterOn) && !result) return kFilterReject;
362 }
363 }
a197a4ce 364
e10815f1 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();
a197a4ce 371
e10815f1 372 // Store header in tree
373 if (fTagDB) fTagDB->Fill();
a197a4ce 374
37f78e68 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
f07ec911 380 if(nBytes >= 0)
381 return nBytes;
382 else
383 return kErrWriting;
e10815f1 384}
385
386//______________________________________________________________________________
d21e9888 387Int_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//______________________________________________________________________________
e10815f1 397Int_t AliMDC::Close()
398{
399// close the current raw DB file
400
f07ec911 401 if (!fRawDB) return -1;
e10815f1 402
403 fRawDB->WriteStats(fStats);
404 fRunDB->Update(fStats);
f07ec911 405 Int_t filesize = fRawDB->Close();
e10815f1 406 delete fRawDB;
407 fRawDB = NULL;
408 delete fStats;
409 fStats = NULL;
f07ec911 410 return filesize;
e10815f1 411}
a197a4ce 412
e10815f1 413//______________________________________________________________________________
414Int_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 }
a197a4ce 443
e10815f1 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());
a197a4ce 474
e10815f1 475 // Create AliStats object
476 fStats = new AliStats(fRawDB->GetDBName(), fCompress,
477 fFilterMode != kFilterOff);
a197a4ce 478
e10815f1 479 // Process input stream
a197a4ce 480#ifdef USE_EB
e10815f1 481 Int_t eorFlag = 0;
a197a4ce 482#endif
e10815f1 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 }
a197a4ce 494
e10815f1 495 if (!inputFile) { // get data from event builder
94d918a7 496#ifdef USE_EB
e10815f1 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;
94d918a7 514#endif
515
e10815f1 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 }
a197a4ce 534 }
e10815f1 535 if (eventSize < header.GetEventSize()) {
536 delete[] event;
537 eventSize = 2 * header.GetEventSize();
538 event = new char[eventSize];
a109e73e 539 }
e10815f1 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 }
a109e73e 549
e10815f1 550 Int_t result = ProcessEvent(event, !inputFile);
f07ec911 551 if(result < -1)
552 Error("Run", "error writing data. Error code: %d",result);
a197a4ce 553
e10815f1 554 if (result >= 0) {
555 numEvents++;
556 if (!(numEvents%10))
557 printf("Processed event %d (%d)\n", numEvents, fRawDB->GetEvents());
558 }
a197a4ce 559
e10815f1 560 if (result > 0) {
a197a4ce 561 // Filling time statistics
e10815f1 562 if (fRawDB->GetBytesWritten() > nextChunk) {
563 tnew = timer.RealTime();
564 fStats->Fill(tnew-told);
565 told = tnew;
566 timer.Continue();
567 nextChunk += chunkSize;
a197a4ce 568 }
569
570 // Check size of raw db. If bigger than maxFileSize, close file
571 // and continue with new file.
e10815f1 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;
a197a4ce 597 }
598
599 // Check size of tag db
e10815f1 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 }
a197a4ce 607 }
e10815f1 608 }
a197a4ce 609
e10815f1 610 // Make top event object ready for next event data
611 //printf("Event %d has %d sub-events\n", numEvents, fEvent->GetNSubEvents());
37f78e68 612 // fEvent->Reset();
e10815f1 613 // Clean up HLT ESD for the next event
37f78e68 614 // if (fESD) fESD->Reset();
e10815f1 615
616 if (!inputFile) {
a197a4ce 617#ifdef USE_EB
e10815f1 618 if (!ebReleaseEvent((iovec*)event)) {
619 Error("Run", "problem releasing event (%s)", ebGetLastError());
620 break;
a197a4ce 621 }
622#endif
e10815f1 623 }
624 }
a197a4ce 625
e10815f1 626 printf("Written raw DB at a rate of %.1f MB/s\n",
627 fRawDB->GetBytesWritten() / timer.RealTime() / 1000000.);
a197a4ce 628
e10815f1 629 // Write stats to raw db and run db and delete stats object
630 Close();
a197a4ce 631
e10815f1 632 if (!inputFile) {
a197a4ce 633#ifdef USE_EB
e10815f1 634 // Print eor flag
635 if (eorFlag) {
a197a4ce 636 Info("Run", "event builder reported end of run (%d)", eorFlag);
e10815f1 637 }
a197a4ce 638#endif
e10815f1 639 } else {
640 // Close input source
641 close(fd);
642 }
a197a4ce 643
e10815f1 644 return 0;
a197a4ce 645}
646
647//______________________________________________________________________________
e10815f1 648Int_t AliMDC::Read(Int_t fd, void *buffer, Int_t length)
a197a4ce 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
e10815f1 655 if (fd < 0) return -1;
a197a4ce 656
657 Int_t n, nrecv = 0;
658 char *buf = (char *)buffer;
659
660 for (n = 0; n < length; n += nrecv) {
e10815f1 661 if ((nrecv = read(fd, buf+n, length-n)) <= 0) {
a197a4ce 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//______________________________________________________________________________
e10815f1 673Int_t AliMDC::ReadHeader(AliRawEventHeader &header, char*& data)
a197a4ce 674{
e10815f1 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.
a197a4ce 677
e10815f1 678 memcpy(header.HeaderBegin(), data, header.HeaderSize());
679 data += header.HeaderSize();
a197a4ce 680
e10815f1 681 // Swap header data if needed
682 if (header.IsSwapped())
683 header.Swap();
a197a4ce 684
e10815f1 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();
a197a4ce 698}
699
700//______________________________________________________________________________
701Int_t AliMDC::ReadEquipmentHeader(AliRawEquipmentHeader &header,
e10815f1 702 Bool_t isSwapped, char*& data)
a197a4ce 703{
e10815f1 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 }
a197a4ce 721
e10815f1 722 return header.HeaderSize();
a197a4ce 723}
724
725//______________________________________________________________________________
e10815f1 726Int_t AliMDC::ReadRawData(AliRawData &raw, Int_t size, char*& data)
a197a4ce 727{
e10815f1 728 // Read raw data from DATE data stream. Returns bytes read (i.e.
729 // size), -1 in case of error and 0 for EOF.
a197a4ce 730
e10815f1 731 raw.SetBuffer(data, size);
732 data += size;
a197a4ce 733
e10815f1 734 return size;
a197a4ce 735}
736
737//______________________________________________________________________________
e10815f1 738void AliMDC::Stop()
a197a4ce 739{
e10815f1 740 // Stop the event loop
741
742 fStop = kTRUE;
743 if (fRawDB) fRawDB->Stop();
a197a4ce 744}
745
e10815f1 746
a197a4ce 747//______________________________________________________________________________
748AliMDC::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//______________________________________________________________________________
759AliMDC::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}