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