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