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