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