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