]> git.uio.no Git - u/mrichter/AliRoot.git/blame - RAW/AliRawEvent.cxx
neatening
[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(),
5ea08be4 508 Form("ALICE MDC%d raw DB", kMDC), fCompress);
509 if (!fRawDB) {
c689d2f6 510 if (retry < kMaxRetry) {
f58b87cb 511 Warning("Create", "failure to open file, sleeping %d %s before retrying...",
c689d2f6 512 kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
513 gSystem->Sleep(kMaxSleep*1000);
20e93573 514 goto again;
515 }
c689d2f6 516 Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
5ea08be4 517 return kFALSE;
518 }
519 if (fRawDB->IsZombie()) {
520 if (fRawDB->GetErrno() == ENOSPC ||
521 fRawDB->GetErrno() == 1018 || // SECOMERR
522 fRawDB->GetErrno() == 1027) { // SESYSERR
523 fRawDB->ResetErrno();
524 delete fRawDB;
f58b87cb 525 Warning("Create", "file is a zombie (no space), sleeping %d %s before retrying...",
c689d2f6 526 kMaxSleepLong, kMaxSleepLong==1 ? "second" : "seconds");
527 gSystem->Sleep(kMaxSleepLong*1000); // sleep 10 seconds before retrying
5ea08be4 528 goto again;
529 }
20e93573 530 Error("Create", "file %s is zombie", fname);
531 fRawDB->ResetErrno();
532 delete fRawDB;
5ea08be4 533 fRawDB = 0;
c689d2f6 534 if (retry < kMaxRetry) {
f58b87cb 535 Warning("Create", "file is a zombie, sleeping %d %s before retrying...",
c689d2f6 536 kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
537 gSystem->Sleep(kMaxSleep*1000);
20e93573 538 goto again;
539 }
c689d2f6 540 Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
5ea08be4 541 return kFALSE;
542 }
543
544 // Create raw data TTree
545 MakeTree();
546
547 return kTRUE;
548}
549
550//______________________________________________________________________________
551void AliRawDB::MakeTree()
552{
553 // Create ROOT Tree object container.
554
555 fTree = new TTree("RAW", Form("ALICE MDC%d raw data tree", kMDC));
556 fTree->SetAutoSave(2000000000); // autosave when 2 Gbyte written
557
558 Int_t bufsize = 256000;
559 // splitting 29.6 MB/s, no splitting 35.3 MB/s on P4 2GHz 15k SCSI
560 //Int_t split = 1;
561 Int_t split = 0;
562 fTree->Branch("rawevent", "AliRawEvent", &fEvent, bufsize, split);
563}
564
565//______________________________________________________________________________
566void AliRawDB::Close()
567{
568 // Close raw DB.
569
570 if (!fRawDB) return;
571
572 fRawDB->cd();
573
574 // Write the tree.
575 fTree->Write();
576
577 // Close DB, this also deletes the fTree
578 fRawDB->Close();
579
580 if (AliMDC::DeleteFiles()) {
581 gSystem->Unlink(fRawDB->GetName());
582 delete fRawDB;
583 fRawDB = 0;
584 return;
585 }
586
587 // Create semaphore to say this file is finished
588 Int_t tfd = ::creat(Form("%s.done", fRawDB->GetName()), 0644);
589 close(tfd);
590
591 delete fRawDB;
592 fRawDB = 0;
593}
594
595//______________________________________________________________________________
596Bool_t AliRawDB::NextFile()
597{
598 // Close te current file and open a new one.
599 // Returns kFALSE in case opening failed.
600
601 Close();
602
603 if (!Create()) return kFALSE;
604 return kTRUE;
605}
606
607//______________________________________________________________________________
608Float_t AliRawDB::GetCompressionFactor() const
609{
610 // Return compression factor.
611
612 if (fTree->GetZipBytes() == 0.)
613 return 1.0;
614 else
615 return fTree->GetTotBytes()/fTree->GetZipBytes();
616}
617
618
619//______________________________________________________________________________
620AliRawRFIODB::AliRawRFIODB(AliRawEvent *event, Double_t maxsize, Int_t compress)
621 : AliRawDB(event, maxsize, compress, kFALSE)
622{
623 // Create a new raw DB that will be accessed via RFIO.
624
625#ifndef USE_RDM
626 static int init = 0;
627 // Set STAGE_POOL environment variable to current host
628 if (!init) {
629 // THESE ENVIRONMENT SYMBOLS ARE NOW DEFINED BY THE ALICE DATE SETUP
630 // THEREFORE WE SHALL NOT USE ANY HARDCODED VALUES BUT RATHER USE
631 // WHATEVER HAS BEEN SET IN THE DATE SITE
9174317d 632 //gSystem->Setenv("STAGE_POOL", "lcg00");
633 //gSystem->Setenv("STAGE_HOST", "stage013");
5ea08be4 634 init = 1;
635 }
636#endif
637
638 if (!Create())
639 MakeZombie();
640 else
641 fRawDB->UseCache(50, 0x200000); //0x100000 = 1MB)
642}
643
644//______________________________________________________________________________
c689d2f6 645const char *AliRawRFIODB::GetFileName() const
5ea08be4 646{
647 // Return filename based on hostname and date and time. This will make
648 // each file unique. Also the directory will be made unique for each
649 // day by adding the date to the fs. Assumes there is always enough
650 // space on the device.
651
652 static TString fname;
653
654 TString fs = kRFIOFS;
655 TDatime dt;
656
657 // make a new subdirectory for each day
658 fs += "/adc-";
659 fs += dt.GetDate();
660
661 Long_t id, size, flags, time;
662 if (gSystem->GetPathInfo(fs, &id, &size, &flags, &time) == 1) {
663 // directory does not exist, create it
664 if (gSystem->mkdir(fs, kTRUE) == -1) {
665 Error("GetFileName", "cannot create dir %s, using %s", fs.Data(),
666 kRFIOFS);
667 fs = kRFIOFS;
668 }
669 }
670 // FIXME: should check if fs is a directory
671
672 TString hostname = gSystem->HostName();
673 Int_t pos;
674 if ((pos = hostname.Index(".")) != kNPOS)
675 hostname.Remove(pos);
676
677 fname = fs + "/" + hostname + "_";
678 fname += dt.GetDate();
679 fname += "_";
680 fname += dt.GetTime();
681 fname += ".root";
682
683 return fname;
684}
685
686//______________________________________________________________________________
687void AliRawRFIODB::Close()
688{
689 // Close raw RFIO DB.
690
691 if (!fRawDB) return;
692
693 fRawDB->cd();
694
695 // Write the tree.
696 fTree->Write();
697
698 // Close DB, this also deletes the fTree
699 fRawDB->Close();
700
9174317d 701 if (AliMDC::DeleteFiles()) {
702 TUrl u(fRawDB->GetName());
703 gSystem->Exec(Form("rfrm %s", u.GetFile()));
704 }
705
706 delete fRawDB;
707 fRawDB = 0;
708}
709
710
711//______________________________________________________________________________
712AliRawCastorDB::AliRawCastorDB(AliRawEvent *event, Double_t maxsize, Int_t compress)
713 : AliRawDB(event, maxsize, compress, kFALSE)
714{
715 // Create a new raw DB that will be accessed via CASTOR and rootd.
716
717#ifndef USE_RDM
718 static int init = 0;
719 // Set STAGE_POOL environment variable to current host
720 if (!init) {
721 // THESE ENVIRONMENT SYMBOLS ARE NOW DEFINED BY THE ALICE DATE SETUP
722 // THEREFORE WE SHALL NOT USE ANY HARDCODED VALUES BUT RATHER USE
723 // WHATEVER HAS BEEN SET IN THE DATE SITE
724 //gSystem->Setenv("STAGE_POOL", "lcg00");
725 //gSystem->Setenv("STAGE_HOST", "stage013");
726 init = 1;
727 }
728#endif
729
730 if (!Create())
731 MakeZombie();
732 else
733 fRawDB->UseCache(50, 0x200000); //0x100000 = 1MB)
734}
735
736//______________________________________________________________________________
c689d2f6 737const char *AliRawCastorDB::GetFileName() const
9174317d 738{
739 // Return filename based on hostname and date and time. This will make
740 // each file unique. Also the directory will be made unique for each
741 // day by adding the date to the fs. Assumes there is always enough
742 // space on the device.
743
744 static TString fname;
745
746 TString fs = kCastorFS;
747 TString fsr = kRFIOFS;
748 TDatime dt;
749
750 // make a new subdirectory for each day
751 fs += "/adc-";
752 fs += dt.GetDate();
753
754 fsr += "/adc-";
755 fsr += dt.GetDate();
756
757 Long_t id, size, flags, time;
758 if (gSystem->GetPathInfo(fsr, &id, &size, &flags, &time) == 1) {
759 // directory does not exist, create it
760 if (gSystem->mkdir(fsr, kTRUE) == -1) {
761 Error("GetFileName", "cannot create dir %s, using %s", fsr.Data(),
762 kRFIOFS);
763 fs = kCastorFS;
764 }
765 }
766 // FIXME: should check if fs is a directory
767
768 TString hostname = gSystem->HostName();
769 Int_t pos;
770 if ((pos = hostname.Index(".")) != kNPOS)
771 hostname.Remove(pos);
772
773 fname = fs + "/" + hostname + "_";
774 fname += dt.GetDate();
775 fname += "_";
776 fname += dt.GetTime();
777 fname += ".root";
778
779 return fname;
780}
781
782//______________________________________________________________________________
783void AliRawCastorDB::Close()
784{
785 // Close raw CASTOR/rootd DB.
786
787 if (!fRawDB) return;
788
789 fRawDB->cd();
790
791 // Write the tree.
792 fTree->Write();
793
794 // Close DB, this also deletes the fTree
795 fRawDB->Close();
796
797 if (AliMDC::DeleteFiles()) {
798 TUrl u(fRawDB->GetName());
799 gSystem->Exec(Form("rfrm %s", u.GetFile()));
800 }
5ea08be4 801
802 delete fRawDB;
803 fRawDB = 0;
804}
805
806
807//______________________________________________________________________________
808AliRawRootdDB::AliRawRootdDB(AliRawEvent *event, Double_t maxsize, Int_t compress)
809 : AliRawDB(event, maxsize, compress, kFALSE)
810{
811 // Create a new raw DB that will be accessed via rootd daemon.
812
813 if (!Create())
814 MakeZombie();
815 else
816 fRawDB->UseCache(50, 0x200000); //0x100000 = 1MB)
817}
818
819//______________________________________________________________________________
c689d2f6 820const char *AliRawRootdDB::GetFileName() const
5ea08be4 821{
822 // Return filename based on hostname and date and time. This will make
823 // each file unique. Also the directory will be made unique for each
824 // day by adding the date to the fs. Assumes there is always enough
825 // space on the device.
826
827 static TString fname;
828
829 TString fs = kRootdFS;
830 TDatime dt;
831
832#if 0
833 // make a new subdirectory for each day
834 fs += "/adc-";
835 fs += dt.GetDate();
836
837 Long_t id, size, flags, time;
838 if (gSystem->GetPathInfo(fs, &id, &size, &flags, &time) == 1) {
839 // directory does not exist, create it
840 if (gSystem->mkdir(fs, kTRUE) == -1) {
841 Error("GetFileName", "cannot create dir %s, using %s", fs.Data(),
842 kRootdFS);
843 fs = kRootdFS;
844 }
845 }
846 // FIXME: should check if fs is a directory
847#endif
848
849 TString hostname = gSystem->HostName();
850 Int_t pos;
851 if ((pos = hostname.Index(".")) != kNPOS)
852 hostname.Remove(pos);
853
854 fname = fs + "/" + hostname + "_";
855 fname += dt.GetDate();
856 fname += "_";
857 fname += dt.GetTime();
858 fname += ".root";
859
860 return fname;
861}
862
863//______________________________________________________________________________
864void AliRawRootdDB::Close()
865{
866 // Close raw rootd DB.
867
868 if (!fRawDB) return;
869
870 fRawDB->cd();
871
872 // Write the tree.
873 fTree->Write();
874
875 // Close DB, this also deletes the fTree
876 fRawDB->Close();
877
878#if 0
879 // can use services of TFTP
880 if (AliMDC::DeleteFiles())
881 gSystem->Exec(Form("rfrm %s", fRawDB->GetName()));
882#endif
883
884 delete fRawDB;
885 fRawDB = 0;
886}
887
888
889//______________________________________________________________________________
890AliRawNullDB::AliRawNullDB(AliRawEvent *event, Double_t maxsize, Int_t compress)
891 : AliRawDB(event, maxsize, compress, kFALSE)
892{
893 // Create a new raw DB that will wrtie to /dev/null.
894
895 if (!Create())
896 MakeZombie();
897}
898
899//______________________________________________________________________________
c689d2f6 900const char *AliRawNullDB::GetFileName() const
5ea08be4 901{
902 // Return /dev/null as filename.
903
904 return "/dev/null";
905}
906
907//______________________________________________________________________________
908void AliRawNullDB::Close()
909{
910 // Close raw RFIO DB.
911
912 if (!fRawDB) return;
913
914 fRawDB->cd();
915
916 // Write the tree.
917 fTree->Write();
918
919 // Close DB, this also deletes the fTree
920 fRawDB->Close();
921
922 delete fRawDB;
923 fRawDB = 0;
924}
925
926
927//______________________________________________________________________________
928AliTagDB::AliTagDB(AliRawEventHeader *header, Double_t maxsize, Bool_t create)
929{
930 // Create tag DB.
931
932 fHeader = header;
933 fMaxSize = maxsize;
934
935 if (create) {
936 if (!Create())
937 MakeZombie();
938 }
939}
940
941//______________________________________________________________________________
942Bool_t AliTagDB::Create()
943{
944 // Create a new tag DB.
945
946 fTagDB = new TFile(GetFileName(), "RECREATE",
947 Form("ALICE MDC%d tag DB", kMDC), 1);
948 if (fTagDB->IsZombie()) {
949 Error("Create", "error opening tag DB");
950 fTagDB = 0;
951 return kFALSE;
952 }
953
954 // Create ROOT Tree object container
955 fTree = new TTree("TAG", Form("ALICE MDC%d header data tree", kMDC));
956 fTree->SetAutoSave(100000000); // autosave when 100 Mbyte written
957
958 Int_t bufsize = 32000;
959 Int_t split = 1;
960 fTree->Branch("header", "AliRawEventHeader", &fHeader, bufsize, split);
961
962 return kTRUE;
963}
964
965//______________________________________________________________________________
966void AliTagDB::Close()
967{
968 // Close tag DB.
969
970 if (!fTagDB) return;
971
972 fTagDB->cd();
973
974 // Write the tree.
975 fTree->Write();
976
977 // Close DB, this also deletes the fTree
978 fTagDB->Close();
979
980 if (AliMDC::DeleteFiles())
981 gSystem->Unlink(fTagDB->GetName());
982
983 delete fTagDB;
984 fTagDB = 0;
985}
986
987//______________________________________________________________________________
988Bool_t AliTagDB::NextFile()
989{
990 // Close te current file and open a new one.
991 // Returns kFALSE in case opening failed.
992
993 Close();
994
995 if (!Create()) return kFALSE;
996 return kTRUE;
997}
998
999//______________________________________________________________________________
1000Float_t AliTagDB::GetCompressionFactor() const
1001{
1002 // Return compression factor.
1003
1004 if (fTree->GetZipBytes() == 0.)
1005 return 1.0;
1006 else
1007 return fTree->GetTotBytes()/fTree->GetZipBytes();
1008}
1009
1010//______________________________________________________________________________
c689d2f6 1011const char *AliTagDB::GetFileName() const
5ea08be4 1012{
1013 // Return filename based on hostname and date and time. This will make
1014 // each file unique. The tags will be stored in the /data1/tags directory.
1015
1016 static char fname[64];
1017 const char *fs = kTagDBFS;
1018
1019 // check that fs exists (crude check fails if fs is a file)
1020 gSystem->MakeDirectory(fs);
1021
1022 char hostname[64];
1023
1024 strcpy(hostname, gSystem->HostName());
1025
1026 char *s;
1027 if ((s = strchr(hostname, '.')))
1028 *s = 0;
1029
1030 TDatime dt;
1031
1032 sprintf(fname, "%s/%s_%d_%d.root", fs, hostname, dt.GetDate(), dt.GetTime());
1033
1034 return fname;
1035}
1036
1037
1038//______________________________________________________________________________
1039AliTagNullDB::AliTagNullDB(AliRawEventHeader *header, Double_t maxsize) :
1040 AliTagDB(header, maxsize, kFALSE)
1041{
1042 // Create tag db writing to /dev/null.
1043
1044 if (!Create())
1045 MakeZombie();
1046}
1047
1048//______________________________________________________________________________
c689d2f6 1049const char *AliTagNullDB::GetFileName() const
5ea08be4 1050{
1051 // Return /dev/null as filename.
1052
1053 return "/dev/null";
1054}
1055
1056//______________________________________________________________________________
1057void AliTagNullDB::Close()
1058{
1059 // Close null tag DB.
1060
1061 if (!fTagDB) return;
1062
1063 fTagDB->cd();
1064
1065 // Write the tree.
1066 fTree->Write();
1067
1068 // Close DB, this also deletes the fTree
1069 fTagDB->Close();
1070
1071 delete fTagDB;
1072 fTagDB = 0;
1073}
1074
1075
1076//______________________________________________________________________________
8ee17d63 1077AliRunDB::AliRunDB(Bool_t noLocalDB)
5ea08be4 1078{
1079 // Open run database, and get or create tree.
1080
8ee17d63 1081 fRunDB = 0;
1082
1083 if (noLocalDB) return;
1084
5ea08be4 1085 // Get hostname
1086 char hostname[64], filename[64];
1087 const char *fs = kRunDBFS;
1088
1089 // check that fs exists (crude check fails if fs is a file)
1090 gSystem->MakeDirectory(fs);
1091
1092 strcpy(hostname, gSystem->HostName());
1093
1094 char *s;
1095 if ((s = strchr(hostname, '.')))
1096 *s = 0;
1097
1098 sprintf(filename, "%s/%s_rundb.root", fs, hostname);
1099
1100 if (!gSystem->AccessPathName(filename, kFileExists))
1101 fRunDB = new TFile(filename, "UPDATE");
1102 else
1103 fRunDB = new TFile(filename, "CREATE", Form("ALICE MDC%d Run DB", kMDC));
1104}
1105
1106//______________________________________________________________________________
1107void AliRunDB::Update(AliStats *stats)
1108{
1109 // Add stats object to database.
1110
8ee17d63 1111 if (!stats || !fRunDB) return;
1112
5ea08be4 1113 TDirectory *ds = gDirectory;
1114 fRunDB->cd();
1115
1116 char sname[64];
cfe26801 1117 char *s = (char*)strrchr(stats->GetFileName(), '/');
5ea08be4 1118 if (s) {
1119 s++;
1120 strcpy(sname, s);
1121 } else
1122 strcpy(sname, stats->GetFileName());
1123 s = strchr(sname, '.');
1124 if (s) *s = 0;
1125
1126 stats->Write(sname);
1127
1128 ds->cd();
1129}
1130
1131//______________________________________________________________________________
1132void AliRunDB::UpdateRDBMS(AliStats *stats)
1133{
1134 // Add stats object to central MySQL DB.
1135
8ee17d63 1136 if (!stats) return;
1137
5ea08be4 1138 char sql[4096];
1139 char bt[25], et[25];
1140
1141 strcpy(bt, stats->GetBeginTime().AsSQLString());
1142 strcpy(et, stats->GetEndTime().AsSQLString());
1143
1144 sprintf(sql, "INSERT INTO mdc%dcatalog VALUES (0, '%s', %d, "
1145 "%d, %d, %d, %d, %d, %d, %.2f, '%s', '%s', '%s')", kMDC,
1146 stats->GetFileName(), (int)stats->GetFileSize(), stats->GetEvents(),
1147 stats->GetFirstRun(), stats->GetFirstEvent(), stats->GetLastRun(),
1148 stats->GetLastEvent(), stats->GetCompressionMode(),
1149 stats->GetCompressionFactor(), stats->GetFilterState() ? "on" : "off",
1150 bt, et);
1151
1152 // open connection to MySQL server on pcsalo
1153 TSQLServer *db = TSQLServer::Connect("mysql://pcsalo.cern.ch/mdc", "alice", "amdc");
1154
1155 if (!db || db->IsZombie()) {
1156 Error("UpdateRDBMS", "failed to connect to MySQL server on pcsalo");
1157 printf("%s\n", sql);
1158 delete db;
1159 return;
1160 }
1161
1162 TSQLResult *res = db->Query(sql);
1163
1164 if (!res) {
1165 Error("UpdateRDBMS", Form("insert into mdc%dcatalog failed", kMDC));
1166 printf("%s\n", sql);
1167 }
1168
1169 delete res;
1170 delete db;
1171}
1172
9174317d 1173//______________________________________________________________________________
1174void AliRunDB::UpdateAliEn(AliStats *stats)
1175{
1176 // Record file in AliEn catalog.
1177
8ee17d63 1178 if (!stats) return;
1179
9174317d 1180 TGrid *g = TGrid::Connect(kAlienHost, "");
1181
1182 TString lfn = kAlienDir;
1183 lfn += "/";
1184 lfn += gSystem->BaseName(stats->GetFileName());
1185
3ddcf5bb 1186 Int_t result = g->AddFile(lfn, stats->GetFileName(),
13d0d987 1187 (int)stats->GetFileSize());
d67af9b1 1188
1189 if (result == -1) {
1190 Error("UpdateAliEn", "error adding file to AliEn catalog");
1191 printf("AliEn: AddFile(%s, %s, %d)\n", lfn.Data(), stats->GetFileName(),
1192 (int)stats->GetFileSize());
1193 }
9174317d 1194
1195 delete g;
1196}
1197
5ea08be4 1198//______________________________________________________________________________
1199void AliRunDB::Close()
1200{
1201 // Close run database.
1202
8ee17d63 1203 if (fRunDB) fRunDB->Close();
5ea08be4 1204 delete fRunDB;
1205}
1206
1207//----------------- Use SIGUSR1 to interupt endless loop -----------------------
1208class AliMDCInterruptHandler : public TSignalHandler {
5ea08be4 1209public:
1210 AliMDCInterruptHandler(AliMDC *mdc) : TSignalHandler(kSigUser1, kFALSE), fMDC(mdc) { }
c689d2f6 1211 AliMDCInterruptHandler(const AliMDCInterruptHandler& handler): TSignalHandler(handler)
1212 {Fatal("AliMDCInterruptHandler", "copy constructor not implemented");};
1213 AliMDCInterruptHandler& operator = (const AliMDCInterruptHandler& /*rawDB*/) {
1214 Fatal("operator =", "assignment operator not implemented");
1215 return *this;
1216 };
a6c3d280 1217 Bool_t Notify() {
1218 Info("Notify", "received a SIGUSR1 signal");
1219 fMDC->SetStopLoop();
1220 return kTRUE;
1221 }
c689d2f6 1222private:
1223 AliMDC *fMDC; // alimdc to signal
5ea08be4 1224};
1225
1226//______________________________________________________________________________
1227AliMDC::AliMDC(Int_t fd, Int_t compress, Double_t maxFileSize, Bool_t useFilter,
9174317d 1228 EWriteMode mode, Bool_t useLoop, Bool_t delFiles)
5ea08be4 1229{
1230 // Create MDC processor object.
1231
1232 fFd = fd;
1233 fCompress = compress;
1234 fMaxFileSize = maxFileSize;
1235 fUseFilter = useFilter;
9174317d 1236 fWriteMode = mode;
5ea08be4 1237 fUseLoop = useLoop;
1238 fUseFifo = kFALSE;
1239 fUseEb = kFALSE;
1240 fStopLoop = kFALSE;
1241 fNumEvents = 0;
1242 fDebugLevel = 0;
1243 fgDeleteFiles = delFiles;
1244
1245 if (fFd == -1) {
1246#ifdef USE_EB
1247 if (!ebRegister()) {
1248 Error("AliMDC", "cannot register with the event builder (%s)",
1249 ebGetLastError());
1250 return;
1251 }
1252 fUseEb = kTRUE;
1253#else
1254 if ((mkfifo(kFifo, 0644) < 0) && (errno != EEXIST)) {
1255 Error("AliMDC", "cannot create fifo %s", kFifo);
1256 return;
1257 }
1258 if ((chmod(kFifo, 0666) == -1) && (errno != EPERM)) {
1259 Error("AliMDC", "cannot change permission of fifo %s", kFifo);
1260 return;
1261 }
1262 if ((fFd = open(kFifo, O_RDONLY)) == -1) {
1263 Error("AliMDC", "cannot open input file %s", kFifo);
1264 return;
1265 }
1266 fUseFifo = kTRUE;
1267#endif
1268 fUseLoop = kFALSE;
1269 }
1270
1271 printf("<AliMDC::AliMDC>: input = %s, rawdb size = %f, filter = %s, "
1272 "looping = %s, compression = %d, delete files = %s",
1273 fUseFifo ? "fifo" : (fUseEb ? "eb" : "file"), fMaxFileSize,
1274 fUseFilter ? "on" : "off", fUseLoop ? "yes" : "no", fCompress,
1275 fgDeleteFiles ? "yes" : "no");
9174317d 1276 if (fWriteMode == kRFIO)
5ea08be4 1277 printf(", use RFIO\n");
9174317d 1278 else if (fWriteMode == kROOTD)
5ea08be4 1279 printf(", use rootd\n");
9174317d 1280 else if (fWriteMode == kCASTOR)
1281 printf(", use CASTOR/rootd\n");
1282 else if (fWriteMode == kDEVNULL)
5ea08be4 1283 printf(", write raw data to /dev/null\n");
1284 else
1285 printf("\n");
1286
1287 // install SIGUSR1 handler to allow clean interrupts
1288 gSystem->AddSignalHandler(new AliMDCInterruptHandler(this));
1289
1290 gAliMDC = this;
1291}
1292
1293//______________________________________________________________________________
1294Int_t AliMDC::Run()
1295{
1296 // Run the MDC processor. Read from the input stream and only return
1297 // when the input gave and EOF or a fatal error occured. On success 0
1298 // is returned, 1 in case of a fatality.
1299
1300 TStopwatch timer;
1301 Int_t status;
1302
1303 // Make sure needed directories exist
1304 const char *dirs[4];
1305 dirs[0] = kRawDBFS[0];
1306 dirs[1] = kRawDBFS[1];
1307 dirs[2] = kTagDBFS;
1308 dirs[3] = kRunDBFS;
1309 for (int idir = 0; idir < 4; idir++) {
1310 gSystem->ResetErrno();
1311 gSystem->MakeDirectory(dirs[idir]);
1312 if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
1313 SysError("Run", "mkdir %s", dirs[idir]);
1314 return 1;
1315 }
1316 }
1317
1318 // Used for statistics
1319 timer.Start();
1320 Double_t told = 0, tnew = 0;
1321 Float_t chunkSize = fMaxFileSize/100, nextChunk = chunkSize;
1322
1323 // Event object used to store event data.
1324 AliRawEvent *event = new AliRawEvent;
1325
1326 // Create new raw DB.
1327 AliRawDB *rawdb;
9174317d 1328 if (fWriteMode == kRFIO)
5ea08be4 1329 rawdb = new AliRawRFIODB(event, fMaxFileSize, fCompress);
9174317d 1330 else if (fWriteMode == kROOTD)
5ea08be4 1331 rawdb = new AliRawRootdDB(event, fMaxFileSize, fCompress);
9174317d 1332 else if (fWriteMode == kCASTOR)
1333 rawdb = new AliRawCastorDB(event, fMaxFileSize, fCompress);
1334 else if (fWriteMode == kDEVNULL)
5ea08be4 1335 rawdb = new AliRawNullDB(event, fMaxFileSize, fCompress);
1336 else
1337 rawdb = new AliRawDB(event, fMaxFileSize, fCompress);
1338
1339 if (rawdb->IsZombie()) return 1;
1340 printf("Filling raw DB %s\n", rawdb->GetDBName());
1341
1342 // Create new tag DB.
9174317d 1343 AliTagDB *tagdb = 0;
1344#if 0
1345 // no tagdb for the time being to get maximum speed
1346 if (fWriteMode == kDEVNULL)
5ea08be4 1347 tagdb = new AliTagNullDB(event->GetHeader(), kMaxTagFileSize);
1348 else
1349 tagdb = new AliTagDB(event->GetHeader(), kMaxTagFileSize);
1350 if (tagdb->IsZombie())
1351 tagdb = 0;
1352 else
1353 printf("Filling tag DB %s\n", tagdb->GetDBName());
9174317d 1354#endif
5ea08be4 1355
1356 // Create AliStats object
1357 AliStats *stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter);
1358
1359 // Shortcut for easy header access
1360 AliRawEventHeader &header = *event->GetHeader();
1361
1362 // Process input stream
1363#ifdef USE_EB
13d0d987 1364 Int_t eorFlag = 0;
1365 while (!(eorFlag = ebEor())) {
5ea08be4 1366 struct iovec *ebvec;
1367 if ((ebvec = ebGetNextEvent()) == (void *)-1) {
1368 Error("Run", "error getting next event (%s)", ebGetLastError());
1369 break;
1370 }
1371 if (ebvec == 0) {
1372 // no event, sleep for 1 second and try again
1373 gSystem->Sleep(1000);
1374 continue;
1375 }
1376 char *ebdata = (char *) ebvec[0].iov_base;
1377#else
1378 while (1) {
1379 char *ebdata = 0;
1380#endif
1381
1382 // Read event header
1383 if ((status = ReadHeader(header, ebdata)) != header.HeaderSize()) {
1384 if (status == 0) {
1385 if (fUseLoop) {
1386#ifndef USE_EB
1387 ::lseek(fFd, 0, SEEK_SET);
1388#endif
1389 continue;
1390 }
1391 printf("<AliMDC::Run>: EOF, processed %d events\n", fNumEvents);
1392 break;
1393 }
1394 return 1;
1395 }
3ddcf5bb 1396 ALIDEBUG(3)
13d0d987 1397 header.Dump();
5ea08be4 1398
1399 // If we were in looping mode stop directly after a SIGUSR1 signal
1400 if (StopLoop()) {
a6c3d280 1401 Info("Run", "Stopping loop, processed %d events", fNumEvents);
5ea08be4 1402 break;
1403 }
1404
1405 // Check if event has any hard track flagged
1406 Bool_t callFilter = kFALSE;
1407 // This needs to be re-engineered for the next ADC...
1408 //if (fUseFilter && TEST_USER_ATTRIBUTE(header.GetTypeAttribute(), 0))
1409 // callFilter = kTRUE;
1410
1411 // Check event type and skip "Start of Run", "End of Run",
1412 // "Start of Run Files" and "End of Run Files"
1413 switch (header.GetType()) {
1414 case kStartOfRun:
1415 case kEndOfRun:
1416 case kStartOfRunFiles:
1417 case kEndOfRunFiles:
1418 {
1419 Int_t skip = header.GetEventSize() - header.HeaderSize();
1420#ifndef USE_EB
1421 ::lseek(fFd, skip, SEEK_CUR);
1422#endif
1423 ALIDEBUG(1)
1424 Info("Run", "Skipping %s (%d bytes)", header.GetTypeName(), skip);
1425 continue;
1426 }
1427 break;
1428 default:
1429 ALIDEBUG(1) {
1430 Int_t s = header.GetEventSize() - header.HeaderSize();
1431 Info("Run", "Processing %s (%d bytes)", header.GetTypeName(), s);
1432 }
1433 }
1434
1435 // Amount of data left to read for this event
1436 Int_t toRead = header.GetEventSize() - header.HeaderSize();
1437
1438 // If there is less data for this event than the next sub-event
1439 // header, something is wrong. Skip to next event...
1440 if (toRead < header.HeaderSize()) {
13d0d987 1441 ALIDEBUG(1) {
3ddcf5bb 1442 Warning("Run",
13d0d987 1443 "header size (%d) exceeds number of bytes to read (%d)\n",
1444 header.HeaderSize(), toRead);
1445 header.Dump();
1446 }
5ea08be4 1447 if ((status = DumpEvent(toRead)) != toRead) {
1448 if (status == 0)
1449 break;
1450 return 1;
1451 }
1452 Error("Run", "discarding event %d (too little data for header)", fNumEvents);
1453 continue;
1454 }
1455
1456 // Loop over all sub-events... (LDCs)
13d0d987 1457 Int_t nsub = 1;
5ea08be4 1458 while (toRead > 0) {
5ea08be4 1459#ifdef USE_EB
1460 ebdata = (char *)ebvec[nsub].iov_base;
1461#endif
5459c838 1462
5ea08be4 1463 ALIDEBUG(1)
1464 Info("Run", "reading LDC %d", nsub);
1465
1466 AliRawEvent *subEvent = event->NextSubEvent();
1467
1468 // Read sub-event header
1469 AliRawEventHeader &subHeader = *subEvent->GetHeader();
1470 if ((status = ReadHeader(subHeader, ebdata)) != subHeader.HeaderSize()) {
1471 if (status == 0) {
1472 Error("Run", "unexpected EOF reading sub-event header");
1473 break;
1474 }
1475 return 1;
1476 }
1477
13d0d987 1478 ALIDEBUG(3)
1479 subHeader.Dump();
1480
5ea08be4 1481 toRead -= subHeader.HeaderSize();
1482
1483#ifdef USE_EB
1484 ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize();
1485#endif
1486
1487 Int_t rawSize = subHeader.GetEventSize() - subHeader.HeaderSize();
1488
1489 // Read Equipment Header (in case of physics or calibration event)
1490 if (header.GetType() == kPhysicsEvent ||
1491 header.GetType() == kCalibrationEvent) {
1492 AliRawEquipmentHeader &equipment = *subEvent->GetEquipmentHeader();
1493 Int_t equipHeaderSize = equipment.HeaderSize();
1494 if ((status = ReadEquipmentHeader(equipment, header.DataIsSwapped(),
1495 ebdata)) != equipHeaderSize) {
1496 if (status == 0) {
1497 Error("Run", "unexpected EOF reading equipment-header");
1498 break;
1499 }
1500 return 1;
1501 }
1502 toRead -= equipHeaderSize;
1503 rawSize -= equipHeaderSize;
1504#ifdef USE_EB
1505 ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize() +
1506 equipHeaderSize;
1507#endif
1508 }
1509
1510 // Make sure raw data less than left over bytes for current event
1511 if (rawSize > toRead) {
13d0d987 1512 ALIDEBUG(1) {
1513 Warning("Run", "raw data size (%d) exceeds number of bytes "
1514 "to read (%d)\n", rawSize, toRead);
1515 subHeader.Dump();
1516 }
5ea08be4 1517 if ((status = DumpEvent(toRead)) != toRead) {
1518 if (status == 0)
1519 break;
1520 return 1;
1521 }
1522 Error("Run", "discarding event %d (too much data)", fNumEvents);
1523 continue;
1524 }
1525
1526 // Read sub-event raw data
1527 AliRawData &subRaw = *subEvent->GetRawData();
1528 if ((status = ReadRawData(subRaw, rawSize, ebdata)) != rawSize) {
1529 if (status == 0) {
1530 Error("Run", "unexpected EOF reading sub-event raw data");
1531 break;
1532 }
1533 return 1;
1534 }
1535
1536 if (callFilter) {
1537 if (TEST_USER_ATTRIBUTE(subHeader.GetTypeAttribute(), 0))
1538 Filter(subRaw);
1539 else {
1540 // set size of all sectors without hard track flag to 0
1541 subRaw.SetSize(0);
1542 }
1543 }
1544
1545 toRead -= rawSize;
1546 nsub++;
1547 }
1548
1549 // Set stat info for first event of this file
1550 if (rawdb->GetEvents() == 0)
1551 stats->SetFirstId(header.GetRunNumber(), header.GetEventInRun());
1552
1553 // Store raw event in tree
1554 rawdb->Fill();
1555
1556 // Store header in tree
1557 if (tagdb) tagdb->Fill();
1558
1559 fNumEvents++;
1560
1561 if (!(fNumEvents%10))
1562 printf("Processed event %d (%d)\n", fNumEvents, rawdb->GetEvents());
1563
1564 // Filling time statistics
1565 if (rawdb->GetBytesWritten() > nextChunk) {
1566 tnew = timer.RealTime();
1567 stats->Fill(tnew-told);
1568 told = tnew;
1569 timer.Continue();
1570 nextChunk += chunkSize;
1571 }
1572
1573 // Check size of raw db. If bigger than maxFileSize, close file
1574 // and continue with new file.
1575 if (rawdb->FileFull()) {
1576
1577 printf("Written raw DB at a rate of %.1f MB/s\n",
f5cda7ba 1578 rawdb->GetBytesWritten() / timer.RealTime() / 1000000.);
5ea08be4 1579
d67af9b1 1580 // Write stats object to raw db, run db, MySQL and AliEn
5ea08be4 1581 stats->WriteToDB(rawdb);
1582 delete stats;
1583
d67af9b1 1584 if (!rawdb->NextFile()) {
1585 Error("Run", "error opening next raw data file");
1586 return 1;
1587 }
5ea08be4 1588
1589 printf("Filling raw DB %s\n", rawdb->GetDBName());
1590 stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter);
1591
1592 timer.Start();
1593 told = 0, tnew = 0;
1594 nextChunk = chunkSize;
1595 }
1596
1597 // Check size of tag db
9174317d 1598 if (tagdb && tagdb->FileFull()) {
5ea08be4 1599 if (!tagdb->NextFile())
1600 tagdb = 0;
1601 else
1602 printf("Filling tag DB %s\n", tagdb->GetDBName());
1603 }
1604
1605 // Make top event object ready for next event data
1606 //printf("Event %d has %d sub-events\n", fNumEvents, event->GetNSubEvents());
1607 event->Reset();
1608
1609#ifdef USE_EB
1610 if (!ebReleaseEvent(ebvec)) {
1611 Error("Run", "problem releasing event (%s)", ebGetLastError());
1612 break;
1613 }
1614#endif
1615 }
1616
1617 printf("Written raw DB at a rate of %.1f MB/s\n",
f5cda7ba 1618 rawdb->GetBytesWritten() / timer.RealTime() / 1000000.);
5ea08be4 1619
1620 // Write stats to raw db and run db and delete stats object
1621 stats->WriteToDB(rawdb);
1622 delete stats;
1623
1624 // Close the raw DB
1625 delete rawdb;
1626
1627 // Close the tag DB
1628 delete tagdb;
1629
1630 // Close input source
1631 close(fFd);
1632
1633#if 0
1634 // Cleanup fifo
1635 if (fUseFifo && ::unlink(kFifo) == -1) {
1636 SysError("Run", "unlink");
1637 return 1;
1638 }
1639#endif
1640
13d0d987 1641#ifdef USE_EB
1642 // Print eor flag
1643 if (eorFlag) {
d67af9b1 1644 Info("Run", "event builder reported end of run (%d)", eorFlag);
13d0d987 1645 }
1646#endif
1647
5ea08be4 1648 return 0;
1649}
1650
1651//______________________________________________________________________________
1652Int_t AliMDC::Read(void *buffer, Int_t length)
1653{
1654 // Read exactly length bytes into buffer. Returns number of bytes
1655 // received, returns -1 in case of error and 0 for EOF.
1656
1657 errno = 0;
1658
1659 if (fFd < 0) return -1;
1660
1661 Int_t n, nrecv = 0;
1662 char *buf = (char *)buffer;
1663
1664 for (n = 0; n < length; n += nrecv) {
1665 if ((nrecv = read(fFd, buf+n, length-n)) <= 0) {
1666 if (nrecv == 0)
1667 break; // EOF
1668 if (errno != EINTR)
1669 SysError("Read", "read");
1670 return -1;
1671 }
1672 }
1673 return n;
1674}
1675
1676//______________________________________________________________________________
1677Int_t AliMDC::ReadHeader(AliRawEventHeader &header, void *eb)
1678{
1679 // Read header info from DATE data stream. Returns bytes read (i.e.
1680 // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
1681
1682 Int_t nrecv;
1683
1684 if (eb) {
1685 // read from event builder memory area
1686 memcpy(header.HeaderBegin(), eb, header.HeaderSize());
1687 nrecv = header.HeaderSize();
1688 } else {
1689 // read from fifo or file
1690 if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) !=
1691 header.HeaderSize()) {
1692 if (nrecv == 0)
1693 return 0;
1694 return -1;
1695 }
1696 }
1697
1698 // Swap header data if needed
1699 if (header.IsSwapped())
1700 header.Swap();
1701
1702 // Is header valid...
1703 if (!header.IsValid()) {
1704 Error("ReadHeader", "invalid header format");
1705 // try recovery... how?
1706 return -1;
1707 }
1708 if (header.GetEventSize() < (UInt_t)header.HeaderSize()) {
1709 Error("ReadHeader", "invalid header size");
1710 // try recovery... how?
1711 return -1;
1712 }
1713
1714 return nrecv;
1715}
1716
1717//______________________________________________________________________________
1718Int_t AliMDC::ReadEquipmentHeader(AliRawEquipmentHeader &header,
1719 Bool_t isSwapped, void *eb)
1720{
1721 // Read equipment header info from DATE data stream. Returns bytes read
1722 // (i.e. AliRawEquipmentHeader::HeaderSize()), -1 in case of error and
1723 // 0 for EOF. If isSwapped is kTRUE the event data is byte swapped
1724 // and we will swap the header to host format.
1725
1726 Int_t nrecv;
1727
1728 if (eb) {
1729 // read from event builder memory area
1730 memcpy(header.HeaderBegin(), eb, header.HeaderSize());
1731 nrecv = header.HeaderSize();
1732 } else {
1733 // read from fifo or file
1734 if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) !=
1735 header.HeaderSize()) {
1736 if (nrecv == 0)
1737 return 0;
1738 return -1;
1739 }
1740 }
1741
1742 // Swap equipment header data if needed
1743 if (isSwapped)
1744 header.Swap();
1745
1746 if (header.GetEquipmentSize() < (UInt_t)header.HeaderSize()) {
1747 Error("ReadEquipmentHeader", "invalid equipment header size");
1748 // try recovery... how?
1749 return -1;
1750 }
1751
1752 return nrecv;
1753}
1754
1755//______________________________________________________________________________
1756Int_t AliMDC::ReadRawData(AliRawData &raw, Int_t size, void *eb)
1757{
1758 // Read raw data from DATE data stream. Returns bytes read (i.e.
1759 // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
1760
1761 Int_t nrecv;
1762
1763 if (eb) {
1764 // read from event builder memory area
1765 raw.SetBuffer(eb, size);
1766 nrecv = size;
1767 } else {
1768 // read from fifo or file
1769 raw.SetSize(size);
1770 if ((nrecv = Read(raw.GetBuffer(), size)) != size) {
1771 if (nrecv == 0) {
1772 Error("ReadRawData", "unexpected EOF");
1773 return 0;
1774 }
1775 return -1;
1776 }
1777 }
1778
1779 return nrecv;
1780}
1781
1782//______________________________________________________________________________
1783Int_t AliMDC::DumpEvent(Int_t toRead)
1784{
1785 // This case should not happen, but if it does try to handle it
1786 // gracefully by reading the rest of the event and discarding it.
1787 // Returns bytes read, -1 in case of fatal error and 0 for EOF.
1788
1789 Error("DumpEvent", "dumping %d bytes of event %d", toRead, fNumEvents);
1790
1791 Int_t nrecv;
1792 char *tbuf = new char[toRead];
1793 if ((nrecv = Read(tbuf, toRead)) != toRead) {
1794 if (nrecv == 0) {
1795 Error("DumpEvent", "unexpected EOF");
1796 return 0;
1797 }
1798 return -1;
1799 }
1800 delete [] tbuf;
1801
1802 return nrecv;
1803}
1804
1805#ifdef USE_HLT
1806#include <AliTPCL3Tunnel.h>
1807#endif
1808
1809//______________________________________________________________________________
1810Int_t AliMDC::Filter(AliRawData &raw)
1811{
1812 // Call 3rd level filter for this raw data segment.
1813
1814#ifdef USE_HLT
1815 AliTPCL3Tunnel *tunnel = 0;
1816 if (!tunnel) {
1817 // initialisation
1818 tunnel = new AliTPCL3Tunnel(Form("%s/TPCparams.root",
1819 gSystem->Getenv("ALITPC")));
1820 }
1821
1822 Int_t obytes, nbytes;
1823 obytes = nbytes = raw.GetSize();
1824 char *outbuf = tunnel->EvalTrack((char *)raw.GetBuffer(), nbytes);
1825
1826 raw.SetSize(nbytes);
1827 memcpy(raw.GetBuffer(), outbuf, nbytes);
1828
1829 printf("Filter called for event %d: reduced from %d to %d\n", fNumEvents,
1830 obytes, nbytes);
1831
1832#else
1833
1834 raw.GetSize();
1835 printf("Filter called for event %d\n", fNumEvents);
1836
1837#endif
1838
1839 return 0;
1840}