1 // @(#)alimdc:$Name$:$Id$
2 // Author: Fons Rademakers 26/11/99
3 // Updated: Dario Favretto 15/04/2003
17 #include <TStopwatch.h>
18 #include <TSQLServer.h>
19 #include <TSQLResult.h>
21 #include "AliRawEvent.h"
25 #include "DateEvent.h"
28 #include "libDateEb.h"
33 ClassImp(AliRawEventHeader)
34 ClassImp(AliRawEquipmentHeader)
38 ClassImp(AliRawRFIODB)
39 ClassImp(AliRawRootdDB)
40 ClassImp(AliRawNullDB)
42 ClassImp(AliTagNullDB)
46 // Which MDC is this...
49 // Fixed file system locations for the different DB's
51 const char *kFifo = "/tmp/alimdc.fifo";
52 const char *kRawDBFS[2] = { "/tmp/mdc1", "/tmp/mdc2" };
53 const char *kTagDBFS = "/tmp/mdc1/tags";
54 const char *kRunDBFS = "/tmp/mdc1/meta";
55 const char *kRFIOFS = "rfio:/castor/cern.ch/user/r/rdm";
56 const char *kRootdFS = "root://localhost//tmp/mdc1";
58 const char *kFifo = "/tmp/alimdc.fifo";
59 const char *kRawDBFS[2] = { "/scratch/mdc1", "/scratch/mdc2" };
60 const char *kTagDBFS = "/scratch/mdc1/tags";
61 const char *kRunDBFS = "/scratch/mdc1/meta";
62 const char *kRFIOFS = "rfio:/castor/cern.ch/lcg/alicemdc4";
65 // Maximum size of tag db files
66 const Double_t kMaxTagFileSize = 2.5e8; // 250MB
68 Bool_t AliMDC::fgDeleteFiles = kFALSE;
73 //______________________________________________________________________________
74 Bool_t AliRawEventHeader::DataIsSwapped() const
76 // Returns true if event data is swapped.
78 if (TEST_SYSTEM_ATTRIBUTE(fTypeAttribute, ATTR_EVENT_SWAPPED))
83 //______________________________________________________________________________
84 void AliRawEventHeader::Swap()
89 fSize = net2host(fSize);
90 fMagic = net2host(fMagic);
91 fHeadLen = net2host(fHeadLen);
92 fVersion = net2host(fVersion);
93 fType = net2host(fType);
94 fRunNb = net2host(fRunNb);
95 for (int i = 0; i < kIdWords; i++)
96 fId[i] = net2host(fId[i]);
97 for (int i = 0; i < kTriggerWords; i++)
98 fTriggerPattern[i] = net2host(fTriggerPattern[i]);
99 for (int i = 0; i < kDetectorWords; i++)
100 fDetectorPattern[i] = net2host(fDetectorPattern[i]);
101 for (int i = 0; i < kAttributeWords; i++)
102 fTypeAttribute[i] = net2host(fTypeAttribute[i]);
103 fLDCId = net2host(fLDCId);
104 fGDCId = net2host(fGDCId);
108 //______________________________________________________________________________
109 UInt_t AliRawEventHeader::GetEventInRun() const
111 // Get event number in run. Correct for fixed target mode which is used
112 // in the Data Challenge Setup.
114 if (!TEST_SYSTEM_ATTRIBUTE(fTypeAttribute, ATTR_ORBIT_BC)) {
115 return EVENT_ID_GET_NB_IN_RUN(fId);
120 //______________________________________________________________________________
121 const char *AliRawEventHeader::GetTypeName() const
123 // Get event type as a string.
127 return "START_OF_RUN";
132 case kStartOfRunFiles:
133 return "START_OF_RUN_FILES";
136 return "END_OF_RUN_FILES";
139 return "START_OF_BURST";
142 return "END_OF_BURST";
145 return "PHYSICS_EVENT";
147 case kCalibrationEvent:
148 return "CALIBRATION_EVENT";
151 return "EVENT_FORMAT_ERROR";
154 return "*** UNKNOWN EVENT TYPE ***";
160 //______________________________________________________________________________
161 void AliRawEquipmentHeader::Swap()
163 // Swap equipment header data. There is no way to see if the data
164 // has already been swapped. This method is only called when the
165 // header is read from the DATE event builder (GDC).
167 fSize = net2host(fSize);
168 fEquipmentType = net2host(fEquipmentType);
169 fEquipmentID = net2host(fEquipmentID);
170 fBasicElementSizeType = net2host(fBasicElementSizeType);
171 for (int i = 0; i < kAttributeWords; i++)
172 fTypeAttribute[i] = net2host(fTypeAttribute[i]);
176 //______________________________________________________________________________
177 AliRawEvent::AliRawEvent()
179 // Create ALICE event object. If ownData is kFALSE we will use a static
180 // raw data object, otherwise a private copy will be made.
183 fEvtHdr = new AliRawEventHeader;
189 //______________________________________________________________________________
190 AliRawEquipmentHeader *AliRawEvent::GetEquipmentHeader()
192 // Get equipment header part of AliRawEvent.
195 fEqpHdr = new AliRawEquipmentHeader;
200 //______________________________________________________________________________
201 AliRawData *AliRawEvent::GetRawData()
203 // Get raw data part of AliRawEvent.
206 fRawData = new AliRawData;
211 //______________________________________________________________________________
212 AliRawEvent *AliRawEvent::NextSubEvent()
214 // Returns next sub-event object.
217 fSubEvents = new TObjArray(100); // arbitrary, probably enough to prevent resizing
219 if (fSubEvents->GetSize() <= fNSubEvents) {
220 fSubEvents->Expand(fNSubEvents+10);
221 Warning("NextSubEvent", "expanded fSubEvents by 10 to %d",
222 fSubEvents->GetSize());
226 if (!(ev = (AliRawEvent *)fSubEvents->At(fNSubEvents))) {
227 ev = new AliRawEvent;
228 fSubEvents->AddAt(ev, fNSubEvents);
236 //______________________________________________________________________________
237 void AliRawEvent::Reset()
239 // Reset the event in case it needs to be re-used (avoiding costly
240 // new/delete cycle). We reset the size marker for the AliRawData
241 // objects and the sub event counter.
243 for (int i = 0; i < fNSubEvents; i++) {
244 AliRawEvent *ev = (AliRawEvent *)fSubEvents->At(i);
245 ev->GetRawData()->SetSize(0);
250 //______________________________________________________________________________
251 AliRawEvent::~AliRawEvent()
253 // Clean up event object. Delete also, possible, private raw data.
259 fSubEvents->Delete();
263 //______________________________________________________________________________
264 AliStats::AliStats(const char *filename, Int_t compmode, Bool_t filter)
266 // Create statistics object.
274 fFileName = filename;
275 fCompMode = compmode;
280 //______________________________________________________________________________
281 AliStats::~AliStats()
283 // Cleanup stats object.
288 //______________________________________________________________________________
289 AliStats &AliStats::operator=(const AliStats &rhs)
291 // AliStats assignment operator.
294 TObject::operator=(rhs);
295 fEvents = rhs.fEvents;
296 fFirstRun = rhs.fFirstRun;
297 fFirstEvent = rhs.fFirstEvent;
298 fLastRun = rhs.fLastRun;
299 fLastEvent = rhs.fLastEvent;
302 fFileName = rhs.fFileName;
303 fFileSize = rhs.fFileSize;
304 fCompFactor = rhs.fCompFactor;
305 fCompMode = rhs.fCompMode;
306 fFilter = rhs.fFilter;
307 fRTHist = rhs.fRTHist ? (TH1F*) rhs.fRTHist->Clone() : 0;
313 //______________________________________________________________________________
314 void AliStats::Fill(Float_t time)
316 // Fill histogram. This histogram shows the (hopefully constant) time
317 // it takes to fill the ROOT DB.
318 // Expects to be called 100 times for each file.
321 fRTHist = new TH1F("rtime","Real-time to write data chunk", 100, 0, 100);
322 fRTHist->SetDirectory(0);
325 fRTHist->Fill(fChunk, time);
329 //______________________________________________________________________________
330 void AliStats::WriteToDB(AliRawDB *rawdb)
332 // Write stats to raw DB, local run DB and global MySQL DB.
334 AliRawEventHeader &header = *rawdb->GetEvent()->GetHeader();
336 // Write stats into RawDB
337 TDirectory *ds = gDirectory;
338 rawdb->GetDB()->cd();
339 SetEvents(rawdb->GetEvents());
340 SetLastId(header.GetRunNumber(), header.GetEventInRun());
341 SetFileSize(rawdb->GetBytesWritten());
342 SetCompressionFactor(rawdb->GetCompressionFactor());
347 // Write stats also in the bookkeeping RunDB
348 AliRunDB *rundb = new AliRunDB;
350 rundb->UpdateRDBMS(this);
354 //______________________________________________________________________________
355 AliRawDB::AliRawDB(AliRawEvent *event, Double_t maxsize, Int_t compress,
358 // Create a new raw DB containing at most maxsize bytes.
362 fCompress = compress;
364 // Consistency check with DATE header file
365 if (fEvent->GetHeader()->HeaderSize() != EVENT_HEAD_BASE_SIZE) {
366 Error("AliRawDB", "inconsistency between DATE and AliRawEvent headers");
377 //______________________________________________________________________________
378 Bool_t AliRawDB::FSHasSpace(const char *fs)
380 // Check for at least fMaxSize bytes of free space on the file system.
381 // If the space is not available return kFALSE, kTRUE otherwise.
383 Long_t id, bsize, blocks, bfree;
385 if (gSystem->GetFsInfo(fs, &id, &bsize, &blocks, &bfree) == 1) {
386 Error("FSHasSpace", "could not stat file system %s", fs);
390 // Leave 5 percent of diskspace free
391 Double_t avail = Double_t(bfree) * 0.95;
392 if (avail*bsize > fMaxSize)
395 Warning("FSHasSpace", "no space on file system %s", fs);
399 //______________________________________________________________________________
400 const char *AliRawDB::GetFileName()
402 // Return filename based on hostname and date and time. This will make
403 // each file unique. Also makes sure (via FSHasSpace()) that there is
404 // enough space on the file system to store the file. Returns 0 in
405 // case of error or interrupt signal.
407 static TString fname;
408 static Bool_t fstoggle = kFALSE;
410 TString fs = fstoggle ? kRawDBFS[1] : kRawDBFS[0];
413 TString hostname = gSystem->HostName();
415 if ((pos = hostname.Index(".")) != kNPOS)
416 hostname.Remove(pos);
418 if (!FSHasSpace(fs)) {
420 fstoggle = !fstoggle;
421 fs = fstoggle ? kRawDBFS[1] : kRawDBFS[0];
422 if (FSHasSpace(fs)) break;
423 Info("GetFileName", "sleeping 30 seconds before retrying...");
424 gSystem->Sleep(30000); // sleep for 30 seconds
425 if (gAliMDC && gAliMDC->StopLoop())
430 fname = fs + "/" + hostname + "_";
431 fname += dt.GetDate();
433 fname += dt.GetTime();
436 fstoggle = !fstoggle;
441 //______________________________________________________________________________
442 Bool_t AliRawDB::Create()
444 // Create a new raw DB.
447 const char *fname = GetFileName();
448 if (!fname) return kFALSE;
450 fRawDB = TFile::Open(fname, "RECREATE",
451 Form("ALICE MDC%d raw DB", kMDC), fCompress);
453 Error("Create", "did not find right plugin to open file");
456 if (fRawDB->IsZombie()) {
457 if (fRawDB->GetErrno() == ENOSPC ||
458 fRawDB->GetErrno() == 1018 || // SECOMERR
459 fRawDB->GetErrno() == 1027) { // SESYSERR
460 fRawDB->ResetErrno();
462 Warning("Create", "file is zombie, sleeping 10 seconds before retrying...");
463 gSystem->Sleep(10000); // sleep 10 seconds before retrying
466 Error("Create", "error opening raw DB");
471 // Create raw data TTree
477 //______________________________________________________________________________
478 void AliRawDB::MakeTree()
480 // Create ROOT Tree object container.
482 fTree = new TTree("RAW", Form("ALICE MDC%d raw data tree", kMDC));
483 fTree->SetAutoSave(2000000000); // autosave when 2 Gbyte written
485 Int_t bufsize = 256000;
486 // splitting 29.6 MB/s, no splitting 35.3 MB/s on P4 2GHz 15k SCSI
489 fTree->Branch("rawevent", "AliRawEvent", &fEvent, bufsize, split);
492 //______________________________________________________________________________
493 void AliRawDB::Close()
504 // Close DB, this also deletes the fTree
507 if (AliMDC::DeleteFiles()) {
508 gSystem->Unlink(fRawDB->GetName());
514 // Create semaphore to say this file is finished
515 Int_t tfd = ::creat(Form("%s.done", fRawDB->GetName()), 0644);
522 //______________________________________________________________________________
523 Bool_t AliRawDB::NextFile()
525 // Close te current file and open a new one.
526 // Returns kFALSE in case opening failed.
530 if (!Create()) return kFALSE;
534 //______________________________________________________________________________
535 Float_t AliRawDB::GetCompressionFactor() const
537 // Return compression factor.
539 if (fTree->GetZipBytes() == 0.)
542 return fTree->GetTotBytes()/fTree->GetZipBytes();
546 //______________________________________________________________________________
547 AliRawRFIODB::AliRawRFIODB(AliRawEvent *event, Double_t maxsize, Int_t compress)
548 : AliRawDB(event, maxsize, compress, kFALSE)
550 // Create a new raw DB that will be accessed via RFIO.
554 // Set STAGE_POOL environment variable to current host
556 // THESE ENVIRONMENT SYMBOLS ARE NOW DEFINED BY THE ALICE DATE SETUP
557 // THEREFORE WE SHALL NOT USE ANY HARDCODED VALUES BUT RATHER USE
558 // WHATEVER HAS BEEN SET IN THE DATE SITE
559 //gSystem->Setenv("STAGE_POOL", "mdc4");
560 //gSystem->Setenv("STAGE_HOST", "lxshare003d");
568 fRawDB->UseCache(50, 0x200000); //0x100000 = 1MB)
571 //______________________________________________________________________________
572 const char *AliRawRFIODB::GetFileName()
574 // Return filename based on hostname and date and time. This will make
575 // each file unique. Also the directory will be made unique for each
576 // day by adding the date to the fs. Assumes there is always enough
577 // space on the device.
579 static TString fname;
581 TString fs = kRFIOFS;
584 // make a new subdirectory for each day
588 Long_t id, size, flags, time;
589 if (gSystem->GetPathInfo(fs, &id, &size, &flags, &time) == 1) {
590 // directory does not exist, create it
591 if (gSystem->mkdir(fs, kTRUE) == -1) {
592 Error("GetFileName", "cannot create dir %s, using %s", fs.Data(),
597 // FIXME: should check if fs is a directory
599 TString hostname = gSystem->HostName();
601 if ((pos = hostname.Index(".")) != kNPOS)
602 hostname.Remove(pos);
604 fname = fs + "/" + hostname + "_";
605 fname += dt.GetDate();
607 fname += dt.GetTime();
613 //______________________________________________________________________________
614 void AliRawRFIODB::Close()
616 // Close raw RFIO DB.
625 // Close DB, this also deletes the fTree
628 if (AliMDC::DeleteFiles())
629 gSystem->Exec(Form("rfrm %s", fRawDB->GetName()));
636 //______________________________________________________________________________
637 AliRawRootdDB::AliRawRootdDB(AliRawEvent *event, Double_t maxsize, Int_t compress)
638 : AliRawDB(event, maxsize, compress, kFALSE)
640 // Create a new raw DB that will be accessed via rootd daemon.
645 fRawDB->UseCache(50, 0x200000); //0x100000 = 1MB)
648 //______________________________________________________________________________
649 const char *AliRawRootdDB::GetFileName()
651 // Return filename based on hostname and date and time. This will make
652 // each file unique. Also the directory will be made unique for each
653 // day by adding the date to the fs. Assumes there is always enough
654 // space on the device.
656 static TString fname;
658 TString fs = kRootdFS;
662 // make a new subdirectory for each day
666 Long_t id, size, flags, time;
667 if (gSystem->GetPathInfo(fs, &id, &size, &flags, &time) == 1) {
668 // directory does not exist, create it
669 if (gSystem->mkdir(fs, kTRUE) == -1) {
670 Error("GetFileName", "cannot create dir %s, using %s", fs.Data(),
675 // FIXME: should check if fs is a directory
678 TString hostname = gSystem->HostName();
680 if ((pos = hostname.Index(".")) != kNPOS)
681 hostname.Remove(pos);
683 fname = fs + "/" + hostname + "_";
684 fname += dt.GetDate();
686 fname += dt.GetTime();
692 //______________________________________________________________________________
693 void AliRawRootdDB::Close()
695 // Close raw rootd DB.
704 // Close DB, this also deletes the fTree
708 // can use services of TFTP
709 if (AliMDC::DeleteFiles())
710 gSystem->Exec(Form("rfrm %s", fRawDB->GetName()));
718 //______________________________________________________________________________
719 AliRawNullDB::AliRawNullDB(AliRawEvent *event, Double_t maxsize, Int_t compress)
720 : AliRawDB(event, maxsize, compress, kFALSE)
722 // Create a new raw DB that will wrtie to /dev/null.
728 //______________________________________________________________________________
729 const char *AliRawNullDB::GetFileName()
731 // Return /dev/null as filename.
736 //______________________________________________________________________________
737 void AliRawNullDB::Close()
739 // Close raw RFIO DB.
748 // Close DB, this also deletes the fTree
756 //______________________________________________________________________________
757 AliTagDB::AliTagDB(AliRawEventHeader *header, Double_t maxsize, Bool_t create)
770 //______________________________________________________________________________
771 Bool_t AliTagDB::Create()
773 // Create a new tag DB.
775 fTagDB = new TFile(GetFileName(), "RECREATE",
776 Form("ALICE MDC%d tag DB", kMDC), 1);
777 if (fTagDB->IsZombie()) {
778 Error("Create", "error opening tag DB");
783 // Create ROOT Tree object container
784 fTree = new TTree("TAG", Form("ALICE MDC%d header data tree", kMDC));
785 fTree->SetAutoSave(100000000); // autosave when 100 Mbyte written
787 Int_t bufsize = 32000;
789 fTree->Branch("header", "AliRawEventHeader", &fHeader, bufsize, split);
794 //______________________________________________________________________________
795 void AliTagDB::Close()
806 // Close DB, this also deletes the fTree
809 if (AliMDC::DeleteFiles())
810 gSystem->Unlink(fTagDB->GetName());
816 //______________________________________________________________________________
817 Bool_t AliTagDB::NextFile()
819 // Close te current file and open a new one.
820 // Returns kFALSE in case opening failed.
824 if (!Create()) return kFALSE;
828 //______________________________________________________________________________
829 Float_t AliTagDB::GetCompressionFactor() const
831 // Return compression factor.
833 if (fTree->GetZipBytes() == 0.)
836 return fTree->GetTotBytes()/fTree->GetZipBytes();
839 //______________________________________________________________________________
840 const char *AliTagDB::GetFileName()
842 // Return filename based on hostname and date and time. This will make
843 // each file unique. The tags will be stored in the /data1/tags directory.
845 static char fname[64];
846 const char *fs = kTagDBFS;
848 // check that fs exists (crude check fails if fs is a file)
849 gSystem->MakeDirectory(fs);
853 strcpy(hostname, gSystem->HostName());
856 if ((s = strchr(hostname, '.')))
861 sprintf(fname, "%s/%s_%d_%d.root", fs, hostname, dt.GetDate(), dt.GetTime());
867 //______________________________________________________________________________
868 AliTagNullDB::AliTagNullDB(AliRawEventHeader *header, Double_t maxsize) :
869 AliTagDB(header, maxsize, kFALSE)
871 // Create tag db writing to /dev/null.
877 //______________________________________________________________________________
878 const char *AliTagNullDB::GetFileName()
880 // Return /dev/null as filename.
885 //______________________________________________________________________________
886 void AliTagNullDB::Close()
888 // Close null tag DB.
897 // Close DB, this also deletes the fTree
905 //______________________________________________________________________________
908 // Open run database, and get or create tree.
911 char hostname[64], filename[64];
912 const char *fs = kRunDBFS;
914 // check that fs exists (crude check fails if fs is a file)
915 gSystem->MakeDirectory(fs);
917 strcpy(hostname, gSystem->HostName());
920 if ((s = strchr(hostname, '.')))
923 sprintf(filename, "%s/%s_rundb.root", fs, hostname);
925 if (!gSystem->AccessPathName(filename, kFileExists))
926 fRunDB = new TFile(filename, "UPDATE");
928 fRunDB = new TFile(filename, "CREATE", Form("ALICE MDC%d Run DB", kMDC));
931 //______________________________________________________________________________
932 void AliRunDB::Update(AliStats *stats)
934 // Add stats object to database.
936 TDirectory *ds = gDirectory;
940 char *s = strrchr(stats->GetFileName(), '/');
945 strcpy(sname, stats->GetFileName());
946 s = strchr(sname, '.');
954 //______________________________________________________________________________
955 void AliRunDB::UpdateRDBMS(AliStats *stats)
957 // Add stats object to central MySQL DB.
962 strcpy(bt, stats->GetBeginTime().AsSQLString());
963 strcpy(et, stats->GetEndTime().AsSQLString());
965 sprintf(sql, "INSERT INTO mdc%dcatalog VALUES (0, '%s', %d, "
966 "%d, %d, %d, %d, %d, %d, %.2f, '%s', '%s', '%s')", kMDC,
967 stats->GetFileName(), (int)stats->GetFileSize(), stats->GetEvents(),
968 stats->GetFirstRun(), stats->GetFirstEvent(), stats->GetLastRun(),
969 stats->GetLastEvent(), stats->GetCompressionMode(),
970 stats->GetCompressionFactor(), stats->GetFilterState() ? "on" : "off",
973 // open connection to MySQL server on pcsalo
974 TSQLServer *db = TSQLServer::Connect("mysql://pcsalo.cern.ch/mdc", "alice", "amdc");
976 if (!db || db->IsZombie()) {
977 Error("UpdateRDBMS", "failed to connect to MySQL server on pcsalo");
983 TSQLResult *res = db->Query(sql);
986 Error("UpdateRDBMS", Form("insert into mdc%dcatalog failed", kMDC));
994 //______________________________________________________________________________
995 void AliRunDB::Close()
997 // Close run database.
1003 //----------------- Use SIGUSR1 to interupt endless loop -----------------------
1004 class AliMDCInterruptHandler : public TSignalHandler {
1006 AliMDC *fMDC; // alimdc to signal
1008 AliMDCInterruptHandler(AliMDC *mdc) : TSignalHandler(kSigUser1, kFALSE), fMDC(mdc) { }
1009 Bool_t Notify() { fMDC->SetStopLoop(); return kTRUE; }
1012 //______________________________________________________________________________
1013 AliMDC::AliMDC(Int_t fd, Int_t compress, Double_t maxFileSize, Bool_t useFilter,
1014 Bool_t useRFIO, Bool_t useROOTD, Bool_t useDEVNULL,
1015 Bool_t useLoop, Bool_t delFiles)
1017 // Create MDC processor object.
1020 fCompress = compress;
1021 fMaxFileSize = maxFileSize;
1022 fUseFilter = useFilter;
1024 fUseRootd = useROOTD;
1025 fUseDevNull = useDEVNULL;
1032 fgDeleteFiles = delFiles;
1036 if (!ebRegister()) {
1037 Error("AliMDC", "cannot register with the event builder (%s)",
1043 if ((mkfifo(kFifo, 0644) < 0) && (errno != EEXIST)) {
1044 Error("AliMDC", "cannot create fifo %s", kFifo);
1047 if ((chmod(kFifo, 0666) == -1) && (errno != EPERM)) {
1048 Error("AliMDC", "cannot change permission of fifo %s", kFifo);
1051 if ((fFd = open(kFifo, O_RDONLY)) == -1) {
1052 Error("AliMDC", "cannot open input file %s", kFifo);
1060 printf("<AliMDC::AliMDC>: input = %s, rawdb size = %f, filter = %s, "
1061 "looping = %s, compression = %d, delete files = %s",
1062 fUseFifo ? "fifo" : (fUseEb ? "eb" : "file"), fMaxFileSize,
1063 fUseFilter ? "on" : "off", fUseLoop ? "yes" : "no", fCompress,
1064 fgDeleteFiles ? "yes" : "no");
1066 printf(", use RFIO\n");
1068 printf(", use rootd\n");
1069 else if (fUseDevNull)
1070 printf(", write raw data to /dev/null\n");
1074 // install SIGUSR1 handler to allow clean interrupts
1075 gSystem->AddSignalHandler(new AliMDCInterruptHandler(this));
1080 //______________________________________________________________________________
1083 // Run the MDC processor. Read from the input stream and only return
1084 // when the input gave and EOF or a fatal error occured. On success 0
1085 // is returned, 1 in case of a fatality.
1090 // Make sure needed directories exist
1091 const char *dirs[4];
1092 dirs[0] = kRawDBFS[0];
1093 dirs[1] = kRawDBFS[1];
1096 for (int idir = 0; idir < 4; idir++) {
1097 gSystem->ResetErrno();
1098 gSystem->MakeDirectory(dirs[idir]);
1099 if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
1100 SysError("Run", "mkdir %s", dirs[idir]);
1105 // Used for statistics
1107 Double_t told = 0, tnew = 0;
1108 Float_t chunkSize = fMaxFileSize/100, nextChunk = chunkSize;
1110 // Event object used to store event data.
1111 AliRawEvent *event = new AliRawEvent;
1113 // Create new raw DB.
1116 rawdb = new AliRawRFIODB(event, fMaxFileSize, fCompress);
1118 rawdb = new AliRawRootdDB(event, fMaxFileSize, fCompress);
1119 else if (fUseDevNull)
1120 rawdb = new AliRawNullDB(event, fMaxFileSize, fCompress);
1122 rawdb = new AliRawDB(event, fMaxFileSize, fCompress);
1124 if (rawdb->IsZombie()) return 1;
1125 printf("Filling raw DB %s\n", rawdb->GetDBName());
1127 // Create new tag DB.
1130 tagdb = new AliTagNullDB(event->GetHeader(), kMaxTagFileSize);
1132 tagdb = new AliTagDB(event->GetHeader(), kMaxTagFileSize);
1133 if (tagdb->IsZombie())
1136 printf("Filling tag DB %s\n", tagdb->GetDBName());
1138 // Create AliStats object
1139 AliStats *stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter);
1141 // Shortcut for easy header access
1142 AliRawEventHeader &header = *event->GetHeader();
1144 // Process input stream
1147 struct iovec *ebvec;
1148 if ((ebvec = ebGetNextEvent()) == (void *)-1) {
1149 Error("Run", "error getting next event (%s)", ebGetLastError());
1153 // no event, sleep for 1 second and try again
1154 gSystem->Sleep(1000);
1157 char *ebdata = (char *) ebvec[0].iov_base;
1163 // Read event header
1164 if ((status = ReadHeader(header, ebdata)) != header.HeaderSize()) {
1168 ::lseek(fFd, 0, SEEK_SET);
1172 printf("<AliMDC::Run>: EOF, processed %d events\n", fNumEvents);
1178 // If we were in looping mode stop directly after a SIGUSR1 signal
1180 Info("Run", "SIGUSR1, processed %d events", fNumEvents);
1184 // Check if event has any hard track flagged
1185 Bool_t callFilter = kFALSE;
1186 // This needs to be re-engineered for the next ADC...
1187 //if (fUseFilter && TEST_USER_ATTRIBUTE(header.GetTypeAttribute(), 0))
1188 // callFilter = kTRUE;
1190 // Check event type and skip "Start of Run", "End of Run",
1191 // "Start of Run Files" and "End of Run Files"
1192 switch (header.GetType()) {
1195 case kStartOfRunFiles:
1196 case kEndOfRunFiles:
1198 Int_t skip = header.GetEventSize() - header.HeaderSize();
1200 ::lseek(fFd, skip, SEEK_CUR);
1203 Info("Run", "Skipping %s (%d bytes)", header.GetTypeName(), skip);
1209 Int_t s = header.GetEventSize() - header.HeaderSize();
1210 Info("Run", "Processing %s (%d bytes)", header.GetTypeName(), s);
1214 // Amount of data left to read for this event
1215 Int_t toRead = header.GetEventSize() - header.HeaderSize();
1217 // If there is less data for this event than the next sub-event
1218 // header, something is wrong. Skip to next event...
1219 if (toRead < header.HeaderSize()) {
1220 if ((status = DumpEvent(toRead)) != toRead) {
1225 Error("Run", "discarding event %d (too little data for header)", fNumEvents);
1229 // Loop over all sub-events... (LDCs)
1230 while (toRead > 0) {
1233 ebdata = (char *)ebvec[nsub].iov_base;
1237 Info("Run", "reading LDC %d", nsub);
1239 AliRawEvent *subEvent = event->NextSubEvent();
1241 // Read sub-event header
1242 AliRawEventHeader &subHeader = *subEvent->GetHeader();
1243 if ((status = ReadHeader(subHeader, ebdata)) != subHeader.HeaderSize()) {
1245 Error("Run", "unexpected EOF reading sub-event header");
1251 toRead -= subHeader.HeaderSize();
1254 ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize();
1257 Int_t rawSize = subHeader.GetEventSize() - subHeader.HeaderSize();
1259 // Read Equipment Header (in case of physics or calibration event)
1260 if (header.GetType() == kPhysicsEvent ||
1261 header.GetType() == kCalibrationEvent) {
1262 AliRawEquipmentHeader &equipment = *subEvent->GetEquipmentHeader();
1263 Int_t equipHeaderSize = equipment.HeaderSize();
1264 if ((status = ReadEquipmentHeader(equipment, header.DataIsSwapped(),
1265 ebdata)) != equipHeaderSize) {
1267 Error("Run", "unexpected EOF reading equipment-header");
1272 toRead -= equipHeaderSize;
1273 rawSize -= equipHeaderSize;
1275 ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize() +
1280 // Make sure raw data less than left over bytes for current event
1281 if (rawSize > toRead) {
1282 if ((status = DumpEvent(toRead)) != toRead) {
1287 Error("Run", "discarding event %d (too much data)", fNumEvents);
1291 // Read sub-event raw data
1292 AliRawData &subRaw = *subEvent->GetRawData();
1293 if ((status = ReadRawData(subRaw, rawSize, ebdata)) != rawSize) {
1295 Error("Run", "unexpected EOF reading sub-event raw data");
1302 if (TEST_USER_ATTRIBUTE(subHeader.GetTypeAttribute(), 0))
1305 // set size of all sectors without hard track flag to 0
1314 // Set stat info for first event of this file
1315 if (rawdb->GetEvents() == 0)
1316 stats->SetFirstId(header.GetRunNumber(), header.GetEventInRun());
1318 // Store raw event in tree
1321 // Store header in tree
1322 if (tagdb) tagdb->Fill();
1326 if (!(fNumEvents%10))
1327 printf("Processed event %d (%d)\n", fNumEvents, rawdb->GetEvents());
1329 // Filling time statistics
1330 if (rawdb->GetBytesWritten() > nextChunk) {
1331 tnew = timer.RealTime();
1332 stats->Fill(tnew-told);
1335 nextChunk += chunkSize;
1338 // Check size of raw db. If bigger than maxFileSize, close file
1339 // and continue with new file.
1340 if (rawdb->FileFull()) {
1342 printf("Written raw DB at a rate of %.1f MB/s\n",
1343 Float_t(fMaxFileSize / timer.RealTime() / 1000000.));
1345 // Write stats object to raw db, run db and MySQL
1346 stats->WriteToDB(rawdb);
1349 if (!rawdb->NextFile()) return 1;
1351 printf("Filling raw DB %s\n", rawdb->GetDBName());
1352 stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter);
1356 nextChunk = chunkSize;
1359 // Check size of tag db
1360 if (tagdb->FileFull()) {
1361 if (!tagdb->NextFile())
1364 printf("Filling tag DB %s\n", tagdb->GetDBName());
1367 // Make top event object ready for next event data
1368 //printf("Event %d has %d sub-events\n", fNumEvents, event->GetNSubEvents());
1372 if (!ebReleaseEvent(ebvec)) {
1373 Error("Run", "problem releasing event (%s)", ebGetLastError());
1379 printf("Written raw DB at a rate of %.1f MB/s\n",
1380 Float_t(fMaxFileSize / timer.RealTime() / 1000000.));
1382 // Write stats to raw db and run db and delete stats object
1383 stats->WriteToDB(rawdb);
1392 // Close input source
1397 if (fUseFifo && ::unlink(kFifo) == -1) {
1398 SysError("Run", "unlink");
1406 //______________________________________________________________________________
1407 Int_t AliMDC::Read(void *buffer, Int_t length)
1409 // Read exactly length bytes into buffer. Returns number of bytes
1410 // received, returns -1 in case of error and 0 for EOF.
1414 if (fFd < 0) return -1;
1417 char *buf = (char *)buffer;
1419 for (n = 0; n < length; n += nrecv) {
1420 if ((nrecv = read(fFd, buf+n, length-n)) <= 0) {
1424 SysError("Read", "read");
1431 //______________________________________________________________________________
1432 Int_t AliMDC::ReadHeader(AliRawEventHeader &header, void *eb)
1434 // Read header info from DATE data stream. Returns bytes read (i.e.
1435 // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
1440 // read from event builder memory area
1441 memcpy(header.HeaderBegin(), eb, header.HeaderSize());
1442 nrecv = header.HeaderSize();
1444 // read from fifo or file
1445 if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) !=
1446 header.HeaderSize()) {
1453 // Swap header data if needed
1454 if (header.IsSwapped())
1457 // Is header valid...
1458 if (!header.IsValid()) {
1459 Error("ReadHeader", "invalid header format");
1460 // try recovery... how?
1463 if (header.GetEventSize() < (UInt_t)header.HeaderSize()) {
1464 Error("ReadHeader", "invalid header size");
1465 // try recovery... how?
1472 //______________________________________________________________________________
1473 Int_t AliMDC::ReadEquipmentHeader(AliRawEquipmentHeader &header,
1474 Bool_t isSwapped, void *eb)
1476 // Read equipment header info from DATE data stream. Returns bytes read
1477 // (i.e. AliRawEquipmentHeader::HeaderSize()), -1 in case of error and
1478 // 0 for EOF. If isSwapped is kTRUE the event data is byte swapped
1479 // and we will swap the header to host format.
1484 // read from event builder memory area
1485 memcpy(header.HeaderBegin(), eb, header.HeaderSize());
1486 nrecv = header.HeaderSize();
1488 // read from fifo or file
1489 if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) !=
1490 header.HeaderSize()) {
1497 // Swap equipment header data if needed
1501 if (header.GetEquipmentSize() < (UInt_t)header.HeaderSize()) {
1502 Error("ReadEquipmentHeader", "invalid equipment header size");
1503 // try recovery... how?
1510 //______________________________________________________________________________
1511 Int_t AliMDC::ReadRawData(AliRawData &raw, Int_t size, void *eb)
1513 // Read raw data from DATE data stream. Returns bytes read (i.e.
1514 // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
1519 // read from event builder memory area
1520 raw.SetBuffer(eb, size);
1523 // read from fifo or file
1525 if ((nrecv = Read(raw.GetBuffer(), size)) != size) {
1527 Error("ReadRawData", "unexpected EOF");
1537 //______________________________________________________________________________
1538 Int_t AliMDC::DumpEvent(Int_t toRead)
1540 // This case should not happen, but if it does try to handle it
1541 // gracefully by reading the rest of the event and discarding it.
1542 // Returns bytes read, -1 in case of fatal error and 0 for EOF.
1544 Error("DumpEvent", "dumping %d bytes of event %d", toRead, fNumEvents);
1547 char *tbuf = new char[toRead];
1548 if ((nrecv = Read(tbuf, toRead)) != toRead) {
1550 Error("DumpEvent", "unexpected EOF");
1561 #include <AliTPCL3Tunnel.h>
1564 //______________________________________________________________________________
1565 Int_t AliMDC::Filter(AliRawData &raw)
1567 // Call 3rd level filter for this raw data segment.
1570 AliTPCL3Tunnel *tunnel = 0;
1573 tunnel = new AliTPCL3Tunnel(Form("%s/TPCparams.root",
1574 gSystem->Getenv("ALITPC")));
1577 Int_t obytes, nbytes;
1578 obytes = nbytes = raw.GetSize();
1579 char *outbuf = tunnel->EvalTrack((char *)raw.GetBuffer(), nbytes);
1581 raw.SetSize(nbytes);
1582 memcpy(raw.GetBuffer(), outbuf, nbytes);
1584 printf("Filter called for event %d: reduced from %d to %d\n", fNumEvents,
1590 printf("Filter called for event %d\n", fNumEvents);