// $Id$
//**************************************************************************
-//* This file is property of and copyright by the ALICE HLT Project *
+//* This file is property of and copyright by the *
//* ALICE Experiment at CERN, All rights reserved. *
//* *
//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
//* provided "as is" without express or implied warranty. *
//**************************************************************************
-// @file AliHLTOUTComponent.cxx
-// @author Matthias Richter
-// @date
-// @brief The HLTOUT data sink component similar to HLTOUT nodes
-// @note Used in the AliRoot environment only.
-
-#if __GNUC__>= 3
-using namespace std;
-#endif
+/// @file AliHLTOUTComponent.cxx
+/// @author Matthias Richter
+/// @date
+/// @brief The HLTOUT data sink component similar to HLTOUT nodes
+/// @note Used in the AliRoot environment only.
#include <cassert>
//#include <iostream>
#include "AliHLTOUT.h"
#include "AliHLTHOMERLibManager.h"
#include "AliHLTHOMERWriter.h"
+#include "AliHLTErrorGuard.h"
#include "AliDAQ.h" // equipment Ids
-#include "AliRawDataHeader.h" // Common Data Header
+#include "AliRawDataHeaderV3.h" // Common Data Header
#include <TDatime.h> // seed for TRandom
#include <TRandom.h> // random int generation for DDL no
#include <TFile.h>
#include <TTree.h>
#include <TArrayC.h>
+#include <TSystem.h>
+
+using namespace std;
/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTOUTComponent)
-AliHLTOUTComponent::AliHLTOUTComponent()
- : AliHLTOfflineDataSink()
+AliHLTOUTComponent::AliHLTOUTComponent(EType type)
+ : AliHLTDataSink()
, fWriters()
, fNofDDLs(10)
, fIdFirstDDL(7680) // 0x1e<<8
, fBuffer()
, fpLibManager(NULL)
+ , fOptions(0)
, fDigitFileName("HLT.Digits.root")
, fpDigitFile(NULL)
, fpDigitTree(NULL)
, fppDigitArrays(NULL)
, fReservedWriter(-1)
, fReservedData(0)
+ , fType(type)
+ , fRoundRobinCounter(0)
{
- // see header file for class documentation
- // or
- // refer to README to build package
- // or
- // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
-
- // I guess DDL definitions should never change any more
- assert(fNofDDLs==AliDAQ::NumberOfDdls("HLT"));
+ // The HLTOUT data sink component which models the behavior of the HLTOUT
+ // nodes of the HLT cluster.
+ // The HLTOUT component is attached at the end of a chain. It stores all input
+ // block in the HOMER format, distributed over a number of DDL link. The data
+ // is stored in a digit file or in raw ddl files.
+ fIdFirstDDL=AliDAQ::DdlIDOffset("HLT");
fNofDDLs=AliDAQ::NumberOfDdls("HLT");
- /* AliDAQ::DdlIDOffset returns wrong offset for HLT links
- assert(fIdFirstDDL==AliDAQ::DdlIDOffset("HLT"));
- fIdFirstDDL=AliDAQ::DdlIDOffset("HLT");
- */
+ if (fType!=kGlobal && fType!=kDigits && fType!=kRaw) {
+ ALIHLTERRORGUARD(1, "invalid component type %d", fType);
+ }
}
int AliHLTOUTComponent::fgOptions=kWriteRawFiles|kWriteDigits;
AliHLTOUTComponent::~AliHLTOUTComponent()
{
- // see header file for class documentation
+ // destructor
if (fpLibManager) delete fpLibManager;
fpLibManager=NULL;
}
const char* AliHLTOUTComponent::GetComponentID()
{
- // see header file for class documentation
- return "HLTOUT";
+ // overloaded from AliHLTComponent: get component id
+ switch (fType) {
+ case kDigits: return "HLTOUTdigits";
+ case kRaw: return "HLTOUTraw";
+ case kGlobal:
+ default:
+ return "HLTOUT";
+ }
+ return NULL;
}
-void AliHLTOUTComponent::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
+void AliHLTOUTComponent::GetInputDataTypes( AliHLTComponentDataTypeList& list)
{
- // see header file for class documentation
+ // overloaded from AliHLTComponent: indicate input data types
list.clear();
list.push_back(kAliHLTAnyDataType);
}
AliHLTComponent* AliHLTOUTComponent::Spawn()
{
- // see header file for class documentation
- return new AliHLTOUTComponent;
+ // overloaded from AliHLTComponent: create instance
+ return new AliHLTOUTComponent(fType);
}
int AliHLTOUTComponent::DoInit( int argc, const char** argv )
{
- // see header file for class documentation
+ // overloaded from AliHLTComponent: initialization
int iResult=0;
- if ((iResult=ConfigureFromArgumentString(argc, argv))<0) return iResult;
- // Make sure there is no library manager before we try and create a new one.
- if (fpLibManager) {
- delete fpLibManager;
- fpLibManager=NULL;
+ switch (fType) {
+ case kDigits:
+ fOptions|=kWriteDigits; fOptions&=~kWriteRawFiles;
+ HLTInfo("initializing HLTOUT component for digits generation");
+ break;
+ case kRaw:
+ fOptions|=kWriteRawFiles; fOptions&=~kWriteDigits;
+ HLTInfo("initializing HLTOUT component for raw data generation");
+ break;
+ case kGlobal:
+ default:
+ fOptions=fgOptions;
}
-
+
+ if ((iResult=ConfigureFromArgumentString(argc, argv))<0) return iResult;
+
// Create a new library manager and allocate the appropriate number of
// HOMER writers for the HLTOUT component.
- fpLibManager=new AliHLTHOMERLibManager;
+ if (!fpLibManager) fpLibManager=new AliHLTHOMERLibManager;
if (fpLibManager) {
int writerNo=0;
for (writerNo=0; writerNo<fNofDDLs; writerNo++) {
int AliHLTOUTComponent::ScanConfigurationArgument(int argc, const char** argv)
{
- // see header file for class documentation
+ // overloaded from AliHLTComponent: argument scan
if (argc<=0) return 0;
int i=0;
TString argument=argv[i];
if (argument.Contains(key)) {
argument.ReplaceAll(key, "");
if (argument.IsNull()) {
- fgOptions|=kWriteRawFiles;
+ fOptions|=kWriteRawFiles;
} else if (argument.CompareTo("=off")==0) {
- fgOptions&=~kWriteRawFiles;
+ fOptions&=~kWriteRawFiles;
} else if (argument.CompareTo("=on")==0) {
- fgOptions|=kWriteRawFiles;
+ fOptions|=kWriteRawFiles;
} else {
HLTError("invalid parameter for argument %s: possible %s=off/%s=on", key, key, key);
return -EPROTO;
if (argument.Contains(key)) {
argument.ReplaceAll(key, "");
if (argument.IsNull()) {
- fgOptions|=kWriteDigits;
+ fOptions|=kWriteDigits;
} else if (argument.CompareTo("=off")==0) {
- fgOptions&=~kWriteDigits;
+ fOptions&=~kWriteDigits;
} else if (argument.CompareTo("=on")==0) {
- fgOptions|=kWriteDigits;
+ fOptions|=kWriteDigits;
} else {
HLTError("invalid parameter for argument %s: possible %s=off/%s=on", key, key, key);
return -EPROTO;
return 1;
}
+ // -distribute-blocks
+ key="-distribute-blocks";
+ if (argument.CompareTo(key)==0) {
+ fRoundRobinCounter=-1;
+
+ return 1;
+ }
+
// unknown argument
return -EINVAL;
}
int AliHLTOUTComponent::DoDeinit()
{
- // see header file for class documentation
+ // overloaded from AliHLTComponent: cleanup
int iResult=0;
if (fpLibManager) {
const AliHLTComponentBlockData* blocks,
AliHLTComponentTriggerData& /*trigData*/ )
{
- // see header file for class documentation
+ // overloaded from AliHLTDataSink: event processing
int iResult=0;
HLTInfo("write %d output block(s)", evtData.fBlockCnt);
int writerNo=0;
}
if (iResult>=0 && bIsDataEvent) {
- iResult=Write(GetEventCount(), GetRunLoader());
+ iResult=Write(GetEventCount());
}
- return iResult;
-}
-
+ if (fRoundRobinCounter>=0) {
+ if (++fRoundRobinCounter>=fNofDDLs) fRoundRobinCounter=0;
+ }
-int AliHLTOUTComponent::FillESD(int eventNo, AliRunLoader* runLoader, AliESDEvent* /*esd*/)
-{
- // see header file for class documentation
- // 2010-04-14 nothing to do any more. The data is written at the end of
- // DumpEvent
- return 0;
+ return iResult;
}
-int AliHLTOUTComponent::Write(int eventNo, AliRunLoader* runLoader)
+int AliHLTOUTComponent::Write(int eventNo)
{
- // see header file for class documentation
+ // write digits and raw files for the current event
int iResult=0;
if (fWriters.size()==0) return 0;
if (fReservedWriter>=0) {
- if (fgOptions&kWriteDigits) WriteDigitArray(fReservedWriter, &fBuffer[0], fReservedData);
- if (fgOptions&kWriteRawFiles) WriteRawFile(eventNo, runLoader, fReservedWriter, &fBuffer[0], fReservedData);
+ if (fOptions&kWriteDigits) WriteDigitArray(fReservedWriter, &fBuffer[0], fReservedData);
+ if (fOptions&kWriteRawFiles) WriteRawFile(eventNo, fReservedWriter, &fBuffer[0], fReservedData);
fReservedData=0;
}
int bufferSize=0;
if ((bufferSize=FillOutputBuffer(eventNo, fWriters[*ddlno], pBuffer))>0) {
- if (fgOptions&kWriteDigits) WriteDigitArray(*ddlno, pBuffer, bufferSize);
- if (fgOptions&kWriteRawFiles) WriteRawFile(eventNo, runLoader, *ddlno, pBuffer, bufferSize);
+ if (fOptions&kWriteDigits) WriteDigitArray(*ddlno, pBuffer, bufferSize);
+ if (fOptions&kWriteRawFiles &&
+ (fRoundRobinCounter<0 || fRoundRobinCounter==*ddlno))
+ WriteRawFile(eventNo, *ddlno, pBuffer, bufferSize);
}
fWriters[*ddlno]->Clear();
ddlno++;
}
- if (fgOptions&kWriteDigits) WriteDigits(eventNo, runLoader);
+ if (fOptions&kWriteDigits) WriteDigits(eventNo);
return iResult;
}
int AliHLTOUTComponent::ShuffleWriters(AliHLTMonitoringWriterPVector &list, AliHLTUInt32_t /*size*/)
{
- // see header file for class documentation
+ /// get a writer for the next block
+ /// in round robin mode (like the online HLTOUT) all blocks of one event go to the same link
+ /// this is now also the default behavior of the HLTOUTComponent and indicated by
+ /// fRoundRobinCounter>=0
+ /// Writers are selected randomly otherwise.
+ if (fRoundRobinCounter>=0) {
+ if (fRoundRobinCounter==fReservedWriter) {
+ if (++fRoundRobinCounter>=fNofDDLs) fRoundRobinCounter=0;
+ if (fRoundRobinCounter==fReservedWriter) {
+ HLTWarning("there are not enough links to use a reserved writer, discarding data in reserved writer %d (total %d)",
+ fReservedWriter, fNofDDLs);
+ fReservedWriter=-1;
+ }
+ }
+ return fRoundRobinCounter;
+ }
+
int iResult=-ENOENT;
assert(list.size()>0);
if (list.size()==0) return iResult;
int AliHLTOUTComponent::FillOutputBuffer(int eventNo, AliHLTMonitoringWriter* pWriter, const AliHLTUInt8_t* &pBuffer)
{
- // see header file for class documentation
+ // prepare the output buffer for writing, consists of
+ // - CDH
+ // - HLTOUT header
+ // - HOMER data
+ // buffer is allocated internally and data is valid until next call
int iResult=0;
unsigned int bufferSize=0;
// space for common data header
- bufferSize+=sizeof(AliRawDataHeader);
- assert(sizeof(AliRawDataHeader)==32);
+ bufferSize+=sizeof(AliRawDataHeaderV3);
// space for HLT event header
bufferSize+=sizeof(AliHLTOUT::AliHLTOUTEventHeader);
memset(&fBuffer[bufferSize-4], 0, 4);
if (bufferSize<=fBuffer.size()) {
- AliRawDataHeader* pCDH=reinterpret_cast<AliRawDataHeader*>(&fBuffer[0]);
- AliHLTOUT::AliHLTOUTEventHeader* pHLTH=reinterpret_cast<AliHLTOUT::AliHLTOUTEventHeader*>(&fBuffer[sizeof(AliRawDataHeader)]);
- *pCDH = AliRawDataHeader(); // Fill with default values.
+ AliRawDataHeaderV3* pCDH=reinterpret_cast<AliRawDataHeaderV3*>(&fBuffer[0]);
+ AliHLTOUT::AliHLTOUTEventHeader* pHLTH=reinterpret_cast<AliHLTOUT::AliHLTOUTEventHeader*>(&fBuffer[sizeof(AliRawDataHeaderV3)]);
+ *pCDH = AliRawDataHeaderV3(); // Fill with default values.
memset(pHLTH, 0, sizeof(AliHLTOUT::AliHLTOUTEventHeader));
if (pWriter) {
// copy payload
- pWriter->Copy(&fBuffer[sizeof(AliRawDataHeader)+sizeof(AliHLTOUT::AliHLTOUTEventHeader)], 0, 0, 0, 0);
+ pWriter->Copy(&fBuffer[sizeof(AliRawDataHeaderV3)+sizeof(AliHLTOUT::AliHLTOUTEventHeader)], 0, 0, 0, 0);
pHLTH->fLength=pWriter->GetTotalMemorySize();
// set status bit to indicate HLT payload
pCDH->fStatusMiniEventID|=0x1<<(AliHLTOUT::kCDHStatusFlagsOffset+AliHLTOUT::kCDHFlagsHLTPayload);
int AliHLTOUTComponent::WriteDigitArray(int hltddl, const AliHLTUInt8_t* pBuffer, unsigned int bufferSize)
{
- // see header file for class documentation
+ // wite a buffer to the associated digit array
int iResult=0;
assert(hltddl<fNofDDLs);
if (hltddl>=fNofDDLs) return -ERANGE;
return iResult;
}
-int AliHLTOUTComponent::WriteDigits(int /*eventNo*/, AliRunLoader* /*runLoader*/)
+int AliHLTOUTComponent::WriteDigits(int /*eventNo*/)
{
- // see header file for class documentation
+ // fill tree with digit arrays and write to file
+ // all links must be written, even in round robin mode, where all links but one
+ // do not contain any data blocks.
+ // This is a limitation of storing the links in a tree
int iResult=0;
if (!fpDigitFile) {
fpDigitFile=new TFile(fDigitFileName, "RECREATE");
}
}
if (fpDigitTree) {
+#ifdef __DEBUG
int res=fpDigitTree->Fill();
HLTDebug("writing digit tree: %d", res);
fpDigitFile->cd();
res=fpDigitTree->Write("",TObject::kOverwrite);
HLTDebug("writing digit tree: %d", res);
+#else
+ fpDigitTree->Fill();
+ fpDigitFile->cd();
+ fpDigitTree->Write("",TObject::kOverwrite);
+#endif
if (fppDigitArrays) for (int i=0; i<fNofDDLs; i++) {
if (fppDigitArrays[i]) fppDigitArrays[i]->Set(0);
}
return iResult;
}
-int AliHLTOUTComponent::WriteRawFile(int eventNo, AliRunLoader* /*runLoader*/, int hltddl, const AliHLTUInt8_t* pBuffer, unsigned int bufferSize)
+int AliHLTOUTComponent::WriteRawFile(int eventNo, int hltddl, const AliHLTUInt8_t* pBuffer, unsigned int bufferSize)
{
- // see header file for class documentation
+ // write buffer to raw file in the current directory
+ // creates the event raw directories in the current directory
int iResult=0;
const char* fileName=AliDAQ::DdlFileName("HLT", hltddl);
assert(fileName!=NULL);
TString filePath;
filePath.Form("raw%d/", eventNo);
+ if (gSystem->AccessPathName(filePath)!=0) {
+ // note: AccessPathName return 0 if the path is existing
+ TString command="mkdir "; command+=filePath;
+ gSystem->Exec(command);
+ }
filePath+=fileName;
if (fileName) {
ios::openmode filemode=(ios::openmode)0;
void AliHLTOUTComponent::SetGlobalOption(unsigned int options)
{
- // see header file for class documentation
+ // set the global options
fgOptions|=options;
}
void AliHLTOUTComponent::ClearGlobalOption(unsigned int options)
{
- // see header file for class documentation
+ // reset the global options
fgOptions&=~options;
}
+
+bool AliHLTOUTComponent::TestGlobalOption(unsigned int option)
+{
+ // check option
+ return (fgOptions&option)!=0;
+}