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