]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/BASE/util/AliHLTFileWriter.cxx
including -dataspec option in the configuration for file publisher
[u/mrichter/AliRoot.git] / HLT / BASE / util / AliHLTFileWriter.cxx
CommitLineData
e74abd18 1// $Id$
2
3/**************************************************************************
9be2600f 4 * This file is property of and copyright by the ALICE HLT Project *
5 * ALICE Experiment at CERN, All rights reserved. *
e74abd18 6 * *
9be2600f 7 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 * for The ALICE HLT Project. *
e74abd18 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 AliHLTFileWriter.cxx
20 @author Matthias Richter
21 @date
22 @brief HLT file writer component implementation. */
23
24#if __GNUC__>= 3
25using namespace std;
26#endif
27
28#include "AliHLTFileWriter.h"
4b31e06b 29#include "AliHLTBlockDataCollection.h"
e74abd18 30#include <TObjArray.h>
31#include <TObjString.h>
5ab95e9a 32#include <TSystem.h>
5df0cbb9 33//#include <TMath.h>
34//#include <TFile.h>
4b31e06b 35#include <cassert>
e74abd18 36
e74abd18 37/** ROOT macro for the implementation of ROOT specific class methods */
38ClassImp(AliHLTFileWriter)
39
40AliHLTFileWriter::AliHLTFileWriter()
41 :
42 AliHLTDataSink(),
4b31e06b 43 fpBlockDataCollection(NULL),
e74abd18 44 fBaseName(""),
45 fExtension(""),
46 fDirectory(""),
5ab95e9a 47 fSubDirFormat(""),
6daf06e2 48 fIdFormat("_0x%08x"),
5ab95e9a 49 fSpecFormat(""),
652cf9d2 50 fBlcknoFormat("_0x%02x"),
e74abd18 51 fCurrentFileName(""),
52 fMode(0)
4b31e06b 53 , fpBurstBuffer(NULL)
54 , fBurstBufferSize(0)
55 , fBurstBlocks()
56 , fBurstBlockEvents()
a9c4e244 57 , fPublisherConfName()
58 , fPublisherConfEvent(-1)
e74abd18 59{
60 // see header file for class documentation
61 // or
62 // refer to README to build package
63 // or
64 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
65}
66
e74abd18 67AliHLTFileWriter::~AliHLTFileWriter()
68{
69 // see header file for class documentation
70
71 // file list and file name list are owner of their objects and
72 // delete all the objects
73}
74
4b31e06b 75int AliHLTFileWriter::SetDefaults()
76{
77 // see header file for class documentation
78 fBaseName="";
79 fExtension="";
80 fDirectory="";
81 fSubDirFormat="";
82 fIdFormat="_0x%08x";
83 fSpecFormat="";
84 fBlcknoFormat="_0x%02x";
85 fCurrentFileName="";
86 fMode=0;
87 fpBurstBuffer=NULL;
88 fBurstBufferSize=0;
89 fBurstBlocks.clear();
90 fBurstBlockEvents.clear();
a9c4e244 91 fPublisherConfEvent=-1;
4b31e06b 92 return 0;
93}
94
e74abd18 95const char* AliHLTFileWriter::GetComponentID()
96{
97 // see header file for class documentation
98 return "FileWriter";
99}
100
101void AliHLTFileWriter::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
102{
103 // see header file for class documentation
104 list.clear();
6daf06e2 105 list.push_back(kAliHLTAllDataTypes);
e74abd18 106}
107
108AliHLTComponent* AliHLTFileWriter::Spawn()
109{
110 // see header file for class documentation
111 return new AliHLTFileWriter;
112}
113
114int AliHLTFileWriter::DoInit( int argc, const char** argv )
115{
116 // see header file for class documentation
117 int iResult=0;
4b31e06b 118 fpBlockDataCollection=new AliHLTBlockDataCollection;
e74abd18 119 TString argument="";
120 int bMissingParam=0;
4b31e06b 121 char* cpErr=NULL;
122 int i=0;
123 for (; i<argc && iResult>=0; i++) {
124 cpErr=NULL;
e74abd18 125 argument=argv[i];
126 if (argument.IsNull()) continue;
127
128 // -basename
129 if (argument.CompareTo("-datafile")==0) {
130 if ((bMissingParam=(++i>=argc))) break;
131 fBaseName=argv[i];
132 TObjArray* pTokens=fBaseName.Tokenize(".");
133 if (pTokens) {
77fd699f 134 int iEntries=pTokens->GetEntriesFast();
e74abd18 135 if (iEntries>1) {
f7561f8d 136 int n=0;
137 fBaseName=((TObjString*)pTokens->At(n++))->GetString();
138 while (n<iEntries-1) {
139 fBaseName+="." + ((TObjString*)pTokens->At(n++))->GetString();
e74abd18 140 }
f7561f8d 141 fExtension=((TObjString*)pTokens->At(n))->GetString();
e74abd18 142 }
143 delete pTokens;
144 }
145
146 // -directory
147 } else if (argument.CompareTo("-directory")==0) {
148 if ((bMissingParam=(++i>=argc))) break;
149 fDirectory=argv[i];
150
5ab95e9a 151 // -subdir
152 } else if (argument.BeginsWith("-subdir")) {
153 argument.ReplaceAll("-subdir", "");
154 if (argument.BeginsWith("=")) {
155 fSubDirFormat=argument.Replace(0,1,"");
2cb9ea42 156 if (strchr(fSubDirFormat.Data(), '%')==NULL) {
157 fSubDirFormat+="%lu";
158 }
5ab95e9a 159 } else {
488eca05 160 fSubDirFormat="event%03lu";
5ab95e9a 161 }
6daf06e2 162 // no additional eventno in the filename unless set again
163 // the sub dir contains the id
164 fIdFormat="";
5ab95e9a 165
166 // -idfmt
167 } else if (argument.BeginsWith("-idfmt")) {
168 argument.ReplaceAll("-idfmt", "");
169 if (argument.BeginsWith("=")) {
170 fIdFormat=argument.Replace(0,1,"");
171 }
172
173 // -specfmt
174 } else if (argument.BeginsWith("-specfmt")) {
175 argument.ReplaceAll("-specfmt", "");
176 if (argument.BeginsWith("=")) {
177 fSpecFormat=argument.Replace(0,1,"");
178 } else {
179 fSpecFormat="_0x%08x";
180 }
181
6daf06e2 182 // -blocknofmt
183 } else if (argument.BeginsWith("-blcknofmt") ||
184 argument.BeginsWith("-blocknofmt")) {
185 // for the sake of backward compatibility we consider also the
186 // old argument with typo for a while
5ab95e9a 187 argument.ReplaceAll("-blcknofmt", "");
6daf06e2 188 argument.ReplaceAll("-blocknofmt", "");
5ab95e9a 189 if (argument.BeginsWith("=")) {
190 fBlcknoFormat=argument.Replace(0,1,"");
191 } else {
192 fBlcknoFormat="_0x%02x";
193 }
194
e74abd18 195 // -enumeration
196 } else if (argument.CompareTo("-enumerate")==0) {
197 SetMode(kEnumerate);
198
199 // -concatenate-blocks
200 } else if (argument.CompareTo("-concatenate-blocks")==0) {
201 SetMode(kConcatenateBlocks);
202
203 // -concatenate-events
204 } else if (argument.CompareTo("-concatenate-events")==0) {
205 SetMode(kConcatenateEvents);
206
a9c4e244 207 // -publisher-conf
208 } else if (argument.CompareTo("-publisher-conf")==0) {
209 if ((bMissingParam=(++i>=argc))) break;
210 fPublisherConfName=argv[i];
211
6b7f77cf 212 // -write-all-events
213 } else if (argument.CompareTo("-write-all-events")==0) {
214 SetMode(kWriteAllEvents);
215
216 // -write-all-blocks
217 } else if (argument.CompareTo("-write-all-blocks")==0) {
218 SetMode(kWriteAllBlocks);
219
220 // -write-all
221 } else if (argument.CompareTo("-write-all")==0) {
222 SetMode(kWriteAllEvents);
223 SetMode(kWriteAllBlocks);
224
4b31e06b 225 // -burst-buffer
226 } else if (argument.CompareTo("-burst-buffer")==0) {
227 if ((bMissingParam=(++i>=argc))) break;
228 fBurstBufferSize = strtoul( argv[i], &cpErr ,0);
229 if ( *cpErr ) break;
230
2cb9ea42 231 // -skip-datatype
232 } else if(argument.CompareTo("-skip-datatype")==0){
233 SetMode(kSkipDataType);
234
4b31e06b 235 // check for selection arguments (AliHLTBlockDataCollection)
236 } else if (fpBlockDataCollection &&
237 (iResult=fpBlockDataCollection->ScanArgument(argc-i, &argv[i]))>0) {
238 i+=iResult-1;
239 iResult=0;
e74abd18 240 } else {
241 if ((iResult=ScanArgument(argc-i, &argv[i]))==-EINVAL) {
242 HLTError("unknown argument %s", argument.Data());
243 break;
244 } else if (iResult==-EPROTO) {
245 bMissingParam=1;
246 break;
13ce8aae 247 } else if (iResult>0) {
248 i+=iResult-1;
e74abd18 249 iResult=0;
250 }
251 }
252 }
4b31e06b 253
254 if (cpErr && *cpErr) {
255 HLTError("Cannot convert specifier '%s' for argument '%s'", argv[i], argument.Data());
256 iResult=-EINVAL;
257 } else if (bMissingParam) {
e74abd18 258 HLTError("missing parameter for argument %s", argument.Data());
259 iResult=-EINVAL;
260 }
4b31e06b 261 if (fpBlockDataCollection &&
262 (iResult<0 || fpBlockDataCollection->IsEmpty())) {
263 delete fpBlockDataCollection;
264 fpBlockDataCollection=NULL;
265 }
266 if (iResult>=0 && fBurstBufferSize>0) {
267 if (!CheckMode(kConcatenateBlocks) || !CheckMode(kConcatenateEvents)) {
268 HLTError("burst write currently only supported for mode kConcatenateBlocks AND kConcatenateEvents");
269 iResult=-EINVAL;
270 } else {
271 fpBurstBuffer=new AliHLTUInt8_t[fBurstBufferSize];
272 if (!fpBurstBuffer) {
273 iResult=-ENOMEM;
274 fBurstBufferSize=0;
275 }
276 }
277 }
278
a9c4e244 279 if (!fPublisherConfName.IsNull()) {
280 if (CheckMode(kConcatenateBlocks) || CheckMode(kConcatenateEvents)) {
281 fPublisherConfName="";
282 HLTWarning("option 'concatenate blocks/events' collides with writing of FilePublisher configuration, ignoring option '-publisher-conf'");
283 }
284 }
285
e74abd18 286 if (iResult>=0) {
287 iResult=InitWriter();
07cd8230 288 if (!fDirectory.IsNull()) {
289 gSystem->mkdir(fDirectory);
290 }
e74abd18 291 }
292
293 return iResult;
294}
295
296int AliHLTFileWriter::InitWriter()
297{
298 // see header file for class documentation
5df0cbb9 299
300 // fCurrentFileName is used in dump event, just touched her to avoid
301 // coding convention violation RC11. The function can not be declared
302 // const since it is just the default implementation, overloaded
303 // virtual function might not be const
304 fCurrentFileName="";
e74abd18 305 return 0; // note: this doesn't mean 'error'
306}
307
6daf06e2 308int AliHLTFileWriter::ScanArgument(int /*argc*/, const char** /*argv*/)
e74abd18 309{
310 // see header file for class documentation
311
312 // there are no other arguments than the standard ones
5df0cbb9 313 // fCurrentFileName is used in dump event, just touched her to avoid
314 // coding convention violation RC11. The function can not be declared
315 // const since it is just the default implementation, overloaded
316 // virtual function might not be const
317 fCurrentFileName="";
e74abd18 318 return -EINVAL;
319}
320
321int AliHLTFileWriter::DoDeinit()
322{
323 // see header file for class documentation
4b31e06b 324 int iResult=0;
325 if (fpBurstBuffer) {
326 if ((iResult=BurstWrite())<0) {
327 HLTError("failed BurstWrite");
328 }
329 delete [] fpBurstBuffer;
330 fpBurstBuffer=NULL;
331 fBurstBufferSize=0;
332 fBurstBlocks.clear();
333 fBurstBlockEvents.clear();
334 }
335
336 iResult=CloseWriter();
e74abd18 337 ClearMode(kEnumerate);
4b31e06b 338
339 if (fpBlockDataCollection) delete fpBlockDataCollection;
340 fpBlockDataCollection=NULL;
341
342 SetDefaults();
e74abd18 343 return iResult;
344}
345
346int AliHLTFileWriter::CloseWriter()
347{
348 // see header file for class documentation
5df0cbb9 349
350 // fCurrentFileName is used in dump event, just touched her to avoid
351 // coding convention violation RC11. The function can not be declared
352 // const since it is just the default implementation, overloaded
353 // virtual function might not be const
354 fCurrentFileName="";
6daf06e2 355 return 0;
e74abd18 356}
357
358int AliHLTFileWriter::DumpEvent( const AliHLTComponentEventData& evtData,
fdb4ca9e 359 AliHLTComponentTriggerData& /*trigData*/ )
e74abd18 360{
361 // see header file for class documentation
362 int iResult=0;
6b7f77cf 363 if (!IsDataEvent() && !CheckMode(kWriteAllEvents)) return 0;
364
e74abd18 365 if (CheckMode(kConcatenateEvents)==0) {
366 // reset the current file name in order to open a new file
367 // for the first block. If events are concatenated, the current
368 // file name stays in order to be opended in append mode.
369 fCurrentFileName="";
370 }
fdb4ca9e 371 const AliHLTComponentBlockData* pDesc=NULL;
372
373 int blockno=0;
6daf06e2 374 for (pDesc=GetFirstInputBlock(); pDesc!=NULL; pDesc=GetNextInputBlock(), blockno++) {
4b31e06b 375 if (fpBlockDataCollection) {
376 if (!fpBlockDataCollection->IsSelected(*pDesc)) continue;
377 } else if (pDesc->fDataType==(kAliHLTAnyDataType|kAliHLTDataOriginPrivate) && !CheckMode(kWriteAllBlocks))
6b7f77cf 378 continue;
fdb4ca9e 379 HLTDebug("block %d out of %d", blockno, evtData.fBlockCnt);
4b31e06b 380 iResult=ScheduleBlock(blockno, evtData.fEventID, pDesc);
e74abd18 381 }
e74abd18 382 return iResult;
383}
384
5ab95e9a 385int AliHLTFileWriter::BuildFileName(const AliHLTEventID_t eventID, const int blockID,
386 const AliHLTComponentDataType& dataType,
387 const AliHLTUInt32_t specification,
388 TString& filename)
e74abd18 389{
390 // see header file for class documentation
391 int iResult=0;
392 //HLTDebug("build file name for event %d block %d", eventID, blockID);
393 filename="";
6b7f77cf 394
395 AliHLTUInt32_t eventType=gkAliEventTypeUnknown;
6b7f77cf 396
e74abd18 397 if (!fDirectory.IsNull()) {
398 filename+=fDirectory;
5ab95e9a 399 if (!filename.EndsWith("/"))
e74abd18 400 filename+="/";
401 }
5ab95e9a 402 if (!fSubDirFormat.IsNull()) {
403 filename+=Form(fSubDirFormat, eventID);
404 if (!filename.EndsWith("/"))
405 filename+="/";
406 }
407 if (filename.EndsWith("/")) {
408 gSystem->mkdir(filename);
409 }
488eca05 410
411 IsDataEvent(&eventType);
8516ea4c 412 if (CheckMode(kWriteAllEvents) && !CheckMode(kConcatenateEvents)) {
413 if (eventType==gkAliEventTypeStartOfRun) filename+="SOR_";
414 else if (eventType==gkAliEventTypeEndOfRun) filename+="EOR_";
415 }
488eca05 416
e74abd18 417 if (!fBaseName.IsNull())
418 filename+=fBaseName;
419 else
420 filename+="event";
421 if (!CheckMode(kConcatenateEvents)) {
422 if (!CheckMode(kEnumerate)) {
5ab95e9a 423 if (eventID!=kAliHLTVoidEventID && !fIdFormat.IsNull()) {
424 filename+=Form(fIdFormat, eventID);
e74abd18 425 }
426 } else {
427 filename+=Form("_%d", GetEventCount());
428 }
429 }
430 if (blockID>=0 && !CheckMode(kConcatenateBlocks)) {
5ab95e9a 431 if (!fBlcknoFormat.IsNull())
432 filename+=Form(fBlcknoFormat, blockID);
2cb9ea42 433 if (dataType!=kAliHLTVoidDataType &&
434 !CheckMode(kSkipDataType)) {
e74abd18 435 filename+="_";
436 filename+=AliHLTComponent::DataType2Text(dataType).data();
437 }
5ab95e9a 438 if (!fSpecFormat.IsNull())
439 filename+=Form(fSpecFormat, specification);
e74abd18 440 }
441 if (!fExtension.IsNull())
442 filename+="." + fExtension;
443 filename.ReplaceAll(" ", "");
444 return iResult;
445}
446
447int AliHLTFileWriter::SetMode(Short_t mode)
448{
449 // see header file for class documentation
450 fMode|=mode;
451 //HLTDebug("mode set to 0x%x", fMode);
452 return fMode;
453}
454
455int AliHLTFileWriter::ClearMode(Short_t mode)
456{
457 // see header file for class documentation
458 fMode&=~mode;
459 //HLTDebug("mode set to 0x%x", fMode);
460 return fMode;
461}
462
5df0cbb9 463int AliHLTFileWriter::CheckMode(Short_t mode) const
e74abd18 464{
465 // see header file for class documentation
466
467 //HLTDebug("check mode 0x%x for flag 0x%x: %d", fMode, mode, (fMode&mode)!=0);
468 return (fMode&mode)!=0;
469}
4b31e06b 470
471int AliHLTFileWriter::ScheduleBlock(int blockno, const AliHLTEventID_t& eventID,
472 const AliHLTComponentBlockData* pDesc)
473{
474 // see header file for class documentation
475 int iResult=0;
476 if (fpBurstBuffer==NULL ||
bb7774d6 477 (fBurstBlocks.size()==0 && pDesc->fSize>fBurstBufferSize) ) {
4b31e06b 478 return WriteBlock(blockno, eventID, pDesc);
479 }
480 AliHLTComponentBlockData bd=*pDesc;
481 bd.fPtr=NULL;
482 if (fBurstBlocks.size()>0) {
483 bd.fOffset=fBurstBlocks.back().fOffset+fBurstBlocks.back().fSize;
484 } else {
485 bd.fOffset=0;
486 }
487 if (bd.fOffset+bd.fSize>fBurstBufferSize) {
488 if ((iResult=BurstWrite())>=0) {
489 iResult=WriteBlock(blockno, eventID, pDesc);
490 }
491 } else {
492 memcpy(fpBurstBuffer+bd.fOffset, pDesc->fPtr, bd.fSize);
493 fBurstBlocks.push_back(bd);
494 fBurstBlockEvents.push_back(eventID);
495 }
496
497 return iResult;
498}
499
500int AliHLTFileWriter::BurstWrite()
501{
502 // see header file for class documentation
503 int iResult=0;
504 if (fBurstBlocks.size()==0) return 0;
505 assert(fBurstBlocks.size()==fBurstBlockEvents.size());
506 HLTDebug("writing %d postponed blocks", fBurstBlocks.size());
507 int blockno=0;
508 AliHLTComponentBlockDataList::iterator block=fBurstBlocks.begin();
509 AliHLTComponentBlockDataList::iterator firstBlock=block;
510 vector<AliHLTEventID_t>::iterator event=fBurstBlockEvents.begin();
511 if (CheckMode(kConcatenateEvents)) {
512 block=fBurstBlocks.end()-1;
513 event=fBurstBlockEvents.end()-1;
514 }
515 for (; block!=fBurstBlocks.end() && iResult>=0; block++, event++, blockno++) {
516 if (event!=fBurstBlockEvents.begin() && *event!=*(event-1)) {
517 blockno=0;
518 }
519 if (CheckMode(kConcatenateEvents)) {
520 // all blocks in the burst buffer are written in one go
521 // just the block descriptor is updated appropriately
522 (*block).fSize+=(*block).fOffset;
523 (*block).fPtr=fpBurstBuffer;
524 } else if (CheckMode(kConcatenateBlocks)) {
525 // all blocks of the same event are written in one go
526 // just the block descriptor is updated appropriately
527 if (event+1==fBurstBlockEvents.end() ||
528 *event!=*(event+1)) {
529 (*block).fSize+=(*block).fOffset-(*firstBlock).fOffset;
530 (*block).fPtr=fpBurstBuffer+(*firstBlock).fOffset;
531 firstBlock=block+1;
532 } else {
533 // coninue if it wasn't the last block of this event
534 continue;
535 }
536 } else {
537 (*block).fPtr=fpBurstBuffer+(*block).fOffset;
538 }
539 (*block).fOffset=0;
540 iResult=WriteBlock(blockno, *event, &(*block));
541 }
542 fBurstBlocks.clear();
543 fBurstBlockEvents.clear();
544
545 return iResult;
546}
547
548int AliHLTFileWriter::WriteBlock(int blockno, const AliHLTEventID_t& eventID,
549 const AliHLTComponentBlockData* pDesc)
550{
551 // see header file for class documentation
552 int iResult=0;
553 TString filename;
554 HLTDebug("dataspec 0x%x", pDesc->fSpecification);
555 iResult=BuildFileName(eventID, blockno, pDesc->fDataType, pDesc->fSpecification, filename);
556 ios::openmode filemode=(ios::openmode)0;
557 if (fCurrentFileName.CompareTo(filename)==0) {
558 // append to the file
559 filemode=ios::app;
560 } else {
561 // store the file for the next block
562 fCurrentFileName=filename;
563 }
564 if (iResult>=0) {
565 ofstream dump(filename.Data(), filemode);
566 if (dump.good()) {
567 dump.write((static_cast<const char*>(pDesc->fPtr)), pDesc->fSize);
568 HLTDebug("wrote %d byte(s) to file %s", pDesc->fSize, filename.Data());
569 } else {
570 HLTError("can not open file %s for writing", filename.Data());
571 iResult=-EBADF;
572 }
573 dump.close();
574 }
a9c4e244 575 if (iResult>=0 && !fPublisherConfName.IsNull()) {
576 if (!CheckMode(kConcatenateBlocks) &&
577 !CheckMode(kConcatenateEvents)) {
578 // append if not the first entry
579 if (fPublisherConfEvent>=0) filemode=ios::app;
580 else filemode=(ios::openmode)0;
581 ofstream conf(fPublisherConfName.Data(), filemode);
582 if (conf.good()) {
583 if (fPublisherConfEvent>=0 &&
584 fPublisherConfEvent!=GetEventCount()) {
585 conf << "-nextevent " << endl;
586 }
587 fPublisherConfEvent=GetEventCount();
588 conf << "-datatype ";
589 conf << DataType2Text(pDesc->fDataType, 3);
af056b7b 590 conf << " -dataspec ";
591 TString specstr; specstr.Form("0x%08x", pDesc->fSpecification);
592 conf << specstr;
a9c4e244 593 conf << " -datafile ";
594 conf << filename;
595 conf << endl;
596 } else {
597 fPublisherConfName="";
598 HLTError("can not open file %s for writing of configuration commands", fPublisherConfName.Data());
599 }
600 conf.close();
601 } else {
602 fPublisherConfName="";
603 HLTWarning("option 'concatenate blocks/events' collides with writing of FilePublisher configuration, disable ...");
604 }
605 }
4b31e06b 606 return iResult;
607}