From 5ea08be4f6cec433bf1e961ede83c04b4b92d441 Mon Sep 17 00:00:00 2001 From: rdm Date: Thu, 11 Sep 2003 14:57:05 +0000 Subject: [PATCH] AliRawEvent classes used in the data challenges and stand-alone alimdc program used to read from DATE and create ALICE RAW ROOT files. --- RAW/.cvsignore | 3 + RAW/AAREADME | 23 + RAW/AARUN | 4 + RAW/AliRawEvent.cxx | 1595 +++++++++++++++++++++++++++++++++++++++++++ RAW/AliRawEvent.h | 447 ++++++++++++ RAW/DateEvent.h | 377 ++++++++++ RAW/LinkDef.h | 23 + RAW/Make-macros | 96 +++ RAW/Makefile | 62 ++ RAW/alimdc.cxx | 175 +++++ 10 files changed, 2805 insertions(+) create mode 100644 RAW/.cvsignore create mode 100644 RAW/AAREADME create mode 100644 RAW/AARUN create mode 100644 RAW/AliRawEvent.cxx create mode 100644 RAW/AliRawEvent.h create mode 100644 RAW/DateEvent.h create mode 100644 RAW/LinkDef.h create mode 100644 RAW/Make-macros create mode 100644 RAW/Makefile create mode 100644 RAW/alimdc.cxx diff --git a/RAW/.cvsignore b/RAW/.cvsignore new file mode 100644 index 00000000000..12c5e030e8b --- /dev/null +++ b/RAW/.cvsignore @@ -0,0 +1,3 @@ +AliRawDict.cxx +AliRawDict.h +alimdc diff --git a/RAW/AAREADME b/RAW/AAREADME new file mode 100644 index 00000000000..94c45b91c83 --- /dev/null +++ b/RAW/AAREADME @@ -0,0 +1,23 @@ +Build alimdc using one of the following targets: + +depend # generate dependencies + +rdm # for local running uses /tmp/mdc1 and /tmp/mdc2 + # and rfio:/castor/cern.ch/user/r/rdm + + # for running in ADC environment but started by hand (not via + # SMI). Uses /pool/mdc and /tmp/mdc and + # rfio:/castor/cern.ch/alice/mdc4 + +smi # idem as above but for running under control of SMI/DIM. + +evb # access eventbuilder via shared memory segment + +debug # enable debug outout + + +typical use: + +make rdm # for local testing +make rdm debug # idem with some debug output +make evb smi # for running in data challenge under control of DATE diff --git a/RAW/AARUN b/RAW/AARUN new file mode 100644 index 00000000000..a2e73a30e4c --- /dev/null +++ b/RAW/AARUN @@ -0,0 +1,4 @@ +./alimdc 1000000000 0 -0 -datebig.raw # endless loop to RFIO +./alimdc 1000000000 0 +0 -datebig.raw # endless loop to rootd +./alimdc 1000000000 0 0 -datebig.raw # endless loop to local file in /tmp +./alimdc 1000000000 0 @0 -datebig.raw # endless loop to /dev/null diff --git a/RAW/AliRawEvent.cxx b/RAW/AliRawEvent.cxx new file mode 100644 index 00000000000..84cf5205f11 --- /dev/null +++ b/RAW/AliRawEvent.cxx @@ -0,0 +1,1595 @@ +// @(#)alimdc:$Name$:$Id$ +// Author: Fons Rademakers 26/11/99 +// Updated: Dario Favretto 15/04/2003 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "AliRawEvent.h" + +// Good for Linux +#define long32 int +#include "DateEvent.h" + +#ifdef USE_EB +#include "libDateEb.h" +#endif + + +ClassImp(AliRawEvent) +ClassImp(AliRawEventHeader) +ClassImp(AliRawEquipmentHeader) +ClassImp(AliRawData) +ClassImp(AliStats) +ClassImp(AliRawDB) +ClassImp(AliRawRFIODB) +ClassImp(AliRawRootdDB) +ClassImp(AliRawNullDB) +ClassImp(AliTagDB) +ClassImp(AliTagNullDB) +ClassImp(AliRunDB) +ClassImp(AliMDC) + +// Which MDC is this... +const Int_t kMDC = 4; + +// Fixed file system locations for the different DB's +#ifdef USE_RDM +const char *kFifo = "/tmp/alimdc.fifo"; +const char *kRawDBFS[2] = { "/tmp/mdc1", "/tmp/mdc2" }; +const char *kTagDBFS = "/tmp/mdc1/tags"; +const char *kRunDBFS = "/tmp/mdc1/meta"; +const char *kRFIOFS = "rfio:/castor/cern.ch/user/r/rdm"; +const char *kRootdFS = "root://localhost//tmp/mdc1"; +#else +const char *kFifo = "/tmp/alimdc.fifo"; +const char *kRawDBFS[2] = { "/scratch/mdc1", "/scratch/mdc2" }; +const char *kTagDBFS = "/scratch/mdc1/tags"; +const char *kRunDBFS = "/scratch/mdc1/meta"; +const char *kRFIOFS = "rfio:/castor/cern.ch/lcg/alicemdc4"; +#endif + +// Maximum size of tag db files +const Double_t kMaxTagFileSize = 2.5e8; // 250MB + +Bool_t AliMDC::fgDeleteFiles = kFALSE; + +AliMDC *gAliMDC = 0; + + +//______________________________________________________________________________ +Bool_t AliRawEventHeader::DataIsSwapped() const +{ + // Returns true if event data is swapped. + + if (TEST_SYSTEM_ATTRIBUTE(fTypeAttribute, ATTR_EVENT_SWAPPED)) + return kTRUE; + return kFALSE; +} + +//______________________________________________________________________________ +void AliRawEventHeader::Swap() +{ + // Swap header data. + + if (IsSwapped()) { + fSize = net2host(fSize); + fMagic = net2host(fMagic); + fHeadLen = net2host(fHeadLen); + fVersion = net2host(fVersion); + fType = net2host(fType); + fRunNb = net2host(fRunNb); + for (int i = 0; i < kIdWords; i++) + fId[i] = net2host(fId[i]); + for (int i = 0; i < kTriggerWords; i++) + fTriggerPattern[i] = net2host(fTriggerPattern[i]); + for (int i = 0; i < kDetectorWords; i++) + fDetectorPattern[i] = net2host(fDetectorPattern[i]); + for (int i = 0; i < kAttributeWords; i++) + fTypeAttribute[i] = net2host(fTypeAttribute[i]); + fLDCId = net2host(fLDCId); + fGDCId = net2host(fGDCId); + } +} + +//______________________________________________________________________________ +UInt_t AliRawEventHeader::GetEventInRun() const +{ + // Get event number in run. Correct for fixed target mode which is used + // in the Data Challenge Setup. + + if (!TEST_SYSTEM_ATTRIBUTE(fTypeAttribute, ATTR_ORBIT_BC)) { + return EVENT_ID_GET_NB_IN_RUN(fId); + } + return 0; +} + +//______________________________________________________________________________ +const char *AliRawEventHeader::GetTypeName() const +{ + // Get event type as a string. + + switch (GetType()) { + case kStartOfRun: + return "START_OF_RUN"; + break; + case kEndOfRun: + return "END_OF_RUN"; + break; + case kStartOfRunFiles: + return "START_OF_RUN_FILES"; + break; + case kEndOfRunFiles: + return "END_OF_RUN_FILES"; + break; + case kStartOfBurst: + return "START_OF_BURST"; + break; + case kEndOfBurst: + return "END_OF_BURST"; + break; + case kPhysicsEvent: + return "PHYSICS_EVENT"; + break; + case kCalibrationEvent: + return "CALIBRATION_EVENT"; + break; + case kFormatError: + return "EVENT_FORMAT_ERROR"; + break; + default: + return "*** UNKNOWN EVENT TYPE ***"; + break; + } +} + + +//______________________________________________________________________________ +void AliRawEquipmentHeader::Swap() +{ + // Swap equipment header data. There is no way to see if the data + // has already been swapped. This method is only called when the + // header is read from the DATE event builder (GDC). + + fSize = net2host(fSize); + fEquipmentType = net2host(fEquipmentType); + fEquipmentID = net2host(fEquipmentID); + fBasicElementSizeType = net2host(fBasicElementSizeType); + for (int i = 0; i < kAttributeWords; i++) + fTypeAttribute[i] = net2host(fTypeAttribute[i]); +} + + +//______________________________________________________________________________ +AliRawEvent::AliRawEvent() +{ + // Create ALICE event object. If ownData is kFALSE we will use a static + // raw data object, otherwise a private copy will be made. + + fNSubEvents = 0; + fEvtHdr = new AliRawEventHeader; + fEqpHdr = 0; + fRawData = 0; + fSubEvents = 0; +} + +//______________________________________________________________________________ +AliRawEquipmentHeader *AliRawEvent::GetEquipmentHeader() +{ + // Get equipment header part of AliRawEvent. + + if (!fEqpHdr) + fEqpHdr = new AliRawEquipmentHeader; + + return fEqpHdr; +} + +//______________________________________________________________________________ +AliRawData *AliRawEvent::GetRawData() +{ + // Get raw data part of AliRawEvent. + + if (!fRawData) + fRawData = new AliRawData; + + return fRawData; +} + +//______________________________________________________________________________ +AliRawEvent *AliRawEvent::NextSubEvent() +{ + // Returns next sub-event object. + + if (!fSubEvents) + fSubEvents = new TObjArray(100); // arbitrary, probably enough to prevent resizing + + if (fSubEvents->GetSize() <= fNSubEvents) { + fSubEvents->Expand(fNSubEvents+10); + Warning("NextSubEvent", "expanded fSubEvents by 10 to %d", + fSubEvents->GetSize()); + } + + AliRawEvent *ev; + if (!(ev = (AliRawEvent *)fSubEvents->At(fNSubEvents))) { + ev = new AliRawEvent; + fSubEvents->AddAt(ev, fNSubEvents); + } + + fNSubEvents++; + + return ev; +} + +//______________________________________________________________________________ +void AliRawEvent::Reset() +{ + // Reset the event in case it needs to be re-used (avoiding costly + // new/delete cycle). We reset the size marker for the AliRawData + // objects and the sub event counter. + + for (int i = 0; i < fNSubEvents; i++) { + AliRawEvent *ev = (AliRawEvent *)fSubEvents->At(i); + ev->GetRawData()->SetSize(0); + } + fNSubEvents = 0; +} + +//______________________________________________________________________________ +AliRawEvent::~AliRawEvent() +{ + // Clean up event object. Delete also, possible, private raw data. + + delete fEvtHdr; + delete fEqpHdr; + delete fRawData; + if (fSubEvents) + fSubEvents->Delete(); + delete fSubEvents; +} + +//______________________________________________________________________________ +AliStats::AliStats(const char *filename, Int_t compmode, Bool_t filter) +{ + // Create statistics object. + + fEvents = 0; + fFirstRun = 0; + fFirstEvent = 0; + fLastRun = 0; + fLastEvent = 0; + fChunk = -0.5; + fFileName = filename; + fCompMode = compmode; + fFilter = filter; + fRTHist = 0; +} + +//______________________________________________________________________________ +AliStats::~AliStats() +{ + // Cleanup stats object. + + delete fRTHist; +} + +//______________________________________________________________________________ +AliStats &AliStats::operator=(const AliStats &rhs) +{ + // AliStats assignment operator. + + if (this != &rhs) { + TObject::operator=(rhs); + fEvents = rhs.fEvents; + fFirstRun = rhs.fFirstRun; + fFirstEvent = rhs.fFirstEvent; + fLastRun = rhs.fLastRun; + fLastEvent = rhs.fLastEvent; + fBegin = rhs.fBegin; + fEnd = rhs.fEnd; + fFileName = rhs.fFileName; + fFileSize = rhs.fFileSize; + fCompFactor = rhs.fCompFactor; + fCompMode = rhs.fCompMode; + fFilter = rhs.fFilter; + fRTHist = rhs.fRTHist ? (TH1F*) rhs.fRTHist->Clone() : 0; + fChunk = rhs.fChunk; + } + return *this; +} + +//______________________________________________________________________________ +void AliStats::Fill(Float_t time) +{ + // Fill histogram. This histogram shows the (hopefully constant) time + // it takes to fill the ROOT DB. + // Expects to be called 100 times for each file. + + if (!fRTHist) { + fRTHist = new TH1F("rtime","Real-time to write data chunk", 100, 0, 100); + fRTHist->SetDirectory(0); + } + + fRTHist->Fill(fChunk, time); + fChunk += 1.0; +} + +//______________________________________________________________________________ +void AliStats::WriteToDB(AliRawDB *rawdb) +{ + // Write stats to raw DB, local run DB and global MySQL DB. + + AliRawEventHeader &header = *rawdb->GetEvent()->GetHeader(); + + // Write stats into RawDB + TDirectory *ds = gDirectory; + rawdb->GetDB()->cd(); + SetEvents(rawdb->GetEvents()); + SetLastId(header.GetRunNumber(), header.GetEventInRun()); + SetFileSize(rawdb->GetBytesWritten()); + SetCompressionFactor(rawdb->GetCompressionFactor()); + SetEndTime(); + Write("stats"); + ds->cd(); + + // Write stats also in the bookkeeping RunDB + AliRunDB *rundb = new AliRunDB; + rundb->Update(this); + rundb->UpdateRDBMS(this); + delete rundb; +} + +//______________________________________________________________________________ +AliRawDB::AliRawDB(AliRawEvent *event, Double_t maxsize, Int_t compress, + Bool_t create) +{ + // Create a new raw DB containing at most maxsize bytes. + + fEvent = event; + fMaxSize = maxsize; + fCompress = compress; + + // Consistency check with DATE header file + if (fEvent->GetHeader()->HeaderSize() != EVENT_HEAD_BASE_SIZE) { + Error("AliRawDB", "inconsistency between DATE and AliRawEvent headers"); + MakeZombie(); + return; + } + + if (create) { + if (!Create()) + MakeZombie(); + } +} + +//______________________________________________________________________________ +Bool_t AliRawDB::FSHasSpace(const char *fs) +{ + // Check for at least fMaxSize bytes of free space on the file system. + // If the space is not available return kFALSE, kTRUE otherwise. + + Long_t id, bsize, blocks, bfree; + + if (gSystem->GetFsInfo(fs, &id, &bsize, &blocks, &bfree) == 1) { + Error("FSHasSpace", "could not stat file system %s", fs); + return kFALSE; + } + + // Leave 5 percent of diskspace free + Double_t avail = Double_t(bfree) * 0.95; + if (avail*bsize > fMaxSize) + return kTRUE; + + Warning("FSHasSpace", "no space on file system %s", fs); + return kFALSE; +} + +//______________________________________________________________________________ +const char *AliRawDB::GetFileName() +{ + // Return filename based on hostname and date and time. This will make + // each file unique. Also makes sure (via FSHasSpace()) that there is + // enough space on the file system to store the file. Returns 0 in + // case of error or interrupt signal. + + static TString fname; + static Bool_t fstoggle = kFALSE; + + TString fs = fstoggle ? kRawDBFS[1] : kRawDBFS[0]; + TDatime dt; + + TString hostname = gSystem->HostName(); + Int_t pos; + if ((pos = hostname.Index(".")) != kNPOS) + hostname.Remove(pos); + + if (!FSHasSpace(fs)) { + while (1) { + fstoggle = !fstoggle; + fs = fstoggle ? kRawDBFS[1] : kRawDBFS[0]; + if (FSHasSpace(fs)) break; + Info("GetFileName", "sleeping 30 seconds before retrying..."); + gSystem->Sleep(30000); // sleep for 30 seconds + if (gAliMDC && gAliMDC->StopLoop()) + return 0; + } + } + + fname = fs + "/" + hostname + "_"; + fname += dt.GetDate(); + fname += "_"; + fname += dt.GetTime(); + fname += ".root"; + + fstoggle = !fstoggle; + + return fname; +} + +//______________________________________________________________________________ +Bool_t AliRawDB::Create() +{ + // Create a new raw DB. + +again: + const char *fname = GetFileName(); + if (!fname) return kFALSE; + + fRawDB = TFile::Open(fname, "RECREATE", + Form("ALICE MDC%d raw DB", kMDC), fCompress); + if (!fRawDB) { + Error("Create", "did not find right plugin to open file"); + return kFALSE; + } + if (fRawDB->IsZombie()) { + if (fRawDB->GetErrno() == ENOSPC || + fRawDB->GetErrno() == 1018 || // SECOMERR + fRawDB->GetErrno() == 1027) { // SESYSERR + fRawDB->ResetErrno(); + delete fRawDB; + Warning("Create", "file is zombie, sleeping 10 seconds before retrying..."); + gSystem->Sleep(10000); // sleep 10 seconds before retrying + goto again; + } + Error("Create", "error opening raw DB"); + fRawDB = 0; + return kFALSE; + } + + // Create raw data TTree + MakeTree(); + + return kTRUE; +} + +//______________________________________________________________________________ +void AliRawDB::MakeTree() +{ + // Create ROOT Tree object container. + + fTree = new TTree("RAW", Form("ALICE MDC%d raw data tree", kMDC)); + fTree->SetAutoSave(2000000000); // autosave when 2 Gbyte written + + Int_t bufsize = 256000; + // splitting 29.6 MB/s, no splitting 35.3 MB/s on P4 2GHz 15k SCSI + //Int_t split = 1; + Int_t split = 0; + fTree->Branch("rawevent", "AliRawEvent", &fEvent, bufsize, split); +} + +//______________________________________________________________________________ +void AliRawDB::Close() +{ + // Close raw DB. + + if (!fRawDB) return; + + fRawDB->cd(); + + // Write the tree. + fTree->Write(); + + // Close DB, this also deletes the fTree + fRawDB->Close(); + + if (AliMDC::DeleteFiles()) { + gSystem->Unlink(fRawDB->GetName()); + delete fRawDB; + fRawDB = 0; + return; + } + + // Create semaphore to say this file is finished + Int_t tfd = ::creat(Form("%s.done", fRawDB->GetName()), 0644); + close(tfd); + + delete fRawDB; + fRawDB = 0; +} + +//______________________________________________________________________________ +Bool_t AliRawDB::NextFile() +{ + // Close te current file and open a new one. + // Returns kFALSE in case opening failed. + + Close(); + + if (!Create()) return kFALSE; + return kTRUE; +} + +//______________________________________________________________________________ +Float_t AliRawDB::GetCompressionFactor() const +{ + // Return compression factor. + + if (fTree->GetZipBytes() == 0.) + return 1.0; + else + return fTree->GetTotBytes()/fTree->GetZipBytes(); +} + + +//______________________________________________________________________________ +AliRawRFIODB::AliRawRFIODB(AliRawEvent *event, Double_t maxsize, Int_t compress) + : AliRawDB(event, maxsize, compress, kFALSE) +{ + // Create a new raw DB that will be accessed via RFIO. + +#ifndef USE_RDM + static int init = 0; + // Set STAGE_POOL environment variable to current host + if (!init) { + // THESE ENVIRONMENT SYMBOLS ARE NOW DEFINED BY THE ALICE DATE SETUP + // THEREFORE WE SHALL NOT USE ANY HARDCODED VALUES BUT RATHER USE + // WHATEVER HAS BEEN SET IN THE DATE SITE + //gSystem->Setenv("STAGE_POOL", "mdc4"); + //gSystem->Setenv("STAGE_HOST", "lxshare003d"); + init = 1; + } +#endif + + if (!Create()) + MakeZombie(); + else + fRawDB->UseCache(50, 0x200000); //0x100000 = 1MB) +} + +//______________________________________________________________________________ +const char *AliRawRFIODB::GetFileName() +{ + // Return filename based on hostname and date and time. This will make + // each file unique. Also the directory will be made unique for each + // day by adding the date to the fs. Assumes there is always enough + // space on the device. + + static TString fname; + + TString fs = kRFIOFS; + TDatime dt; + + // make a new subdirectory for each day + fs += "/adc-"; + fs += dt.GetDate(); + + Long_t id, size, flags, time; + if (gSystem->GetPathInfo(fs, &id, &size, &flags, &time) == 1) { + // directory does not exist, create it + if (gSystem->mkdir(fs, kTRUE) == -1) { + Error("GetFileName", "cannot create dir %s, using %s", fs.Data(), + kRFIOFS); + fs = kRFIOFS; + } + } + // FIXME: should check if fs is a directory + + TString hostname = gSystem->HostName(); + Int_t pos; + if ((pos = hostname.Index(".")) != kNPOS) + hostname.Remove(pos); + + fname = fs + "/" + hostname + "_"; + fname += dt.GetDate(); + fname += "_"; + fname += dt.GetTime(); + fname += ".root"; + + return fname; +} + +//______________________________________________________________________________ +void AliRawRFIODB::Close() +{ + // Close raw RFIO DB. + + if (!fRawDB) return; + + fRawDB->cd(); + + // Write the tree. + fTree->Write(); + + // Close DB, this also deletes the fTree + fRawDB->Close(); + + if (AliMDC::DeleteFiles()) + gSystem->Exec(Form("rfrm %s", fRawDB->GetName())); + + delete fRawDB; + fRawDB = 0; +} + + +//______________________________________________________________________________ +AliRawRootdDB::AliRawRootdDB(AliRawEvent *event, Double_t maxsize, Int_t compress) + : AliRawDB(event, maxsize, compress, kFALSE) +{ + // Create a new raw DB that will be accessed via rootd daemon. + + if (!Create()) + MakeZombie(); + else + fRawDB->UseCache(50, 0x200000); //0x100000 = 1MB) +} + +//______________________________________________________________________________ +const char *AliRawRootdDB::GetFileName() +{ + // Return filename based on hostname and date and time. This will make + // each file unique. Also the directory will be made unique for each + // day by adding the date to the fs. Assumes there is always enough + // space on the device. + + static TString fname; + + TString fs = kRootdFS; + TDatime dt; + +#if 0 + // make a new subdirectory for each day + fs += "/adc-"; + fs += dt.GetDate(); + + Long_t id, size, flags, time; + if (gSystem->GetPathInfo(fs, &id, &size, &flags, &time) == 1) { + // directory does not exist, create it + if (gSystem->mkdir(fs, kTRUE) == -1) { + Error("GetFileName", "cannot create dir %s, using %s", fs.Data(), + kRootdFS); + fs = kRootdFS; + } + } + // FIXME: should check if fs is a directory +#endif + + TString hostname = gSystem->HostName(); + Int_t pos; + if ((pos = hostname.Index(".")) != kNPOS) + hostname.Remove(pos); + + fname = fs + "/" + hostname + "_"; + fname += dt.GetDate(); + fname += "_"; + fname += dt.GetTime(); + fname += ".root"; + + return fname; +} + +//______________________________________________________________________________ +void AliRawRootdDB::Close() +{ + // Close raw rootd DB. + + if (!fRawDB) return; + + fRawDB->cd(); + + // Write the tree. + fTree->Write(); + + // Close DB, this also deletes the fTree + fRawDB->Close(); + +#if 0 + // can use services of TFTP + if (AliMDC::DeleteFiles()) + gSystem->Exec(Form("rfrm %s", fRawDB->GetName())); +#endif + + delete fRawDB; + fRawDB = 0; +} + + +//______________________________________________________________________________ +AliRawNullDB::AliRawNullDB(AliRawEvent *event, Double_t maxsize, Int_t compress) + : AliRawDB(event, maxsize, compress, kFALSE) +{ + // Create a new raw DB that will wrtie to /dev/null. + + if (!Create()) + MakeZombie(); +} + +//______________________________________________________________________________ +const char *AliRawNullDB::GetFileName() +{ + // Return /dev/null as filename. + + return "/dev/null"; +} + +//______________________________________________________________________________ +void AliRawNullDB::Close() +{ + // Close raw RFIO DB. + + if (!fRawDB) return; + + fRawDB->cd(); + + // Write the tree. + fTree->Write(); + + // Close DB, this also deletes the fTree + fRawDB->Close(); + + delete fRawDB; + fRawDB = 0; +} + + +//______________________________________________________________________________ +AliTagDB::AliTagDB(AliRawEventHeader *header, Double_t maxsize, Bool_t create) +{ + // Create tag DB. + + fHeader = header; + fMaxSize = maxsize; + + if (create) { + if (!Create()) + MakeZombie(); + } +} + +//______________________________________________________________________________ +Bool_t AliTagDB::Create() +{ + // Create a new tag DB. + + fTagDB = new TFile(GetFileName(), "RECREATE", + Form("ALICE MDC%d tag DB", kMDC), 1); + if (fTagDB->IsZombie()) { + Error("Create", "error opening tag DB"); + fTagDB = 0; + return kFALSE; + } + + // Create ROOT Tree object container + fTree = new TTree("TAG", Form("ALICE MDC%d header data tree", kMDC)); + fTree->SetAutoSave(100000000); // autosave when 100 Mbyte written + + Int_t bufsize = 32000; + Int_t split = 1; + fTree->Branch("header", "AliRawEventHeader", &fHeader, bufsize, split); + + return kTRUE; +} + +//______________________________________________________________________________ +void AliTagDB::Close() +{ + // Close tag DB. + + if (!fTagDB) return; + + fTagDB->cd(); + + // Write the tree. + fTree->Write(); + + // Close DB, this also deletes the fTree + fTagDB->Close(); + + if (AliMDC::DeleteFiles()) + gSystem->Unlink(fTagDB->GetName()); + + delete fTagDB; + fTagDB = 0; +} + +//______________________________________________________________________________ +Bool_t AliTagDB::NextFile() +{ + // Close te current file and open a new one. + // Returns kFALSE in case opening failed. + + Close(); + + if (!Create()) return kFALSE; + return kTRUE; +} + +//______________________________________________________________________________ +Float_t AliTagDB::GetCompressionFactor() const +{ + // Return compression factor. + + if (fTree->GetZipBytes() == 0.) + return 1.0; + else + return fTree->GetTotBytes()/fTree->GetZipBytes(); +} + +//______________________________________________________________________________ +const char *AliTagDB::GetFileName() +{ + // Return filename based on hostname and date and time. This will make + // each file unique. The tags will be stored in the /data1/tags directory. + + static char fname[64]; + const char *fs = kTagDBFS; + + // check that fs exists (crude check fails if fs is a file) + gSystem->MakeDirectory(fs); + + char hostname[64]; + + strcpy(hostname, gSystem->HostName()); + + char *s; + if ((s = strchr(hostname, '.'))) + *s = 0; + + TDatime dt; + + sprintf(fname, "%s/%s_%d_%d.root", fs, hostname, dt.GetDate(), dt.GetTime()); + + return fname; +} + + +//______________________________________________________________________________ +AliTagNullDB::AliTagNullDB(AliRawEventHeader *header, Double_t maxsize) : + AliTagDB(header, maxsize, kFALSE) +{ + // Create tag db writing to /dev/null. + + if (!Create()) + MakeZombie(); +} + +//______________________________________________________________________________ +const char *AliTagNullDB::GetFileName() +{ + // Return /dev/null as filename. + + return "/dev/null"; +} + +//______________________________________________________________________________ +void AliTagNullDB::Close() +{ + // Close null tag DB. + + if (!fTagDB) return; + + fTagDB->cd(); + + // Write the tree. + fTree->Write(); + + // Close DB, this also deletes the fTree + fTagDB->Close(); + + delete fTagDB; + fTagDB = 0; +} + + +//______________________________________________________________________________ +AliRunDB::AliRunDB() +{ + // Open run database, and get or create tree. + + // Get hostname + char hostname[64], filename[64]; + const char *fs = kRunDBFS; + + // check that fs exists (crude check fails if fs is a file) + gSystem->MakeDirectory(fs); + + strcpy(hostname, gSystem->HostName()); + + char *s; + if ((s = strchr(hostname, '.'))) + *s = 0; + + sprintf(filename, "%s/%s_rundb.root", fs, hostname); + + if (!gSystem->AccessPathName(filename, kFileExists)) + fRunDB = new TFile(filename, "UPDATE"); + else + fRunDB = new TFile(filename, "CREATE", Form("ALICE MDC%d Run DB", kMDC)); +} + +//______________________________________________________________________________ +void AliRunDB::Update(AliStats *stats) +{ + // Add stats object to database. + + TDirectory *ds = gDirectory; + fRunDB->cd(); + + char sname[64]; + char *s = strrchr(stats->GetFileName(), '/'); + if (s) { + s++; + strcpy(sname, s); + } else + strcpy(sname, stats->GetFileName()); + s = strchr(sname, '.'); + if (s) *s = 0; + + stats->Write(sname); + + ds->cd(); +} + +//______________________________________________________________________________ +void AliRunDB::UpdateRDBMS(AliStats *stats) +{ + // Add stats object to central MySQL DB. + + char sql[4096]; + char bt[25], et[25]; + + strcpy(bt, stats->GetBeginTime().AsSQLString()); + strcpy(et, stats->GetEndTime().AsSQLString()); + + sprintf(sql, "INSERT INTO mdc%dcatalog VALUES (0, '%s', %d, " + "%d, %d, %d, %d, %d, %d, %.2f, '%s', '%s', '%s')", kMDC, + stats->GetFileName(), (int)stats->GetFileSize(), stats->GetEvents(), + stats->GetFirstRun(), stats->GetFirstEvent(), stats->GetLastRun(), + stats->GetLastEvent(), stats->GetCompressionMode(), + stats->GetCompressionFactor(), stats->GetFilterState() ? "on" : "off", + bt, et); + + // open connection to MySQL server on pcsalo + TSQLServer *db = TSQLServer::Connect("mysql://pcsalo.cern.ch/mdc", "alice", "amdc"); + + if (!db || db->IsZombie()) { + Error("UpdateRDBMS", "failed to connect to MySQL server on pcsalo"); + printf("%s\n", sql); + delete db; + return; + } + + TSQLResult *res = db->Query(sql); + + if (!res) { + Error("UpdateRDBMS", Form("insert into mdc%dcatalog failed", kMDC)); + printf("%s\n", sql); + } + + delete res; + delete db; +} + +//______________________________________________________________________________ +void AliRunDB::Close() +{ + // Close run database. + + fRunDB->Close(); + delete fRunDB; +} + +//----------------- Use SIGUSR1 to interupt endless loop ----------------------- +class AliMDCInterruptHandler : public TSignalHandler { +private: + AliMDC *fMDC; // alimdc to signal +public: + AliMDCInterruptHandler(AliMDC *mdc) : TSignalHandler(kSigUser1, kFALSE), fMDC(mdc) { } + Bool_t Notify() { fMDC->SetStopLoop(); return kTRUE; } +}; + +//______________________________________________________________________________ +AliMDC::AliMDC(Int_t fd, Int_t compress, Double_t maxFileSize, Bool_t useFilter, + Bool_t useRFIO, Bool_t useROOTD, Bool_t useDEVNULL, + Bool_t useLoop, Bool_t delFiles) +{ + // Create MDC processor object. + + fFd = fd; + fCompress = compress; + fMaxFileSize = maxFileSize; + fUseFilter = useFilter; + fUseRFIO = useRFIO; + fUseRootd = useROOTD; + fUseDevNull = useDEVNULL; + fUseLoop = useLoop; + fUseFifo = kFALSE; + fUseEb = kFALSE; + fStopLoop = kFALSE; + fNumEvents = 0; + fDebugLevel = 0; + fgDeleteFiles = delFiles; + + if (fFd == -1) { +#ifdef USE_EB + if (!ebRegister()) { + Error("AliMDC", "cannot register with the event builder (%s)", + ebGetLastError()); + return; + } + fUseEb = kTRUE; +#else + if ((mkfifo(kFifo, 0644) < 0) && (errno != EEXIST)) { + Error("AliMDC", "cannot create fifo %s", kFifo); + return; + } + if ((chmod(kFifo, 0666) == -1) && (errno != EPERM)) { + Error("AliMDC", "cannot change permission of fifo %s", kFifo); + return; + } + if ((fFd = open(kFifo, O_RDONLY)) == -1) { + Error("AliMDC", "cannot open input file %s", kFifo); + return; + } + fUseFifo = kTRUE; +#endif + fUseLoop = kFALSE; + } + + printf(": input = %s, rawdb size = %f, filter = %s, " + "looping = %s, compression = %d, delete files = %s", + fUseFifo ? "fifo" : (fUseEb ? "eb" : "file"), fMaxFileSize, + fUseFilter ? "on" : "off", fUseLoop ? "yes" : "no", fCompress, + fgDeleteFiles ? "yes" : "no"); + if (fUseRFIO) + printf(", use RFIO\n"); + else if (fUseRootd) + printf(", use rootd\n"); + else if (fUseDevNull) + printf(", write raw data to /dev/null\n"); + else + printf("\n"); + + // install SIGUSR1 handler to allow clean interrupts + gSystem->AddSignalHandler(new AliMDCInterruptHandler(this)); + + gAliMDC = this; +} + +//______________________________________________________________________________ +Int_t AliMDC::Run() +{ + // Run the MDC processor. Read from the input stream and only return + // when the input gave and EOF or a fatal error occured. On success 0 + // is returned, 1 in case of a fatality. + + TStopwatch timer; + Int_t status; + + // Make sure needed directories exist + const char *dirs[4]; + dirs[0] = kRawDBFS[0]; + dirs[1] = kRawDBFS[1]; + dirs[2] = kTagDBFS; + dirs[3] = kRunDBFS; + for (int idir = 0; idir < 4; idir++) { + gSystem->ResetErrno(); + gSystem->MakeDirectory(dirs[idir]); + if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) { + SysError("Run", "mkdir %s", dirs[idir]); + return 1; + } + } + + // Used for statistics + timer.Start(); + Double_t told = 0, tnew = 0; + Float_t chunkSize = fMaxFileSize/100, nextChunk = chunkSize; + + // Event object used to store event data. + AliRawEvent *event = new AliRawEvent; + + // Create new raw DB. + AliRawDB *rawdb; + if (fUseRFIO) + rawdb = new AliRawRFIODB(event, fMaxFileSize, fCompress); + else if (fUseRootd) + rawdb = new AliRawRootdDB(event, fMaxFileSize, fCompress); + else if (fUseDevNull) + rawdb = new AliRawNullDB(event, fMaxFileSize, fCompress); + else + rawdb = new AliRawDB(event, fMaxFileSize, fCompress); + + if (rawdb->IsZombie()) return 1; + printf("Filling raw DB %s\n", rawdb->GetDBName()); + + // Create new tag DB. + AliTagDB *tagdb; + if (fUseDevNull) + tagdb = new AliTagNullDB(event->GetHeader(), kMaxTagFileSize); + else + tagdb = new AliTagDB(event->GetHeader(), kMaxTagFileSize); + if (tagdb->IsZombie()) + tagdb = 0; + else + printf("Filling tag DB %s\n", tagdb->GetDBName()); + + // Create AliStats object + AliStats *stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter); + + // Shortcut for easy header access + AliRawEventHeader &header = *event->GetHeader(); + + // Process input stream +#ifdef USE_EB + while (!ebEor()) { + struct iovec *ebvec; + if ((ebvec = ebGetNextEvent()) == (void *)-1) { + Error("Run", "error getting next event (%s)", ebGetLastError()); + break; + } + if (ebvec == 0) { + // no event, sleep for 1 second and try again + gSystem->Sleep(1000); + continue; + } + char *ebdata = (char *) ebvec[0].iov_base; +#else + while (1) { + char *ebdata = 0; +#endif + + // Read event header + if ((status = ReadHeader(header, ebdata)) != header.HeaderSize()) { + if (status == 0) { + if (fUseLoop) { +#ifndef USE_EB + ::lseek(fFd, 0, SEEK_SET); +#endif + continue; + } + printf(": EOF, processed %d events\n", fNumEvents); + break; + } + return 1; + } + + // If we were in looping mode stop directly after a SIGUSR1 signal + if (StopLoop()) { + Info("Run", "SIGUSR1, processed %d events", fNumEvents); + break; + } + + // Check if event has any hard track flagged + Bool_t callFilter = kFALSE; + // This needs to be re-engineered for the next ADC... + //if (fUseFilter && TEST_USER_ATTRIBUTE(header.GetTypeAttribute(), 0)) + // callFilter = kTRUE; + + // Check event type and skip "Start of Run", "End of Run", + // "Start of Run Files" and "End of Run Files" + switch (header.GetType()) { + case kStartOfRun: + case kEndOfRun: + case kStartOfRunFiles: + case kEndOfRunFiles: + { + Int_t skip = header.GetEventSize() - header.HeaderSize(); +#ifndef USE_EB + ::lseek(fFd, skip, SEEK_CUR); +#endif + ALIDEBUG(1) + Info("Run", "Skipping %s (%d bytes)", header.GetTypeName(), skip); + continue; + } + break; + default: + ALIDEBUG(1) { + Int_t s = header.GetEventSize() - header.HeaderSize(); + Info("Run", "Processing %s (%d bytes)", header.GetTypeName(), s); + } + } + + // Amount of data left to read for this event + Int_t toRead = header.GetEventSize() - header.HeaderSize(); + + // If there is less data for this event than the next sub-event + // header, something is wrong. Skip to next event... + if (toRead < header.HeaderSize()) { + if ((status = DumpEvent(toRead)) != toRead) { + if (status == 0) + break; + return 1; + } + Error("Run", "discarding event %d (too little data for header)", fNumEvents); + continue; + } + + // Loop over all sub-events... (LDCs) + while (toRead > 0) { + Int_t nsub = 1; +#ifdef USE_EB + ebdata = (char *)ebvec[nsub].iov_base; +#endif + + ALIDEBUG(1) + Info("Run", "reading LDC %d", nsub); + + AliRawEvent *subEvent = event->NextSubEvent(); + + // Read sub-event header + AliRawEventHeader &subHeader = *subEvent->GetHeader(); + if ((status = ReadHeader(subHeader, ebdata)) != subHeader.HeaderSize()) { + if (status == 0) { + Error("Run", "unexpected EOF reading sub-event header"); + break; + } + return 1; + } + + toRead -= subHeader.HeaderSize(); + +#ifdef USE_EB + ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize(); +#endif + + Int_t rawSize = subHeader.GetEventSize() - subHeader.HeaderSize(); + + // Read Equipment Header (in case of physics or calibration event) + if (header.GetType() == kPhysicsEvent || + header.GetType() == kCalibrationEvent) { + AliRawEquipmentHeader &equipment = *subEvent->GetEquipmentHeader(); + Int_t equipHeaderSize = equipment.HeaderSize(); + if ((status = ReadEquipmentHeader(equipment, header.DataIsSwapped(), + ebdata)) != equipHeaderSize) { + if (status == 0) { + Error("Run", "unexpected EOF reading equipment-header"); + break; + } + return 1; + } + toRead -= equipHeaderSize; + rawSize -= equipHeaderSize; +#ifdef USE_EB + ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize() + + equipHeaderSize; +#endif + } + + // Make sure raw data less than left over bytes for current event + if (rawSize > toRead) { + if ((status = DumpEvent(toRead)) != toRead) { + if (status == 0) + break; + return 1; + } + Error("Run", "discarding event %d (too much data)", fNumEvents); + continue; + } + + // Read sub-event raw data + AliRawData &subRaw = *subEvent->GetRawData(); + if ((status = ReadRawData(subRaw, rawSize, ebdata)) != rawSize) { + if (status == 0) { + Error("Run", "unexpected EOF reading sub-event raw data"); + break; + } + return 1; + } + + if (callFilter) { + if (TEST_USER_ATTRIBUTE(subHeader.GetTypeAttribute(), 0)) + Filter(subRaw); + else { + // set size of all sectors without hard track flag to 0 + subRaw.SetSize(0); + } + } + + toRead -= rawSize; + nsub++; + } + + // Set stat info for first event of this file + if (rawdb->GetEvents() == 0) + stats->SetFirstId(header.GetRunNumber(), header.GetEventInRun()); + + // Store raw event in tree + rawdb->Fill(); + + // Store header in tree + if (tagdb) tagdb->Fill(); + + fNumEvents++; + + if (!(fNumEvents%10)) + printf("Processed event %d (%d)\n", fNumEvents, rawdb->GetEvents()); + + // Filling time statistics + if (rawdb->GetBytesWritten() > nextChunk) { + tnew = timer.RealTime(); + stats->Fill(tnew-told); + told = tnew; + timer.Continue(); + nextChunk += chunkSize; + } + + // Check size of raw db. If bigger than maxFileSize, close file + // and continue with new file. + if (rawdb->FileFull()) { + + printf("Written raw DB at a rate of %.1f MB/s\n", + Float_t(fMaxFileSize / timer.RealTime() / 1000000.)); + + // Write stats object to raw db, run db and MySQL + stats->WriteToDB(rawdb); + delete stats; + + if (!rawdb->NextFile()) return 1; + + printf("Filling raw DB %s\n", rawdb->GetDBName()); + stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter); + + timer.Start(); + told = 0, tnew = 0; + nextChunk = chunkSize; + } + + // Check size of tag db + if (tagdb->FileFull()) { + if (!tagdb->NextFile()) + tagdb = 0; + else + printf("Filling tag DB %s\n", tagdb->GetDBName()); + } + + // Make top event object ready for next event data + //printf("Event %d has %d sub-events\n", fNumEvents, event->GetNSubEvents()); + event->Reset(); + +#ifdef USE_EB + if (!ebReleaseEvent(ebvec)) { + Error("Run", "problem releasing event (%s)", ebGetLastError()); + break; + } +#endif + } + + printf("Written raw DB at a rate of %.1f MB/s\n", + Float_t(fMaxFileSize / timer.RealTime() / 1000000.)); + + // Write stats to raw db and run db and delete stats object + stats->WriteToDB(rawdb); + delete stats; + + // Close the raw DB + delete rawdb; + + // Close the tag DB + delete tagdb; + + // Close input source + close(fFd); + +#if 0 + // Cleanup fifo + if (fUseFifo && ::unlink(kFifo) == -1) { + SysError("Run", "unlink"); + return 1; + } +#endif + + return 0; +} + +//______________________________________________________________________________ +Int_t AliMDC::Read(void *buffer, Int_t length) +{ + // Read exactly length bytes into buffer. Returns number of bytes + // received, returns -1 in case of error and 0 for EOF. + + errno = 0; + + if (fFd < 0) return -1; + + Int_t n, nrecv = 0; + char *buf = (char *)buffer; + + for (n = 0; n < length; n += nrecv) { + if ((nrecv = read(fFd, buf+n, length-n)) <= 0) { + if (nrecv == 0) + break; // EOF + if (errno != EINTR) + SysError("Read", "read"); + return -1; + } + } + return n; +} + +//______________________________________________________________________________ +Int_t AliMDC::ReadHeader(AliRawEventHeader &header, void *eb) +{ + // Read header info from DATE data stream. Returns bytes read (i.e. + // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF. + + Int_t nrecv; + + if (eb) { + // read from event builder memory area + memcpy(header.HeaderBegin(), eb, header.HeaderSize()); + nrecv = header.HeaderSize(); + } else { + // read from fifo or file + if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) != + header.HeaderSize()) { + if (nrecv == 0) + return 0; + return -1; + } + } + + // Swap header data if needed + if (header.IsSwapped()) + header.Swap(); + + // Is header valid... + if (!header.IsValid()) { + Error("ReadHeader", "invalid header format"); + // try recovery... how? + return -1; + } + if (header.GetEventSize() < (UInt_t)header.HeaderSize()) { + Error("ReadHeader", "invalid header size"); + // try recovery... how? + return -1; + } + + return nrecv; +} + +//______________________________________________________________________________ +Int_t AliMDC::ReadEquipmentHeader(AliRawEquipmentHeader &header, + Bool_t isSwapped, void *eb) +{ + // Read equipment header info from DATE data stream. Returns bytes read + // (i.e. AliRawEquipmentHeader::HeaderSize()), -1 in case of error and + // 0 for EOF. If isSwapped is kTRUE the event data is byte swapped + // and we will swap the header to host format. + + Int_t nrecv; + + if (eb) { + // read from event builder memory area + memcpy(header.HeaderBegin(), eb, header.HeaderSize()); + nrecv = header.HeaderSize(); + } else { + // read from fifo or file + if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) != + header.HeaderSize()) { + if (nrecv == 0) + return 0; + return -1; + } + } + + // Swap equipment header data if needed + if (isSwapped) + header.Swap(); + + if (header.GetEquipmentSize() < (UInt_t)header.HeaderSize()) { + Error("ReadEquipmentHeader", "invalid equipment header size"); + // try recovery... how? + return -1; + } + + return nrecv; +} + +//______________________________________________________________________________ +Int_t AliMDC::ReadRawData(AliRawData &raw, Int_t size, void *eb) +{ + // Read raw data from DATE data stream. Returns bytes read (i.e. + // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF. + + Int_t nrecv; + + if (eb) { + // read from event builder memory area + raw.SetBuffer(eb, size); + nrecv = size; + } else { + // read from fifo or file + raw.SetSize(size); + if ((nrecv = Read(raw.GetBuffer(), size)) != size) { + if (nrecv == 0) { + Error("ReadRawData", "unexpected EOF"); + return 0; + } + return -1; + } + } + + return nrecv; +} + +//______________________________________________________________________________ +Int_t AliMDC::DumpEvent(Int_t toRead) +{ + // This case should not happen, but if it does try to handle it + // gracefully by reading the rest of the event and discarding it. + // Returns bytes read, -1 in case of fatal error and 0 for EOF. + + Error("DumpEvent", "dumping %d bytes of event %d", toRead, fNumEvents); + + Int_t nrecv; + char *tbuf = new char[toRead]; + if ((nrecv = Read(tbuf, toRead)) != toRead) { + if (nrecv == 0) { + Error("DumpEvent", "unexpected EOF"); + return 0; + } + return -1; + } + delete [] tbuf; + + return nrecv; +} + +#ifdef USE_HLT +#include +#endif + +//______________________________________________________________________________ +Int_t AliMDC::Filter(AliRawData &raw) +{ + // Call 3rd level filter for this raw data segment. + +#ifdef USE_HLT + AliTPCL3Tunnel *tunnel = 0; + if (!tunnel) { + // initialisation + tunnel = new AliTPCL3Tunnel(Form("%s/TPCparams.root", + gSystem->Getenv("ALITPC"))); + } + + Int_t obytes, nbytes; + obytes = nbytes = raw.GetSize(); + char *outbuf = tunnel->EvalTrack((char *)raw.GetBuffer(), nbytes); + + raw.SetSize(nbytes); + memcpy(raw.GetBuffer(), outbuf, nbytes); + + printf("Filter called for event %d: reduced from %d to %d\n", fNumEvents, + obytes, nbytes); + +#else + + raw.GetSize(); + printf("Filter called for event %d\n", fNumEvents); + +#endif + + return 0; +} diff --git a/RAW/AliRawEvent.h b/RAW/AliRawEvent.h new file mode 100644 index 00000000000..e1f07849416 --- /dev/null +++ b/RAW/AliRawEvent.h @@ -0,0 +1,447 @@ +// @(#)alimdc:$Name$:$Id$ +// Author: Fons Rademakers 26/11/99 +// Updated: Dario Favretto 15/04/2003 + +#ifndef ALIRAWEVENT_H +#define ALIRAWEVENT_H + +#ifndef ROOT_TObject +#include +#endif + +#ifndef ROOT_Bytes +#include +#endif + +#ifndef ROOT_TDatime +#include +#endif + +#ifndef ROOT_TString +#include +#endif + +#ifndef ROOT_TFile +#include +#endif + +#ifndef ROOT_TTree +#include +#endif + + +// Forward class declarations +class TH1F; +class AliRawDB; + + +// The following enumeration can be used once the kEventTypeMask has been +// applied to the raw event type +enum EAliRawEventType { + kStartOfRun = 1, // START_OF_RUN + kEndOfRun = 2, // END_OF_RUN + kStartOfRunFiles = 3, // START_OF_RUN_FILES + kEndOfRunFiles = 4, // END_OF_RUN_FILES + kStartOfBurst = 5, // START_OF_BURST + kEndOfBurst = 6, // END_OF_BURST + kPhysicsEvent = 7, // PHYSICS_EVENT + kCalibrationEvent = 8, // CALIBRATION_EVENT + kFormatError = 9 // EVENT_FORMAT_ERROR +}; + +const Int_t kEventTypeMin = kStartOfRun; +const Int_t kEventTypeMax = kFormatError; + +const UInt_t kEventMagicNumber = 0xDA1E5AFE; +const UInt_t kEventMagicNumberSwapped = 0xFE5A1EDA; + +// Type sizes +const Int_t kIdWords = 2; +const Int_t kTriggerWords = 2; +const Int_t kDetectorWords = 1; +const Int_t kAttributeWords = 3; + + +class AliRawEventHeader : public TObject { + +private: + UInt_t fSize; // size of event in bytes + UInt_t fMagic; // magic number used for consistency check + UInt_t fHeadLen; // size of header in bytes + UInt_t fVersion; // unique version identifier + UInt_t fType; // event type + UInt_t fRunNb; // run number + UInt_t fId[kIdWords]; // id field + UInt_t fTriggerPattern[kTriggerWords]; // trigger pattern + UInt_t fDetectorPattern[kDetectorWords]; // detector pattern + UInt_t fTypeAttribute[kAttributeWords]; // system (0,1) and user (2) attributes + UInt_t fLDCId; // LDC id + UInt_t fGDCId; // GDC id + +public: + AliRawEventHeader() { fSize = 0; } + virtual ~AliRawEventHeader() { } + + void *HeaderBegin() { return (void *) &fSize; } + Int_t HeaderSize() const { return (Long_t) &fGDCId - (Long_t) &fSize + sizeof(fGDCId); } + Bool_t DataIsSwapped() const; + Bool_t IsSwapped() const { return (fMagic == kEventMagicNumberSwapped) ? kTRUE : kFALSE; } + Bool_t IsValid() const { return IsSwapped() ? kTRUE : ((fMagic == kEventMagicNumber) ? kTRUE : kFALSE); } + void Swap(); + + UInt_t GetEventSize() const { return fSize; } + UInt_t GetMagic() const { return fMagic; } + UInt_t GetHeaderLength() const { return fHeadLen; } + UInt_t GetVersion() const { return fVersion; } + UInt_t GetType() const { return fType; } + const char *GetTypeName() const; + UInt_t GetRunNumber() const { return fRunNb; } + UInt_t GetEventInRun() const; + const UInt_t *GetId() const { return fId; } + const UInt_t *GetTriggerPattern() const { return fTriggerPattern; } + const UInt_t *GetDetectorPattern() const { return fDetectorPattern; } + const UInt_t *GetTypeAttribute() const { return fTypeAttribute; } + UInt_t GetLDCId() const { return fLDCId; } + UInt_t GetGDCId() const { return fGDCId; } + + ClassDef(AliRawEventHeader,1) // Alice raw event header +}; + + +class AliRawEquipmentHeader : public TObject { + +private: + UInt_t fSize; // number of raw data bytes + UInt_t fEquipmentType; // equipment type + UInt_t fEquipmentID; // equipment ID + UInt_t fTypeAttribute[kAttributeWords]; // system (0,1) and user (2) attributes + UInt_t fBasicElementSizeType; // basic element size type + +public: + AliRawEquipmentHeader() { fSize = 0; } + ~AliRawEquipmentHeader() { } + + void *HeaderBegin() { return (void *) &fSize; } + Int_t HeaderSize() const { return (Long_t) &fBasicElementSizeType - (Long_t) &fSize + sizeof(fBasicElementSizeType); } + void Swap(); + + UInt_t GetEquipmentSize() const { return fSize; } + UInt_t GetEquipmentType() const { return fEquipmentType; } + UInt_t GetId() const { return fEquipmentID; } + const UInt_t *GetTypeAttribute() const { return fTypeAttribute; } + UInt_t GetBasicSizeType() const { return fBasicElementSizeType; } + + ClassDef(AliRawEquipmentHeader,1) //Alice equipment header +}; + + +class AliRawData : public TObject { + +private: + Int_t fSize; // number of raw data bytes + Int_t fBufSize; //!actual size of fRawData + char *fRawData; //[fSize] raw event data + Bool_t fOwner; //!if true object owns fRawData buffer + +public: + AliRawData() { fSize = fBufSize = 0; fRawData = 0; fOwner = kFALSE; } + virtual ~AliRawData() { if (fOwner) delete [] fRawData; } + + void SetSize(Int_t size) { + if (size > fBufSize) { + if (fOwner) delete [] fRawData; + fRawData = new char [size]; + fBufSize = size; + fOwner = kTRUE; + } + fSize = size; + } + void SetBuffer(void *buf, Int_t size) { + if (fOwner) delete [] fRawData; + fRawData = (char *) buf; + fBufSize = size; + fSize = size; + fOwner = kFALSE; + } + Int_t GetSize() const { return fSize; } + void *GetBuffer() { return fRawData; } + + ClassDef(AliRawData,1) // Alice raw event buffer +}; + + +class AliRawEvent : public TObject { + +private: + Int_t fNSubEvents; // number of valid sub-events + AliRawEventHeader *fEvtHdr; // event header object + AliRawEquipmentHeader *fEqpHdr; // equipment header + AliRawData *fRawData; // raw data container + TObjArray *fSubEvents; // sub AliRawEvent's + +public: + AliRawEvent(); + virtual ~AliRawEvent(); + + AliRawEventHeader *GetHeader() const { return fEvtHdr; } + AliRawEquipmentHeader *GetEquipmentHeader(); + AliRawData *GetRawData(); + Int_t GetNSubEvents() const { return fNSubEvents; } + AliRawEvent *NextSubEvent(); + void Reset(); + + ClassDef(AliRawEvent,1) // ALICE raw event object +}; + + +class AliStats : public TObject { + +private: + Int_t fEvents; // number of events in this file + Int_t fFirstRun; // run number of first event in file + Int_t fFirstEvent; // event number of first event in file + Int_t fLastRun; // run number of last event in file + Int_t fLastEvent; // event number of last event in file + TDatime fBegin; // begin of filling time + TDatime fEnd; // end of filling time + TString fFileName; // name of file containing this data + Double_t fFileSize; // size of file + Float_t fCompFactor; // tree compression factor + Int_t fCompMode; // compression mode + Bool_t fFilter; // 3rd level filter on/off + TH1F *fRTHist; // histogram of real-time to process chunck of data + Float_t fChunk; //!chunk to be histogrammed + +public: + AliStats(const char *filename = "", Int_t compmode = 0, Bool_t filter = kFALSE); + virtual ~AliStats(); + AliStats &operator=(const AliStats &rhs); + + void SetEvents(Int_t events) { fEvents = events; } + void SetFirstId(Int_t run, Int_t event) { fFirstRun = run; fFirstEvent = event; } + void SetLastId(Int_t run, Int_t event) { fLastRun = run; fLastEvent = event; } + void SetBeginTime() { fBegin.Set(); } + void SetEndTime() { fEnd.Set(); } + void SetFileSize(Double_t size) { fFileSize = size; } + void SetCompressionFactor(Float_t comp) { fCompFactor = comp; } + void Fill(Float_t time); + void WriteToDB(AliRawDB *rawdb); + + Int_t GetEvents() const { return fEvents; } + Int_t GetFirstRun() const { return fFirstRun; } + Int_t GetFirstEvent() const { return fFirstEvent; } + Int_t GetLastRun() const { return fLastRun; } + Int_t GetLastEvent() const { return fLastEvent; } + TDatime &GetBeginTime() { return fBegin; } + TDatime &GetEndTime() { return fEnd; } + Double_t GetFileSize() const { return fFileSize; } + Int_t GetCompressionMode() const { return fCompMode; } + Float_t GetCompressionFactor() const { return fCompFactor; } + Bool_t GetFilterState() const { return fFilter; } + const char *GetFileName() const { return fFileName; } + TH1F *GetRTHist() const { return fRTHist; } + + ClassDef(AliStats,1) // Statistics object +}; + + +class AliRawDB : public TObject { + +protected: + TFile *fRawDB; // DB to store raw data + TTree *fTree; // tree used to store raw data + AliRawEvent *fEvent; // AliRawEvent via which data is stored + Int_t fCompress; // compression mode (1 default) + Double_t fMaxSize; // maximum size in bytes of the raw DB + + virtual const char *GetFileName(); + virtual Bool_t FSHasSpace(const char *fs); + virtual void MakeTree(); + +public: + AliRawDB(AliRawEvent *event, Double_t maxsize, Int_t compress, + Bool_t create = kTRUE); + ~AliRawDB() { Close(); } + + virtual Bool_t Create(); + virtual void Close(); + void Fill() { fTree->Fill(); } + Bool_t FileFull() { return (fRawDB->GetBytesWritten() > fMaxSize) ? + kTRUE : kFALSE; } + + Bool_t NextFile(); + + Double_t GetBytesWritten() const { return fRawDB->GetBytesWritten(); } + TFile *GetDB() const { return fRawDB; } + const char *GetDBName() const { return fRawDB->GetName(); } + Int_t GetEvents() const { return (Int_t) fTree->GetEntries(); } + AliRawEvent *GetEvent() const { return fEvent; } + Float_t GetCompressionFactor() const; + Int_t GetCompressionMode() const { return fRawDB->GetCompressionLevel(); } + + ClassDef(AliRawDB,0) // Raw DB +}; + + +class AliRawRFIODB : public AliRawDB { + +private: + const char *GetFileName(); + +public: + AliRawRFIODB(AliRawEvent *event, Double_t maxsize, Int_t compress); + ~AliRawRFIODB() { Close(); } + + void Close(); + + ClassDef(AliRawRFIODB,0) // Raw DB via RFIO +}; + + +class AliRawRootdDB : public AliRawDB { + +private: + const char *GetFileName(); + +public: + AliRawRootdDB(AliRawEvent *event, Double_t maxsize, Int_t compress); + ~AliRawRootdDB() { Close(); } + + void Close(); + + ClassDef(AliRawRootdDB,0) // Raw DB via rootd +}; + + +class AliRawNullDB : public AliRawDB { + +private: + const char *GetFileName(); + +public: + AliRawNullDB(AliRawEvent *event, Double_t maxsize, Int_t compress); + ~AliRawNullDB() { Close(); } + + void Close(); + + ClassDef(AliRawNullDB,0) // Raw DB to /dev/null +}; + + +class AliTagDB : public TObject { + +protected: + TFile *fTagDB; // DB to store header information only (tag) + TTree *fTree; // tree use to store header + AliRawEventHeader *fHeader; // header via which data is stored + Double_t fMaxSize; // maximum size in bytes of tag DB + + virtual const char *GetFileName(); + +public: + AliTagDB(AliRawEventHeader *header, Double_t maxsize, Bool_t create = kTRUE); + ~AliTagDB() { Close(); } + + Bool_t Create(); + virtual void Close(); + void Fill() { fTree->Fill(); } + Bool_t FileFull() + { return (fTagDB->GetBytesWritten() > fMaxSize) ? kTRUE : kFALSE; } + + Bool_t NextFile(); + + Double_t GetBytesWritten() const { return fTagDB->GetBytesWritten(); } + TFile *GetDB() const { return fTagDB; } + const char *GetDBName() const { return fTagDB->GetName(); } + AliRawEventHeader *GetHeader() const { return fHeader; } + Int_t GetEvents() const { return (Int_t) fTree->GetEntries(); } + Float_t GetCompressionFactor() const; + + ClassDef(AliTagDB,0) // Tag DB +}; + + +class AliTagNullDB : public AliTagDB { + +private: + const char *GetFileName(); + +public: + AliTagNullDB(AliRawEventHeader *header, Double_t maxsize); + ~AliTagNullDB() { Close(); } + + void Close(); + + ClassDef(AliTagNullDB,0) // Tag DB to /dev/null +}; + + +class AliRunDB : public TObject { + +private: + TFile *fRunDB; // run database + +public: + AliRunDB(); + ~AliRunDB() { Close(); } + + void Update(AliStats *stats); + void UpdateRDBMS(AliStats *stats); + void Close(); + + ClassDef(AliRunDB,0) // Run (bookkeeping) DB +}; + + +class AliMDC : public TObject { + +private: + Int_t fFd; // DATE input stream + Int_t fCompress; // compression factor used for raw output DB + Int_t fNumEvents; // number of events processed + Int_t fDebugLevel; // controls debug print-out + Double_t fMaxFileSize; // maximum size of raw output DB + Bool_t fUseFifo; // read from fifo, file otherwise + Bool_t fUseEb; // use event builder API instead of fifo + Bool_t fUseFilter; // use 3rd level trigger filter + Bool_t fUseRFIO; // write directly to RFIO file + Bool_t fUseRootd; // write directly to rootd file + Bool_t fUseDevNull; // write to /dev/null + Bool_t fUseLoop; // loop on input source (must be file) + Bool_t fStopLoop; // break from endless loop (triggered by SIGUSR1) + + static Bool_t fgDeleteFiles; + + Int_t Read(const char *name) { return TObject::Read(name); } + Int_t Read(void *buffer, Int_t length); + Int_t ReadHeader(AliRawEventHeader &header, void *eb = 0); + Int_t ReadEquipmentHeader(AliRawEquipmentHeader &header, + Bool_t isSwapped, void *eb = 0); + Int_t ReadRawData(AliRawData &raw, Int_t size, void *eb = 0); + Int_t DumpEvent(Int_t toRead); + Int_t Filter(AliRawData &raw); + +public: + AliMDC(Int_t fd, Int_t compress, Double_t maxFileSize, Bool_t useFilter, + Bool_t useRFIO, Bool_t useROOTD, Bool_t useDEVNULL, + Bool_t useLoop, Bool_t delFiles); + ~AliMDC() { } + + Int_t Run(); + void SetStopLoop() { fStopLoop = kTRUE; } + Bool_t StopLoop() const { return fStopLoop; } + + void SetDebugLevel(Int_t level) { fDebugLevel = level; } + Bool_t GetDebugLevel() const { return fDebugLevel; } + + static Bool_t DeleteFiles() { return fgDeleteFiles; } + + ClassDef(AliMDC,0) // MDC processor +}; + +R__EXTERN AliMDC *gAliMDC; + +#define ALIDEBUG(level) \ + if (gAliMDC && gAliMDC->GetDebugLevel() >= (level)) + +#endif diff --git a/RAW/DateEvent.h b/RAW/DateEvent.h new file mode 100644 index 00000000000..7f339300c3f --- /dev/null +++ b/RAW/DateEvent.h @@ -0,0 +1,377 @@ +/**************************************************************************** + * + * event.h: DATE event data format + * + * Revision History: + * V01.00 RD PVV 09-Jan-97 Initial version + * V01.01 AV 24-Feb-97 Added START_OF_RUN_FILES and triggerNb + * V02.02 RD 13-Mar-97 Detector ID mask type added + * V02.03 PVV 20-Mar-97 Detector ID on 128 bits + * V02.03 RD PVV 20-Mar-97 Added EVENT_DATA_TRUNCATED + * V02.04 PVV 06-May-97 Added EVENT_TYPE_MASK + * V02.05 RD PVV 09-May-97 Increase EVENT_DATA_MAX_SIZE to 50 K + * V02.06 WB MG 22-May-97 Added END_OF_RUN_FILES + * V02.07 WB 23-May-97 Added errorCode, deadTime, deadTimeusec + * EVENT_DATA_MAX_SIZE set to 100 * 1024 + * MAX_DETECTORS set to 126 + * V02.08 PVV 02-Jun-97 Modify the encoding of types + * V02.09 WB RD PVV 28-Jul-98 Add fileSeqNb in the header. + * Reduce detector mask to 3 long + * V02.10 RD 31-Jul-98 (start|end)OfRunFiles added to eventType + * V02.11 PVV RD 02-Sep-98 Event type re-numbered + * Equipment bit added to event type + * V02.12 AV PVV RD 03-Sep-98 FileSeqNo moved before detectorId + * V02.13 RD 08-Oct-98 32 bits fields defined as long32 + * V02.13 RD 19-Feb-99 Endianness/swap definitions added + * V02.14 WB PVV RD 21-Jun-99 typeAttribute added + * V02.15 RD 27-Jul-99 Macros for typeAttribute handling added + * V02.16 RD 19-Nov-99 Bug in Attributes test/set fixed + * V02.17 WB PVV RD 08-May-00 System attributes for SOR and EOR added + * V02.18 RD 18-May-00 EVENT_H_ID added + * V02.19 RD 10-Aug-00 Macros for detectorId handling added + * V03.00 RD 23-Nov-00 Version for DATE V4 + * + * Preprocessor definitions: + * NDEBUG Define BEFORE including this file to disable run-time checks on + * various parameters + * + * Related facilities: + * validateEvent.c Validation program, should be run after EACH change to + * the definitions given here below + ***************************************************************************/ +#ifndef __event_h__ +#define __event_h__ + +#define EVENT_MAJOR_VERSION_NUMBER 0x0003 +#define EVENT_MINOR_VERSION_NUMBER 0x0000 + +/* ========== System includes ========= */ +#include /* Needed by: memset, memcpy */ +#include /* Needed by: assert */ + +/* ========== Definitions for the event header ========== */ + +/* ---------- Header base size ---------- */ +/* This value must be updated for each change in the eventHeaderStruct */ +#define EVENT_HEAD_BASE_SIZE 64 + +/* ---------- Event size ---------- */ +typedef unsigned long32 eventSizeType; + +/* ---------- Magic signature and its byte-swapped version ---------- */ +#define EVENT_MAGIC_NUMBER ((eventMagicType)0xDA1E5AFE) +#define EVENT_MAGIC_NUMBER_SWAPPED ((eventMagicType)0xFE5A1EDA) +typedef unsigned long32 eventMagicType; + +/* ---------- Header size ---------- */ +typedef unsigned long32 eventHeadSizeType; + +/* ---------- Unique version identifier ---------- */ +#define EVENT_CURRENT_VERSION \ + (((EVENT_MAJOR_VERSION_NUMBER<<16)&0xffff0000)|\ + (EVENT_MINOR_VERSION_NUMBER&0x0000ffff)) +typedef unsigned long32 eventVersionType; + +/* ---------- Event type ---------- */ +typedef unsigned long32 eventTypeType; +#define START_OF_RUN ((eventTypeType)1) +#define END_OF_RUN ((eventTypeType)2) +#define START_OF_RUN_FILES ((eventTypeType)3) +#define END_OF_RUN_FILES ((eventTypeType)4) +#define START_OF_BURST ((eventTypeType)5) +#define END_OF_BURST ((eventTypeType)6) +#define PHYSICS_EVENT ((eventTypeType)7) +#define CALIBRATION_EVENT ((eventTypeType)8) +#define EVENT_FORMAT_ERROR ((eventTypeType)9) +#define EVENT_TYPE_MIN 1 +#define EVENT_TYPE_MAX 9 +enum eventTypeEnum { + startOfRun = START_OF_RUN, + endOfRun = END_OF_RUN, + startOfRunFiles = START_OF_RUN_FILES, + endOfRunFiles = END_OF_RUN_FILES, + startOfBurst = START_OF_BURST, + endOfBurst = END_OF_BURST, + physicsEvent = PHYSICS_EVENT, + calibrationEvent = CALIBRATION_EVENT, + formatError = EVENT_FORMAT_ERROR +}; +#define EVENT_TYPE_OK(t) (((t) >= EVENT_TYPE_MIN) && (((t) <= EVENT_TYPE_MAX))) + +/* ---------- Run number ---------- */ +typedef unsigned long32 eventRunNbType; + +/* ---------- The eventId field ---------- */ +#define EVENT_ID_BYTES 8 +#define EVENT_ID_WORDS ((EVENT_ID_BYTES) >> 2) +typedef unsigned long32 eventIdType[EVENT_ID_WORDS]; + + /* PERIOD - ORBIT - BUNCH crossing type events */ +#define EVENT_ID_MAX_PERIOD 0x0fffffff +#define EVENT_ID_MAX_ORBIT 0x00ffffff +#define EVENT_ID_MAX_BUNCH_CROSSING 0x00000fff +#define LOAD_EVENT_ID(id,s,o,bc) \ + (EVENT_ID_SET_PERIOD(id,s), \ + EVENT_ID_SET_ORBIT(id,o), \ + EVENT_ID_SET_BUNCH_CROSSING(id,bc)) +#define EVENT_ID_GET_BUNCH_CROSSING(id) ((id)[1]&0x00000fff) +#define EVENT_ID_GET_ORBIT(id) \ + ((((id)[0]<<20)&0xf00000)|(((id)[1]>>12)&0xfffff)) +#define EVENT_ID_GET_PERIOD(id) (((id)[0]>>4)&0x0fffffff) + +#define EVENT_ID_SET_BUNCH_CROSSING(id,v) \ + (assert(((v)>=0)&&((v)<=EVENT_ID_MAX_BUNCH_CROSSING)), \ + (id)[1]=((id)[1]&0xfffff000)|((v)&0xfff)) +#define EVENT_ID_SET_ORBIT(id,v) \ + (assert(((v)>=0)&&((v)<=EVENT_ID_MAX_ORBIT)), \ + (id)[0]=(((id)[0])&0xfffffff0)|(((v)&0x00f00000)>>20), \ + (id)[1]=(((id)[1])&0x00000fff)|(((v)&0x000fffff)<<12)) +#define EVENT_ID_SET_PERIOD(id,v) \ + (assert(((v)>=0)&&((v)<=EVENT_ID_MAX_PERIOD)), \ + (id)[0]=(((id)[0])&0x0000000f)|(((v)&0x0fffffff)<<4)) + + /* RAW type event */ +#define EVENT_ID_MAX_NB_IN_RUN 0xffffffff +#define EVENT_ID_MAX_BURST_NB 0x00000fff +#define EVENT_ID_MAX_NB_IN_BURST 0x000fffff +#define LOAD_RAW_EVENT_ID(id,nir,bn,nib) \ + (assert(((nir)>=0) && ((nir) <= EVENT_ID_MAX_NB_IN_RUN) && \ + ((bn)>=0) && ((bn)<=EVENT_ID_MAX_BURST_NB) && \ + ((nib)>=0) && ((nib)<=EVENT_ID_MAX_NB_IN_BURST)), \ + (id)[0]=nir, \ + (id)[1]=((bn<<20)&0xfff00000)|(nib&0x000fffff)) +#define EVENT_ID_SET_NB_IN_RUN(id,nir) \ + (assert(((nir)>=0)&&((nir)<=EVENT_ID_MAX_NB_IN_RUN)), \ + (id)[0]=(nir)) +#define EVENT_ID_SET_BURST_NB(id,bn) \ + (assert(((bn)>=0)&&((bn)<=EVENT_ID_MAX_BURST_NB)), \ + (id)[1]=((id)[1]&0x000fffff)|(((bn)<<20)&0xfff00000)) +#define EVENT_ID_SET_NB_IN_BURST(id,nib) \ + (assert(((nib)>=0)&&((nib)<=EVENT_ID_MAX_NB_IN_BURST)), \ + (id)[1]=((id)[1]&0xfff00000)|((nib)&0x000fffff)) +#define EVENT_ID_GET_NB_IN_RUN(id) ((id)[0]) +#define EVENT_ID_GET_BURST_NB(id) (((id)[1]>>20)&0x00000fff) +#define EVENT_ID_GET_NB_IN_BURST(id) ((id)[1]&0x000fffff) + + /* All events */ +#define EQ_EVENT_ID(a,b) ((((a)[0])==((b)[0]))&&(((a)[1])==((b)[1]))) +#define GT_EVENT_ID(a,b) \ + (((((a)[0])>((b)[0])))||((((a)[0])==((b)[0]))&&(((a)[1])>((b)[1])))) +#define LT_EVENT_ID(a,b) \ + ((((a)[0])<((b)[0])) || ((((a)[0])==((b)[0]))&&(((a)[1])<((b)[1])))) +#define GE_EVENT_ID(a,b) (!LT_EVENT_ID(a,b)) +#define LE_EVENT_ID(a,b) (!GT_EVENT_ID(a,b)) +#define COPY_EVENT_ID(from,to) \ + memcpy((void*)to,(const void*)from,EVENT_ID_BYTES) +#define ADD_EVENT_ID(a,b) ((a)[1]+=(b)[1],(a)[0]+=(b)[0]) +#define SUB_EVENT_ID(a,b) ((a)[1]-=(b)[1],(a)[0]-=(b)[0]) +#define ZERO_EVENT_ID(id) memset(id,0,EVENT_ID_BYTES) + +/* ---------- Trigger pattern (and relative masks) ---------- */ +#define EVENT_TRIGGER_PATTERN_BYTES 8 +#define EVENT_TRIGGER_PATTERN_WORDS ((EVENT_TRIGGER_PATTERN_BYTES)>>2) +typedef unsigned long32 eventTriggerPatternType[EVENT_TRIGGER_PATTERN_WORDS]; +#define EVENT_TRIGGER_ID_MIN 1 +#define EVENT_TRIGGER_ID_MAX 50 +#define CHECK_TRIGGER(t) (assert(((t)>=EVENT_TRIGGER_ID_MIN) && \ + ((t)<=EVENT_TRIGGER_ID_MAX))) +#define TRIGGER_TO_BIT(t) (1<<((t)&0x1f)) +#define TRIGGER_TO_WORD(t) (CHECK_TRIGGER(t), (t)>>5) +#define ZERO_TRIGGER_PATTERN(p) memset(p,0,EVENT_TRIGGER_PATTERN_BYTES) +#define SET_TRIGGER_IN_PATTERN(p,id) (p)[TRIGGER_TO_WORD(id)] |= \ + TRIGGER_TO_BIT(id) +#define CLEAR_TRIGGER_IN_PATTERN(p,id) (p)[TRIGGER_TO_WORD(id)] &= \ + ~(TRIGGER_TO_BIT(id)) +#define FLIP_TRIGGER_IN_PATTERN(p,id) (p)[TRIGGER_TO_WORD(id)] ^= \ + TRIGGER_TO_BIT(id) +#define TEST_TRIGGER_IN_PATTERN(p,id) (((p)[TRIGGER_TO_WORD(id)] & \ + TRIGGER_TO_BIT(id)) != 0) +#define TRIGGER_PATTERN_INVALID(p) (((p)[0] & 1) == 0) +#define TRIGGER_PATTERN_VALID(p) (((p)[0] & 1) != 0) +#define VALIDATE_TRIGGER_PATTERN(p) ((p)[0] |= 1) +#define INVALIDATE_TRIGGER_PATTERN(p) ((p)[0] &= 0xfffffffe) +#define COPY_TRIGGER_PATTERN(f,t) memcpy(t,f,EVENT_TRIGGER_PATTERN_BYTES) +#define TRIGGER_PATTERN_OK(p) (((p)[1] & 0xfff80000) == 0) + +/* ---------- Detectors cluster (and relative masks) ---------- */ +#define EVENT_DETECTOR_PATTERN_BYTES 4 +#define EVENT_DETECTOR_PATTERN_WORDS (EVENT_DETECTOR_PATTERN_BYTES>>2) +typedef unsigned long32 eventDetectorPatternType[EVENT_DETECTOR_PATTERN_WORDS]; +#define EVENT_DETECTOR_ID_MIN 1 +#define EVENT_DETECTOR_ID_MAX 24 +#define CHECK_DETECTOR(d) (assert(((d) >= EVENT_DETECTOR_ID_MIN) &&\ + ((d) <= EVENT_DETECTOR_ID_MAX))) +#define DETECTOR_TO_BIT(d) (CHECK_DETECTOR(d), 1<<(d)) +#define ZERO_DETECTOR_PATTERN(p) ((p)[0] = 0) +#define SET_DETECTOR_IN_PATTERN(p,d) ((p)[0] |= DETECTOR_TO_BIT(d)) +#define CLEAR_DETECTOR_IN_PATTERN(p,d) ((p)[0] &= ~(DETECTOR_TO_BIT(d))) +#define FLIP_DETECTOR_IN_PATTERN(p,d) ((p)[0] ^= DETECTOR_TO_BIT(d)) +#define TEST_DETECTOR_IN_PATTERN(p,d) (((p)[0] & DETECTOR_TO_BIT(d))!=0) +#define DETECTOR_PATTERN_INVALID(p) (((p)[0] & 1) == 0) +#define DETECTOR_PATTERN_VALID(p) (((p)[0] & 1) != 0) +#define VALIDATE_DETECTOR_PATTERN(p) ((p)[0] |= 1) +#define INVALIDATE_DETECTOR_PATTERN(p) ((p)[0] &= 0xfffffffe) +#define COPY_DETECTOR_PATTERN(f,t) ((t)[0] = (f)[0]) +#define DETECTOR_PATTERN_OK(p) (((p)[0] & 0xfe000000) == 0) + +/* ---------- The sizes and positions of the typeAttribute field ---------- */ +#define ALL_ATTRIBUTE_WORDS 3 +#define ALL_ATTRIBUTE_BYTES (ALL_ATTRIBUTE_WORDS * 4) +#define ALL_ATTRIBUTE_BITS (ALL_ATTRIBUTE_BYTES * 8) +#define USER_ATTRIBUTE_WORDS 2 +#define USER_ATTRIBUTE_BYTES (USER_ATTRIBUTE_WORDS * 4) +#define USER_ATTRIBUTE_BITS (USER_ATTRIBUTE_BYTES * 8) +#define FIRST_USER_ATTRIBUTE 0 +#define LAST_USER_ATTRIBUTE (USER_ATTRIBUTE_BITS - 1) +#define SYSTEM_ATTRIBUTE_WORDS 1 +#define SYSTEM_ATTRIBUTE_BYTES (SYSTEM_ATTRIBUTE_WORDS * 4) +#define SYSTEM_ATTRIBUTE_BITS (SYSTEM_ATTRIBUTE_BYTES * 8) +#define FIRST_SYSTEM_ATTRIBUTE USER_ATTRIBUTE_BITS +#define LAST_SYSTEM_ATTRIBUTE (USER_ATTRIBUTE_BITS + \ + SYSTEM_ATTRIBUTE_BITS - 1) +typedef unsigned long32 eventTypeAttributeType[ALL_ATTRIBUTE_WORDS]; + + /* Word and bit definitions */ +#define SYS_ATTR_2_W(b) (assert(((b)>=64)&&((b)<=95)),2) +#define USR_ATTR_2_W(b) (assert(((b)>= 0)&&((b)<=63)),(b)>>5) +#define ATTR_2_W(b) (assert(((b)>= 0)&&((b)<=95)),(b)>>5) +#define ATTR_2_B(b) (1<<((b)&0x1f)) + + /* Macros to handle all attributes without distinction */ +#define RESET_ATTRIBUTES(m) ((m)[2] = (m)[1] = (m)[0] = 0) +#define SET_ANY_ATTRIBUTE(m,b) (m)[ATTR_2_W(b)] |= ATTR_2_B(b) +#define CLEAR_ANY_ATTRIBUTE(m,b) (m)[ATTR_2_W(b)] &= ~(ATTR_2_B(b)) +#define FLIP_ANY_ATTRIBUTE(m,b) (m)[ATTR_2_W(b)] ^= ATTR_2_B(b) +#define TEST_ANY_ATTRIBUTE(m,b) (((m)[ATTR_2_W(b)] & ATTR_2_B(b))!= 0) +#define COPY_ALL_ATTRIBUTES( from, to )\ + memcpy((void *)&to[0], (const void *)&from[0], ALL_ATTRIBUTE_BYTES) + + /* Macros to handle SYSTEM attributes */ +#define RESET_SYSTEM_ATTRIBUTES(m) ((m)[2] = 0) +#define SET_SYSTEM_ATTRIBUTE(m,b) (m)[SYS_ATTR_2_W(b)] |= ATTR_2_B(b) +#define CLEAR_SYSTEM_ATTRIBUTE(m,b) (m)[SYS_ATTR_2_W(b)] &= ~(ATTR_2_B(b)) +#define FLIP_SYSTEM_ATTRIBUTE(m,b) (m)[SYS_ATTR_2_W(b)] ^= ATTR_2_B(b) +#define TEST_SYSTEM_ATTRIBUTE(m,b) (((m)[SYS_ATTR_2_W(b)] & ATTR_2_B(b)) != 0) +#define COPY_SYSTEM_ATTRIBUTES( from, to ) \ + memcpy((void *)&to[2], (const void *)&from[2], SYSTEM_ATTRIBUTE_BYTES) + + /* Macros to handle USER attributes */ +#define RESET_USER_ATTRIBUTES(m) ((m)[0] = (m)[1] = 0) +#define SET_USER_ATTRIBUTE(m,b) (m)[USR_ATTR_2_W(b)] |= ATTR_2_B(b) +#define CLEAR_USER_ATTRIBUTE(m,b) (m)[USR_ATTR_2_W(b)] &= ~(ATTR_2_B(b)) +#define FLIP_USER_ATTRIBUTE(m,b) (m)[USR_ATTR_2_W(b)] ^= ATTR_2_B(b) +#define TEST_USER_ATTRIBUTE(m,b) (((m)[USR_ATTR_2_W(b)] & ATTR_2_B(b)) != 0) +#define COPY_USER_ATTRIBUTES( from, to ) \ + memcpy((void *)&to[0], (const void *)&from[0], USER_ATTRIBUTE_BYTES) + + /* System attributes assignment */ +#define ATTR_P_START 64 /* Start of a phase */ +#define ATTR_P_END 65 /* End of a phase */ +#define ATTR_START_OF_RUN_START ATTR_P_START/* Start of SOR phase */ +#define ATTR_START_OF_RUN_END ATTR_P_END /* End of SOR phase */ +#define ATTR_END_OF_RUN_START ATTR_P_START/* Start of EOR phase */ +#define ATTR_END_OF_RUN_END ATTR_P_END /* End of SOR phase */ +#define ATTR_EVENT_SWAPPED 66 /* Swapped event header */ +#define ATTR_EVENT_PAGED 67 /* Paged event */ +#define ATTR_SUPER_EVENT 68 /* Super event */ +#define ATTR_ORBIT_BC 69 /* Orbit/bunch crossing in ID*/ + +#define ATTR_EVENT_DATA_TRUNCATED 94 /* Truncated payload */ +#define ATTR_EVENT_ERROR 95 /* Invalid event content */ + +#define SYSTEM_ATTRIBUTES_OK(m) \ + ((((m)[2]) & ~(ATTR_2_B(ATTR_P_START) | \ + ATTR_2_B(ATTR_P_END) | \ + ATTR_2_B(ATTR_EVENT_SWAPPED) | \ + ATTR_2_B(ATTR_EVENT_PAGED) | \ + ATTR_2_B(ATTR_SUPER_EVENT) | \ + ATTR_2_B(ATTR_ORBIT_BC) | \ + ATTR_2_B(ATTR_EVENT_DATA_TRUNCATED) | \ + ATTR_2_B(ATTR_EVENT_ERROR))) == 0) + +/* ---------- LDC and GDC identifier ---------- */ +typedef unsigned long32 eventHostIdType; +typedef eventHostIdType eventLdcIdType; +typedef eventHostIdType eventGdcIdType; +#define HOST_ID_MIN ((eventHostIdType)0) /* The minimum allowed ID */ +#define HOST_ID_MAX ((eventHostIdType)511) /* The maximum allowed ID */ +#define VOID_ID ((eventHostIdType)-1) /* Unloaded ID */ + +/* ---------- The event header structure (with + without data) ---------- */ +struct eventHeaderStruct { + eventSizeType eventSize; + eventMagicType eventMagic; + eventHeadSizeType eventHeadSize; + eventVersionType eventVersion; + eventTypeType eventType; + eventRunNbType eventRunNb; + eventIdType eventId; + eventTriggerPatternType eventTriggerPattern; + eventDetectorPatternType eventDetectorPattern; + eventTypeAttributeType eventTypeAttribute; + eventLdcIdType eventLdcId; + eventGdcIdType eventGdcId; +}; + +struct eventStruct { + struct eventHeaderStruct eventHeader; + unsigned short eventRawData[1]; +}; + +/* ========== Definitions for the Vector ========== */ +typedef short eventVectorBankIdType; +typedef unsigned int eventVectorSizeType; +typedef unsigned int eventVectorOffsetType; + +struct eventVectorStruct { + eventVectorBankIdType eventVectorBankId; + unsigned eventVectorPointsToVector : 1; + eventVectorSizeType eventVectorSize; + eventVectorOffsetType eventVectorStartOffset; +}; + +/* ========== Definitions for the payload descriptor ========== */ +typedef unsigned long32 eventNumEquipmentsType; +typedef struct eventVectorStruct eventExtensionVectorType; + +struct vectorPayloadDescriptorStruct { + eventNumEquipmentsType eventNumEquipments; + eventExtensionVectorType eventExtensionVector; +}; + +/* ========== Definitions for the equipment header ========== */ +typedef long32 equipmentSizeType; +typedef long32 equipmentTypeType; +typedef long32 equipmentIdType; +typedef eventTypeAttributeType equipmentTypeAttributeType; +typedef long32 equipmentBasicElementSizeType; + +struct equipmentHeaderStruct { + equipmentSizeType equipmentSize; + equipmentTypeType equipmentType; + equipmentIdType equipmentId; + equipmentTypeAttributeType equipmentTypeAttribute; + equipmentBasicElementSizeType equipmentBasicElementSize; +}; + +struct equipmentDescriptorStruct { + struct equipmentHeaderStruct equipmentHeader; + struct eventVectorStruct equipmentVector; +}; + +struct equipmentStruct { + struct equipmentHeaderStruct equipmentHeader; + unsigned short equipmentRawData[1]; +}; + +/* ========== Global macros ========== */ + +/* The macro PAGED_EVENT_SIZE receives in input the ADDRESS of a paged + event and returns the size (in bytes) of the first page of the + event */ +#define PAGED_EVENT_SIZE( event ) \ + (EVENT_HEAD_BASE_SIZE +sizeof( struct vectorPayloadDescriptorStruct ) + \ + ((*(eventNumEquipmentsType *)((void*)event+EVENT_HEAD_BASE_SIZE))* \ + (sizeof( struct equipmentDescriptorStruct )))) + +#endif diff --git a/RAW/LinkDef.h b/RAW/LinkDef.h new file mode 100644 index 00000000000..e64c85dda08 --- /dev/null +++ b/RAW/LinkDef.h @@ -0,0 +1,23 @@ +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ enum EAliRawEventType; + +#pragma link C++ class AliRawEvent; +#pragma link C++ class AliRawEventHeader; +#pragma link C++ class AliRawEquipmentHeader; +#pragma link C++ class AliRawData; +#pragma link C++ class AliStats; +#pragma link C++ class AliRawDB; +#pragma link C++ class AliRawRFIODB; +#pragma link C++ class AliRawRootdDB; +#pragma link C++ class AliRawNullDB; +#pragma link C++ class AliTagDB; +#pragma link C++ class AliTagNullDB; +#pragma link C++ class AliRunDB; +#pragma link C++ class AliMDC; + +#endif diff --git a/RAW/Make-macros b/RAW/Make-macros new file mode 100644 index 00000000000..8900b5590dc --- /dev/null +++ b/RAW/Make-macros @@ -0,0 +1,96 @@ +##### MACROS ##### + +ROOTH = TH1.h + +SRCS = AliRawEvent.cxx + +HDRS = AliRawEvent.h LinkDef.h + +DICT = AliRawDict.cxx +DICTH = $(DICT:.cxx=.h) +DICTO = $(DICT:.cxx=.o) + +MAIN = alimdc.cxx +MAINO = $(MAIN:.cxx=.o) + +OBJS = $(SRCS:.cxx=.o) $(DICTO) + +ALLDICT = $(DICT) $(DICTH) +ALLSRCS = $(SRCS) $(HDRS) $(MAIN) DateEvent.h +ALLOBJS = $(OBJS) $(MAINO) + +ALIRAW = libAliRaw.so +ALIMDC = alimdc + + + +##### RULES ##### + +.SUFFIXES: .cxx +.PHONY: all rdm smi evb hlt debug + +.cxx.o: + $(CXX) $(OPT) $(CXXFLAGS) -c $< + + +##### TARGETS ##### + +all: $(ALIRAW) $(ALIMDC) + +rdm: $(ALIRAW) $(ALIMDC) + +smi: $(ALIRAW) $(ALIMDC) + +evb: $(ALIRAW) $(ALIMDC) + +hlt: $(ALIRAW) $(ALIMDC) + +$(ALIRAW): $(DICT) $(OBJS) + rm -f $(ALIRAW) + ifeq ($(PLATFORM),aix) + $(SHLD) -o $(ALIRAW) $(LIBS) -p 0 $(OBJS) + else + ifeq ($(PLATFORM),alpha) + $(SHLD) -o $(ALIRAW) $(OBJS) -lcxxstd -lcxx -lexc -lots -lc + else + $(LD) $(SOFLAGS) $(LDFLAGS) $(OBJS) -o $(ALIRAW) + endif + endif + chmod 555 $(ALIRAW) + @echo "$(ALIRAW) done" + + +$(ALIMDC): $(MAINO) $(ALIRAW) + ifeq ($(PLATFORM),aix) + ln -fs $(ALILRAW) libAliRaw.a + $(LD) $(LDFLAGS) $(MAINO) libAliRaw.a \ + $(LIBS) -o $(ALIMDC) + else + $(LD) $(LDFLAGS) $(MAINO) $(ALIRAW) \ + $(LIBS) -o $(ALIMDC) + endif + @if [ `id -u -n` = "alicemdc" ]; then \ + chmod 6755 alimdc; \ + fi + +$(DICT): $(HDRS) + @echo "Generating dictionary ..." + rootcint -f $(DICT) -c $(ROOTH) $(HDRS) + +$(DICTO): $(DICT) + $(CXX) $(NOOPT) $(CXXFLAGS) -c $(DICT) + +depend: + rmkdepend -fMake-depend -- $(CXXFLAGS) -- $(SRCS) $(MAIN) \ + > /dev/null 2>&1 + +dist: + rm -f alimdc.tar.gz ; \ + tar cvf alimdc.tar AA* $(ALLSRCS) .rootrc *.C Make* ; \ + gzip alimdc.tar + +clean: + @rm -f $(ALLOBJS) $(ALLDICT) + +distclean: clean + @rm -f $(ALIMDC) $(ALIRAW) diff --git a/RAW/Makefile b/RAW/Makefile new file mode 100644 index 00000000000..afc2a677dae --- /dev/null +++ b/RAW/Makefile @@ -0,0 +1,62 @@ +# Makefile for ALICE MDC program for Linux + +include $(ROOTSYS)/test/Makefile.arch + +LDFLAGS += -Wl,-rpath,/ROOT/Linux/CurrentRelease/root/lib \ + -Wl,-rpath,/date/smi/linux \ + -Wl,-rpath,/date/dim/linux \ + -Wl,-rpath,/adcRoot/alimdc4 + +ifneq ($(findstring rdm,$(MAKECMDGOALS)),) +CXXFLAGS += -DUSE_RDM +endif + +ifneq ($(findstring debug,$(MAKECMDGOALS)),) +CXXFLAGS += -DUSE_DEBUG -g +endif + +ifneq ($(findstring smi,$(MAKECMDGOALS)),) +#SMIDIR = ./smi +#DIMDIR = ./dim +SMIDIR = ../date/smi +DIMDIR = ../date/dim +CXXFLAGS += -DUSE_SMI -I$(SMIDIR)/smixx -I$(DIMDIR)/dim +LIBS += -L$(SMIDIR)/linux -lsmiui -lsmi -L$(DIMDIR)/linux -ldim +endif + +ifneq ($(findstring evb,$(MAKECMDGOALS)),) +ifneq ($(findstring rdm,$(MAKECMDGOALS)),) +EBDIR = ./eb +BMDIR = ./eb +DBMDIR = ./eb +DBDIR = ./eb +FIFODIR = ./eb +INFODIR = ./eb +else +EBDIR = ../date/eventBuilder +BMDIR = ../date/banksManager +DBMDIR = ../date/bufferManager +DBDIR = ../date/db +FIFODIR = ../date/simpleFifo +INFODIR = ../date/infoLogger +endif +CXXFLAGS += -DUSE_EB -I$(EBDIR) +LIBS += -L$(EBDIR)/Linux -L$(BMDIR)/Linux -L$(DBMDIR)/Linux \ + -L$(DBDIR)/Linux -L$(FIFODIR)/Linux -L$(INFODIR)/Linux \ + -lDateEb -lBanksManager -lDateBufferManager \ + -lDb -lFifo -lInfo +endif + +ifneq ($(findstring hlt,$(MAKECMDGOALS)),) +CXXFLAGS += -DUSE_HLT -I$(ALITPC) +LIBS += -L$(ALITPC) -lSTEER -lTPC +endif + +##### MACROS and TARGETS ##### + +include Make-macros + + +##### DEPENDENCIES ##### + +include Make-depend diff --git a/RAW/alimdc.cxx b/RAW/alimdc.cxx new file mode 100644 index 00000000000..3b631238ab7 --- /dev/null +++ b/RAW/alimdc.cxx @@ -0,0 +1,175 @@ +// @(#)alimdc:$Name$:$Id$ +// Author: Fons Rademakers 26/11/99 + +////////////////////////////////////////////////////////////////////////// +// // +// alimdc // +// // +// Main program used to create application that reads a data stream // +// from the DATE DAQ system and that creates a ROOT database. // +// // +// Written by: Fons Rademakers, 1/4/99. // +// // +////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef USE_SMI +extern "C" { + #include +} +#endif + +#include "AliRawEvent.h" + + +#ifdef USE_SMI +void SMI_handle_command() +{ + // Handle SMI commands + + char action[64], param[64]; + int n_params; + + smi_get_action(action, &n_params); + if (n_params >= 1) { + smi_get_par_value("PARAM", param); + } else { + strcpy(param, ""); + } + if (strcmp(action, "STOP") == 0) { + gAliMDC->StopLoop(); + } + smi_set_state("RUNNING"); +} +#endif + +//______________________________________________________________________________ +static void Usage(const char *prognam) +{ +#ifdef USE_SMI + fprintf(stderr, "Usage: %s [date_file]\n", + prognam); + fprintf(stderr, " = name used by SMI\n"); +#else + fprintf(stderr, "Usage: %s [date_file]\n", + prognam); +#endif + fprintf(stderr, " = maximum raw DB size (in bytes)\n"); + fprintf(stderr, " (precede by - to delete raw and tag databases on close)\n"); + fprintf(stderr, " = state of 3rd level filter (0 or 1)\n"); + fprintf(stderr, " = compression level (see TFile)\n"); + fprintf(stderr, " (precede by - to use RFIO, -0 is RFIO and 0 compression)\n"); + fprintf(stderr, " (precede by + to use rootd, -0 is rootd and 0 compression)\n"); + fprintf(stderr, " (precede by @ to use /dev/null as sink)\n"); +#ifdef USE_EB + fprintf(stderr, " [date_file] = optional input file (default reads from DATE EventBuffer)\n"); +#else + fprintf(stderr, " [date_file] = optional input file (default reads from pipe /tmp/alimdc.fifo)\n"); +#endif + fprintf(stderr, " (precede with - for endless loop on same file (use SIGUSR1 to stop)\n"); +} + +//______________________________________________________________________________ +int main(int argc, char **argv) +{ + // Convert a DATE data stream to a ROOT DB. + + // Set ROOT in batch mode + gROOT->SetBatch(); + +#ifdef USE_SMI + // Handle command line arguments + if ((argc == 2 && (!strcmp(argv[1], "-?") || !strcmp(argv[1], "-help"))) || + argc > 6 || argc < 5) { + Usage(argv[0]); + return 1; + } + + char smiobj[128]; + strcpy(smiobj, argv[1]); + smi_attach(smiobj, SMI_handle_command); + smi_volatile(); + smi_set_state("RUNNING"); + + for (int i = 1; i < argc-1; i++) + argv[i] = argv[i+1]; + argc--; + +#else + // Handle command line arguments + if ((argc == 2 && (!strcmp(argv[1], "-?") || !strcmp(argv[1], "-help"))) || + argc > 5 || argc < 4) { + Usage(argv[0]); + return 1; + } +#endif + + Bool_t useRFIO = kFALSE, useROOTD = kFALSE, useDEVNULL = kFALSE; + Bool_t useFilter = kFALSE, useLoop = kFALSE; + Bool_t delFiles = kFALSE; + Int_t fd = -1, compress; + Double_t maxFileSize; + + // no special arg checking so don't make errors + if (argv[1][0] == '-') { + delFiles = kTRUE; + maxFileSize = atoi(argv[1]+1); + } else + maxFileSize = atoi(argv[1]); + if (maxFileSize < 1000 || maxFileSize > 2.e9) { + Error(argv[0], "unreasonable file size %f\n", maxFileSize); + return 1; + } + + int filter = atoi(argv[2]); + if (filter != 0) + useFilter = kTRUE; + + if (argv[3][0] == '-') { + useRFIO = kTRUE; + compress = atoi(argv[3]+1); + } else if (argv[3][0] == '+') { + useROOTD = kTRUE; + compress = atoi(argv[3]+1); + } else if (argv[3][0] == '@') { + useDEVNULL = kTRUE; + compress = atoi(argv[3]+1); + } else + compress = atoi(argv[3]); + if (compress > 9) { + Error(argv[0], "unreasonable compression mode %d\n", compress); + return 1; + } + + if (argc == 5) { + char *file = argv[4]; + if (argv[4][0] == '-') { + useLoop = kTRUE; + file = argv[4]+1; + } + if ((fd = open(file, O_RDONLY)) == -1) { + Error(argv[0], "cannot open input file %s", argv[4]); + return 1; + } + } + + // Create MDC processor object and process input stream + AliMDC mdcproc(fd, compress, maxFileSize, useFilter, useRFIO, useROOTD, + useDEVNULL, useLoop, delFiles); + +#ifdef USE_DEBUG + mdcproc.SetDebugLevel(3); +#endif + + return mdcproc.Run(); +} -- 2.39.3