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