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) const
252 // Get specified sub event. Returns 0 if sub event does not exist.
257 return (AliRawEvent *) fSubEvents->At(index);
260 //______________________________________________________________________________
261 void AliRawEvent::Reset()
263 // Reset the event in case it needs to be re-used (avoiding costly
264 // new/delete cycle). We reset the size marker for the AliRawData
265 // objects and the sub event counter.
267 for (int i = 0; i < fNSubEvents; i++) {
268 AliRawEvent *ev = (AliRawEvent *)fSubEvents->At(i);
269 ev->GetRawData()->SetSize(0);
274 //______________________________________________________________________________
275 AliRawEvent::~AliRawEvent()
277 // Clean up event object. Delete also, possible, private raw data.
283 fSubEvents->Delete();
287 //______________________________________________________________________________
288 AliStats::AliStats(const char *filename, Int_t compmode, Bool_t filter)
290 // Create statistics object.
298 fFileName = filename;
299 fCompMode = compmode;
304 //______________________________________________________________________________
305 AliStats::~AliStats()
307 // Cleanup stats object.
312 //______________________________________________________________________________
313 AliStats &AliStats::operator=(const AliStats &rhs)
315 // AliStats assignment operator.
318 TObject::operator=(rhs);
319 fEvents = rhs.fEvents;
320 fFirstRun = rhs.fFirstRun;
321 fFirstEvent = rhs.fFirstEvent;
322 fLastRun = rhs.fLastRun;
323 fLastEvent = rhs.fLastEvent;
326 fFileName = rhs.fFileName;
327 fFileSize = rhs.fFileSize;
328 fCompFactor = rhs.fCompFactor;
329 fCompMode = rhs.fCompMode;
330 fFilter = rhs.fFilter;
331 fRTHist = rhs.fRTHist ? (TH1F*) rhs.fRTHist->Clone() : 0;
337 //______________________________________________________________________________
338 void AliStats::Fill(Float_t time)
340 // Fill histogram. This histogram shows the (hopefully constant) time
341 // it takes to fill the ROOT DB.
342 // Expects to be called 100 times for each file.
345 fRTHist = new TH1F("rtime","Real-time to write data chunk", 100, 0, 100);
346 fRTHist->SetDirectory(0);
349 fRTHist->Fill(fChunk, time);
353 //______________________________________________________________________________
354 void AliStats::WriteToDB(AliRawDB *rawdb)
356 // Write stats to raw DB, local run DB and global MySQL DB.
358 AliRawEventHeader &header = *rawdb->GetEvent()->GetHeader();
360 // Write stats into RawDB
361 TDirectory *ds = gDirectory;
362 rawdb->GetDB()->cd();
363 SetEvents(rawdb->GetEvents());
364 SetLastId(header.GetRunNumber(), header.GetEventInRun());
365 SetFileSize(rawdb->GetBytesWritten());
366 SetCompressionFactor(rawdb->GetCompressionFactor());
371 // Write stats also in the bookkeeping RunDB
372 AliRunDB *rundb = new AliRunDB;
374 rundb->UpdateRDBMS(this);
378 //______________________________________________________________________________
379 AliRawDB::AliRawDB(AliRawEvent *event, Double_t maxsize, Int_t compress,
382 // Create a new raw DB containing at most maxsize bytes.
386 fCompress = compress;
388 // Consistency check with DATE header file
389 if (fEvent->GetHeader()->HeaderSize() != EVENT_HEAD_BASE_SIZE) {
390 Error("AliRawDB", "inconsistency between DATE and AliRawEvent headers");
401 //______________________________________________________________________________
402 Bool_t AliRawDB::FSHasSpace(const char *fs)
404 // Check for at least fMaxSize bytes of free space on the file system.
405 // If the space is not available return kFALSE, kTRUE otherwise.
407 Long_t id, bsize, blocks, bfree;
409 if (gSystem->GetFsInfo(fs, &id, &bsize, &blocks, &bfree) == 1) {
410 Error("FSHasSpace", "could not stat file system %s", fs);
414 // Leave 5 percent of diskspace free
415 Double_t avail = Double_t(bfree) * 0.95;
416 if (avail*bsize > fMaxSize)
419 Warning("FSHasSpace", "no space on file system %s", fs);
423 //______________________________________________________________________________
424 const char *AliRawDB::GetFileName()
426 // Return filename based on hostname and date and time. This will make
427 // each file unique. Also makes sure (via FSHasSpace()) that there is
428 // enough space on the file system to store the file. Returns 0 in
429 // case of error or interrupt signal.
431 static TString fname;
432 static Bool_t fstoggle = kFALSE;
434 TString fs = fstoggle ? kRawDBFS[1] : kRawDBFS[0];
437 TString hostname = gSystem->HostName();
439 if ((pos = hostname.Index(".")) != kNPOS)
440 hostname.Remove(pos);
442 if (!FSHasSpace(fs)) {
444 fstoggle = !fstoggle;
445 fs = fstoggle ? kRawDBFS[1] : kRawDBFS[0];
446 if (FSHasSpace(fs)) break;
447 Info("GetFileName", "sleeping 30 seconds before retrying...");
448 gSystem->Sleep(30000); // sleep for 30 seconds
449 if (gAliMDC && gAliMDC->StopLoop())
454 fname = fs + "/" + hostname + "_";
455 fname += dt.GetDate();
457 fname += dt.GetTime();
460 fstoggle = !fstoggle;
465 //______________________________________________________________________________
466 Bool_t AliRawDB::Create()
468 // Create a new raw DB.
471 const char *fname = GetFileName();
472 if (!fname) return kFALSE;
474 fRawDB = TFile::Open(fname, "RECREATE",
475 Form("ALICE MDC%d raw DB", kMDC), fCompress);
477 Error("Create", "did not find right plugin to open file");
480 if (fRawDB->IsZombie()) {
481 if (fRawDB->GetErrno() == ENOSPC ||
482 fRawDB->GetErrno() == 1018 || // SECOMERR
483 fRawDB->GetErrno() == 1027) { // SESYSERR
484 fRawDB->ResetErrno();
486 Warning("Create", "file is zombie, sleeping 10 seconds before retrying...");
487 gSystem->Sleep(10000); // sleep 10 seconds before retrying
490 Error("Create", "error opening raw DB");
495 // Create raw data TTree
501 //______________________________________________________________________________
502 void AliRawDB::MakeTree()
504 // Create ROOT Tree object container.
506 fTree = new TTree("RAW", Form("ALICE MDC%d raw data tree", kMDC));
507 fTree->SetAutoSave(2000000000); // autosave when 2 Gbyte written
509 Int_t bufsize = 256000;
510 // splitting 29.6 MB/s, no splitting 35.3 MB/s on P4 2GHz 15k SCSI
513 fTree->Branch("rawevent", "AliRawEvent", &fEvent, bufsize, split);
516 //______________________________________________________________________________
517 void AliRawDB::Close()
528 // Close DB, this also deletes the fTree
531 if (AliMDC::DeleteFiles()) {
532 gSystem->Unlink(fRawDB->GetName());
538 // Create semaphore to say this file is finished
539 Int_t tfd = ::creat(Form("%s.done", fRawDB->GetName()), 0644);
546 //______________________________________________________________________________
547 Bool_t AliRawDB::NextFile()
549 // Close te current file and open a new one.
550 // Returns kFALSE in case opening failed.
554 if (!Create()) return kFALSE;
558 //______________________________________________________________________________
559 Float_t AliRawDB::GetCompressionFactor() const
561 // Return compression factor.
563 if (fTree->GetZipBytes() == 0.)
566 return fTree->GetTotBytes()/fTree->GetZipBytes();
570 //______________________________________________________________________________
571 AliRawRFIODB::AliRawRFIODB(AliRawEvent *event, Double_t maxsize, Int_t compress)
572 : AliRawDB(event, maxsize, compress, kFALSE)
574 // Create a new raw DB that will be accessed via RFIO.
578 // Set STAGE_POOL environment variable to current host
580 // THESE ENVIRONMENT SYMBOLS ARE NOW DEFINED BY THE ALICE DATE SETUP
581 // THEREFORE WE SHALL NOT USE ANY HARDCODED VALUES BUT RATHER USE
582 // WHATEVER HAS BEEN SET IN THE DATE SITE
583 //gSystem->Setenv("STAGE_POOL", "mdc4");
584 //gSystem->Setenv("STAGE_HOST", "lxshare003d");
592 fRawDB->UseCache(50, 0x200000); //0x100000 = 1MB)
595 //______________________________________________________________________________
596 const char *AliRawRFIODB::GetFileName()
598 // Return filename based on hostname and date and time. This will make
599 // each file unique. Also the directory will be made unique for each
600 // day by adding the date to the fs. Assumes there is always enough
601 // space on the device.
603 static TString fname;
605 TString fs = kRFIOFS;
608 // make a new subdirectory for each day
612 Long_t id, size, flags, time;
613 if (gSystem->GetPathInfo(fs, &id, &size, &flags, &time) == 1) {
614 // directory does not exist, create it
615 if (gSystem->mkdir(fs, kTRUE) == -1) {
616 Error("GetFileName", "cannot create dir %s, using %s", fs.Data(),
621 // FIXME: should check if fs is a directory
623 TString hostname = gSystem->HostName();
625 if ((pos = hostname.Index(".")) != kNPOS)
626 hostname.Remove(pos);
628 fname = fs + "/" + hostname + "_";
629 fname += dt.GetDate();
631 fname += dt.GetTime();
637 //______________________________________________________________________________
638 void AliRawRFIODB::Close()
640 // Close raw RFIO DB.
649 // Close DB, this also deletes the fTree
652 if (AliMDC::DeleteFiles())
653 gSystem->Exec(Form("rfrm %s", fRawDB->GetName()));
660 //______________________________________________________________________________
661 AliRawRootdDB::AliRawRootdDB(AliRawEvent *event, Double_t maxsize, Int_t compress)
662 : AliRawDB(event, maxsize, compress, kFALSE)
664 // Create a new raw DB that will be accessed via rootd daemon.
669 fRawDB->UseCache(50, 0x200000); //0x100000 = 1MB)
672 //______________________________________________________________________________
673 const char *AliRawRootdDB::GetFileName()
675 // Return filename based on hostname and date and time. This will make
676 // each file unique. Also the directory will be made unique for each
677 // day by adding the date to the fs. Assumes there is always enough
678 // space on the device.
680 static TString fname;
682 TString fs = kRootdFS;
686 // make a new subdirectory for each day
690 Long_t id, size, flags, time;
691 if (gSystem->GetPathInfo(fs, &id, &size, &flags, &time) == 1) {
692 // directory does not exist, create it
693 if (gSystem->mkdir(fs, kTRUE) == -1) {
694 Error("GetFileName", "cannot create dir %s, using %s", fs.Data(),
699 // FIXME: should check if fs is a directory
702 TString hostname = gSystem->HostName();
704 if ((pos = hostname.Index(".")) != kNPOS)
705 hostname.Remove(pos);
707 fname = fs + "/" + hostname + "_";
708 fname += dt.GetDate();
710 fname += dt.GetTime();
716 //______________________________________________________________________________
717 void AliRawRootdDB::Close()
719 // Close raw rootd DB.
728 // Close DB, this also deletes the fTree
732 // can use services of TFTP
733 if (AliMDC::DeleteFiles())
734 gSystem->Exec(Form("rfrm %s", fRawDB->GetName()));
742 //______________________________________________________________________________
743 AliRawNullDB::AliRawNullDB(AliRawEvent *event, Double_t maxsize, Int_t compress)
744 : AliRawDB(event, maxsize, compress, kFALSE)
746 // Create a new raw DB that will wrtie to /dev/null.
752 //______________________________________________________________________________
753 const char *AliRawNullDB::GetFileName()
755 // Return /dev/null as filename.
760 //______________________________________________________________________________
761 void AliRawNullDB::Close()
763 // Close raw RFIO DB.
772 // Close DB, this also deletes the fTree
780 //______________________________________________________________________________
781 AliTagDB::AliTagDB(AliRawEventHeader *header, Double_t maxsize, Bool_t create)
794 //______________________________________________________________________________
795 Bool_t AliTagDB::Create()
797 // Create a new tag DB.
799 fTagDB = new TFile(GetFileName(), "RECREATE",
800 Form("ALICE MDC%d tag DB", kMDC), 1);
801 if (fTagDB->IsZombie()) {
802 Error("Create", "error opening tag DB");
807 // Create ROOT Tree object container
808 fTree = new TTree("TAG", Form("ALICE MDC%d header data tree", kMDC));
809 fTree->SetAutoSave(100000000); // autosave when 100 Mbyte written
811 Int_t bufsize = 32000;
813 fTree->Branch("header", "AliRawEventHeader", &fHeader, bufsize, split);
818 //______________________________________________________________________________
819 void AliTagDB::Close()
830 // Close DB, this also deletes the fTree
833 if (AliMDC::DeleteFiles())
834 gSystem->Unlink(fTagDB->GetName());
840 //______________________________________________________________________________
841 Bool_t AliTagDB::NextFile()
843 // Close te current file and open a new one.
844 // Returns kFALSE in case opening failed.
848 if (!Create()) return kFALSE;
852 //______________________________________________________________________________
853 Float_t AliTagDB::GetCompressionFactor() const
855 // Return compression factor.
857 if (fTree->GetZipBytes() == 0.)
860 return fTree->GetTotBytes()/fTree->GetZipBytes();
863 //______________________________________________________________________________
864 const char *AliTagDB::GetFileName()
866 // Return filename based on hostname and date and time. This will make
867 // each file unique. The tags will be stored in the /data1/tags directory.
869 static char fname[64];
870 const char *fs = kTagDBFS;
872 // check that fs exists (crude check fails if fs is a file)
873 gSystem->MakeDirectory(fs);
877 strcpy(hostname, gSystem->HostName());
880 if ((s = strchr(hostname, '.')))
885 sprintf(fname, "%s/%s_%d_%d.root", fs, hostname, dt.GetDate(), dt.GetTime());
891 //______________________________________________________________________________
892 AliTagNullDB::AliTagNullDB(AliRawEventHeader *header, Double_t maxsize) :
893 AliTagDB(header, maxsize, kFALSE)
895 // Create tag db writing to /dev/null.
901 //______________________________________________________________________________
902 const char *AliTagNullDB::GetFileName()
904 // Return /dev/null as filename.
909 //______________________________________________________________________________
910 void AliTagNullDB::Close()
912 // Close null tag DB.
921 // Close DB, this also deletes the fTree
929 //______________________________________________________________________________
932 // Open run database, and get or create tree.
935 char hostname[64], filename[64];
936 const char *fs = kRunDBFS;
938 // check that fs exists (crude check fails if fs is a file)
939 gSystem->MakeDirectory(fs);
941 strcpy(hostname, gSystem->HostName());
944 if ((s = strchr(hostname, '.')))
947 sprintf(filename, "%s/%s_rundb.root", fs, hostname);
949 if (!gSystem->AccessPathName(filename, kFileExists))
950 fRunDB = new TFile(filename, "UPDATE");
952 fRunDB = new TFile(filename, "CREATE", Form("ALICE MDC%d Run DB", kMDC));
955 //______________________________________________________________________________
956 void AliRunDB::Update(AliStats *stats)
958 // Add stats object to database.
960 TDirectory *ds = gDirectory;
964 char *s = (char*)strrchr(stats->GetFileName(), '/');
969 strcpy(sname, stats->GetFileName());
970 s = strchr(sname, '.');
978 //______________________________________________________________________________
979 void AliRunDB::UpdateRDBMS(AliStats *stats)
981 // Add stats object to central MySQL DB.
986 strcpy(bt, stats->GetBeginTime().AsSQLString());
987 strcpy(et, stats->GetEndTime().AsSQLString());
989 sprintf(sql, "INSERT INTO mdc%dcatalog VALUES (0, '%s', %d, "
990 "%d, %d, %d, %d, %d, %d, %.2f, '%s', '%s', '%s')", kMDC,
991 stats->GetFileName(), (int)stats->GetFileSize(), stats->GetEvents(),
992 stats->GetFirstRun(), stats->GetFirstEvent(), stats->GetLastRun(),
993 stats->GetLastEvent(), stats->GetCompressionMode(),
994 stats->GetCompressionFactor(), stats->GetFilterState() ? "on" : "off",
997 // open connection to MySQL server on pcsalo
998 TSQLServer *db = TSQLServer::Connect("mysql://pcsalo.cern.ch/mdc", "alice", "amdc");
1000 if (!db || db->IsZombie()) {
1001 Error("UpdateRDBMS", "failed to connect to MySQL server on pcsalo");
1002 printf("%s\n", sql);
1007 TSQLResult *res = db->Query(sql);
1010 Error("UpdateRDBMS", Form("insert into mdc%dcatalog failed", kMDC));
1011 printf("%s\n", sql);
1018 //______________________________________________________________________________
1019 void AliRunDB::Close()
1021 // Close run database.
1027 //----------------- Use SIGUSR1 to interupt endless loop -----------------------
1028 class AliMDCInterruptHandler : public TSignalHandler {
1030 AliMDC *fMDC; // alimdc to signal
1032 AliMDCInterruptHandler(AliMDC *mdc) : TSignalHandler(kSigUser1, kFALSE), fMDC(mdc) { }
1033 Bool_t Notify() { fMDC->SetStopLoop(); return kTRUE; }
1036 //______________________________________________________________________________
1037 AliMDC::AliMDC(Int_t fd, Int_t compress, Double_t maxFileSize, Bool_t useFilter,
1038 Bool_t useRFIO, Bool_t useROOTD, Bool_t useDEVNULL,
1039 Bool_t useLoop, Bool_t delFiles)
1041 // Create MDC processor object.
1044 fCompress = compress;
1045 fMaxFileSize = maxFileSize;
1046 fUseFilter = useFilter;
1048 fUseRootd = useROOTD;
1049 fUseDevNull = useDEVNULL;
1056 fgDeleteFiles = delFiles;
1060 if (!ebRegister()) {
1061 Error("AliMDC", "cannot register with the event builder (%s)",
1067 if ((mkfifo(kFifo, 0644) < 0) && (errno != EEXIST)) {
1068 Error("AliMDC", "cannot create fifo %s", kFifo);
1071 if ((chmod(kFifo, 0666) == -1) && (errno != EPERM)) {
1072 Error("AliMDC", "cannot change permission of fifo %s", kFifo);
1075 if ((fFd = open(kFifo, O_RDONLY)) == -1) {
1076 Error("AliMDC", "cannot open input file %s", kFifo);
1084 printf("<AliMDC::AliMDC>: input = %s, rawdb size = %f, filter = %s, "
1085 "looping = %s, compression = %d, delete files = %s",
1086 fUseFifo ? "fifo" : (fUseEb ? "eb" : "file"), fMaxFileSize,
1087 fUseFilter ? "on" : "off", fUseLoop ? "yes" : "no", fCompress,
1088 fgDeleteFiles ? "yes" : "no");
1090 printf(", use RFIO\n");
1092 printf(", use rootd\n");
1093 else if (fUseDevNull)
1094 printf(", write raw data to /dev/null\n");
1098 // install SIGUSR1 handler to allow clean interrupts
1099 gSystem->AddSignalHandler(new AliMDCInterruptHandler(this));
1104 //______________________________________________________________________________
1107 // Run the MDC processor. Read from the input stream and only return
1108 // when the input gave and EOF or a fatal error occured. On success 0
1109 // is returned, 1 in case of a fatality.
1114 // Make sure needed directories exist
1115 const char *dirs[4];
1116 dirs[0] = kRawDBFS[0];
1117 dirs[1] = kRawDBFS[1];
1120 for (int idir = 0; idir < 4; idir++) {
1121 gSystem->ResetErrno();
1122 gSystem->MakeDirectory(dirs[idir]);
1123 if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
1124 SysError("Run", "mkdir %s", dirs[idir]);
1129 // Used for statistics
1131 Double_t told = 0, tnew = 0;
1132 Float_t chunkSize = fMaxFileSize/100, nextChunk = chunkSize;
1134 // Event object used to store event data.
1135 AliRawEvent *event = new AliRawEvent;
1137 // Create new raw DB.
1140 rawdb = new AliRawRFIODB(event, fMaxFileSize, fCompress);
1142 rawdb = new AliRawRootdDB(event, fMaxFileSize, fCompress);
1143 else if (fUseDevNull)
1144 rawdb = new AliRawNullDB(event, fMaxFileSize, fCompress);
1146 rawdb = new AliRawDB(event, fMaxFileSize, fCompress);
1148 if (rawdb->IsZombie()) return 1;
1149 printf("Filling raw DB %s\n", rawdb->GetDBName());
1151 // Create new tag DB.
1154 tagdb = new AliTagNullDB(event->GetHeader(), kMaxTagFileSize);
1156 tagdb = new AliTagDB(event->GetHeader(), kMaxTagFileSize);
1157 if (tagdb->IsZombie())
1160 printf("Filling tag DB %s\n", tagdb->GetDBName());
1162 // Create AliStats object
1163 AliStats *stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter);
1165 // Shortcut for easy header access
1166 AliRawEventHeader &header = *event->GetHeader();
1168 // Process input stream
1171 struct iovec *ebvec;
1172 if ((ebvec = ebGetNextEvent()) == (void *)-1) {
1173 Error("Run", "error getting next event (%s)", ebGetLastError());
1177 // no event, sleep for 1 second and try again
1178 gSystem->Sleep(1000);
1181 char *ebdata = (char *) ebvec[0].iov_base;
1187 // Read event header
1188 if ((status = ReadHeader(header, ebdata)) != header.HeaderSize()) {
1192 ::lseek(fFd, 0, SEEK_SET);
1196 printf("<AliMDC::Run>: EOF, processed %d events\n", fNumEvents);
1202 // If we were in looping mode stop directly after a SIGUSR1 signal
1204 Info("Run", "SIGUSR1, processed %d events", fNumEvents);
1208 // Check if event has any hard track flagged
1209 Bool_t callFilter = kFALSE;
1210 // This needs to be re-engineered for the next ADC...
1211 //if (fUseFilter && TEST_USER_ATTRIBUTE(header.GetTypeAttribute(), 0))
1212 // callFilter = kTRUE;
1214 // Check event type and skip "Start of Run", "End of Run",
1215 // "Start of Run Files" and "End of Run Files"
1216 switch (header.GetType()) {
1219 case kStartOfRunFiles:
1220 case kEndOfRunFiles:
1222 Int_t skip = header.GetEventSize() - header.HeaderSize();
1224 ::lseek(fFd, skip, SEEK_CUR);
1227 Info("Run", "Skipping %s (%d bytes)", header.GetTypeName(), skip);
1233 Int_t s = header.GetEventSize() - header.HeaderSize();
1234 Info("Run", "Processing %s (%d bytes)", header.GetTypeName(), s);
1238 // Amount of data left to read for this event
1239 Int_t toRead = header.GetEventSize() - header.HeaderSize();
1241 // If there is less data for this event than the next sub-event
1242 // header, something is wrong. Skip to next event...
1243 if (toRead < header.HeaderSize()) {
1244 if ((status = DumpEvent(toRead)) != toRead) {
1249 Error("Run", "discarding event %d (too little data for header)", fNumEvents);
1253 // Loop over all sub-events... (LDCs)
1254 while (toRead > 0) {
1257 ebdata = (char *)ebvec[nsub].iov_base;
1261 Info("Run", "reading LDC %d", nsub);
1263 AliRawEvent *subEvent = event->NextSubEvent();
1265 // Read sub-event header
1266 AliRawEventHeader &subHeader = *subEvent->GetHeader();
1267 if ((status = ReadHeader(subHeader, ebdata)) != subHeader.HeaderSize()) {
1269 Error("Run", "unexpected EOF reading sub-event header");
1275 toRead -= subHeader.HeaderSize();
1278 ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize();
1281 Int_t rawSize = subHeader.GetEventSize() - subHeader.HeaderSize();
1283 // Read Equipment Header (in case of physics or calibration event)
1284 if (header.GetType() == kPhysicsEvent ||
1285 header.GetType() == kCalibrationEvent) {
1286 AliRawEquipmentHeader &equipment = *subEvent->GetEquipmentHeader();
1287 Int_t equipHeaderSize = equipment.HeaderSize();
1288 if ((status = ReadEquipmentHeader(equipment, header.DataIsSwapped(),
1289 ebdata)) != equipHeaderSize) {
1291 Error("Run", "unexpected EOF reading equipment-header");
1296 toRead -= equipHeaderSize;
1297 rawSize -= equipHeaderSize;
1299 ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize() +
1304 // Make sure raw data less than left over bytes for current event
1305 if (rawSize > toRead) {
1306 if ((status = DumpEvent(toRead)) != toRead) {
1311 Error("Run", "discarding event %d (too much data)", fNumEvents);
1315 // Read sub-event raw data
1316 AliRawData &subRaw = *subEvent->GetRawData();
1317 if ((status = ReadRawData(subRaw, rawSize, ebdata)) != rawSize) {
1319 Error("Run", "unexpected EOF reading sub-event raw data");
1326 if (TEST_USER_ATTRIBUTE(subHeader.GetTypeAttribute(), 0))
1329 // set size of all sectors without hard track flag to 0
1338 // Set stat info for first event of this file
1339 if (rawdb->GetEvents() == 0)
1340 stats->SetFirstId(header.GetRunNumber(), header.GetEventInRun());
1342 // Store raw event in tree
1345 // Store header in tree
1346 if (tagdb) tagdb->Fill();
1350 if (!(fNumEvents%10))
1351 printf("Processed event %d (%d)\n", fNumEvents, rawdb->GetEvents());
1353 // Filling time statistics
1354 if (rawdb->GetBytesWritten() > nextChunk) {
1355 tnew = timer.RealTime();
1356 stats->Fill(tnew-told);
1359 nextChunk += chunkSize;
1362 // Check size of raw db. If bigger than maxFileSize, close file
1363 // and continue with new file.
1364 if (rawdb->FileFull()) {
1366 printf("Written raw DB at a rate of %.1f MB/s\n",
1367 Float_t(fMaxFileSize / timer.RealTime() / 1000000.));
1369 // Write stats object to raw db, run db and MySQL
1370 stats->WriteToDB(rawdb);
1373 if (!rawdb->NextFile()) return 1;
1375 printf("Filling raw DB %s\n", rawdb->GetDBName());
1376 stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter);
1380 nextChunk = chunkSize;
1383 // Check size of tag db
1384 if (tagdb->FileFull()) {
1385 if (!tagdb->NextFile())
1388 printf("Filling tag DB %s\n", tagdb->GetDBName());
1391 // Make top event object ready for next event data
1392 //printf("Event %d has %d sub-events\n", fNumEvents, event->GetNSubEvents());
1396 if (!ebReleaseEvent(ebvec)) {
1397 Error("Run", "problem releasing event (%s)", ebGetLastError());
1403 printf("Written raw DB at a rate of %.1f MB/s\n",
1404 Float_t(fMaxFileSize / timer.RealTime() / 1000000.));
1406 // Write stats to raw db and run db and delete stats object
1407 stats->WriteToDB(rawdb);
1416 // Close input source
1421 if (fUseFifo && ::unlink(kFifo) == -1) {
1422 SysError("Run", "unlink");
1430 //______________________________________________________________________________
1431 Int_t AliMDC::Read(void *buffer, Int_t length)
1433 // Read exactly length bytes into buffer. Returns number of bytes
1434 // received, returns -1 in case of error and 0 for EOF.
1438 if (fFd < 0) return -1;
1441 char *buf = (char *)buffer;
1443 for (n = 0; n < length; n += nrecv) {
1444 if ((nrecv = read(fFd, buf+n, length-n)) <= 0) {
1448 SysError("Read", "read");
1455 //______________________________________________________________________________
1456 Int_t AliMDC::ReadHeader(AliRawEventHeader &header, void *eb)
1458 // Read header info from DATE data stream. Returns bytes read (i.e.
1459 // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
1464 // read from event builder memory area
1465 memcpy(header.HeaderBegin(), eb, header.HeaderSize());
1466 nrecv = header.HeaderSize();
1468 // read from fifo or file
1469 if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) !=
1470 header.HeaderSize()) {
1477 // Swap header data if needed
1478 if (header.IsSwapped())
1481 // Is header valid...
1482 if (!header.IsValid()) {
1483 Error("ReadHeader", "invalid header format");
1484 // try recovery... how?
1487 if (header.GetEventSize() < (UInt_t)header.HeaderSize()) {
1488 Error("ReadHeader", "invalid header size");
1489 // try recovery... how?
1496 //______________________________________________________________________________
1497 Int_t AliMDC::ReadEquipmentHeader(AliRawEquipmentHeader &header,
1498 Bool_t isSwapped, void *eb)
1500 // Read equipment header info from DATE data stream. Returns bytes read
1501 // (i.e. AliRawEquipmentHeader::HeaderSize()), -1 in case of error and
1502 // 0 for EOF. If isSwapped is kTRUE the event data is byte swapped
1503 // and we will swap the header to host format.
1508 // read from event builder memory area
1509 memcpy(header.HeaderBegin(), eb, header.HeaderSize());
1510 nrecv = header.HeaderSize();
1512 // read from fifo or file
1513 if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) !=
1514 header.HeaderSize()) {
1521 // Swap equipment header data if needed
1525 if (header.GetEquipmentSize() < (UInt_t)header.HeaderSize()) {
1526 Error("ReadEquipmentHeader", "invalid equipment header size");
1527 // try recovery... how?
1534 //______________________________________________________________________________
1535 Int_t AliMDC::ReadRawData(AliRawData &raw, Int_t size, void *eb)
1537 // Read raw data from DATE data stream. Returns bytes read (i.e.
1538 // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
1543 // read from event builder memory area
1544 raw.SetBuffer(eb, size);
1547 // read from fifo or file
1549 if ((nrecv = Read(raw.GetBuffer(), size)) != size) {
1551 Error("ReadRawData", "unexpected EOF");
1561 //______________________________________________________________________________
1562 Int_t AliMDC::DumpEvent(Int_t toRead)
1564 // This case should not happen, but if it does try to handle it
1565 // gracefully by reading the rest of the event and discarding it.
1566 // Returns bytes read, -1 in case of fatal error and 0 for EOF.
1568 Error("DumpEvent", "dumping %d bytes of event %d", toRead, fNumEvents);
1571 char *tbuf = new char[toRead];
1572 if ((nrecv = Read(tbuf, toRead)) != toRead) {
1574 Error("DumpEvent", "unexpected EOF");
1585 #include <AliTPCL3Tunnel.h>
1588 //______________________________________________________________________________
1589 Int_t AliMDC::Filter(AliRawData &raw)
1591 // Call 3rd level filter for this raw data segment.
1594 AliTPCL3Tunnel *tunnel = 0;
1597 tunnel = new AliTPCL3Tunnel(Form("%s/TPCparams.root",
1598 gSystem->Getenv("ALITPC")));
1601 Int_t obytes, nbytes;
1602 obytes = nbytes = raw.GetSize();
1603 char *outbuf = tunnel->EvalTrack((char *)raw.GetBuffer(), nbytes);
1605 raw.SetSize(nbytes);
1606 memcpy(raw.GetBuffer(), outbuf, nbytes);
1608 printf("Filter called for event %d: reduced from %d to %d\n", fNumEvents,
1614 printf("Filter called for event %d\n", fNumEvents);