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 AliHLTFileWriter.cxx
20 @author Matthias Richter
22 @brief HLT file writer component implementation. */
28 #include "AliHLTFileWriter.h"
29 #include "AliHLTBlockDataCollection.h"
30 #include <TObjArray.h>
31 #include <TObjString.h>
37 /** ROOT macro for the implementation of ROOT specific class methods */
38 ClassImp(AliHLTFileWriter)
40 AliHLTFileWriter::AliHLTFileWriter()
43 fpBlockDataCollection(NULL),
50 fBlcknoFormat("_0x%02x"),
58 // see header file for class documentation
60 // refer to README to build package
62 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
65 AliHLTFileWriter::~AliHLTFileWriter()
67 // see header file for class documentation
69 // file list and file name list are owner of their objects and
70 // delete all the objects
73 int AliHLTFileWriter::SetDefaults()
75 // see header file for class documentation
82 fBlcknoFormat="_0x%02x";
88 fBurstBlockEvents.clear();
92 const char* AliHLTFileWriter::GetComponentID()
94 // see header file for class documentation
98 void AliHLTFileWriter::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
100 // see header file for class documentation
102 list.push_back(kAliHLTAllDataTypes);
105 AliHLTComponent* AliHLTFileWriter::Spawn()
107 // see header file for class documentation
108 return new AliHLTFileWriter;
111 int AliHLTFileWriter::DoInit( int argc, const char** argv )
113 // see header file for class documentation
115 fpBlockDataCollection=new AliHLTBlockDataCollection;
120 for (; i<argc && iResult>=0; i++) {
123 if (argument.IsNull()) continue;
126 if (argument.CompareTo("-datafile")==0) {
127 if ((bMissingParam=(++i>=argc))) break;
129 TObjArray* pTokens=fBaseName.Tokenize(".");
131 int iEntries=pTokens->GetEntriesFast();
134 fBaseName=((TObjString*)pTokens->At(n++))->GetString();
135 while (n<iEntries-1) {
136 fBaseName+="." + ((TObjString*)pTokens->At(n++))->GetString();
138 fExtension=((TObjString*)pTokens->At(n))->GetString();
144 } else if (argument.CompareTo("-directory")==0) {
145 if ((bMissingParam=(++i>=argc))) break;
149 } else if (argument.BeginsWith("-subdir")) {
150 argument.ReplaceAll("-subdir", "");
151 if (argument.BeginsWith("=")) {
152 fSubDirFormat=argument.Replace(0,1,"");
153 if (strchr(fSubDirFormat.Data(), '%')==NULL) {
154 fSubDirFormat+="%lu";
157 fSubDirFormat="event%03lu";
159 // no additional eventno in the filename unless set again
160 // the sub dir contains the id
164 } else if (argument.BeginsWith("-idfmt")) {
165 argument.ReplaceAll("-idfmt", "");
166 if (argument.BeginsWith("=")) {
167 fIdFormat=argument.Replace(0,1,"");
171 } else if (argument.BeginsWith("-specfmt")) {
172 argument.ReplaceAll("-specfmt", "");
173 if (argument.BeginsWith("=")) {
174 fSpecFormat=argument.Replace(0,1,"");
176 fSpecFormat="_0x%08x";
180 } else if (argument.BeginsWith("-blcknofmt") ||
181 argument.BeginsWith("-blocknofmt")) {
182 // for the sake of backward compatibility we consider also the
183 // old argument with typo for a while
184 argument.ReplaceAll("-blcknofmt", "");
185 argument.ReplaceAll("-blocknofmt", "");
186 if (argument.BeginsWith("=")) {
187 fBlcknoFormat=argument.Replace(0,1,"");
189 fBlcknoFormat="_0x%02x";
193 } else if (argument.CompareTo("-enumerate")==0) {
196 // -concatenate-blocks
197 } else if (argument.CompareTo("-concatenate-blocks")==0) {
198 SetMode(kConcatenateBlocks);
200 // -concatenate-events
201 } else if (argument.CompareTo("-concatenate-events")==0) {
202 SetMode(kConcatenateEvents);
205 } else if (argument.CompareTo("-write-all-events")==0) {
206 SetMode(kWriteAllEvents);
209 } else if (argument.CompareTo("-write-all-blocks")==0) {
210 SetMode(kWriteAllBlocks);
213 } else if (argument.CompareTo("-write-all")==0) {
214 SetMode(kWriteAllEvents);
215 SetMode(kWriteAllBlocks);
218 } else if (argument.CompareTo("-burst-buffer")==0) {
219 if ((bMissingParam=(++i>=argc))) break;
220 fBurstBufferSize = strtoul( argv[i], &cpErr ,0);
224 } else if(argument.CompareTo("-skip-datatype")==0){
225 SetMode(kSkipDataType);
227 // check for selection arguments (AliHLTBlockDataCollection)
228 } else if (fpBlockDataCollection &&
229 (iResult=fpBlockDataCollection->ScanArgument(argc-i, &argv[i]))>0) {
233 if ((iResult=ScanArgument(argc-i, &argv[i]))==-EINVAL) {
234 HLTError("unknown argument %s", argument.Data());
236 } else if (iResult==-EPROTO) {
239 } else if (iResult>0) {
246 if (cpErr && *cpErr) {
247 HLTError("Cannot convert specifier '%s' for argument '%s'", argv[i], argument.Data());
249 } else if (bMissingParam) {
250 HLTError("missing parameter for argument %s", argument.Data());
253 if (fpBlockDataCollection &&
254 (iResult<0 || fpBlockDataCollection->IsEmpty())) {
255 delete fpBlockDataCollection;
256 fpBlockDataCollection=NULL;
258 if (iResult>=0 && fBurstBufferSize>0) {
259 if (!CheckMode(kConcatenateBlocks) || !CheckMode(kConcatenateEvents)) {
260 HLTError("burst write currently only supported for mode kConcatenateBlocks AND kConcatenateEvents");
263 fpBurstBuffer=new AliHLTUInt8_t[fBurstBufferSize];
264 if (!fpBurstBuffer) {
272 iResult=InitWriter();
273 if (!fDirectory.IsNull()) {
274 gSystem->mkdir(fDirectory);
281 int AliHLTFileWriter::InitWriter()
283 // see header file for class documentation
285 // fCurrentFileName is used in dump event, just touched her to avoid
286 // coding convention violation RC11. The function can not be declared
287 // const since it is just the default implementation, overloaded
288 // virtual function might not be const
290 return 0; // note: this doesn't mean 'error'
293 int AliHLTFileWriter::ScanArgument(int /*argc*/, const char** /*argv*/)
295 // see header file for class documentation
297 // there are no other arguments than the standard ones
298 // fCurrentFileName is used in dump event, just touched her to avoid
299 // coding convention violation RC11. The function can not be declared
300 // const since it is just the default implementation, overloaded
301 // virtual function might not be const
306 int AliHLTFileWriter::DoDeinit()
308 // see header file for class documentation
311 if ((iResult=BurstWrite())<0) {
312 HLTError("failed BurstWrite");
314 delete [] fpBurstBuffer;
317 fBurstBlocks.clear();
318 fBurstBlockEvents.clear();
321 iResult=CloseWriter();
322 ClearMode(kEnumerate);
324 if (fpBlockDataCollection) delete fpBlockDataCollection;
325 fpBlockDataCollection=NULL;
331 int AliHLTFileWriter::CloseWriter()
333 // see header file for class documentation
335 // fCurrentFileName is used in dump event, just touched her to avoid
336 // coding convention violation RC11. The function can not be declared
337 // const since it is just the default implementation, overloaded
338 // virtual function might not be const
343 int AliHLTFileWriter::DumpEvent( const AliHLTComponentEventData& evtData,
344 AliHLTComponentTriggerData& /*trigData*/ )
346 // see header file for class documentation
348 if (!IsDataEvent() && !CheckMode(kWriteAllEvents)) return 0;
350 if (CheckMode(kConcatenateEvents)==0) {
351 // reset the current file name in order to open a new file
352 // for the first block. If events are concatenated, the current
353 // file name stays in order to be opended in append mode.
356 const AliHLTComponentBlockData* pDesc=NULL;
359 for (pDesc=GetFirstInputBlock(); pDesc!=NULL; pDesc=GetNextInputBlock(), blockno++) {
360 if (fpBlockDataCollection) {
361 if (!fpBlockDataCollection->IsSelected(*pDesc)) continue;
362 } else if (pDesc->fDataType==(kAliHLTAnyDataType|kAliHLTDataOriginPrivate) && !CheckMode(kWriteAllBlocks))
364 HLTDebug("block %d out of %d", blockno, evtData.fBlockCnt);
365 iResult=ScheduleBlock(blockno, evtData.fEventID, pDesc);
370 int AliHLTFileWriter::BuildFileName(const AliHLTEventID_t eventID, const int blockID,
371 const AliHLTComponentDataType& dataType,
372 const AliHLTUInt32_t specification,
375 // see header file for class documentation
377 //HLTDebug("build file name for event %d block %d", eventID, blockID);
380 AliHLTUInt32_t eventType=gkAliEventTypeUnknown;
382 if (!fDirectory.IsNull()) {
383 filename+=fDirectory;
384 if (!filename.EndsWith("/"))
387 if (!fSubDirFormat.IsNull()) {
388 filename+=Form(fSubDirFormat, eventID);
389 if (!filename.EndsWith("/"))
392 if (filename.EndsWith("/")) {
393 gSystem->mkdir(filename);
396 IsDataEvent(&eventType);
397 if (CheckMode(kWriteAllEvents) && !CheckMode(kConcatenateEvents)) {
398 if (eventType==gkAliEventTypeStartOfRun) filename+="SOR_";
399 else if (eventType==gkAliEventTypeEndOfRun) filename+="EOR_";
402 if (!fBaseName.IsNull())
406 if (!CheckMode(kConcatenateEvents)) {
407 if (!CheckMode(kEnumerate)) {
408 if (eventID!=kAliHLTVoidEventID && !fIdFormat.IsNull()) {
409 filename+=Form(fIdFormat, eventID);
412 filename+=Form("_%d", GetEventCount());
415 if (blockID>=0 && !CheckMode(kConcatenateBlocks)) {
416 if (!fBlcknoFormat.IsNull())
417 filename+=Form(fBlcknoFormat, blockID);
418 if (dataType!=kAliHLTVoidDataType &&
419 !CheckMode(kSkipDataType)) {
421 filename+=AliHLTComponent::DataType2Text(dataType).data();
423 if (!fSpecFormat.IsNull())
424 filename+=Form(fSpecFormat, specification);
426 if (!fExtension.IsNull())
427 filename+="." + fExtension;
428 filename.ReplaceAll(" ", "");
432 int AliHLTFileWriter::SetMode(Short_t mode)
434 // see header file for class documentation
436 //HLTDebug("mode set to 0x%x", fMode);
440 int AliHLTFileWriter::ClearMode(Short_t mode)
442 // see header file for class documentation
444 //HLTDebug("mode set to 0x%x", fMode);
448 int AliHLTFileWriter::CheckMode(Short_t mode) const
450 // see header file for class documentation
452 //HLTDebug("check mode 0x%x for flag 0x%x: %d", fMode, mode, (fMode&mode)!=0);
453 return (fMode&mode)!=0;
456 int AliHLTFileWriter::ScheduleBlock(int blockno, const AliHLTEventID_t& eventID,
457 const AliHLTComponentBlockData* pDesc)
459 // see header file for class documentation
461 if (fpBurstBuffer==NULL ||
462 (fBurstBlocks.size()==0 && pDesc->fSize>fBurstBufferSize) ) {
463 return WriteBlock(blockno, eventID, pDesc);
465 AliHLTComponentBlockData bd=*pDesc;
467 if (fBurstBlocks.size()>0) {
468 bd.fOffset=fBurstBlocks.back().fOffset+fBurstBlocks.back().fSize;
472 if (bd.fOffset+bd.fSize>fBurstBufferSize) {
473 if ((iResult=BurstWrite())>=0) {
474 iResult=WriteBlock(blockno, eventID, pDesc);
477 memcpy(fpBurstBuffer+bd.fOffset, pDesc->fPtr, bd.fSize);
478 fBurstBlocks.push_back(bd);
479 fBurstBlockEvents.push_back(eventID);
485 int AliHLTFileWriter::BurstWrite()
487 // see header file for class documentation
489 if (fBurstBlocks.size()==0) return 0;
490 assert(fBurstBlocks.size()==fBurstBlockEvents.size());
491 HLTDebug("writing %d postponed blocks", fBurstBlocks.size());
493 AliHLTComponentBlockDataList::iterator block=fBurstBlocks.begin();
494 AliHLTComponentBlockDataList::iterator firstBlock=block;
495 vector<AliHLTEventID_t>::iterator event=fBurstBlockEvents.begin();
496 if (CheckMode(kConcatenateEvents)) {
497 block=fBurstBlocks.end()-1;
498 event=fBurstBlockEvents.end()-1;
500 for (; block!=fBurstBlocks.end() && iResult>=0; block++, event++, blockno++) {
501 if (event!=fBurstBlockEvents.begin() && *event!=*(event-1)) {
504 if (CheckMode(kConcatenateEvents)) {
505 // all blocks in the burst buffer are written in one go
506 // just the block descriptor is updated appropriately
507 (*block).fSize+=(*block).fOffset;
508 (*block).fPtr=fpBurstBuffer;
509 } else if (CheckMode(kConcatenateBlocks)) {
510 // all blocks of the same event are written in one go
511 // just the block descriptor is updated appropriately
512 if (event+1==fBurstBlockEvents.end() ||
513 *event!=*(event+1)) {
514 (*block).fSize+=(*block).fOffset-(*firstBlock).fOffset;
515 (*block).fPtr=fpBurstBuffer+(*firstBlock).fOffset;
518 // coninue if it wasn't the last block of this event
522 (*block).fPtr=fpBurstBuffer+(*block).fOffset;
525 iResult=WriteBlock(blockno, *event, &(*block));
527 fBurstBlocks.clear();
528 fBurstBlockEvents.clear();
533 int AliHLTFileWriter::WriteBlock(int blockno, const AliHLTEventID_t& eventID,
534 const AliHLTComponentBlockData* pDesc)
536 // see header file for class documentation
539 HLTDebug("dataspec 0x%x", pDesc->fSpecification);
540 iResult=BuildFileName(eventID, blockno, pDesc->fDataType, pDesc->fSpecification, filename);
541 ios::openmode filemode=(ios::openmode)0;
542 if (fCurrentFileName.CompareTo(filename)==0) {
543 // append to the file
546 // store the file for the next block
547 fCurrentFileName=filename;
550 ofstream dump(filename.Data(), filemode);
552 dump.write((static_cast<const char*>(pDesc->fPtr)), pDesc->fSize);
553 HLTDebug("wrote %d byte(s) to file %s", pDesc->fSize, filename.Data());
555 HLTError("can not open file %s for writing", filename.Data());