3 /**************************************************************************
4 * This file is property of and copyright by the ALICE HLT Project *
5 * ALICE Experiment at CERN, All rights reserved. *
7 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 * for The ALICE HLT Project. *
10 * Permission to use, copy, modify and distribute this software and its *
11 * documentation strictly for non-commercial purposes is hereby granted *
12 * without fee, provided that the above copyright notice appears in all *
13 * copies and that both the copyright notice and this permission notice *
14 * appear in the supporting documentation. The authors make no claims *
15 * about the suitability of this software for any purpose. It is *
16 * provided "as is" without express or implied warranty. *
17 **************************************************************************/
19 /** @file AliHLTOUTComponent.cxx
20 @author Matthias Richter
22 @brief The HLTOUT data sink component similar to HLTOUT nodes */
24 // see header file for class documentation
26 // refer to README to build package
28 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
36 #include "AliHLTOUTComponent.h"
37 #include "AliHLTOUT.h"
38 #include "AliHLTHOMERLibManager.h"
39 #include "AliHLTHOMERWriter.h"
40 #include "AliDAQ.h" // equipment Ids
41 #include "AliRawDataHeader.h" // Common Data Header
42 #include <TDatime.h> // seed for TRandom
43 #include <TRandom.h> // random int generation for DDL no
45 /** ROOT macro for the implementation of ROOT specific class methods */
46 ClassImp(AliHLTOUTComponent)
48 AliHLTOUTComponent::AliHLTOUTComponent()
50 AliHLTOfflineDataSink(),
53 fIdFirstDDL(4864), // 0x13<<8
59 // see header file for class documentation
61 // refer to README to build package
63 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
65 // I guess DDL definitions should never change any more
66 assert(fNofDDLs==AliDAQ::NumberOfDdls("HLT"));
67 fNofDDLs=AliDAQ::NumberOfDdls("HLT");
68 assert(fIdFirstDDL==AliDAQ::DdlIDOffset("HLT"));
69 fIdFirstDDL=AliDAQ::DdlIDOffset("HLT");
72 AliHLTOUTComponent::~AliHLTOUTComponent()
74 // see header file for class documentation
75 if (fpLibManager) delete fpLibManager;
79 const char* AliHLTOUTComponent::GetComponentID()
81 // see header file for class documentation
85 void AliHLTOUTComponent::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
87 // see header file for class documentation
89 list.push_back(kAliHLTAnyDataType);
92 AliHLTComponent* AliHLTOUTComponent::Spawn()
94 // see header file for class documentation
95 return new AliHLTOUTComponent;
98 int AliHLTOUTComponent::DoInit( int argc, const char** argv )
100 // see header file for class documentation
104 for (int i=0; i<argc && iResult>=0; i++) {
106 if (argument.IsNull()) continue;
109 HLTError("unknown argument %s", argument.Data());
114 HLTError("missing parameter for argument %s", argument.Data());
120 fpLibManager=new AliHLTHOMERLibManager;
123 for (writerNo=0; writerNo<fNofDDLs; writerNo++) {
124 AliHLTMonitoringWriter* pWriter=fpLibManager->OpenWriter();
126 fWriters.push_back(pWriter);
139 int AliHLTOUTComponent::DoDeinit()
141 // see header file for class documentation
145 AliHLTMonitoringWriterPVector::iterator element=fWriters.begin();
146 while (element!= fWriters.end()) {
148 // wanted to have a dynamic_cast<AliHLTHOMERWriter*> here, but this results into
149 // undefined symbol when loading the library
150 if (*element!=NULL) fpLibManager->DeleteWriter((AliHLTHOMERWriter*)(*element));
151 element=fWriters.erase(element);
158 int AliHLTOUTComponent::DumpEvent( const AliHLTComponentEventData& evtData,
159 const AliHLTComponentBlockData* blocks,
160 AliHLTComponentTriggerData& /*trigData*/ )
162 // see header file for class documentation
164 HLTInfo("write %d output blocks", evtData.fBlockCnt);
167 homer_uint64 homerHeader[kCount_64b_Words];
168 HOMERBlockDescriptor homerDescriptor(homerHeader);
169 for (int n=0; n<(int)evtData.fBlockCnt; n++ ) {
170 memset( homerHeader, 0, sizeof(homer_uint64)*kCount_64b_Words );
171 homerDescriptor.Initialize();
172 homerDescriptor.SetType(reinterpret_cast<homer_uint64>(blocks[n].fDataType.fID));
173 homerDescriptor.SetSubType1(reinterpret_cast<homer_uint64>(blocks[n].fDataType.fOrigin));
174 homerDescriptor.SetSubType2(static_cast<homer_uint64>(blocks[n].fSpecification));
175 int writerNo=ShuffleWriters(fWriters, blocks[n].fSize);
176 assert(writerNo>=0 && writerNo<fWriters.size());
177 fWriters[writerNo]->AddBlock(&homerDescriptor, blocks[n].fPtr);
184 int AliHLTOUTComponent::FillESD(int eventNo, AliRunLoader* runLoader, AliESDEvent* /*esd*/)
186 // see header file for class documentation
188 if (fWriters.size()==0) return 0;
190 // search for the writer with the biggest data volume in order to allocate the
191 // output buffer of sufficient size
193 for (size_t i=0; i<fWriters.size(); i++) {
196 //TODO: sorted.size() can never ever ever be negative. Please check the logic.
197 if (/*sorted.size()>=0 &&*/ fWriters[i]->GetTotalMemorySize()>fWriters[sorted[0]]->GetTotalMemorySize()) {
198 sorted.insert(sorted.begin(), i);
205 vector<int>::iterator ddlno=sorted.begin();
206 while (ddlno!=sorted.end()) {
207 const AliHLTUInt8_t* pBuffer=NULL;
210 if ((bufferSize=FillOutputBuffer(eventNo, fWriters[*ddlno], pBuffer))>0) {
211 if (fWriteDigits) WriteDigits(eventNo, runLoader, *ddlno, pBuffer, bufferSize);
212 if (fWriteRaw) WriteRawFile(eventNo, runLoader, *ddlno, pBuffer, bufferSize);
219 int AliHLTOUTComponent::ShuffleWriters(AliHLTMonitoringWriterPVector &list, AliHLTUInt32_t /*size*/)
221 // see header file for class documentation
223 assert(list.size()>0);
224 if (list.size()==0) return iResult;
227 for (i=0; i<list.size(); i++) {
228 if (list[i]->GetTotalMemorySize()==0)
229 writers.push_back(i);
230 else if (iResult<0 ||
231 list[i]->GetTotalMemorySize()<list[iResult]->GetTotalMemorySize())
235 if (writers.size()>0) {
237 if (writers.size()>0) {
238 // shuffle among the empty writers
241 rand.SetSeed(dt.Get()*(iResult+1));
242 i=rand.Integer(writers.size()-1);
243 assert(i>0 && i<writers.size()-1);
247 // take the writer with the least data volume
253 int AliHLTOUTComponent::FillOutputBuffer(int eventNo, AliHLTMonitoringWriter* pWriter, const AliHLTUInt8_t* &pBuffer)
255 // see header file for class documentation
257 unsigned int bufferSize=0;
259 // space for common data header
260 bufferSize+=sizeof(AliRawDataHeader);
261 assert(sizeof(AliRawDataHeader)==24);
263 // space for HLT event header
264 bufferSize+=sizeof(AliHLTOUT::AliHLTOUTEventHeader);
266 // space for payload from the writer
267 if (pWriter) bufferSize+=pWriter->GetTotalMemorySize();
269 if (bufferSize>fBuffer.size())
270 fBuffer.resize(bufferSize);
272 if (bufferSize<=fBuffer.size()) {
273 AliRawDataHeader* pCDH=reinterpret_cast<AliRawDataHeader*>(&fBuffer[0]);
274 AliHLTOUT::AliHLTOUTEventHeader* pHLTH=reinterpret_cast<AliHLTOUT::AliHLTOUTEventHeader*>(&fBuffer[sizeof(AliRawDataHeader)]);
275 memset(pCDH, 0, sizeof(AliRawDataHeader));
276 memset(pHLTH, 0, sizeof(AliHLTOUT::AliHLTOUTEventHeader));
280 pWriter->Copy(&fBuffer[sizeof(AliRawDataHeader)+sizeof(AliHLTOUT::AliHLTOUTEventHeader)], 0, 0, 0, 0);
281 pHLTH->fLength=pWriter->GetTotalMemorySize();
282 // set status bit to indicate HLT payload
283 pCDH->fStatusMiniEventID|=0x1<<(AliHLTOUT::fgkCDHStatusFlagsOffset+AliHLTOUT::fgkCDHFlagsHLTPayload);
285 pHLTH->fLength+=sizeof(AliHLTOUT::AliHLTOUTEventHeader);
286 pHLTH->fEventID=eventNo;
288 pCDH->fSize=sizeof(AliRawDataHeader)+pHLTH->fLength;
299 //TODO: Please consider making bufferSize unsigned int and not just int.
300 int AliHLTOUTComponent::WriteDigits(int /*eventNo*/, AliRunLoader* /*runLoader*/, int /*hltddl*/, const AliHLTUInt8_t* /*pBuffer*/, int /*bufferSize*/)
302 // see header file for class documentation
307 //TODO: Please consider making bufferSize unsigned int and not just int.
308 int AliHLTOUTComponent::WriteRawFile(int /*eventNo*/, AliRunLoader* /*runLoader*/, int hltddl, const AliHLTUInt8_t* pBuffer, int bufferSize)
310 // see header file for class documentation
312 const char* fileName=AliDAQ::DdlFileName("HLT", hltddl);
313 assert(fileName!=NULL);
314 TString filePath(fileName);
316 ios::openmode filemode=(ios::openmode)0;
317 ofstream rawfile(filePath.Data(), filemode);
318 if (rawfile.good()) {
319 if (pBuffer && bufferSize>0) {
320 rawfile.write(reinterpret_cast<const char*>(pBuffer), bufferSize);
322 HLTWarning("writing zero length raw data file %s");
324 HLTDebug("wrote %d byte(s) to file %s", bufferSize, filePath.Data());
326 HLTError("can not open file %s for writing", filePath.Data());