ALIROOT-5433 Transition to CDHv3 in HLT
[u/mrichter/AliRoot.git] / HLT / sim / AliHLTOUTComponent.cxx
CommitLineData
c4228ec4 1// $Id$
2
c5123824 3//**************************************************************************
3c29512c 4//* This file is property of and copyright by the *
c5123824 5//* ALICE Experiment at CERN, All rights reserved. *
6//* *
7//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8//* for The ALICE HLT Project. *
9//* *
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//**************************************************************************
c4228ec4 18
4aa34abc 19/// @file AliHLTOUTComponent.cxx
20/// @author Matthias Richter
21/// @date
22/// @brief The HLTOUT data sink component similar to HLTOUT nodes
23/// @note Used in the AliRoot environment only.
c4228ec4 24
4b113031 25#include <cassert>
13398559 26//#include <iostream>
c4228ec4 27#include "AliHLTOUTComponent.h"
4b113031 28#include "AliHLTOUT.h"
64defa03 29#include "AliHLTHOMERLibManager.h"
4b113031 30#include "AliHLTHOMERWriter.h"
6a904136 31#include "AliHLTErrorGuard.h"
a183f221 32#include "AliDAQ.h" // equipment Ids
16e6f752 33#include "AliRawDataHeaderV3.h" // Common Data Header
4b113031 34#include <TDatime.h> // seed for TRandom
35#include <TRandom.h> // random int generation for DDL no
c5123824 36#include <TFile.h>
37#include <TTree.h>
38#include <TArrayC.h>
6a904136 39#include <TSystem.h>
c4228ec4 40
3c29512c 41using namespace std;
42
c4228ec4 43/** ROOT macro for the implementation of ROOT specific class methods */
44ClassImp(AliHLTOUTComponent)
45
6a904136 46AliHLTOUTComponent::AliHLTOUTComponent(EType type)
3c29512c 47 : AliHLTDataSink()
e2640fbd 48 , fWriters()
49 , fNofDDLs(10)
50 , fIdFirstDDL(7680) // 0x1e<<8
51 , fBuffer()
52 , fpLibManager(NULL)
6a904136 53 , fOptions(0)
e2640fbd 54 , fDigitFileName("HLT.Digits.root")
55 , fpDigitFile(NULL)
56 , fpDigitTree(NULL)
57 , fppDigitArrays(NULL)
58 , fReservedWriter(-1)
59 , fReservedData(0)
6a904136 60 , fType(type)
4aa34abc 61 , fRoundRobinCounter(0)
c4228ec4 62{
3c29512c 63 // The HLTOUT data sink component which models the behavior of the HLTOUT
64 // nodes of the HLT cluster.
65 // The HLTOUT component is attached at the end of a chain. It stores all input
66 // block in the HOMER format, distributed over a number of DDL link. The data
67 // is stored in a digit file or in raw ddl files.
398bd766 68 fIdFirstDDL=AliDAQ::DdlIDOffset("HLT");
4b113031 69 fNofDDLs=AliDAQ::NumberOfDdls("HLT");
44dc7683 70
6a904136 71 if (fType!=kGlobal && fType!=kDigits && fType!=kRaw) {
72 ALIHLTERRORGUARD(1, "invalid component type %d", fType);
73 }
c4228ec4 74}
75
2c0e5942 76int AliHLTOUTComponent::fgOptions=kWriteRawFiles|kWriteDigits;
77
c4228ec4 78AliHLTOUTComponent::~AliHLTOUTComponent()
79{
4aa34abc 80 // destructor
a183f221 81 if (fpLibManager) delete fpLibManager;
82 fpLibManager=NULL;
c4228ec4 83}
84
85const char* AliHLTOUTComponent::GetComponentID()
86{
4aa34abc 87 // overloaded from AliHLTComponent: get component id
6a904136 88 switch (fType) {
89 case kDigits: return "HLTOUTdigits";
90 case kRaw: return "HLTOUTraw";
91 case kGlobal:
92 default:
93 return "HLTOUT";
94 }
95 return NULL;
c4228ec4 96}
97
3c29512c 98void AliHLTOUTComponent::GetInputDataTypes( AliHLTComponentDataTypeList& list)
c4228ec4 99{
4aa34abc 100 // overloaded from AliHLTComponent: indicate input data types
c4228ec4 101 list.clear();
102 list.push_back(kAliHLTAnyDataType);
103}
104
105AliHLTComponent* AliHLTOUTComponent::Spawn()
106{
4aa34abc 107 // overloaded from AliHLTComponent: create instance
6a904136 108 return new AliHLTOUTComponent(fType);
c4228ec4 109}
110
111int AliHLTOUTComponent::DoInit( int argc, const char** argv )
112{
4aa34abc 113 // overloaded from AliHLTComponent: initialization
c4228ec4 114 int iResult=0;
6a904136 115
116 switch (fType) {
117 case kDigits:
118 fOptions|=kWriteDigits; fOptions&=~kWriteRawFiles;
119 HLTInfo("initializing HLTOUT component for digits generation");
120 break;
121 case kRaw:
122 fOptions|=kWriteRawFiles; fOptions&=~kWriteDigits;
123 HLTInfo("initializing HLTOUT component for raw data generation");
124 break;
125 case kGlobal:
126 default:
127 fOptions=fgOptions;
128 }
129
3d24abe7 130 if ((iResult=ConfigureFromArgumentString(argc, argv))<0) return iResult;
c4228ec4 131
1b820a65 132 // Create a new library manager and allocate the appropriate number of
133 // HOMER writers for the HLTOUT component.
4aa34abc 134 if (!fpLibManager) fpLibManager=new AliHLTHOMERLibManager;
a183f221 135 if (fpLibManager) {
136 int writerNo=0;
137 for (writerNo=0; writerNo<fNofDDLs; writerNo++) {
138 AliHLTMonitoringWriter* pWriter=fpLibManager->OpenWriter();
139 if (pWriter) {
a8420176 140 HLTDebug("HOMER writer %p added", pWriter);
a183f221 141 fWriters.push_back(pWriter);
142 } else {
c5123824 143 HLTError("can not open HOMER writer");
5db0e774 144 iResult=-ENODEV;
a183f221 145 break;
146 }
4b113031 147 }
a183f221 148 } else {
149 iResult=-ENOMEM;
4b113031 150 }
151
c4228ec4 152 return iResult;
153}
154
e2640fbd 155int AliHLTOUTComponent::ScanConfigurationArgument(int argc, const char** argv)
156{
4aa34abc 157 // overloaded from AliHLTComponent: argument scan
e2640fbd 158 if (argc<=0) return 0;
159 int i=0;
160 TString argument=argv[i];
161 const char* key="";
162
163 // -links n
164 // specify number of ddl links
165 if (argument.CompareTo("-links")==0) {
166 if (++i>=argc) return -EPROTO;
167 TString parameter(argv[i]);
168 parameter.Remove(TString::kLeading, ' '); // remove all blanks
169 if (parameter.IsDigit()) {
170 fNofDDLs=parameter.Atoi();
171 } else {
172 HLTError("wrong parameter for argument %s, number expected", argument.Data());
173 return -EINVAL;
174 }
175
176 return 2;
177 }
178
179 // -digitfile name
180 if (argument.CompareTo("-digitfile")==0) {
181 if (++i>=argc) return -EPROTO;
182 fDigitFileName=argv[i];
183
184 return 2;
185 }
186
187 // -rawout
188 key="-rawout";
189 if (argument.Contains(key)) {
190 argument.ReplaceAll(key, "");
191 if (argument.IsNull()) {
6a904136 192 fOptions|=kWriteRawFiles;
e2640fbd 193 } else if (argument.CompareTo("=off")==0) {
6a904136 194 fOptions&=~kWriteRawFiles;
e2640fbd 195 } else if (argument.CompareTo("=on")==0) {
6a904136 196 fOptions|=kWriteRawFiles;
e2640fbd 197 } else {
198 HLTError("invalid parameter for argument %s: possible %s=off/%s=on", key, key, key);
199 return -EPROTO;
200 }
201
202 return 1;
203 }
204
205 // -digitout
206 key="-digitout";
207 if (argument.Contains(key)) {
208 argument.ReplaceAll(key, "");
209 if (argument.IsNull()) {
6a904136 210 fOptions|=kWriteDigits;
e2640fbd 211 } else if (argument.CompareTo("=off")==0) {
6a904136 212 fOptions&=~kWriteDigits;
e2640fbd 213 } else if (argument.CompareTo("=on")==0) {
6a904136 214 fOptions|=kWriteDigits;
e2640fbd 215 } else {
216 HLTError("invalid parameter for argument %s: possible %s=off/%s=on", key, key, key);
217 return -EPROTO;
218 }
219
220 return 1;
221 }
222
4aa34abc 223 // -distribute-blocks
224 key="-distribute-blocks";
225 if (argument.CompareTo(key)==0) {
226 fRoundRobinCounter=-1;
227
228 return 1;
229 }
230
e2640fbd 231 // unknown argument
232 return -EINVAL;
233}
234
c4228ec4 235int AliHLTOUTComponent::DoDeinit()
236{
4aa34abc 237 // overloaded from AliHLTComponent: cleanup
c4228ec4 238 int iResult=0;
4b113031 239
a183f221 240 if (fpLibManager) {
241 AliHLTMonitoringWriterPVector::iterator element=fWriters.begin();
242 while (element!= fWriters.end()) {
243 assert(*element);
b9dd5a11 244 // wanted to have a dynamic_cast<AliHLTHOMERWriter*> here, but this results into
245 // undefined symbol when loading the library
c74eec40 246 if (*element!=NULL) {
1b820a65 247 (*element)->Clear();
248 fpLibManager->DeleteWriter((AliHLTHOMERWriter*)(*element));
c74eec40 249 } else {
250 HLTError("writer instance is NULL");
251 }
a183f221 252 element=fWriters.erase(element);
253 }
4b113031 254 }
1b820a65 255 if (fpLibManager) {
256 delete fpLibManager;
257 fpLibManager=NULL;
258 }
c5123824 259
260 if (fpDigitTree) {
261 delete fpDigitTree;
262 fpDigitTree=NULL;
263 }
264
265 if (fpDigitFile) {
266 fpDigitFile->Close();
267 delete fpDigitFile;
268 fpDigitFile=NULL;
269 }
270
271 if (fppDigitArrays) {
272 for (int i=0; i<fNofDDLs; i++) {
273 if (fppDigitArrays[i]) delete fppDigitArrays[i];
274 }
275 delete[] fppDigitArrays;
276 fppDigitArrays=NULL;
277 }
c4228ec4 278
279 return iResult;
280}
281
282int AliHLTOUTComponent::DumpEvent( const AliHLTComponentEventData& evtData,
283 const AliHLTComponentBlockData* blocks,
284 AliHLTComponentTriggerData& /*trigData*/ )
285{
4aa34abc 286 // overloaded from AliHLTDataSink: event processing
c4228ec4 287 int iResult=0;
2c0e5942 288 HLTInfo("write %d output block(s)", evtData.fBlockCnt);
6478b06b 289 int writerNo=0;
3d24abe7 290 int blockCount=0;
6478b06b 291 AliHLTUInt32_t eventType=gkAliEventTypeUnknown;
292 bool bIsDataEvent=IsDataEvent(&eventType);
4b113031 293 if (iResult>=0) {
294 homer_uint64 homerHeader[kCount_64b_Words];
295 HOMERBlockDescriptor homerDescriptor(homerHeader);
296 for (int n=0; n<(int)evtData.fBlockCnt; n++ ) {
6478b06b 297 if (blocks[n].fDataType==kAliHLTDataTypeEvent ||
298 blocks[n].fDataType==kAliHLTDataTypeSOR ||
299 blocks[n].fDataType==kAliHLTDataTypeEOR ||
300 blocks[n].fDataType==kAliHLTDataTypeComConf ||
301 blocks[n].fDataType==kAliHLTDataTypeUpdtDCS)
302 {
303 // the special events have to be ignored.
304 continue;
305 }
306 if (!bIsDataEvent &&
307 (blocks[n].fDataType!=kAliHLTDataTypeComponentTable))
308 {
309 // In simulation, there are no SOR and EOR events created. Thats
310 // why all data blocks of those events are currently ignored.
311 // Strictly speaking, components should not create output blocks
312 // on the SOR/EOR event
313 //
314 // Exeptions: some blocks are added, the buffer must be prepared and
315 // kept since the pointers will be invalid
316 // - kAliHLTDataTypeComponentTable component table entries
317 continue;
318 }
4b113031 319 memset( homerHeader, 0, sizeof(homer_uint64)*kCount_64b_Words );
320 homerDescriptor.Initialize();
44dc7683 321 // for some traditional reason the TCPDumpSubscriber swaps the bytes
322 // of the data type id and data type origin. Actually I do not understand
323 // the corresponding code line
324 // homerBlock.SetType( blocks[n].fDataType.fID );
325 // this compiles in the PubSub framework and in addition does a byte swap
326 homer_uint64 id=0;
327 homer_uint64 origin=0;
328 memcpy(&id, blocks[n].fDataType.fID, sizeof(homer_uint64));
329 memcpy(((AliHLTUInt8_t*)&origin)+sizeof(homer_uint32), blocks[n].fDataType.fOrigin, sizeof(homer_uint32));
ff3b6fed 330 homerDescriptor.SetType(AliHLTOUT::ByteSwap64(id));
c5123824 331 homerDescriptor.SetSubType1(AliHLTOUT::ByteSwap64(origin));
44dc7683 332 homerDescriptor.SetSubType2(blocks[n].fSpecification);
a8420176 333 homerDescriptor.SetBlockSize(blocks[n].fSize);
6478b06b 334 if (bIsDataEvent) {
335 writerNo=ShuffleWriters(fWriters, blocks[n].fSize);
336 }
13398559 337 assert(writerNo>=0 && writerNo<(int)fWriters.size());
a8420176 338 // I'm puzzled by the different headers, buffers etc. used in the
339 // HOMER writer/data. In additional, there is no type check as there
340 // are void pointers used and names mixed.
341 // It seems that HOMERBlockDescriptor is just a tool to set the
342 // different fields in the homer header, which is an array of 64 bit
343 // words.
344 fWriters[writerNo]->AddBlock(homerHeader, blocks[n].fPtr);
3d24abe7 345 blockCount++;
4b113031 346 }
347 }
348
3d24abe7 349 if (iResult>=0 && !bIsDataEvent && fNofDDLs>=2) {
6478b06b 350 // data blocks from a special event are kept to be added to the
3d24abe7 351 // following event. In the current implementation at least 2 DDLs
352 // are required to allow to keep the blocks of the SOR event and
353 // include it in the first event. If only one writer is available
354 // the blocks are ignored. For the moment this is not expexted to
355 // be a problem since components should not gererate anything on
356 // SOR/EOR. The only case is the list of AliHLTComponentTableEntry
357 // transmitted for component statistics in debug mode.
6478b06b 358 if (fReservedWriter>=0) {
359 HLTWarning("overriding previous buffer of non-data event data blocks");
360 }
361 const AliHLTUInt8_t* pBuffer=NULL;
362 int bufferSize=0;
363 // TODO: not yet clear whether it is smart to send the event id of
364 // this special event or if it should be set from the id of the
365 // following event where the data will be added
3d24abe7 366 if (blockCount>0 && (bufferSize=FillOutputBuffer(evtData.fEventID, fWriters[writerNo], pBuffer))>0) {
6478b06b 367 fReservedWriter=writerNo;
368 fReservedData=bufferSize;
369 }
370 fWriters[writerNo]->Clear();
3d24abe7 371 } else if (iResult>=0 && !bIsDataEvent && fNofDDLs<2 && blockCount>0) {
372 HLTWarning("ignoring %d block(s) for special event of type %d: at least 2 DDLs are required", blockCount, eventType);
373 }
374
375 if (iResult>=0 && bIsDataEvent) {
3c29512c 376 iResult=Write(GetEventCount());
6478b06b 377 }
378
4aa34abc 379 if (fRoundRobinCounter>=0) {
380 if (++fRoundRobinCounter>=fNofDDLs) fRoundRobinCounter=0;
381 }
382
4b113031 383 return iResult;
384}
385
3c29512c 386int AliHLTOUTComponent::Write(int eventNo)
3d24abe7 387{
4aa34abc 388 // write digits and raw files for the current event
4b113031 389 int iResult=0;
6478b06b 390
4b113031 391 if (fWriters.size()==0) return 0;
3d24abe7 392
6478b06b 393 if (fReservedWriter>=0) {
6a904136 394 if (fOptions&kWriteDigits) WriteDigitArray(fReservedWriter, &fBuffer[0], fReservedData);
3c29512c 395 if (fOptions&kWriteRawFiles) WriteRawFile(eventNo, fReservedWriter, &fBuffer[0], fReservedData);
6478b06b 396 fReservedData=0;
397 }
398
4b113031 399 // search for the writer with the biggest data volume in order to allocate the
400 // output buffer of sufficient size
4b113031 401 vector<int> sorted;
d76bc02a 402 for (size_t i=0; i<fWriters.size(); i++) {
6478b06b 403 if ((int)i==fReservedWriter) continue;
4b113031 404 assert(fWriters[i]);
405 if (fWriters[i]) {
a8420176 406 if (sorted.size()==0 || fWriters[i]->GetTotalMemorySize()<=fWriters[sorted[0]]->GetTotalMemorySize()) {
4b113031 407 sorted.push_back(i);
a8420176 408 } else {
409 sorted.insert(sorted.begin(), i);
4b113031 410 }
411 }
4b113031 412 }
6478b06b 413 fReservedWriter=-1;
4b113031 414
415 vector<int>::iterator ddlno=sorted.begin();
416 while (ddlno!=sorted.end()) {
417 const AliHLTUInt8_t* pBuffer=NULL;
418 int bufferSize=0;
419
b9dd5a11 420 if ((bufferSize=FillOutputBuffer(eventNo, fWriters[*ddlno], pBuffer))>0) {
6a904136 421 if (fOptions&kWriteDigits) WriteDigitArray(*ddlno, pBuffer, bufferSize);
4aa34abc 422 if (fOptions&kWriteRawFiles &&
423 (fRoundRobinCounter<0 || fRoundRobinCounter==*ddlno))
3c29512c 424 WriteRawFile(eventNo, *ddlno, pBuffer, bufferSize);
4b113031 425 }
a8420176 426 fWriters[*ddlno]->Clear();
4b113031 427 ddlno++;
428 }
3c29512c 429 if (fOptions&kWriteDigits) WriteDigits(eventNo);
4b113031 430 return iResult;
431}
432
d76bc02a 433int AliHLTOUTComponent::ShuffleWriters(AliHLTMonitoringWriterPVector &list, AliHLTUInt32_t /*size*/)
4b113031 434{
4aa34abc 435 /// get a writer for the next block
436 /// in round robin mode (like the online HLTOUT) all blocks of one event go to the same link
437 /// this is now also the default behavior of the HLTOUTComponent and indicated by
438 /// fRoundRobinCounter>=0
439 /// Writers are selected randomly otherwise.
440 if (fRoundRobinCounter>=0) {
441 if (fRoundRobinCounter==fReservedWriter) {
442 if (++fRoundRobinCounter>=fNofDDLs) fRoundRobinCounter=0;
443 if (fRoundRobinCounter==fReservedWriter) {
444 HLTWarning("there are not enough links to use a reserved writer, discarding data in reserved writer %d (total %d)",
445 fReservedWriter, fNofDDLs);
446 fReservedWriter=-1;
447 }
448 }
449 return fRoundRobinCounter;
450 }
451
4b113031 452 int iResult=-ENOENT;
453 assert(list.size()>0);
454 if (list.size()==0) return iResult;
455 vector<int> writers;
d76bc02a 456 size_t i=0;
4b113031 457 for (i=0; i<list.size(); i++) {
6478b06b 458 if ((int)i==fReservedWriter) continue;
4b113031 459 if (list[i]->GetTotalMemorySize()==0)
460 writers.push_back(i);
461 else if (iResult<0 ||
462 list[i]->GetTotalMemorySize()<list[iResult]->GetTotalMemorySize())
463 iResult=i;
464
465 }
466 if (writers.size()>0) {
467 iResult=writers[0];
468 if (writers.size()>0) {
469 // shuffle among the empty writers
470 TDatime dt;
471 TRandom rand;
472 rand.SetSeed(dt.Get()*(iResult+1));
473 i=rand.Integer(writers.size()-1);
474 assert(i>0 && i<writers.size()-1);
475 iResult=writers[i];
476 }
477 } else {
478 // take the writer with the least data volume
479 assert(iResult>=0);
480 }
481 return iResult;
482}
483
a183f221 484int AliHLTOUTComponent::FillOutputBuffer(int eventNo, AliHLTMonitoringWriter* pWriter, const AliHLTUInt8_t* &pBuffer)
4b113031 485{
4aa34abc 486 // prepare the output buffer for writing, consists of
487 // - CDH
488 // - HLTOUT header
489 // - HOMER data
490 // buffer is allocated internally and data is valid until next call
4b113031 491 int iResult=0;
d76bc02a 492 unsigned int bufferSize=0;
4b113031 493
494 // space for common data header
16e6f752 495 bufferSize+=sizeof(AliRawDataHeaderV3);
4b113031 496
497 // space for HLT event header
498 bufferSize+=sizeof(AliHLTOUT::AliHLTOUTEventHeader);
499
500 // space for payload from the writer
501 if (pWriter) bufferSize+=pWriter->GetTotalMemorySize();
502
737bab1f 503 // payload data must be aligned to 32bit
504 bufferSize=(bufferSize+3)/4;
505 bufferSize*=4;
506
4b113031 507 if (bufferSize>fBuffer.size())
508 fBuffer.resize(bufferSize);
509
737bab1f 510 // reset the last 32bit word, rest will be overwritten
511 memset(&fBuffer[bufferSize-4], 0, 4);
512
4b113031 513 if (bufferSize<=fBuffer.size()) {
16e6f752 514 AliRawDataHeaderV3* pCDH=reinterpret_cast<AliRawDataHeaderV3*>(&fBuffer[0]);
515 AliHLTOUT::AliHLTOUTEventHeader* pHLTH=reinterpret_cast<AliHLTOUT::AliHLTOUTEventHeader*>(&fBuffer[sizeof(AliRawDataHeaderV3)]);
516 *pCDH = AliRawDataHeaderV3(); // Fill with default values.
4b113031 517 memset(pHLTH, 0, sizeof(AliHLTOUT::AliHLTOUTEventHeader));
44dc7683 518
4b113031 519 if (pWriter) {
520 // copy payload
16e6f752 521 pWriter->Copy(&fBuffer[sizeof(AliRawDataHeaderV3)+sizeof(AliHLTOUT::AliHLTOUTEventHeader)], 0, 0, 0, 0);
4b113031 522 pHLTH->fLength=pWriter->GetTotalMemorySize();
523 // set status bit to indicate HLT payload
13398559 524 pCDH->fStatusMiniEventID|=0x1<<(AliHLTOUT::kCDHStatusFlagsOffset+AliHLTOUT::kCDHFlagsHLTPayload);
4b113031 525 }
526 pHLTH->fLength+=sizeof(AliHLTOUT::AliHLTOUTEventHeader);
c2b283d6 527 // pHLTH->fEventIDLow is already set to zero in memset above.
528 pHLTH->fEventIDLow = eventNo;
44dc7683 529 // version does not really matter since we do not add decision data
530 pHLTH->fVersion=AliHLTOUT::kVersion1;
4b113031 531
31d7df34 532 pCDH->fSize=bufferSize;
44dc7683 533 pCDH->fStatusMiniEventID|=0x1<<(AliHLTOUT::kCDHStatusFlagsOffset + AliHLTOUT::kCDHFlagsHLTPayload);
c4228ec4 534
4b113031 535 pBuffer=&fBuffer[0];
a8420176 536 iResult=(int)bufferSize;
4b113031 537 } else {
538 pBuffer=NULL;
539 iResult=-ENOMEM;
c4228ec4 540 }
541
542 return iResult;
543}
544
c5123824 545int AliHLTOUTComponent::WriteDigitArray(int hltddl, const AliHLTUInt8_t* pBuffer, unsigned int bufferSize)
546{
4aa34abc 547 // wite a buffer to the associated digit array
c5123824 548 int iResult=0;
549 assert(hltddl<fNofDDLs);
550 if (hltddl>=fNofDDLs) return -ERANGE;
551
552 if (!fppDigitArrays) {
553 fppDigitArrays=new TArrayC*[fNofDDLs];
554 if (fppDigitArrays) {
555 for (int i=0; i<fNofDDLs; i++) {
556 fppDigitArrays[i]=new TArrayC(0);
557 }
558 }
559 }
560 if (fppDigitArrays && fppDigitArrays[hltddl]) {
561 fppDigitArrays[hltddl]->Set(bufferSize, reinterpret_cast<const Char_t*>(pBuffer));
562 } else {
563 iResult=-ENOMEM;
564 }
565 return iResult;
566}
567
3c29512c 568int AliHLTOUTComponent::WriteDigits(int /*eventNo*/)
c4228ec4 569{
4aa34abc 570 // fill tree with digit arrays and write to file
571 // all links must be written, even in round robin mode, where all links but one
572 // do not contain any data blocks.
573 // This is a limitation of storing the links in a tree
c4228ec4 574 int iResult=0;
c5123824 575 if (!fpDigitFile) {
e2640fbd 576 fpDigitFile=new TFile(fDigitFileName, "RECREATE");
c5123824 577 }
578 if (fpDigitFile && !fpDigitFile->IsZombie()) {
579 if (!fpDigitTree) {
580 fpDigitTree=new TTree("rawhltout","HLTOUT raw data");
581 if (fpDigitTree && fppDigitArrays) {
582 for (int i=0; i<fNofDDLs; i++) {
583 const char* branchName=AliDAQ::DdlFileName("HLT", i);
584 if (fppDigitArrays[i]) fpDigitTree->Branch(branchName, "TArrayC", &fppDigitArrays[i], 32000/*just as the default*/, 0);
585 }
586 }
587 }
588 if (fpDigitTree) {
d1035b66 589#ifdef __DEBUG
c5123824 590 int res=fpDigitTree->Fill();
591 HLTDebug("writing digit tree: %d", res);
592 fpDigitFile->cd();
593 res=fpDigitTree->Write("",TObject::kOverwrite);
594 HLTDebug("writing digit tree: %d", res);
d1035b66 595#else
596 fpDigitTree->Fill();
597 fpDigitFile->cd();
598 fpDigitTree->Write("",TObject::kOverwrite);
599#endif
c5123824 600 if (fppDigitArrays) for (int i=0; i<fNofDDLs; i++) {
601 if (fppDigitArrays[i]) fppDigitArrays[i]->Set(0);
602 }
603 }
604 } else {
605 const char* errorMsg="";
606 if (GetEventCount()==5) {
607 errorMsg=" (suppressing further error messages)";
608 }
609 if (GetEventCount()<5) {
e2640fbd 610 HLTError("can not open HLT digit file %s%s", fDigitFileName.Data(), errorMsg);
c5123824 611 }
612 iResult=-EBADF;
613 }
c4228ec4 614 return iResult;
615}
4b113031 616
3c29512c 617int AliHLTOUTComponent::WriteRawFile(int eventNo, int hltddl, const AliHLTUInt8_t* pBuffer, unsigned int bufferSize)
4b113031 618{
4aa34abc 619 // write buffer to raw file in the current directory
620 // creates the event raw directories in the current directory
4b113031 621 int iResult=0;
622 const char* fileName=AliDAQ::DdlFileName("HLT", hltddl);
4b113031 623 assert(fileName!=NULL);
a8420176 624 TString filePath;
625 filePath.Form("raw%d/", eventNo);
4aa34abc 626 if (gSystem->AccessPathName(filePath)!=0) {
627 // note: AccessPathName return 0 if the path is existing
6a904136 628 TString command="mkdir "; command+=filePath;
629 gSystem->Exec(command);
630 }
a8420176 631 filePath+=fileName;
4b113031 632 if (fileName) {
633 ios::openmode filemode=(ios::openmode)0;
634 ofstream rawfile(filePath.Data(), filemode);
635 if (rawfile.good()) {
636 if (pBuffer && bufferSize>0) {
637 rawfile.write(reinterpret_cast<const char*>(pBuffer), bufferSize);
638 } else {
639 HLTWarning("writing zero length raw data file %s");
640 }
641 HLTDebug("wrote %d byte(s) to file %s", bufferSize, filePath.Data());
642 } else {
643 HLTError("can not open file %s for writing", filePath.Data());
644 iResult=-EBADF;
645 }
646 rawfile.close();
647 }
648 return iResult;
649}
2c0e5942 650
651void AliHLTOUTComponent::SetGlobalOption(unsigned int options)
652{
4aa34abc 653 // set the global options
2c0e5942 654 fgOptions|=options;
655}
656
657void AliHLTOUTComponent::ClearGlobalOption(unsigned int options)
658{
4aa34abc 659 // reset the global options
2c0e5942 660 fgOptions&=~options;
661}
6a904136 662
663bool AliHLTOUTComponent::TestGlobalOption(unsigned int option)
664{
4aa34abc 665 // check option
6a904136 666 return (fgOptions&option)!=0;
667}