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