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