]> git.uio.no Git - u/mrichter/AliRoot.git/blame - RAW/AliRawEvent.cxx
Bug in MUONTestTrigger
[u/mrichter/AliRoot.git] / RAW / AliRawEvent.cxx
CommitLineData
5ea08be4 1// @(#)alimdc:$Name$:$Id$
2// Author: Fons Rademakers 26/11/99
3// Updated: Dario Favretto 15/04/2003
4
5#include <sys/types.h>
6#include <sys/stat.h>
64ae962c 7#if defined(__DECCXX)
8#include <sys/statvfs.h>
9#else
5ea08be4 10#include <sys/vfs.h>
64ae962c 11#endif
5ea08be4 12#include <unistd.h>
13#include <stdlib.h>
14#include <fcntl.h>
15#include <errno.h>
16
17#include <TBuffer.h>
18#include <TH1.h>
19#include <TSystem.h>
20#include <TError.h>
21#include <TStopwatch.h>
22#include <TSQLServer.h>
23#include <TSQLResult.h>
24
25#include "AliRawEvent.h"
26
27// Good for Linux
28#define long32 int
29#include "DateEvent.h"
30
31#ifdef USE_EB
32#include "libDateEb.h"
33#endif
34
35
36ClassImp(AliRawEvent)
37ClassImp(AliRawEventHeader)
38ClassImp(AliRawEquipmentHeader)
39ClassImp(AliRawData)
40ClassImp(AliStats)
41ClassImp(AliRawDB)
42ClassImp(AliRawRFIODB)
43ClassImp(AliRawRootdDB)
44ClassImp(AliRawNullDB)
45ClassImp(AliTagDB)
46ClassImp(AliTagNullDB)
47ClassImp(AliRunDB)
48ClassImp(AliMDC)
49
50// Which MDC is this...
51const Int_t kMDC = 4;
52
53// Fixed file system locations for the different DB's
54#ifdef USE_RDM
55const char *kFifo = "/tmp/alimdc.fifo";
56const char *kRawDBFS[2] = { "/tmp/mdc1", "/tmp/mdc2" };
57const char *kTagDBFS = "/tmp/mdc1/tags";
58const char *kRunDBFS = "/tmp/mdc1/meta";
59const char *kRFIOFS = "rfio:/castor/cern.ch/user/r/rdm";
60const char *kRootdFS = "root://localhost//tmp/mdc1";
61#else
62const char *kFifo = "/tmp/alimdc.fifo";
63const char *kRawDBFS[2] = { "/scratch/mdc1", "/scratch/mdc2" };
64const char *kTagDBFS = "/scratch/mdc1/tags";
65const char *kRunDBFS = "/scratch/mdc1/meta";
66const char *kRFIOFS = "rfio:/castor/cern.ch/lcg/alicemdc4";
04fa961a 67const char *kRootdFS = "root://localhost//tmp/mdc1";
5ea08be4 68#endif
69
70// Maximum size of tag db files
71const Double_t kMaxTagFileSize = 2.5e8; // 250MB
72
73Bool_t AliMDC::fgDeleteFiles = kFALSE;
74
75AliMDC *gAliMDC = 0;
76
77
78//______________________________________________________________________________
79Bool_t AliRawEventHeader::DataIsSwapped() const
80{
81 // Returns true if event data is swapped.
82
83 if (TEST_SYSTEM_ATTRIBUTE(fTypeAttribute, ATTR_EVENT_SWAPPED))
84 return kTRUE;
85 return kFALSE;
86}
87
88//______________________________________________________________________________
89void AliRawEventHeader::Swap()
90{
91 // Swap header data.
92
93 if (IsSwapped()) {
94 fSize = net2host(fSize);
95 fMagic = net2host(fMagic);
96 fHeadLen = net2host(fHeadLen);
97 fVersion = net2host(fVersion);
98 fType = net2host(fType);
99 fRunNb = net2host(fRunNb);
100 for (int i = 0; i < kIdWords; i++)
101 fId[i] = net2host(fId[i]);
102 for (int i = 0; i < kTriggerWords; i++)
103 fTriggerPattern[i] = net2host(fTriggerPattern[i]);
104 for (int i = 0; i < kDetectorWords; i++)
105 fDetectorPattern[i] = net2host(fDetectorPattern[i]);
106 for (int i = 0; i < kAttributeWords; i++)
107 fTypeAttribute[i] = net2host(fTypeAttribute[i]);
108 fLDCId = net2host(fLDCId);
109 fGDCId = net2host(fGDCId);
110 }
111}
112
113//______________________________________________________________________________
114UInt_t AliRawEventHeader::GetEventInRun() const
115{
116 // Get event number in run. Correct for fixed target mode which is used
117 // in the Data Challenge Setup.
118
119 if (!TEST_SYSTEM_ATTRIBUTE(fTypeAttribute, ATTR_ORBIT_BC)) {
120 return EVENT_ID_GET_NB_IN_RUN(fId);
121 }
122 return 0;
123}
124
125//______________________________________________________________________________
126const char *AliRawEventHeader::GetTypeName() const
127{
128 // Get event type as a string.
129
130 switch (GetType()) {
131 case kStartOfRun:
132 return "START_OF_RUN";
133 break;
134 case kEndOfRun:
135 return "END_OF_RUN";
136 break;
137 case kStartOfRunFiles:
138 return "START_OF_RUN_FILES";
139 break;
140 case kEndOfRunFiles:
141 return "END_OF_RUN_FILES";
142 break;
143 case kStartOfBurst:
144 return "START_OF_BURST";
145 break;
146 case kEndOfBurst:
147 return "END_OF_BURST";
148 break;
149 case kPhysicsEvent:
150 return "PHYSICS_EVENT";
151 break;
152 case kCalibrationEvent:
153 return "CALIBRATION_EVENT";
154 break;
155 case kFormatError:
156 return "EVENT_FORMAT_ERROR";
157 break;
158 default:
159 return "*** UNKNOWN EVENT TYPE ***";
160 break;
161 }
162}
163
164
165//______________________________________________________________________________
166void AliRawEquipmentHeader::Swap()
167{
168 // Swap equipment header data. There is no way to see if the data
169 // has already been swapped. This method is only called when the
170 // header is read from the DATE event builder (GDC).
171
172 fSize = net2host(fSize);
173 fEquipmentType = net2host(fEquipmentType);
174 fEquipmentID = net2host(fEquipmentID);
175 fBasicElementSizeType = net2host(fBasicElementSizeType);
176 for (int i = 0; i < kAttributeWords; i++)
177 fTypeAttribute[i] = net2host(fTypeAttribute[i]);
178}
179
180
181//______________________________________________________________________________
182AliRawEvent::AliRawEvent()
183{
184 // Create ALICE event object. If ownData is kFALSE we will use a static
185 // raw data object, otherwise a private copy will be made.
186
187 fNSubEvents = 0;
188 fEvtHdr = new AliRawEventHeader;
189 fEqpHdr = 0;
190 fRawData = 0;
191 fSubEvents = 0;
192}
193
194//______________________________________________________________________________
195AliRawEquipmentHeader *AliRawEvent::GetEquipmentHeader()
196{
197 // Get equipment header part of AliRawEvent.
198
199 if (!fEqpHdr)
200 fEqpHdr = new AliRawEquipmentHeader;
201
202 return fEqpHdr;
203}
204
205//______________________________________________________________________________
206AliRawData *AliRawEvent::GetRawData()
207{
208 // Get raw data part of AliRawEvent.
209
210 if (!fRawData)
211 fRawData = new AliRawData;
212
213 return fRawData;
214}
215
216//______________________________________________________________________________
217AliRawEvent *AliRawEvent::NextSubEvent()
218{
219 // Returns next sub-event object.
220
221 if (!fSubEvents)
222 fSubEvents = new TObjArray(100); // arbitrary, probably enough to prevent resizing
223
224 if (fSubEvents->GetSize() <= fNSubEvents) {
225 fSubEvents->Expand(fNSubEvents+10);
226 Warning("NextSubEvent", "expanded fSubEvents by 10 to %d",
227 fSubEvents->GetSize());
228 }
229
230 AliRawEvent *ev;
231 if (!(ev = (AliRawEvent *)fSubEvents->At(fNSubEvents))) {
232 ev = new AliRawEvent;
233 fSubEvents->AddAt(ev, fNSubEvents);
234 }
235
236 fNSubEvents++;
237
238 return ev;
239}
240
04fa961a 241//______________________________________________________________________________
242AliRawEvent *AliRawEvent::GetSubEvent(Int_t index)
243{
244 return (AliRawEvent *)fSubEvents->At(index);
245}
246
5ea08be4 247//______________________________________________________________________________
248void AliRawEvent::Reset()
249{
250 // Reset the event in case it needs to be re-used (avoiding costly
251 // new/delete cycle). We reset the size marker for the AliRawData
252 // objects and the sub event counter.
253
254 for (int i = 0; i < fNSubEvents; i++) {
255 AliRawEvent *ev = (AliRawEvent *)fSubEvents->At(i);
256 ev->GetRawData()->SetSize(0);
257 }
258 fNSubEvents = 0;
259}
260
261//______________________________________________________________________________
262AliRawEvent::~AliRawEvent()
263{
264 // Clean up event object. Delete also, possible, private raw data.
265
266 delete fEvtHdr;
267 delete fEqpHdr;
268 delete fRawData;
269 if (fSubEvents)
270 fSubEvents->Delete();
271 delete fSubEvents;
272}
273
274//______________________________________________________________________________
275AliStats::AliStats(const char *filename, Int_t compmode, Bool_t filter)
276{
277 // Create statistics object.
278
279 fEvents = 0;
280 fFirstRun = 0;
281 fFirstEvent = 0;
282 fLastRun = 0;
283 fLastEvent = 0;
284 fChunk = -0.5;
285 fFileName = filename;
286 fCompMode = compmode;
287 fFilter = filter;
288 fRTHist = 0;
289}
290
291//______________________________________________________________________________
292AliStats::~AliStats()
293{
294 // Cleanup stats object.
295
296 delete fRTHist;
297}
298
299//______________________________________________________________________________
300AliStats &AliStats::operator=(const AliStats &rhs)
301{
302 // AliStats assignment operator.
303
304 if (this != &rhs) {
305 TObject::operator=(rhs);
306 fEvents = rhs.fEvents;
307 fFirstRun = rhs.fFirstRun;
308 fFirstEvent = rhs.fFirstEvent;
309 fLastRun = rhs.fLastRun;
310 fLastEvent = rhs.fLastEvent;
311 fBegin = rhs.fBegin;
312 fEnd = rhs.fEnd;
313 fFileName = rhs.fFileName;
314 fFileSize = rhs.fFileSize;
315 fCompFactor = rhs.fCompFactor;
316 fCompMode = rhs.fCompMode;
317 fFilter = rhs.fFilter;
318 fRTHist = rhs.fRTHist ? (TH1F*) rhs.fRTHist->Clone() : 0;
319 fChunk = rhs.fChunk;
320 }
321 return *this;
322}
323
324//______________________________________________________________________________
325void AliStats::Fill(Float_t time)
326{
327 // Fill histogram. This histogram shows the (hopefully constant) time
328 // it takes to fill the ROOT DB.
329 // Expects to be called 100 times for each file.
330
331 if (!fRTHist) {
332 fRTHist = new TH1F("rtime","Real-time to write data chunk", 100, 0, 100);
333 fRTHist->SetDirectory(0);
334 }
335
336 fRTHist->Fill(fChunk, time);
337 fChunk += 1.0;
338}
339
340//______________________________________________________________________________
341void AliStats::WriteToDB(AliRawDB *rawdb)
342{
343 // Write stats to raw DB, local run DB and global MySQL DB.
344
345 AliRawEventHeader &header = *rawdb->GetEvent()->GetHeader();
346
347 // Write stats into RawDB
348 TDirectory *ds = gDirectory;
349 rawdb->GetDB()->cd();
350 SetEvents(rawdb->GetEvents());
351 SetLastId(header.GetRunNumber(), header.GetEventInRun());
352 SetFileSize(rawdb->GetBytesWritten());
353 SetCompressionFactor(rawdb->GetCompressionFactor());
354 SetEndTime();
355 Write("stats");
356 ds->cd();
357
358 // Write stats also in the bookkeeping RunDB
359 AliRunDB *rundb = new AliRunDB;
360 rundb->Update(this);
361 rundb->UpdateRDBMS(this);
362 delete rundb;
363}
364
365//______________________________________________________________________________
366AliRawDB::AliRawDB(AliRawEvent *event, Double_t maxsize, Int_t compress,
367 Bool_t create)
368{
369 // Create a new raw DB containing at most maxsize bytes.
370
371 fEvent = event;
372 fMaxSize = maxsize;
373 fCompress = compress;
374
375 // Consistency check with DATE header file
376 if (fEvent->GetHeader()->HeaderSize() != EVENT_HEAD_BASE_SIZE) {
377 Error("AliRawDB", "inconsistency between DATE and AliRawEvent headers");
378 MakeZombie();
379 return;
380 }
381
382 if (create) {
383 if (!Create())
384 MakeZombie();
385 }
386}
387
388//______________________________________________________________________________
389Bool_t AliRawDB::FSHasSpace(const char *fs)
390{
391 // Check for at least fMaxSize bytes of free space on the file system.
392 // If the space is not available return kFALSE, kTRUE otherwise.
393
394 Long_t id, bsize, blocks, bfree;
395
396 if (gSystem->GetFsInfo(fs, &id, &bsize, &blocks, &bfree) == 1) {
397 Error("FSHasSpace", "could not stat file system %s", fs);
398 return kFALSE;
399 }
400
401 // Leave 5 percent of diskspace free
402 Double_t avail = Double_t(bfree) * 0.95;
403 if (avail*bsize > fMaxSize)
404 return kTRUE;
405
406 Warning("FSHasSpace", "no space on file system %s", fs);
407 return kFALSE;
408}
409
410//______________________________________________________________________________
411const char *AliRawDB::GetFileName()
412{
413 // Return filename based on hostname and date and time. This will make
414 // each file unique. Also makes sure (via FSHasSpace()) that there is
415 // enough space on the file system to store the file. Returns 0 in
416 // case of error or interrupt signal.
417
418 static TString fname;
419 static Bool_t fstoggle = kFALSE;
420
421 TString fs = fstoggle ? kRawDBFS[1] : kRawDBFS[0];
422 TDatime dt;
423
424 TString hostname = gSystem->HostName();
425 Int_t pos;
426 if ((pos = hostname.Index(".")) != kNPOS)
427 hostname.Remove(pos);
428
429 if (!FSHasSpace(fs)) {
430 while (1) {
431 fstoggle = !fstoggle;
432 fs = fstoggle ? kRawDBFS[1] : kRawDBFS[0];
433 if (FSHasSpace(fs)) break;
434 Info("GetFileName", "sleeping 30 seconds before retrying...");
435 gSystem->Sleep(30000); // sleep for 30 seconds
436 if (gAliMDC && gAliMDC->StopLoop())
437 return 0;
438 }
439 }
440
441 fname = fs + "/" + hostname + "_";
442 fname += dt.GetDate();
443 fname += "_";
444 fname += dt.GetTime();
445 fname += ".root";
446
447 fstoggle = !fstoggle;
448
449 return fname;
450}
451
452//______________________________________________________________________________
453Bool_t AliRawDB::Create()
454{
455 // Create a new raw DB.
456
457again:
458 const char *fname = GetFileName();
459 if (!fname) return kFALSE;
460
461 fRawDB = TFile::Open(fname, "RECREATE",
462 Form("ALICE MDC%d raw DB", kMDC), fCompress);
463 if (!fRawDB) {
464 Error("Create", "did not find right plugin to open file");
465 return kFALSE;
466 }
467 if (fRawDB->IsZombie()) {
468 if (fRawDB->GetErrno() == ENOSPC ||
469 fRawDB->GetErrno() == 1018 || // SECOMERR
470 fRawDB->GetErrno() == 1027) { // SESYSERR
471 fRawDB->ResetErrno();
472 delete fRawDB;
473 Warning("Create", "file is zombie, sleeping 10 seconds before retrying...");
474 gSystem->Sleep(10000); // sleep 10 seconds before retrying
475 goto again;
476 }
477 Error("Create", "error opening raw DB");
478 fRawDB = 0;
479 return kFALSE;
480 }
481
482 // Create raw data TTree
483 MakeTree();
484
485 return kTRUE;
486}
487
488//______________________________________________________________________________
489void AliRawDB::MakeTree()
490{
491 // Create ROOT Tree object container.
492
493 fTree = new TTree("RAW", Form("ALICE MDC%d raw data tree", kMDC));
494 fTree->SetAutoSave(2000000000); // autosave when 2 Gbyte written
495
496 Int_t bufsize = 256000;
497 // splitting 29.6 MB/s, no splitting 35.3 MB/s on P4 2GHz 15k SCSI
498 //Int_t split = 1;
499 Int_t split = 0;
500 fTree->Branch("rawevent", "AliRawEvent", &fEvent, bufsize, split);
501}
502
503//______________________________________________________________________________
504void AliRawDB::Close()
505{
506 // Close raw DB.
507
508 if (!fRawDB) return;
509
510 fRawDB->cd();
511
512 // Write the tree.
513 fTree->Write();
514
515 // Close DB, this also deletes the fTree
516 fRawDB->Close();
517
518 if (AliMDC::DeleteFiles()) {
519 gSystem->Unlink(fRawDB->GetName());
520 delete fRawDB;
521 fRawDB = 0;
522 return;
523 }
524
525 // Create semaphore to say this file is finished
526 Int_t tfd = ::creat(Form("%s.done", fRawDB->GetName()), 0644);
527 close(tfd);
528
529 delete fRawDB;
530 fRawDB = 0;
531}
532
533//______________________________________________________________________________
534Bool_t AliRawDB::NextFile()
535{
536 // Close te current file and open a new one.
537 // Returns kFALSE in case opening failed.
538
539 Close();
540
541 if (!Create()) return kFALSE;
542 return kTRUE;
543}
544
545//______________________________________________________________________________
546Float_t AliRawDB::GetCompressionFactor() const
547{
548 // Return compression factor.
549
550 if (fTree->GetZipBytes() == 0.)
551 return 1.0;
552 else
553 return fTree->GetTotBytes()/fTree->GetZipBytes();
554}
555
556
557//______________________________________________________________________________
558AliRawRFIODB::AliRawRFIODB(AliRawEvent *event, Double_t maxsize, Int_t compress)
559 : AliRawDB(event, maxsize, compress, kFALSE)
560{
561 // Create a new raw DB that will be accessed via RFIO.
562
563#ifndef USE_RDM
564 static int init = 0;
565 // Set STAGE_POOL environment variable to current host
566 if (!init) {
567 // THESE ENVIRONMENT SYMBOLS ARE NOW DEFINED BY THE ALICE DATE SETUP
568 // THEREFORE WE SHALL NOT USE ANY HARDCODED VALUES BUT RATHER USE
569 // WHATEVER HAS BEEN SET IN THE DATE SITE
570 //gSystem->Setenv("STAGE_POOL", "mdc4");
571 //gSystem->Setenv("STAGE_HOST", "lxshare003d");
572 init = 1;
573 }
574#endif
575
576 if (!Create())
577 MakeZombie();
578 else
579 fRawDB->UseCache(50, 0x200000); //0x100000 = 1MB)
580}
581
582//______________________________________________________________________________
583const char *AliRawRFIODB::GetFileName()
584{
585 // Return filename based on hostname and date and time. This will make
586 // each file unique. Also the directory will be made unique for each
587 // day by adding the date to the fs. Assumes there is always enough
588 // space on the device.
589
590 static TString fname;
591
592 TString fs = kRFIOFS;
593 TDatime dt;
594
595 // make a new subdirectory for each day
596 fs += "/adc-";
597 fs += dt.GetDate();
598
599 Long_t id, size, flags, time;
600 if (gSystem->GetPathInfo(fs, &id, &size, &flags, &time) == 1) {
601 // directory does not exist, create it
602 if (gSystem->mkdir(fs, kTRUE) == -1) {
603 Error("GetFileName", "cannot create dir %s, using %s", fs.Data(),
604 kRFIOFS);
605 fs = kRFIOFS;
606 }
607 }
608 // FIXME: should check if fs is a directory
609
610 TString hostname = gSystem->HostName();
611 Int_t pos;
612 if ((pos = hostname.Index(".")) != kNPOS)
613 hostname.Remove(pos);
614
615 fname = fs + "/" + hostname + "_";
616 fname += dt.GetDate();
617 fname += "_";
618 fname += dt.GetTime();
619 fname += ".root";
620
621 return fname;
622}
623
624//______________________________________________________________________________
625void AliRawRFIODB::Close()
626{
627 // Close raw RFIO DB.
628
629 if (!fRawDB) return;
630
631 fRawDB->cd();
632
633 // Write the tree.
634 fTree->Write();
635
636 // Close DB, this also deletes the fTree
637 fRawDB->Close();
638
639 if (AliMDC::DeleteFiles())
640 gSystem->Exec(Form("rfrm %s", fRawDB->GetName()));
641
642 delete fRawDB;
643 fRawDB = 0;
644}
645
646
647//______________________________________________________________________________
648AliRawRootdDB::AliRawRootdDB(AliRawEvent *event, Double_t maxsize, Int_t compress)
649 : AliRawDB(event, maxsize, compress, kFALSE)
650{
651 // Create a new raw DB that will be accessed via rootd daemon.
652
653 if (!Create())
654 MakeZombie();
655 else
656 fRawDB->UseCache(50, 0x200000); //0x100000 = 1MB)
657}
658
659//______________________________________________________________________________
660const char *AliRawRootdDB::GetFileName()
661{
662 // Return filename based on hostname and date and time. This will make
663 // each file unique. Also the directory will be made unique for each
664 // day by adding the date to the fs. Assumes there is always enough
665 // space on the device.
666
667 static TString fname;
668
669 TString fs = kRootdFS;
670 TDatime dt;
671
672#if 0
673 // make a new subdirectory for each day
674 fs += "/adc-";
675 fs += dt.GetDate();
676
677 Long_t id, size, flags, time;
678 if (gSystem->GetPathInfo(fs, &id, &size, &flags, &time) == 1) {
679 // directory does not exist, create it
680 if (gSystem->mkdir(fs, kTRUE) == -1) {
681 Error("GetFileName", "cannot create dir %s, using %s", fs.Data(),
682 kRootdFS);
683 fs = kRootdFS;
684 }
685 }
686 // FIXME: should check if fs is a directory
687#endif
688
689 TString hostname = gSystem->HostName();
690 Int_t pos;
691 if ((pos = hostname.Index(".")) != kNPOS)
692 hostname.Remove(pos);
693
694 fname = fs + "/" + hostname + "_";
695 fname += dt.GetDate();
696 fname += "_";
697 fname += dt.GetTime();
698 fname += ".root";
699
700 return fname;
701}
702
703//______________________________________________________________________________
704void AliRawRootdDB::Close()
705{
706 // Close raw rootd DB.
707
708 if (!fRawDB) return;
709
710 fRawDB->cd();
711
712 // Write the tree.
713 fTree->Write();
714
715 // Close DB, this also deletes the fTree
716 fRawDB->Close();
717
718#if 0
719 // can use services of TFTP
720 if (AliMDC::DeleteFiles())
721 gSystem->Exec(Form("rfrm %s", fRawDB->GetName()));
722#endif
723
724 delete fRawDB;
725 fRawDB = 0;
726}
727
728
729//______________________________________________________________________________
730AliRawNullDB::AliRawNullDB(AliRawEvent *event, Double_t maxsize, Int_t compress)
731 : AliRawDB(event, maxsize, compress, kFALSE)
732{
733 // Create a new raw DB that will wrtie to /dev/null.
734
735 if (!Create())
736 MakeZombie();
737}
738
739//______________________________________________________________________________
740const char *AliRawNullDB::GetFileName()
741{
742 // Return /dev/null as filename.
743
744 return "/dev/null";
745}
746
747//______________________________________________________________________________
748void AliRawNullDB::Close()
749{
750 // Close raw RFIO DB.
751
752 if (!fRawDB) return;
753
754 fRawDB->cd();
755
756 // Write the tree.
757 fTree->Write();
758
759 // Close DB, this also deletes the fTree
760 fRawDB->Close();
761
762 delete fRawDB;
763 fRawDB = 0;
764}
765
766
767//______________________________________________________________________________
768AliTagDB::AliTagDB(AliRawEventHeader *header, Double_t maxsize, Bool_t create)
769{
770 // Create tag DB.
771
772 fHeader = header;
773 fMaxSize = maxsize;
774
775 if (create) {
776 if (!Create())
777 MakeZombie();
778 }
779}
780
781//______________________________________________________________________________
782Bool_t AliTagDB::Create()
783{
784 // Create a new tag DB.
785
786 fTagDB = new TFile(GetFileName(), "RECREATE",
787 Form("ALICE MDC%d tag DB", kMDC), 1);
788 if (fTagDB->IsZombie()) {
789 Error("Create", "error opening tag DB");
790 fTagDB = 0;
791 return kFALSE;
792 }
793
794 // Create ROOT Tree object container
795 fTree = new TTree("TAG", Form("ALICE MDC%d header data tree", kMDC));
796 fTree->SetAutoSave(100000000); // autosave when 100 Mbyte written
797
798 Int_t bufsize = 32000;
799 Int_t split = 1;
800 fTree->Branch("header", "AliRawEventHeader", &fHeader, bufsize, split);
801
802 return kTRUE;
803}
804
805//______________________________________________________________________________
806void AliTagDB::Close()
807{
808 // Close tag DB.
809
810 if (!fTagDB) return;
811
812 fTagDB->cd();
813
814 // Write the tree.
815 fTree->Write();
816
817 // Close DB, this also deletes the fTree
818 fTagDB->Close();
819
820 if (AliMDC::DeleteFiles())
821 gSystem->Unlink(fTagDB->GetName());
822
823 delete fTagDB;
824 fTagDB = 0;
825}
826
827//______________________________________________________________________________
828Bool_t AliTagDB::NextFile()
829{
830 // Close te current file and open a new one.
831 // Returns kFALSE in case opening failed.
832
833 Close();
834
835 if (!Create()) return kFALSE;
836 return kTRUE;
837}
838
839//______________________________________________________________________________
840Float_t AliTagDB::GetCompressionFactor() const
841{
842 // Return compression factor.
843
844 if (fTree->GetZipBytes() == 0.)
845 return 1.0;
846 else
847 return fTree->GetTotBytes()/fTree->GetZipBytes();
848}
849
850//______________________________________________________________________________
851const char *AliTagDB::GetFileName()
852{
853 // Return filename based on hostname and date and time. This will make
854 // each file unique. The tags will be stored in the /data1/tags directory.
855
856 static char fname[64];
857 const char *fs = kTagDBFS;
858
859 // check that fs exists (crude check fails if fs is a file)
860 gSystem->MakeDirectory(fs);
861
862 char hostname[64];
863
864 strcpy(hostname, gSystem->HostName());
865
866 char *s;
867 if ((s = strchr(hostname, '.')))
868 *s = 0;
869
870 TDatime dt;
871
872 sprintf(fname, "%s/%s_%d_%d.root", fs, hostname, dt.GetDate(), dt.GetTime());
873
874 return fname;
875}
876
877
878//______________________________________________________________________________
879AliTagNullDB::AliTagNullDB(AliRawEventHeader *header, Double_t maxsize) :
880 AliTagDB(header, maxsize, kFALSE)
881{
882 // Create tag db writing to /dev/null.
883
884 if (!Create())
885 MakeZombie();
886}
887
888//______________________________________________________________________________
889const char *AliTagNullDB::GetFileName()
890{
891 // Return /dev/null as filename.
892
893 return "/dev/null";
894}
895
896//______________________________________________________________________________
897void AliTagNullDB::Close()
898{
899 // Close null tag DB.
900
901 if (!fTagDB) return;
902
903 fTagDB->cd();
904
905 // Write the tree.
906 fTree->Write();
907
908 // Close DB, this also deletes the fTree
909 fTagDB->Close();
910
911 delete fTagDB;
912 fTagDB = 0;
913}
914
915
916//______________________________________________________________________________
917AliRunDB::AliRunDB()
918{
919 // Open run database, and get or create tree.
920
921 // Get hostname
922 char hostname[64], filename[64];
923 const char *fs = kRunDBFS;
924
925 // check that fs exists (crude check fails if fs is a file)
926 gSystem->MakeDirectory(fs);
927
928 strcpy(hostname, gSystem->HostName());
929
930 char *s;
931 if ((s = strchr(hostname, '.')))
932 *s = 0;
933
934 sprintf(filename, "%s/%s_rundb.root", fs, hostname);
935
936 if (!gSystem->AccessPathName(filename, kFileExists))
937 fRunDB = new TFile(filename, "UPDATE");
938 else
939 fRunDB = new TFile(filename, "CREATE", Form("ALICE MDC%d Run DB", kMDC));
940}
941
942//______________________________________________________________________________
943void AliRunDB::Update(AliStats *stats)
944{
945 // Add stats object to database.
946
947 TDirectory *ds = gDirectory;
948 fRunDB->cd();
949
950 char sname[64];
cfe26801 951 char *s = (char*)strrchr(stats->GetFileName(), '/');
5ea08be4 952 if (s) {
953 s++;
954 strcpy(sname, s);
955 } else
956 strcpy(sname, stats->GetFileName());
957 s = strchr(sname, '.');
958 if (s) *s = 0;
959
960 stats->Write(sname);
961
962 ds->cd();
963}
964
965//______________________________________________________________________________
966void AliRunDB::UpdateRDBMS(AliStats *stats)
967{
968 // Add stats object to central MySQL DB.
969
970 char sql[4096];
971 char bt[25], et[25];
972
973 strcpy(bt, stats->GetBeginTime().AsSQLString());
974 strcpy(et, stats->GetEndTime().AsSQLString());
975
976 sprintf(sql, "INSERT INTO mdc%dcatalog VALUES (0, '%s', %d, "
977 "%d, %d, %d, %d, %d, %d, %.2f, '%s', '%s', '%s')", kMDC,
978 stats->GetFileName(), (int)stats->GetFileSize(), stats->GetEvents(),
979 stats->GetFirstRun(), stats->GetFirstEvent(), stats->GetLastRun(),
980 stats->GetLastEvent(), stats->GetCompressionMode(),
981 stats->GetCompressionFactor(), stats->GetFilterState() ? "on" : "off",
982 bt, et);
983
984 // open connection to MySQL server on pcsalo
985 TSQLServer *db = TSQLServer::Connect("mysql://pcsalo.cern.ch/mdc", "alice", "amdc");
986
987 if (!db || db->IsZombie()) {
988 Error("UpdateRDBMS", "failed to connect to MySQL server on pcsalo");
989 printf("%s\n", sql);
990 delete db;
991 return;
992 }
993
994 TSQLResult *res = db->Query(sql);
995
996 if (!res) {
997 Error("UpdateRDBMS", Form("insert into mdc%dcatalog failed", kMDC));
998 printf("%s\n", sql);
999 }
1000
1001 delete res;
1002 delete db;
1003}
1004
1005//______________________________________________________________________________
1006void AliRunDB::Close()
1007{
1008 // Close run database.
1009
1010 fRunDB->Close();
1011 delete fRunDB;
1012}
1013
1014//----------------- Use SIGUSR1 to interupt endless loop -----------------------
1015class AliMDCInterruptHandler : public TSignalHandler {
1016private:
1017 AliMDC *fMDC; // alimdc to signal
1018public:
1019 AliMDCInterruptHandler(AliMDC *mdc) : TSignalHandler(kSigUser1, kFALSE), fMDC(mdc) { }
1020 Bool_t Notify() { fMDC->SetStopLoop(); return kTRUE; }
1021};
1022
1023//______________________________________________________________________________
1024AliMDC::AliMDC(Int_t fd, Int_t compress, Double_t maxFileSize, Bool_t useFilter,
1025 Bool_t useRFIO, Bool_t useROOTD, Bool_t useDEVNULL,
1026 Bool_t useLoop, Bool_t delFiles)
1027{
1028 // Create MDC processor object.
1029
1030 fFd = fd;
1031 fCompress = compress;
1032 fMaxFileSize = maxFileSize;
1033 fUseFilter = useFilter;
1034 fUseRFIO = useRFIO;
1035 fUseRootd = useROOTD;
1036 fUseDevNull = useDEVNULL;
1037 fUseLoop = useLoop;
1038 fUseFifo = kFALSE;
1039 fUseEb = kFALSE;
1040 fStopLoop = kFALSE;
1041 fNumEvents = 0;
1042 fDebugLevel = 0;
1043 fgDeleteFiles = delFiles;
1044
1045 if (fFd == -1) {
1046#ifdef USE_EB
1047 if (!ebRegister()) {
1048 Error("AliMDC", "cannot register with the event builder (%s)",
1049 ebGetLastError());
1050 return;
1051 }
1052 fUseEb = kTRUE;
1053#else
1054 if ((mkfifo(kFifo, 0644) < 0) && (errno != EEXIST)) {
1055 Error("AliMDC", "cannot create fifo %s", kFifo);
1056 return;
1057 }
1058 if ((chmod(kFifo, 0666) == -1) && (errno != EPERM)) {
1059 Error("AliMDC", "cannot change permission of fifo %s", kFifo);
1060 return;
1061 }
1062 if ((fFd = open(kFifo, O_RDONLY)) == -1) {
1063 Error("AliMDC", "cannot open input file %s", kFifo);
1064 return;
1065 }
1066 fUseFifo = kTRUE;
1067#endif
1068 fUseLoop = kFALSE;
1069 }
1070
1071 printf("<AliMDC::AliMDC>: input = %s, rawdb size = %f, filter = %s, "
1072 "looping = %s, compression = %d, delete files = %s",
1073 fUseFifo ? "fifo" : (fUseEb ? "eb" : "file"), fMaxFileSize,
1074 fUseFilter ? "on" : "off", fUseLoop ? "yes" : "no", fCompress,
1075 fgDeleteFiles ? "yes" : "no");
1076 if (fUseRFIO)
1077 printf(", use RFIO\n");
1078 else if (fUseRootd)
1079 printf(", use rootd\n");
1080 else if (fUseDevNull)
1081 printf(", write raw data to /dev/null\n");
1082 else
1083 printf("\n");
1084
1085 // install SIGUSR1 handler to allow clean interrupts
1086 gSystem->AddSignalHandler(new AliMDCInterruptHandler(this));
1087
1088 gAliMDC = this;
1089}
1090
1091//______________________________________________________________________________
1092Int_t AliMDC::Run()
1093{
1094 // Run the MDC processor. Read from the input stream and only return
1095 // when the input gave and EOF or a fatal error occured. On success 0
1096 // is returned, 1 in case of a fatality.
1097
1098 TStopwatch timer;
1099 Int_t status;
1100
1101 // Make sure needed directories exist
1102 const char *dirs[4];
1103 dirs[0] = kRawDBFS[0];
1104 dirs[1] = kRawDBFS[1];
1105 dirs[2] = kTagDBFS;
1106 dirs[3] = kRunDBFS;
1107 for (int idir = 0; idir < 4; idir++) {
1108 gSystem->ResetErrno();
1109 gSystem->MakeDirectory(dirs[idir]);
1110 if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
1111 SysError("Run", "mkdir %s", dirs[idir]);
1112 return 1;
1113 }
1114 }
1115
1116 // Used for statistics
1117 timer.Start();
1118 Double_t told = 0, tnew = 0;
1119 Float_t chunkSize = fMaxFileSize/100, nextChunk = chunkSize;
1120
1121 // Event object used to store event data.
1122 AliRawEvent *event = new AliRawEvent;
1123
1124 // Create new raw DB.
1125 AliRawDB *rawdb;
1126 if (fUseRFIO)
1127 rawdb = new AliRawRFIODB(event, fMaxFileSize, fCompress);
1128 else if (fUseRootd)
1129 rawdb = new AliRawRootdDB(event, fMaxFileSize, fCompress);
1130 else if (fUseDevNull)
1131 rawdb = new AliRawNullDB(event, fMaxFileSize, fCompress);
1132 else
1133 rawdb = new AliRawDB(event, fMaxFileSize, fCompress);
1134
1135 if (rawdb->IsZombie()) return 1;
1136 printf("Filling raw DB %s\n", rawdb->GetDBName());
1137
1138 // Create new tag DB.
1139 AliTagDB *tagdb;
1140 if (fUseDevNull)
1141 tagdb = new AliTagNullDB(event->GetHeader(), kMaxTagFileSize);
1142 else
1143 tagdb = new AliTagDB(event->GetHeader(), kMaxTagFileSize);
1144 if (tagdb->IsZombie())
1145 tagdb = 0;
1146 else
1147 printf("Filling tag DB %s\n", tagdb->GetDBName());
1148
1149 // Create AliStats object
1150 AliStats *stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter);
1151
1152 // Shortcut for easy header access
1153 AliRawEventHeader &header = *event->GetHeader();
1154
1155 // Process input stream
1156#ifdef USE_EB
1157 while (!ebEor()) {
1158 struct iovec *ebvec;
1159 if ((ebvec = ebGetNextEvent()) == (void *)-1) {
1160 Error("Run", "error getting next event (%s)", ebGetLastError());
1161 break;
1162 }
1163 if (ebvec == 0) {
1164 // no event, sleep for 1 second and try again
1165 gSystem->Sleep(1000);
1166 continue;
1167 }
1168 char *ebdata = (char *) ebvec[0].iov_base;
1169#else
1170 while (1) {
1171 char *ebdata = 0;
1172#endif
1173
1174 // Read event header
1175 if ((status = ReadHeader(header, ebdata)) != header.HeaderSize()) {
1176 if (status == 0) {
1177 if (fUseLoop) {
1178#ifndef USE_EB
1179 ::lseek(fFd, 0, SEEK_SET);
1180#endif
1181 continue;
1182 }
1183 printf("<AliMDC::Run>: EOF, processed %d events\n", fNumEvents);
1184 break;
1185 }
1186 return 1;
1187 }
1188
1189 // If we were in looping mode stop directly after a SIGUSR1 signal
1190 if (StopLoop()) {
1191 Info("Run", "SIGUSR1, processed %d events", fNumEvents);
1192 break;
1193 }
1194
1195 // Check if event has any hard track flagged
1196 Bool_t callFilter = kFALSE;
1197 // This needs to be re-engineered for the next ADC...
1198 //if (fUseFilter && TEST_USER_ATTRIBUTE(header.GetTypeAttribute(), 0))
1199 // callFilter = kTRUE;
1200
1201 // Check event type and skip "Start of Run", "End of Run",
1202 // "Start of Run Files" and "End of Run Files"
1203 switch (header.GetType()) {
1204 case kStartOfRun:
1205 case kEndOfRun:
1206 case kStartOfRunFiles:
1207 case kEndOfRunFiles:
1208 {
1209 Int_t skip = header.GetEventSize() - header.HeaderSize();
1210#ifndef USE_EB
1211 ::lseek(fFd, skip, SEEK_CUR);
1212#endif
1213 ALIDEBUG(1)
1214 Info("Run", "Skipping %s (%d bytes)", header.GetTypeName(), skip);
1215 continue;
1216 }
1217 break;
1218 default:
1219 ALIDEBUG(1) {
1220 Int_t s = header.GetEventSize() - header.HeaderSize();
1221 Info("Run", "Processing %s (%d bytes)", header.GetTypeName(), s);
1222 }
1223 }
1224
1225 // Amount of data left to read for this event
1226 Int_t toRead = header.GetEventSize() - header.HeaderSize();
1227
1228 // If there is less data for this event than the next sub-event
1229 // header, something is wrong. Skip to next event...
1230 if (toRead < header.HeaderSize()) {
1231 if ((status = DumpEvent(toRead)) != toRead) {
1232 if (status == 0)
1233 break;
1234 return 1;
1235 }
1236 Error("Run", "discarding event %d (too little data for header)", fNumEvents);
1237 continue;
1238 }
1239
1240 // Loop over all sub-events... (LDCs)
1241 while (toRead > 0) {
1242 Int_t nsub = 1;
1243#ifdef USE_EB
1244 ebdata = (char *)ebvec[nsub].iov_base;
1245#endif
1246
1247 ALIDEBUG(1)
1248 Info("Run", "reading LDC %d", nsub);
1249
1250 AliRawEvent *subEvent = event->NextSubEvent();
1251
1252 // Read sub-event header
1253 AliRawEventHeader &subHeader = *subEvent->GetHeader();
1254 if ((status = ReadHeader(subHeader, ebdata)) != subHeader.HeaderSize()) {
1255 if (status == 0) {
1256 Error("Run", "unexpected EOF reading sub-event header");
1257 break;
1258 }
1259 return 1;
1260 }
1261
1262 toRead -= subHeader.HeaderSize();
1263
1264#ifdef USE_EB
1265 ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize();
1266#endif
1267
1268 Int_t rawSize = subHeader.GetEventSize() - subHeader.HeaderSize();
1269
1270 // Read Equipment Header (in case of physics or calibration event)
1271 if (header.GetType() == kPhysicsEvent ||
1272 header.GetType() == kCalibrationEvent) {
1273 AliRawEquipmentHeader &equipment = *subEvent->GetEquipmentHeader();
1274 Int_t equipHeaderSize = equipment.HeaderSize();
1275 if ((status = ReadEquipmentHeader(equipment, header.DataIsSwapped(),
1276 ebdata)) != equipHeaderSize) {
1277 if (status == 0) {
1278 Error("Run", "unexpected EOF reading equipment-header");
1279 break;
1280 }
1281 return 1;
1282 }
1283 toRead -= equipHeaderSize;
1284 rawSize -= equipHeaderSize;
1285#ifdef USE_EB
1286 ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize() +
1287 equipHeaderSize;
1288#endif
1289 }
1290
1291 // Make sure raw data less than left over bytes for current event
1292 if (rawSize > toRead) {
1293 if ((status = DumpEvent(toRead)) != toRead) {
1294 if (status == 0)
1295 break;
1296 return 1;
1297 }
1298 Error("Run", "discarding event %d (too much data)", fNumEvents);
1299 continue;
1300 }
1301
1302 // Read sub-event raw data
1303 AliRawData &subRaw = *subEvent->GetRawData();
1304 if ((status = ReadRawData(subRaw, rawSize, ebdata)) != rawSize) {
1305 if (status == 0) {
1306 Error("Run", "unexpected EOF reading sub-event raw data");
1307 break;
1308 }
1309 return 1;
1310 }
1311
1312 if (callFilter) {
1313 if (TEST_USER_ATTRIBUTE(subHeader.GetTypeAttribute(), 0))
1314 Filter(subRaw);
1315 else {
1316 // set size of all sectors without hard track flag to 0
1317 subRaw.SetSize(0);
1318 }
1319 }
1320
1321 toRead -= rawSize;
1322 nsub++;
1323 }
1324
1325 // Set stat info for first event of this file
1326 if (rawdb->GetEvents() == 0)
1327 stats->SetFirstId(header.GetRunNumber(), header.GetEventInRun());
1328
1329 // Store raw event in tree
1330 rawdb->Fill();
1331
1332 // Store header in tree
1333 if (tagdb) tagdb->Fill();
1334
1335 fNumEvents++;
1336
1337 if (!(fNumEvents%10))
1338 printf("Processed event %d (%d)\n", fNumEvents, rawdb->GetEvents());
1339
1340 // Filling time statistics
1341 if (rawdb->GetBytesWritten() > nextChunk) {
1342 tnew = timer.RealTime();
1343 stats->Fill(tnew-told);
1344 told = tnew;
1345 timer.Continue();
1346 nextChunk += chunkSize;
1347 }
1348
1349 // Check size of raw db. If bigger than maxFileSize, close file
1350 // and continue with new file.
1351 if (rawdb->FileFull()) {
1352
1353 printf("Written raw DB at a rate of %.1f MB/s\n",
1354 Float_t(fMaxFileSize / timer.RealTime() / 1000000.));
1355
1356 // Write stats object to raw db, run db and MySQL
1357 stats->WriteToDB(rawdb);
1358 delete stats;
1359
1360 if (!rawdb->NextFile()) return 1;
1361
1362 printf("Filling raw DB %s\n", rawdb->GetDBName());
1363 stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter);
1364
1365 timer.Start();
1366 told = 0, tnew = 0;
1367 nextChunk = chunkSize;
1368 }
1369
1370 // Check size of tag db
1371 if (tagdb->FileFull()) {
1372 if (!tagdb->NextFile())
1373 tagdb = 0;
1374 else
1375 printf("Filling tag DB %s\n", tagdb->GetDBName());
1376 }
1377
1378 // Make top event object ready for next event data
1379 //printf("Event %d has %d sub-events\n", fNumEvents, event->GetNSubEvents());
1380 event->Reset();
1381
1382#ifdef USE_EB
1383 if (!ebReleaseEvent(ebvec)) {
1384 Error("Run", "problem releasing event (%s)", ebGetLastError());
1385 break;
1386 }
1387#endif
1388 }
1389
1390 printf("Written raw DB at a rate of %.1f MB/s\n",
1391 Float_t(fMaxFileSize / timer.RealTime() / 1000000.));
1392
1393 // Write stats to raw db and run db and delete stats object
1394 stats->WriteToDB(rawdb);
1395 delete stats;
1396
1397 // Close the raw DB
1398 delete rawdb;
1399
1400 // Close the tag DB
1401 delete tagdb;
1402
1403 // Close input source
1404 close(fFd);
1405
1406#if 0
1407 // Cleanup fifo
1408 if (fUseFifo && ::unlink(kFifo) == -1) {
1409 SysError("Run", "unlink");
1410 return 1;
1411 }
1412#endif
1413
1414 return 0;
1415}
1416
1417//______________________________________________________________________________
1418Int_t AliMDC::Read(void *buffer, Int_t length)
1419{
1420 // Read exactly length bytes into buffer. Returns number of bytes
1421 // received, returns -1 in case of error and 0 for EOF.
1422
1423 errno = 0;
1424
1425 if (fFd < 0) return -1;
1426
1427 Int_t n, nrecv = 0;
1428 char *buf = (char *)buffer;
1429
1430 for (n = 0; n < length; n += nrecv) {
1431 if ((nrecv = read(fFd, buf+n, length-n)) <= 0) {
1432 if (nrecv == 0)
1433 break; // EOF
1434 if (errno != EINTR)
1435 SysError("Read", "read");
1436 return -1;
1437 }
1438 }
1439 return n;
1440}
1441
1442//______________________________________________________________________________
1443Int_t AliMDC::ReadHeader(AliRawEventHeader &header, void *eb)
1444{
1445 // Read header info from DATE data stream. Returns bytes read (i.e.
1446 // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
1447
1448 Int_t nrecv;
1449
1450 if (eb) {
1451 // read from event builder memory area
1452 memcpy(header.HeaderBegin(), eb, header.HeaderSize());
1453 nrecv = header.HeaderSize();
1454 } else {
1455 // read from fifo or file
1456 if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) !=
1457 header.HeaderSize()) {
1458 if (nrecv == 0)
1459 return 0;
1460 return -1;
1461 }
1462 }
1463
1464 // Swap header data if needed
1465 if (header.IsSwapped())
1466 header.Swap();
1467
1468 // Is header valid...
1469 if (!header.IsValid()) {
1470 Error("ReadHeader", "invalid header format");
1471 // try recovery... how?
1472 return -1;
1473 }
1474 if (header.GetEventSize() < (UInt_t)header.HeaderSize()) {
1475 Error("ReadHeader", "invalid header size");
1476 // try recovery... how?
1477 return -1;
1478 }
1479
1480 return nrecv;
1481}
1482
1483//______________________________________________________________________________
1484Int_t AliMDC::ReadEquipmentHeader(AliRawEquipmentHeader &header,
1485 Bool_t isSwapped, void *eb)
1486{
1487 // Read equipment header info from DATE data stream. Returns bytes read
1488 // (i.e. AliRawEquipmentHeader::HeaderSize()), -1 in case of error and
1489 // 0 for EOF. If isSwapped is kTRUE the event data is byte swapped
1490 // and we will swap the header to host format.
1491
1492 Int_t nrecv;
1493
1494 if (eb) {
1495 // read from event builder memory area
1496 memcpy(header.HeaderBegin(), eb, header.HeaderSize());
1497 nrecv = header.HeaderSize();
1498 } else {
1499 // read from fifo or file
1500 if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) !=
1501 header.HeaderSize()) {
1502 if (nrecv == 0)
1503 return 0;
1504 return -1;
1505 }
1506 }
1507
1508 // Swap equipment header data if needed
1509 if (isSwapped)
1510 header.Swap();
1511
1512 if (header.GetEquipmentSize() < (UInt_t)header.HeaderSize()) {
1513 Error("ReadEquipmentHeader", "invalid equipment header size");
1514 // try recovery... how?
1515 return -1;
1516 }
1517
1518 return nrecv;
1519}
1520
1521//______________________________________________________________________________
1522Int_t AliMDC::ReadRawData(AliRawData &raw, Int_t size, void *eb)
1523{
1524 // Read raw data from DATE data stream. Returns bytes read (i.e.
1525 // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
1526
1527 Int_t nrecv;
1528
1529 if (eb) {
1530 // read from event builder memory area
1531 raw.SetBuffer(eb, size);
1532 nrecv = size;
1533 } else {
1534 // read from fifo or file
1535 raw.SetSize(size);
1536 if ((nrecv = Read(raw.GetBuffer(), size)) != size) {
1537 if (nrecv == 0) {
1538 Error("ReadRawData", "unexpected EOF");
1539 return 0;
1540 }
1541 return -1;
1542 }
1543 }
1544
1545 return nrecv;
1546}
1547
1548//______________________________________________________________________________
1549Int_t AliMDC::DumpEvent(Int_t toRead)
1550{
1551 // This case should not happen, but if it does try to handle it
1552 // gracefully by reading the rest of the event and discarding it.
1553 // Returns bytes read, -1 in case of fatal error and 0 for EOF.
1554
1555 Error("DumpEvent", "dumping %d bytes of event %d", toRead, fNumEvents);
1556
1557 Int_t nrecv;
1558 char *tbuf = new char[toRead];
1559 if ((nrecv = Read(tbuf, toRead)) != toRead) {
1560 if (nrecv == 0) {
1561 Error("DumpEvent", "unexpected EOF");
1562 return 0;
1563 }
1564 return -1;
1565 }
1566 delete [] tbuf;
1567
1568 return nrecv;
1569}
1570
1571#ifdef USE_HLT
1572#include <AliTPCL3Tunnel.h>
1573#endif
1574
1575//______________________________________________________________________________
1576Int_t AliMDC::Filter(AliRawData &raw)
1577{
1578 // Call 3rd level filter for this raw data segment.
1579
1580#ifdef USE_HLT
1581 AliTPCL3Tunnel *tunnel = 0;
1582 if (!tunnel) {
1583 // initialisation
1584 tunnel = new AliTPCL3Tunnel(Form("%s/TPCparams.root",
1585 gSystem->Getenv("ALITPC")));
1586 }
1587
1588 Int_t obytes, nbytes;
1589 obytes = nbytes = raw.GetSize();
1590 char *outbuf = tunnel->EvalTrack((char *)raw.GetBuffer(), nbytes);
1591
1592 raw.SetSize(nbytes);
1593 memcpy(raw.GetBuffer(), outbuf, nbytes);
1594
1595 printf("Filter called for event %d: reduced from %d to %d\n", fNumEvents,
1596 obytes, nbytes);
1597
1598#else
1599
1600 raw.GetSize();
1601 printf("Filter called for event %d\n", fNumEvents);
1602
1603#endif
1604
1605 return 0;
1606}