1 // @(#)alimdc:$Name$:$Id$
2 // Author: Fons Rademakers 26/11/99
3 // Updated: Dario Favretto 15/04/2003
8 #include <sys/statvfs.h>
10 #if defined(__APPLE__)
11 #include <sys/param.h>
12 #include <sys/mount.h>
26 #include <TStopwatch.h>
27 #include <TSQLServer.h>
28 #include <TSQLResult.h>
30 #if defined(__APPLE__)
33 #include "AliRawEvent.h"
37 #include "DateEvent.h"
40 #include "libDateEb.h"
45 ClassImp(AliRawEventHeader)
46 ClassImp(AliRawEquipmentHeader)
50 ClassImp(AliRawRFIODB)
51 ClassImp(AliRawRootdDB)
52 ClassImp(AliRawNullDB)
54 ClassImp(AliTagNullDB)
58 // Which MDC is this...
61 // Fixed file system locations for the different DB's
63 const char *kFifo = "/tmp/alimdc.fifo";
64 const char *kRawDBFS[2] = { "/tmp/mdc1", "/tmp/mdc2" };
65 const char *kTagDBFS = "/tmp/mdc1/tags";
66 const char *kRunDBFS = "/tmp/mdc1/meta";
67 const char *kRFIOFS = "rfio:/castor/cern.ch/user/r/rdm";
68 const char *kRootdFS = "root://localhost//tmp/mdc1";
70 const char *kFifo = "/tmp/alimdc.fifo";
71 const char *kRawDBFS[2] = { "/scratch/mdc1", "/scratch/mdc2" };
72 const char *kTagDBFS = "/scratch/mdc1/tags";
73 const char *kRunDBFS = "/scratch/mdc1/meta";
74 const char *kRFIOFS = "rfio:/castor/cern.ch/lcg/alicemdc4";
75 const char *kRootdFS = "root://localhost//tmp/mdc1";
78 // Maximum size of tag db files
79 const Double_t kMaxTagFileSize = 2.5e8; // 250MB
81 Bool_t AliMDC::fgDeleteFiles = kFALSE;
86 //______________________________________________________________________________
87 Bool_t AliRawEventHeader::DataIsSwapped() const
89 // Returns true if event data is swapped.
91 if (TEST_SYSTEM_ATTRIBUTE(fTypeAttribute, ATTR_EVENT_SWAPPED))
96 //______________________________________________________________________________
97 void AliRawEventHeader::Swap()
102 fSize = net2host(fSize);
103 fMagic = net2host(fMagic);
104 fHeadLen = net2host(fHeadLen);
105 fVersion = net2host(fVersion);
106 fType = net2host(fType);
107 fRunNb = net2host(fRunNb);
108 for (int i = 0; i < kIdWords; i++)
109 fId[i] = net2host(fId[i]);
110 for (int i = 0; i < kTriggerWords; i++)
111 fTriggerPattern[i] = net2host(fTriggerPattern[i]);
112 for (int i = 0; i < kDetectorWords; i++)
113 fDetectorPattern[i] = net2host(fDetectorPattern[i]);
114 for (int i = 0; i < kAttributeWords; i++)
115 fTypeAttribute[i] = net2host(fTypeAttribute[i]);
116 fLDCId = net2host(fLDCId);
117 fGDCId = net2host(fGDCId);
121 //______________________________________________________________________________
122 UInt_t AliRawEventHeader::GetEventInRun() const
124 // Get event number in run. Correct for fixed target mode which is used
125 // in the Data Challenge Setup.
127 if (!TEST_SYSTEM_ATTRIBUTE(fTypeAttribute, ATTR_ORBIT_BC)) {
128 return EVENT_ID_GET_NB_IN_RUN(fId);
133 //______________________________________________________________________________
134 const char *AliRawEventHeader::GetTypeName() const
136 // Get event type as a string.
140 return "START_OF_RUN";
145 case kStartOfRunFiles:
146 return "START_OF_RUN_FILES";
149 return "END_OF_RUN_FILES";
152 return "START_OF_BURST";
155 return "END_OF_BURST";
158 return "PHYSICS_EVENT";
160 case kCalibrationEvent:
161 return "CALIBRATION_EVENT";
164 return "EVENT_FORMAT_ERROR";
167 return "*** UNKNOWN EVENT TYPE ***";
173 //______________________________________________________________________________
174 void AliRawEquipmentHeader::Swap()
176 // Swap equipment header data. There is no way to see if the data
177 // has already been swapped. This method is only called when the
178 // header is read from the DATE event builder (GDC).
180 fSize = net2host(fSize);
181 fEquipmentType = net2host(fEquipmentType);
182 fEquipmentID = net2host(fEquipmentID);
183 fBasicElementSizeType = net2host(fBasicElementSizeType);
184 for (int i = 0; i < kAttributeWords; i++)
185 fTypeAttribute[i] = net2host(fTypeAttribute[i]);
189 //______________________________________________________________________________
190 AliRawEvent::AliRawEvent()
192 // Create ALICE event object. If ownData is kFALSE we will use a static
193 // raw data object, otherwise a private copy will be made.
196 fEvtHdr = new AliRawEventHeader;
202 //______________________________________________________________________________
203 AliRawEquipmentHeader *AliRawEvent::GetEquipmentHeader()
205 // Get equipment header part of AliRawEvent.
208 fEqpHdr = new AliRawEquipmentHeader;
213 //______________________________________________________________________________
214 AliRawData *AliRawEvent::GetRawData()
216 // Get raw data part of AliRawEvent.
219 fRawData = new AliRawData;
224 //______________________________________________________________________________
225 AliRawEvent *AliRawEvent::NextSubEvent()
227 // Returns next sub-event object.
230 fSubEvents = new TObjArray(100); // arbitrary, probably enough to prevent resizing
232 if (fSubEvents->GetSize() <= fNSubEvents) {
233 fSubEvents->Expand(fNSubEvents+10);
234 Warning("NextSubEvent", "expanded fSubEvents by 10 to %d",
235 fSubEvents->GetSize());
239 if (!(ev = (AliRawEvent *)fSubEvents->At(fNSubEvents))) {
240 ev = new AliRawEvent;
241 fSubEvents->AddAt(ev, fNSubEvents);
249 //______________________________________________________________________________
250 AliRawEvent *AliRawEvent::GetSubEvent(Int_t index)
252 return (AliRawEvent *)fSubEvents->At(index);
255 //______________________________________________________________________________
256 void AliRawEvent::Reset()
258 // Reset the event in case it needs to be re-used (avoiding costly
259 // new/delete cycle). We reset the size marker for the AliRawData
260 // objects and the sub event counter.
262 for (int i = 0; i < fNSubEvents; i++) {
263 AliRawEvent *ev = (AliRawEvent *)fSubEvents->At(i);
264 ev->GetRawData()->SetSize(0);
269 //______________________________________________________________________________
270 AliRawEvent::~AliRawEvent()
272 // Clean up event object. Delete also, possible, private raw data.
278 fSubEvents->Delete();
282 //______________________________________________________________________________
283 AliStats::AliStats(const char *filename, Int_t compmode, Bool_t filter)
285 // Create statistics object.
293 fFileName = filename;
294 fCompMode = compmode;
299 //______________________________________________________________________________
300 AliStats::~AliStats()
302 // Cleanup stats object.
307 //______________________________________________________________________________
308 AliStats &AliStats::operator=(const AliStats &rhs)
310 // AliStats assignment operator.
313 TObject::operator=(rhs);
314 fEvents = rhs.fEvents;
315 fFirstRun = rhs.fFirstRun;
316 fFirstEvent = rhs.fFirstEvent;
317 fLastRun = rhs.fLastRun;
318 fLastEvent = rhs.fLastEvent;
321 fFileName = rhs.fFileName;
322 fFileSize = rhs.fFileSize;
323 fCompFactor = rhs.fCompFactor;
324 fCompMode = rhs.fCompMode;
325 fFilter = rhs.fFilter;
326 fRTHist = rhs.fRTHist ? (TH1F*) rhs.fRTHist->Clone() : 0;
332 //______________________________________________________________________________
333 void AliStats::Fill(Float_t time)
335 // Fill histogram. This histogram shows the (hopefully constant) time
336 // it takes to fill the ROOT DB.
337 // Expects to be called 100 times for each file.
340 fRTHist = new TH1F("rtime","Real-time to write data chunk", 100, 0, 100);
341 fRTHist->SetDirectory(0);
344 fRTHist->Fill(fChunk, time);
348 //______________________________________________________________________________
349 void AliStats::WriteToDB(AliRawDB *rawdb)
351 // Write stats to raw DB, local run DB and global MySQL DB.
353 AliRawEventHeader &header = *rawdb->GetEvent()->GetHeader();
355 // Write stats into RawDB
356 TDirectory *ds = gDirectory;
357 rawdb->GetDB()->cd();
358 SetEvents(rawdb->GetEvents());
359 SetLastId(header.GetRunNumber(), header.GetEventInRun());
360 SetFileSize(rawdb->GetBytesWritten());
361 SetCompressionFactor(rawdb->GetCompressionFactor());
366 // Write stats also in the bookkeeping RunDB
367 AliRunDB *rundb = new AliRunDB;
369 rundb->UpdateRDBMS(this);
373 //______________________________________________________________________________
374 AliRawDB::AliRawDB(AliRawEvent *event, Double_t maxsize, Int_t compress,
377 // Create a new raw DB containing at most maxsize bytes.
381 fCompress = compress;
383 // Consistency check with DATE header file
384 if (fEvent->GetHeader()->HeaderSize() != EVENT_HEAD_BASE_SIZE) {
385 Error("AliRawDB", "inconsistency between DATE and AliRawEvent headers");
396 //______________________________________________________________________________
397 Bool_t AliRawDB::FSHasSpace(const char *fs)
399 // Check for at least fMaxSize bytes of free space on the file system.
400 // If the space is not available return kFALSE, kTRUE otherwise.
402 Long_t id, bsize, blocks, bfree;
404 if (gSystem->GetFsInfo(fs, &id, &bsize, &blocks, &bfree) == 1) {
405 Error("FSHasSpace", "could not stat file system %s", fs);
409 // Leave 5 percent of diskspace free
410 Double_t avail = Double_t(bfree) * 0.95;
411 if (avail*bsize > fMaxSize)
414 Warning("FSHasSpace", "no space on file system %s", fs);
418 //______________________________________________________________________________
419 const char *AliRawDB::GetFileName()
421 // Return filename based on hostname and date and time. This will make
422 // each file unique. Also makes sure (via FSHasSpace()) that there is
423 // enough space on the file system to store the file. Returns 0 in
424 // case of error or interrupt signal.
426 static TString fname;
427 static Bool_t fstoggle = kFALSE;
429 TString fs = fstoggle ? kRawDBFS[1] : kRawDBFS[0];
432 TString hostname = gSystem->HostName();
434 if ((pos = hostname.Index(".")) != kNPOS)
435 hostname.Remove(pos);
437 if (!FSHasSpace(fs)) {
439 fstoggle = !fstoggle;
440 fs = fstoggle ? kRawDBFS[1] : kRawDBFS[0];
441 if (FSHasSpace(fs)) break;
442 Info("GetFileName", "sleeping 30 seconds before retrying...");
443 gSystem->Sleep(30000); // sleep for 30 seconds
444 if (gAliMDC && gAliMDC->StopLoop())
449 fname = fs + "/" + hostname + "_";
450 fname += dt.GetDate();
452 fname += dt.GetTime();
455 fstoggle = !fstoggle;
460 //______________________________________________________________________________
461 Bool_t AliRawDB::Create()
463 // Create a new raw DB.
466 const char *fname = GetFileName();
467 if (!fname) return kFALSE;
469 fRawDB = TFile::Open(fname, "RECREATE",
470 Form("ALICE MDC%d raw DB", kMDC), fCompress);
472 Error("Create", "did not find right plugin to open file");
475 if (fRawDB->IsZombie()) {
476 if (fRawDB->GetErrno() == ENOSPC ||
477 fRawDB->GetErrno() == 1018 || // SECOMERR
478 fRawDB->GetErrno() == 1027) { // SESYSERR
479 fRawDB->ResetErrno();
481 Warning("Create", "file is zombie, sleeping 10 seconds before retrying...");
482 gSystem->Sleep(10000); // sleep 10 seconds before retrying
485 Error("Create", "error opening raw DB");
490 // Create raw data TTree
496 //______________________________________________________________________________
497 void AliRawDB::MakeTree()
499 // Create ROOT Tree object container.
501 fTree = new TTree("RAW", Form("ALICE MDC%d raw data tree", kMDC));
502 fTree->SetAutoSave(2000000000); // autosave when 2 Gbyte written
504 Int_t bufsize = 256000;
505 // splitting 29.6 MB/s, no splitting 35.3 MB/s on P4 2GHz 15k SCSI
508 fTree->Branch("rawevent", "AliRawEvent", &fEvent, bufsize, split);
511 //______________________________________________________________________________
512 void AliRawDB::Close()
523 // Close DB, this also deletes the fTree
526 if (AliMDC::DeleteFiles()) {
527 gSystem->Unlink(fRawDB->GetName());
533 // Create semaphore to say this file is finished
534 Int_t tfd = ::creat(Form("%s.done", fRawDB->GetName()), 0644);
541 //______________________________________________________________________________
542 Bool_t AliRawDB::NextFile()
544 // Close te current file and open a new one.
545 // Returns kFALSE in case opening failed.
549 if (!Create()) return kFALSE;
553 //______________________________________________________________________________
554 Float_t AliRawDB::GetCompressionFactor() const
556 // Return compression factor.
558 if (fTree->GetZipBytes() == 0.)
561 return fTree->GetTotBytes()/fTree->GetZipBytes();
565 //______________________________________________________________________________
566 AliRawRFIODB::AliRawRFIODB(AliRawEvent *event, Double_t maxsize, Int_t compress)
567 : AliRawDB(event, maxsize, compress, kFALSE)
569 // Create a new raw DB that will be accessed via RFIO.
573 // Set STAGE_POOL environment variable to current host
575 // THESE ENVIRONMENT SYMBOLS ARE NOW DEFINED BY THE ALICE DATE SETUP
576 // THEREFORE WE SHALL NOT USE ANY HARDCODED VALUES BUT RATHER USE
577 // WHATEVER HAS BEEN SET IN THE DATE SITE
578 //gSystem->Setenv("STAGE_POOL", "mdc4");
579 //gSystem->Setenv("STAGE_HOST", "lxshare003d");
587 fRawDB->UseCache(50, 0x200000); //0x100000 = 1MB)
590 //______________________________________________________________________________
591 const char *AliRawRFIODB::GetFileName()
593 // Return filename based on hostname and date and time. This will make
594 // each file unique. Also the directory will be made unique for each
595 // day by adding the date to the fs. Assumes there is always enough
596 // space on the device.
598 static TString fname;
600 TString fs = kRFIOFS;
603 // make a new subdirectory for each day
607 Long_t id, size, flags, time;
608 if (gSystem->GetPathInfo(fs, &id, &size, &flags, &time) == 1) {
609 // directory does not exist, create it
610 if (gSystem->mkdir(fs, kTRUE) == -1) {
611 Error("GetFileName", "cannot create dir %s, using %s", fs.Data(),
616 // FIXME: should check if fs is a directory
618 TString hostname = gSystem->HostName();
620 if ((pos = hostname.Index(".")) != kNPOS)
621 hostname.Remove(pos);
623 fname = fs + "/" + hostname + "_";
624 fname += dt.GetDate();
626 fname += dt.GetTime();
632 //______________________________________________________________________________
633 void AliRawRFIODB::Close()
635 // Close raw RFIO DB.
644 // Close DB, this also deletes the fTree
647 if (AliMDC::DeleteFiles())
648 gSystem->Exec(Form("rfrm %s", fRawDB->GetName()));
655 //______________________________________________________________________________
656 AliRawRootdDB::AliRawRootdDB(AliRawEvent *event, Double_t maxsize, Int_t compress)
657 : AliRawDB(event, maxsize, compress, kFALSE)
659 // Create a new raw DB that will be accessed via rootd daemon.
664 fRawDB->UseCache(50, 0x200000); //0x100000 = 1MB)
667 //______________________________________________________________________________
668 const char *AliRawRootdDB::GetFileName()
670 // Return filename based on hostname and date and time. This will make
671 // each file unique. Also the directory will be made unique for each
672 // day by adding the date to the fs. Assumes there is always enough
673 // space on the device.
675 static TString fname;
677 TString fs = kRootdFS;
681 // make a new subdirectory for each day
685 Long_t id, size, flags, time;
686 if (gSystem->GetPathInfo(fs, &id, &size, &flags, &time) == 1) {
687 // directory does not exist, create it
688 if (gSystem->mkdir(fs, kTRUE) == -1) {
689 Error("GetFileName", "cannot create dir %s, using %s", fs.Data(),
694 // FIXME: should check if fs is a directory
697 TString hostname = gSystem->HostName();
699 if ((pos = hostname.Index(".")) != kNPOS)
700 hostname.Remove(pos);
702 fname = fs + "/" + hostname + "_";
703 fname += dt.GetDate();
705 fname += dt.GetTime();
711 //______________________________________________________________________________
712 void AliRawRootdDB::Close()
714 // Close raw rootd DB.
723 // Close DB, this also deletes the fTree
727 // can use services of TFTP
728 if (AliMDC::DeleteFiles())
729 gSystem->Exec(Form("rfrm %s", fRawDB->GetName()));
737 //______________________________________________________________________________
738 AliRawNullDB::AliRawNullDB(AliRawEvent *event, Double_t maxsize, Int_t compress)
739 : AliRawDB(event, maxsize, compress, kFALSE)
741 // Create a new raw DB that will wrtie to /dev/null.
747 //______________________________________________________________________________
748 const char *AliRawNullDB::GetFileName()
750 // Return /dev/null as filename.
755 //______________________________________________________________________________
756 void AliRawNullDB::Close()
758 // Close raw RFIO DB.
767 // Close DB, this also deletes the fTree
775 //______________________________________________________________________________
776 AliTagDB::AliTagDB(AliRawEventHeader *header, Double_t maxsize, Bool_t create)
789 //______________________________________________________________________________
790 Bool_t AliTagDB::Create()
792 // Create a new tag DB.
794 fTagDB = new TFile(GetFileName(), "RECREATE",
795 Form("ALICE MDC%d tag DB", kMDC), 1);
796 if (fTagDB->IsZombie()) {
797 Error("Create", "error opening tag DB");
802 // Create ROOT Tree object container
803 fTree = new TTree("TAG", Form("ALICE MDC%d header data tree", kMDC));
804 fTree->SetAutoSave(100000000); // autosave when 100 Mbyte written
806 Int_t bufsize = 32000;
808 fTree->Branch("header", "AliRawEventHeader", &fHeader, bufsize, split);
813 //______________________________________________________________________________
814 void AliTagDB::Close()
825 // Close DB, this also deletes the fTree
828 if (AliMDC::DeleteFiles())
829 gSystem->Unlink(fTagDB->GetName());
835 //______________________________________________________________________________
836 Bool_t AliTagDB::NextFile()
838 // Close te current file and open a new one.
839 // Returns kFALSE in case opening failed.
843 if (!Create()) return kFALSE;
847 //______________________________________________________________________________
848 Float_t AliTagDB::GetCompressionFactor() const
850 // Return compression factor.
852 if (fTree->GetZipBytes() == 0.)
855 return fTree->GetTotBytes()/fTree->GetZipBytes();
858 //______________________________________________________________________________
859 const char *AliTagDB::GetFileName()
861 // Return filename based on hostname and date and time. This will make
862 // each file unique. The tags will be stored in the /data1/tags directory.
864 static char fname[64];
865 const char *fs = kTagDBFS;
867 // check that fs exists (crude check fails if fs is a file)
868 gSystem->MakeDirectory(fs);
872 strcpy(hostname, gSystem->HostName());
875 if ((s = strchr(hostname, '.')))
880 sprintf(fname, "%s/%s_%d_%d.root", fs, hostname, dt.GetDate(), dt.GetTime());
886 //______________________________________________________________________________
887 AliTagNullDB::AliTagNullDB(AliRawEventHeader *header, Double_t maxsize) :
888 AliTagDB(header, maxsize, kFALSE)
890 // Create tag db writing to /dev/null.
896 //______________________________________________________________________________
897 const char *AliTagNullDB::GetFileName()
899 // Return /dev/null as filename.
904 //______________________________________________________________________________
905 void AliTagNullDB::Close()
907 // Close null tag DB.
916 // Close DB, this also deletes the fTree
924 //______________________________________________________________________________
927 // Open run database, and get or create tree.
930 char hostname[64], filename[64];
931 const char *fs = kRunDBFS;
933 // check that fs exists (crude check fails if fs is a file)
934 gSystem->MakeDirectory(fs);
936 strcpy(hostname, gSystem->HostName());
939 if ((s = strchr(hostname, '.')))
942 sprintf(filename, "%s/%s_rundb.root", fs, hostname);
944 if (!gSystem->AccessPathName(filename, kFileExists))
945 fRunDB = new TFile(filename, "UPDATE");
947 fRunDB = new TFile(filename, "CREATE", Form("ALICE MDC%d Run DB", kMDC));
950 //______________________________________________________________________________
951 void AliRunDB::Update(AliStats *stats)
953 // Add stats object to database.
955 TDirectory *ds = gDirectory;
959 char *s = (char*)strrchr(stats->GetFileName(), '/');
964 strcpy(sname, stats->GetFileName());
965 s = strchr(sname, '.');
973 //______________________________________________________________________________
974 void AliRunDB::UpdateRDBMS(AliStats *stats)
976 // Add stats object to central MySQL DB.
981 strcpy(bt, stats->GetBeginTime().AsSQLString());
982 strcpy(et, stats->GetEndTime().AsSQLString());
984 sprintf(sql, "INSERT INTO mdc%dcatalog VALUES (0, '%s', %d, "
985 "%d, %d, %d, %d, %d, %d, %.2f, '%s', '%s', '%s')", kMDC,
986 stats->GetFileName(), (int)stats->GetFileSize(), stats->GetEvents(),
987 stats->GetFirstRun(), stats->GetFirstEvent(), stats->GetLastRun(),
988 stats->GetLastEvent(), stats->GetCompressionMode(),
989 stats->GetCompressionFactor(), stats->GetFilterState() ? "on" : "off",
992 // open connection to MySQL server on pcsalo
993 TSQLServer *db = TSQLServer::Connect("mysql://pcsalo.cern.ch/mdc", "alice", "amdc");
995 if (!db || db->IsZombie()) {
996 Error("UpdateRDBMS", "failed to connect to MySQL server on pcsalo");
1002 TSQLResult *res = db->Query(sql);
1005 Error("UpdateRDBMS", Form("insert into mdc%dcatalog failed", kMDC));
1006 printf("%s\n", sql);
1013 //______________________________________________________________________________
1014 void AliRunDB::Close()
1016 // Close run database.
1022 //----------------- Use SIGUSR1 to interupt endless loop -----------------------
1023 class AliMDCInterruptHandler : public TSignalHandler {
1025 AliMDC *fMDC; // alimdc to signal
1027 AliMDCInterruptHandler(AliMDC *mdc) : TSignalHandler(kSigUser1, kFALSE), fMDC(mdc) { }
1028 Bool_t Notify() { fMDC->SetStopLoop(); return kTRUE; }
1031 //______________________________________________________________________________
1032 AliMDC::AliMDC(Int_t fd, Int_t compress, Double_t maxFileSize, Bool_t useFilter,
1033 Bool_t useRFIO, Bool_t useROOTD, Bool_t useDEVNULL,
1034 Bool_t useLoop, Bool_t delFiles)
1036 // Create MDC processor object.
1039 fCompress = compress;
1040 fMaxFileSize = maxFileSize;
1041 fUseFilter = useFilter;
1043 fUseRootd = useROOTD;
1044 fUseDevNull = useDEVNULL;
1051 fgDeleteFiles = delFiles;
1055 if (!ebRegister()) {
1056 Error("AliMDC", "cannot register with the event builder (%s)",
1062 if ((mkfifo(kFifo, 0644) < 0) && (errno != EEXIST)) {
1063 Error("AliMDC", "cannot create fifo %s", kFifo);
1066 if ((chmod(kFifo, 0666) == -1) && (errno != EPERM)) {
1067 Error("AliMDC", "cannot change permission of fifo %s", kFifo);
1070 if ((fFd = open(kFifo, O_RDONLY)) == -1) {
1071 Error("AliMDC", "cannot open input file %s", kFifo);
1079 printf("<AliMDC::AliMDC>: input = %s, rawdb size = %f, filter = %s, "
1080 "looping = %s, compression = %d, delete files = %s",
1081 fUseFifo ? "fifo" : (fUseEb ? "eb" : "file"), fMaxFileSize,
1082 fUseFilter ? "on" : "off", fUseLoop ? "yes" : "no", fCompress,
1083 fgDeleteFiles ? "yes" : "no");
1085 printf(", use RFIO\n");
1087 printf(", use rootd\n");
1088 else if (fUseDevNull)
1089 printf(", write raw data to /dev/null\n");
1093 // install SIGUSR1 handler to allow clean interrupts
1094 gSystem->AddSignalHandler(new AliMDCInterruptHandler(this));
1099 //______________________________________________________________________________
1102 // Run the MDC processor. Read from the input stream and only return
1103 // when the input gave and EOF or a fatal error occured. On success 0
1104 // is returned, 1 in case of a fatality.
1109 // Make sure needed directories exist
1110 const char *dirs[4];
1111 dirs[0] = kRawDBFS[0];
1112 dirs[1] = kRawDBFS[1];
1115 for (int idir = 0; idir < 4; idir++) {
1116 gSystem->ResetErrno();
1117 gSystem->MakeDirectory(dirs[idir]);
1118 if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
1119 SysError("Run", "mkdir %s", dirs[idir]);
1124 // Used for statistics
1126 Double_t told = 0, tnew = 0;
1127 Float_t chunkSize = fMaxFileSize/100, nextChunk = chunkSize;
1129 // Event object used to store event data.
1130 AliRawEvent *event = new AliRawEvent;
1132 // Create new raw DB.
1135 rawdb = new AliRawRFIODB(event, fMaxFileSize, fCompress);
1137 rawdb = new AliRawRootdDB(event, fMaxFileSize, fCompress);
1138 else if (fUseDevNull)
1139 rawdb = new AliRawNullDB(event, fMaxFileSize, fCompress);
1141 rawdb = new AliRawDB(event, fMaxFileSize, fCompress);
1143 if (rawdb->IsZombie()) return 1;
1144 printf("Filling raw DB %s\n", rawdb->GetDBName());
1146 // Create new tag DB.
1149 tagdb = new AliTagNullDB(event->GetHeader(), kMaxTagFileSize);
1151 tagdb = new AliTagDB(event->GetHeader(), kMaxTagFileSize);
1152 if (tagdb->IsZombie())
1155 printf("Filling tag DB %s\n", tagdb->GetDBName());
1157 // Create AliStats object
1158 AliStats *stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter);
1160 // Shortcut for easy header access
1161 AliRawEventHeader &header = *event->GetHeader();
1163 // Process input stream
1166 struct iovec *ebvec;
1167 if ((ebvec = ebGetNextEvent()) == (void *)-1) {
1168 Error("Run", "error getting next event (%s)", ebGetLastError());
1172 // no event, sleep for 1 second and try again
1173 gSystem->Sleep(1000);
1176 char *ebdata = (char *) ebvec[0].iov_base;
1182 // Read event header
1183 if ((status = ReadHeader(header, ebdata)) != header.HeaderSize()) {
1187 ::lseek(fFd, 0, SEEK_SET);
1191 printf("<AliMDC::Run>: EOF, processed %d events\n", fNumEvents);
1197 // If we were in looping mode stop directly after a SIGUSR1 signal
1199 Info("Run", "SIGUSR1, processed %d events", fNumEvents);
1203 // Check if event has any hard track flagged
1204 Bool_t callFilter = kFALSE;
1205 // This needs to be re-engineered for the next ADC...
1206 //if (fUseFilter && TEST_USER_ATTRIBUTE(header.GetTypeAttribute(), 0))
1207 // callFilter = kTRUE;
1209 // Check event type and skip "Start of Run", "End of Run",
1210 // "Start of Run Files" and "End of Run Files"
1211 switch (header.GetType()) {
1214 case kStartOfRunFiles:
1215 case kEndOfRunFiles:
1217 Int_t skip = header.GetEventSize() - header.HeaderSize();
1219 ::lseek(fFd, skip, SEEK_CUR);
1222 Info("Run", "Skipping %s (%d bytes)", header.GetTypeName(), skip);
1228 Int_t s = header.GetEventSize() - header.HeaderSize();
1229 Info("Run", "Processing %s (%d bytes)", header.GetTypeName(), s);
1233 // Amount of data left to read for this event
1234 Int_t toRead = header.GetEventSize() - header.HeaderSize();
1236 // If there is less data for this event than the next sub-event
1237 // header, something is wrong. Skip to next event...
1238 if (toRead < header.HeaderSize()) {
1239 if ((status = DumpEvent(toRead)) != toRead) {
1244 Error("Run", "discarding event %d (too little data for header)", fNumEvents);
1248 // Loop over all sub-events... (LDCs)
1249 while (toRead > 0) {
1252 ebdata = (char *)ebvec[nsub].iov_base;
1256 Info("Run", "reading LDC %d", nsub);
1258 AliRawEvent *subEvent = event->NextSubEvent();
1260 // Read sub-event header
1261 AliRawEventHeader &subHeader = *subEvent->GetHeader();
1262 if ((status = ReadHeader(subHeader, ebdata)) != subHeader.HeaderSize()) {
1264 Error("Run", "unexpected EOF reading sub-event header");
1270 toRead -= subHeader.HeaderSize();
1273 ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize();
1276 Int_t rawSize = subHeader.GetEventSize() - subHeader.HeaderSize();
1278 // Read Equipment Header (in case of physics or calibration event)
1279 if (header.GetType() == kPhysicsEvent ||
1280 header.GetType() == kCalibrationEvent) {
1281 AliRawEquipmentHeader &equipment = *subEvent->GetEquipmentHeader();
1282 Int_t equipHeaderSize = equipment.HeaderSize();
1283 if ((status = ReadEquipmentHeader(equipment, header.DataIsSwapped(),
1284 ebdata)) != equipHeaderSize) {
1286 Error("Run", "unexpected EOF reading equipment-header");
1291 toRead -= equipHeaderSize;
1292 rawSize -= equipHeaderSize;
1294 ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize() +
1299 // Make sure raw data less than left over bytes for current event
1300 if (rawSize > toRead) {
1301 if ((status = DumpEvent(toRead)) != toRead) {
1306 Error("Run", "discarding event %d (too much data)", fNumEvents);
1310 // Read sub-event raw data
1311 AliRawData &subRaw = *subEvent->GetRawData();
1312 if ((status = ReadRawData(subRaw, rawSize, ebdata)) != rawSize) {
1314 Error("Run", "unexpected EOF reading sub-event raw data");
1321 if (TEST_USER_ATTRIBUTE(subHeader.GetTypeAttribute(), 0))
1324 // set size of all sectors without hard track flag to 0
1333 // Set stat info for first event of this file
1334 if (rawdb->GetEvents() == 0)
1335 stats->SetFirstId(header.GetRunNumber(), header.GetEventInRun());
1337 // Store raw event in tree
1340 // Store header in tree
1341 if (tagdb) tagdb->Fill();
1345 if (!(fNumEvents%10))
1346 printf("Processed event %d (%d)\n", fNumEvents, rawdb->GetEvents());
1348 // Filling time statistics
1349 if (rawdb->GetBytesWritten() > nextChunk) {
1350 tnew = timer.RealTime();
1351 stats->Fill(tnew-told);
1354 nextChunk += chunkSize;
1357 // Check size of raw db. If bigger than maxFileSize, close file
1358 // and continue with new file.
1359 if (rawdb->FileFull()) {
1361 printf("Written raw DB at a rate of %.1f MB/s\n",
1362 Float_t(fMaxFileSize / timer.RealTime() / 1000000.));
1364 // Write stats object to raw db, run db and MySQL
1365 stats->WriteToDB(rawdb);
1368 if (!rawdb->NextFile()) return 1;
1370 printf("Filling raw DB %s\n", rawdb->GetDBName());
1371 stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter);
1375 nextChunk = chunkSize;
1378 // Check size of tag db
1379 if (tagdb->FileFull()) {
1380 if (!tagdb->NextFile())
1383 printf("Filling tag DB %s\n", tagdb->GetDBName());
1386 // Make top event object ready for next event data
1387 //printf("Event %d has %d sub-events\n", fNumEvents, event->GetNSubEvents());
1391 if (!ebReleaseEvent(ebvec)) {
1392 Error("Run", "problem releasing event (%s)", ebGetLastError());
1398 printf("Written raw DB at a rate of %.1f MB/s\n",
1399 Float_t(fMaxFileSize / timer.RealTime() / 1000000.));
1401 // Write stats to raw db and run db and delete stats object
1402 stats->WriteToDB(rawdb);
1411 // Close input source
1416 if (fUseFifo && ::unlink(kFifo) == -1) {
1417 SysError("Run", "unlink");
1425 //______________________________________________________________________________
1426 Int_t AliMDC::Read(void *buffer, Int_t length)
1428 // Read exactly length bytes into buffer. Returns number of bytes
1429 // received, returns -1 in case of error and 0 for EOF.
1433 if (fFd < 0) return -1;
1436 char *buf = (char *)buffer;
1438 for (n = 0; n < length; n += nrecv) {
1439 if ((nrecv = read(fFd, buf+n, length-n)) <= 0) {
1443 SysError("Read", "read");
1450 //______________________________________________________________________________
1451 Int_t AliMDC::ReadHeader(AliRawEventHeader &header, void *eb)
1453 // Read header info from DATE data stream. Returns bytes read (i.e.
1454 // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
1459 // read from event builder memory area
1460 memcpy(header.HeaderBegin(), eb, header.HeaderSize());
1461 nrecv = header.HeaderSize();
1463 // read from fifo or file
1464 if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) !=
1465 header.HeaderSize()) {
1472 // Swap header data if needed
1473 if (header.IsSwapped())
1476 // Is header valid...
1477 if (!header.IsValid()) {
1478 Error("ReadHeader", "invalid header format");
1479 // try recovery... how?
1482 if (header.GetEventSize() < (UInt_t)header.HeaderSize()) {
1483 Error("ReadHeader", "invalid header size");
1484 // try recovery... how?
1491 //______________________________________________________________________________
1492 Int_t AliMDC::ReadEquipmentHeader(AliRawEquipmentHeader &header,
1493 Bool_t isSwapped, void *eb)
1495 // Read equipment header info from DATE data stream. Returns bytes read
1496 // (i.e. AliRawEquipmentHeader::HeaderSize()), -1 in case of error and
1497 // 0 for EOF. If isSwapped is kTRUE the event data is byte swapped
1498 // and we will swap the header to host format.
1503 // read from event builder memory area
1504 memcpy(header.HeaderBegin(), eb, header.HeaderSize());
1505 nrecv = header.HeaderSize();
1507 // read from fifo or file
1508 if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) !=
1509 header.HeaderSize()) {
1516 // Swap equipment header data if needed
1520 if (header.GetEquipmentSize() < (UInt_t)header.HeaderSize()) {
1521 Error("ReadEquipmentHeader", "invalid equipment header size");
1522 // try recovery... how?
1529 //______________________________________________________________________________
1530 Int_t AliMDC::ReadRawData(AliRawData &raw, Int_t size, void *eb)
1532 // Read raw data from DATE data stream. Returns bytes read (i.e.
1533 // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
1538 // read from event builder memory area
1539 raw.SetBuffer(eb, size);
1542 // read from fifo or file
1544 if ((nrecv = Read(raw.GetBuffer(), size)) != size) {
1546 Error("ReadRawData", "unexpected EOF");
1556 //______________________________________________________________________________
1557 Int_t AliMDC::DumpEvent(Int_t toRead)
1559 // This case should not happen, but if it does try to handle it
1560 // gracefully by reading the rest of the event and discarding it.
1561 // Returns bytes read, -1 in case of fatal error and 0 for EOF.
1563 Error("DumpEvent", "dumping %d bytes of event %d", toRead, fNumEvents);
1566 char *tbuf = new char[toRead];
1567 if ((nrecv = Read(tbuf, toRead)) != toRead) {
1569 Error("DumpEvent", "unexpected EOF");
1580 #include <AliTPCL3Tunnel.h>
1583 //______________________________________________________________________________
1584 Int_t AliMDC::Filter(AliRawData &raw)
1586 // Call 3rd level filter for this raw data segment.
1589 AliTPCL3Tunnel *tunnel = 0;
1592 tunnel = new AliTPCL3Tunnel(Form("%s/TPCparams.root",
1593 gSystem->Getenv("ALITPC")));
1596 Int_t obytes, nbytes;
1597 obytes = nbytes = raw.GetSize();
1598 char *outbuf = tunnel->EvalTrack((char *)raw.GetBuffer(), nbytes);
1600 raw.SetSize(nbytes);
1601 memcpy(raw.GetBuffer(), outbuf, nbytes);
1603 printf("Filter called for event %d: reduced from %d to %d\n", fNumEvents,
1609 printf("Filter called for event %d\n", fNumEvents);