]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/BASE/util/AliHLTFileWriter.cxx
bugfix: '-nextevent' command in configuration file for publisher inserted correctly...
[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 }
bdc4041c 371
372 if (!fPublisherConfName.IsNull() && fPublisherConfEvent>=0) {
373 // write '-nextevent' command for all but the first event
374 ofstream conf(fPublisherConfName.Data(), ios::app);
375 if (conf.good()) {
376 conf << "-nextevent " << endl;
377 }
378 conf.close();
379 }
380
fdb4ca9e 381 const AliHLTComponentBlockData* pDesc=NULL;
382
383 int blockno=0;
6daf06e2 384 for (pDesc=GetFirstInputBlock(); pDesc!=NULL; pDesc=GetNextInputBlock(), blockno++) {
4b31e06b 385 if (fpBlockDataCollection) {
386 if (!fpBlockDataCollection->IsSelected(*pDesc)) continue;
387 } else if (pDesc->fDataType==(kAliHLTAnyDataType|kAliHLTDataOriginPrivate) && !CheckMode(kWriteAllBlocks))
6b7f77cf 388 continue;
fdb4ca9e 389 HLTDebug("block %d out of %d", blockno, evtData.fBlockCnt);
4b31e06b 390 iResult=ScheduleBlock(blockno, evtData.fEventID, pDesc);
e74abd18 391 }
e74abd18 392 return iResult;
393}
394
5ab95e9a 395int AliHLTFileWriter::BuildFileName(const AliHLTEventID_t eventID, const int blockID,
396 const AliHLTComponentDataType& dataType,
397 const AliHLTUInt32_t specification,
398 TString& filename)
e74abd18 399{
400 // see header file for class documentation
401 int iResult=0;
402 //HLTDebug("build file name for event %d block %d", eventID, blockID);
403 filename="";
6b7f77cf 404
405 AliHLTUInt32_t eventType=gkAliEventTypeUnknown;
6b7f77cf 406
e74abd18 407 if (!fDirectory.IsNull()) {
408 filename+=fDirectory;
5ab95e9a 409 if (!filename.EndsWith("/"))
e74abd18 410 filename+="/";
411 }
5ab95e9a 412 if (!fSubDirFormat.IsNull()) {
413 filename+=Form(fSubDirFormat, eventID);
414 if (!filename.EndsWith("/"))
415 filename+="/";
416 }
417 if (filename.EndsWith("/")) {
418 gSystem->mkdir(filename);
419 }
488eca05 420
421 IsDataEvent(&eventType);
8516ea4c 422 if (CheckMode(kWriteAllEvents) && !CheckMode(kConcatenateEvents)) {
423 if (eventType==gkAliEventTypeStartOfRun) filename+="SOR_";
424 else if (eventType==gkAliEventTypeEndOfRun) filename+="EOR_";
425 }
488eca05 426
e74abd18 427 if (!fBaseName.IsNull())
428 filename+=fBaseName;
429 else
430 filename+="event";
431 if (!CheckMode(kConcatenateEvents)) {
432 if (!CheckMode(kEnumerate)) {
5ab95e9a 433 if (eventID!=kAliHLTVoidEventID && !fIdFormat.IsNull()) {
434 filename+=Form(fIdFormat, eventID);
e74abd18 435 }
436 } else {
437 filename+=Form("_%d", GetEventCount());
438 }
439 }
440 if (blockID>=0 && !CheckMode(kConcatenateBlocks)) {
5ab95e9a 441 if (!fBlcknoFormat.IsNull())
442 filename+=Form(fBlcknoFormat, blockID);
2cb9ea42 443 if (dataType!=kAliHLTVoidDataType &&
444 !CheckMode(kSkipDataType)) {
e74abd18 445 filename+="_";
446 filename+=AliHLTComponent::DataType2Text(dataType).data();
447 }
5ab95e9a 448 if (!fSpecFormat.IsNull())
449 filename+=Form(fSpecFormat, specification);
e74abd18 450 }
451 if (!fExtension.IsNull())
452 filename+="." + fExtension;
453 filename.ReplaceAll(" ", "");
454 return iResult;
455}
456
457int AliHLTFileWriter::SetMode(Short_t mode)
458{
459 // see header file for class documentation
460 fMode|=mode;
461 //HLTDebug("mode set to 0x%x", fMode);
462 return fMode;
463}
464
465int AliHLTFileWriter::ClearMode(Short_t mode)
466{
467 // see header file for class documentation
468 fMode&=~mode;
469 //HLTDebug("mode set to 0x%x", fMode);
470 return fMode;
471}
472
5df0cbb9 473int AliHLTFileWriter::CheckMode(Short_t mode) const
e74abd18 474{
475 // see header file for class documentation
476
477 //HLTDebug("check mode 0x%x for flag 0x%x: %d", fMode, mode, (fMode&mode)!=0);
478 return (fMode&mode)!=0;
479}
4b31e06b 480
481int AliHLTFileWriter::ScheduleBlock(int blockno, const AliHLTEventID_t& eventID,
482 const AliHLTComponentBlockData* pDesc)
483{
484 // see header file for class documentation
485 int iResult=0;
486 if (fpBurstBuffer==NULL ||
bb7774d6 487 (fBurstBlocks.size()==0 && pDesc->fSize>fBurstBufferSize) ) {
4b31e06b 488 return WriteBlock(blockno, eventID, pDesc);
489 }
490 AliHLTComponentBlockData bd=*pDesc;
491 bd.fPtr=NULL;
492 if (fBurstBlocks.size()>0) {
493 bd.fOffset=fBurstBlocks.back().fOffset+fBurstBlocks.back().fSize;
494 } else {
495 bd.fOffset=0;
496 }
497 if (bd.fOffset+bd.fSize>fBurstBufferSize) {
498 if ((iResult=BurstWrite())>=0) {
499 iResult=WriteBlock(blockno, eventID, pDesc);
500 }
501 } else {
502 memcpy(fpBurstBuffer+bd.fOffset, pDesc->fPtr, bd.fSize);
503 fBurstBlocks.push_back(bd);
504 fBurstBlockEvents.push_back(eventID);
505 }
506
507 return iResult;
508}
509
510int AliHLTFileWriter::BurstWrite()
511{
512 // see header file for class documentation
513 int iResult=0;
514 if (fBurstBlocks.size()==0) return 0;
515 assert(fBurstBlocks.size()==fBurstBlockEvents.size());
516 HLTDebug("writing %d postponed blocks", fBurstBlocks.size());
517 int blockno=0;
518 AliHLTComponentBlockDataList::iterator block=fBurstBlocks.begin();
519 AliHLTComponentBlockDataList::iterator firstBlock=block;
520 vector<AliHLTEventID_t>::iterator event=fBurstBlockEvents.begin();
521 if (CheckMode(kConcatenateEvents)) {
522 block=fBurstBlocks.end()-1;
523 event=fBurstBlockEvents.end()-1;
524 }
bdc4041c 525
4b31e06b 526 for (; block!=fBurstBlocks.end() && iResult>=0; block++, event++, blockno++) {
527 if (event!=fBurstBlockEvents.begin() && *event!=*(event-1)) {
528 blockno=0;
529 }
530 if (CheckMode(kConcatenateEvents)) {
531 // all blocks in the burst buffer are written in one go
532 // just the block descriptor is updated appropriately
533 (*block).fSize+=(*block).fOffset;
534 (*block).fPtr=fpBurstBuffer;
535 } else if (CheckMode(kConcatenateBlocks)) {
536 // all blocks of the same event are written in one go
537 // just the block descriptor is updated appropriately
538 if (event+1==fBurstBlockEvents.end() ||
539 *event!=*(event+1)) {
540 (*block).fSize+=(*block).fOffset-(*firstBlock).fOffset;
541 (*block).fPtr=fpBurstBuffer+(*firstBlock).fOffset;
542 firstBlock=block+1;
543 } else {
544 // coninue if it wasn't the last block of this event
545 continue;
546 }
547 } else {
548 (*block).fPtr=fpBurstBuffer+(*block).fOffset;
549 }
550 (*block).fOffset=0;
551 iResult=WriteBlock(blockno, *event, &(*block));
552 }
553 fBurstBlocks.clear();
554 fBurstBlockEvents.clear();
555
556 return iResult;
557}
558
559int AliHLTFileWriter::WriteBlock(int blockno, const AliHLTEventID_t& eventID,
560 const AliHLTComponentBlockData* pDesc)
561{
562 // see header file for class documentation
563 int iResult=0;
564 TString filename;
565 HLTDebug("dataspec 0x%x", pDesc->fSpecification);
566 iResult=BuildFileName(eventID, blockno, pDesc->fDataType, pDesc->fSpecification, filename);
567 ios::openmode filemode=(ios::openmode)0;
568 if (fCurrentFileName.CompareTo(filename)==0) {
569 // append to the file
570 filemode=ios::app;
571 } else {
572 // store the file for the next block
573 fCurrentFileName=filename;
574 }
575 if (iResult>=0) {
576 ofstream dump(filename.Data(), filemode);
577 if (dump.good()) {
578 dump.write((static_cast<const char*>(pDesc->fPtr)), pDesc->fSize);
579 HLTDebug("wrote %d byte(s) to file %s", pDesc->fSize, filename.Data());
580 } else {
581 HLTError("can not open file %s for writing", filename.Data());
582 iResult=-EBADF;
583 }
584 dump.close();
585 }
a9c4e244 586 if (iResult>=0 && !fPublisherConfName.IsNull()) {
587 if (!CheckMode(kConcatenateBlocks) &&
588 !CheckMode(kConcatenateEvents)) {
589 // append if not the first entry
590 if (fPublisherConfEvent>=0) filemode=ios::app;
591 else filemode=(ios::openmode)0;
592 ofstream conf(fPublisherConfName.Data(), filemode);
593 if (conf.good()) {
a9c4e244 594 conf << "-datatype ";
595 conf << DataType2Text(pDesc->fDataType, 3);
af056b7b 596 conf << " -dataspec ";
597 TString specstr; specstr.Form("0x%08x", pDesc->fSpecification);
598 conf << specstr;
a9c4e244 599 conf << " -datafile ";
600 conf << filename;
601 conf << endl;
602 } else {
603 fPublisherConfName="";
604 HLTError("can not open file %s for writing of configuration commands", fPublisherConfName.Data());
605 }
606 conf.close();
bdc4041c 607 fPublisherConfEvent=GetEventCount();
a9c4e244 608 } else {
609 fPublisherConfName="";
610 HLTWarning("option 'concatenate blocks/events' collides with writing of FilePublisher configuration, disable ...");
611 }
612 }
4b31e06b 613 return iResult;
614}