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