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