]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/BASE/util/AliHLTFileWriter.cxx
Preparing the RootSchemaEvolutionComponent to run at 2kHz
[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()
e74abd18 57{
58 // see header file for class documentation
59 // or
60 // refer to README to build package
61 // or
62 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
63}
64
e74abd18 65AliHLTFileWriter::~AliHLTFileWriter()
66{
67 // see header file for class documentation
68
69 // file list and file name list are owner of their objects and
70 // delete all the objects
71}
72
4b31e06b 73int AliHLTFileWriter::SetDefaults()
74{
75 // see header file for class documentation
76 fBaseName="";
77 fExtension="";
78 fDirectory="";
79 fSubDirFormat="";
80 fIdFormat="_0x%08x";
81 fSpecFormat="";
82 fBlcknoFormat="_0x%02x";
83 fCurrentFileName="";
84 fMode=0;
85 fpBurstBuffer=NULL;
86 fBurstBufferSize=0;
87 fBurstBlocks.clear();
88 fBurstBlockEvents.clear();
89 return 0;
90}
91
e74abd18 92const char* AliHLTFileWriter::GetComponentID()
93{
94 // see header file for class documentation
95 return "FileWriter";
96}
97
98void AliHLTFileWriter::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
99{
100 // see header file for class documentation
101 list.clear();
6daf06e2 102 list.push_back(kAliHLTAllDataTypes);
e74abd18 103}
104
105AliHLTComponent* AliHLTFileWriter::Spawn()
106{
107 // see header file for class documentation
108 return new AliHLTFileWriter;
109}
110
111int AliHLTFileWriter::DoInit( int argc, const char** argv )
112{
113 // see header file for class documentation
114 int iResult=0;
4b31e06b 115 fpBlockDataCollection=new AliHLTBlockDataCollection;
e74abd18 116 TString argument="";
117 int bMissingParam=0;
4b31e06b 118 char* cpErr=NULL;
119 int i=0;
120 for (; i<argc && iResult>=0; i++) {
121 cpErr=NULL;
e74abd18 122 argument=argv[i];
123 if (argument.IsNull()) continue;
124
125 // -basename
126 if (argument.CompareTo("-datafile")==0) {
127 if ((bMissingParam=(++i>=argc))) break;
128 fBaseName=argv[i];
129 TObjArray* pTokens=fBaseName.Tokenize(".");
130 if (pTokens) {
77fd699f 131 int iEntries=pTokens->GetEntriesFast();
e74abd18 132 if (iEntries>1) {
f7561f8d 133 int n=0;
134 fBaseName=((TObjString*)pTokens->At(n++))->GetString();
135 while (n<iEntries-1) {
136 fBaseName+="." + ((TObjString*)pTokens->At(n++))->GetString();
e74abd18 137 }
f7561f8d 138 fExtension=((TObjString*)pTokens->At(n))->GetString();
e74abd18 139 }
140 delete pTokens;
141 }
142
143 // -directory
144 } else if (argument.CompareTo("-directory")==0) {
145 if ((bMissingParam=(++i>=argc))) break;
146 fDirectory=argv[i];
147
5ab95e9a 148 // -subdir
149 } else if (argument.BeginsWith("-subdir")) {
150 argument.ReplaceAll("-subdir", "");
151 if (argument.BeginsWith("=")) {
152 fSubDirFormat=argument.Replace(0,1,"");
2cb9ea42 153 if (strchr(fSubDirFormat.Data(), '%')==NULL) {
154 fSubDirFormat+="%lu";
155 }
5ab95e9a 156 } else {
488eca05 157 fSubDirFormat="event%03lu";
5ab95e9a 158 }
6daf06e2 159 // no additional eventno in the filename unless set again
160 // the sub dir contains the id
161 fIdFormat="";
5ab95e9a 162
163 // -idfmt
164 } else if (argument.BeginsWith("-idfmt")) {
165 argument.ReplaceAll("-idfmt", "");
166 if (argument.BeginsWith("=")) {
167 fIdFormat=argument.Replace(0,1,"");
168 }
169
170 // -specfmt
171 } else if (argument.BeginsWith("-specfmt")) {
172 argument.ReplaceAll("-specfmt", "");
173 if (argument.BeginsWith("=")) {
174 fSpecFormat=argument.Replace(0,1,"");
175 } else {
176 fSpecFormat="_0x%08x";
177 }
178
6daf06e2 179 // -blocknofmt
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
5ab95e9a 184 argument.ReplaceAll("-blcknofmt", "");
6daf06e2 185 argument.ReplaceAll("-blocknofmt", "");
5ab95e9a 186 if (argument.BeginsWith("=")) {
187 fBlcknoFormat=argument.Replace(0,1,"");
188 } else {
189 fBlcknoFormat="_0x%02x";
190 }
191
e74abd18 192 // -enumeration
193 } else if (argument.CompareTo("-enumerate")==0) {
194 SetMode(kEnumerate);
195
196 // -concatenate-blocks
197 } else if (argument.CompareTo("-concatenate-blocks")==0) {
198 SetMode(kConcatenateBlocks);
199
200 // -concatenate-events
201 } else if (argument.CompareTo("-concatenate-events")==0) {
202 SetMode(kConcatenateEvents);
203
6b7f77cf 204 // -write-all-events
205 } else if (argument.CompareTo("-write-all-events")==0) {
206 SetMode(kWriteAllEvents);
207
208 // -write-all-blocks
209 } else if (argument.CompareTo("-write-all-blocks")==0) {
210 SetMode(kWriteAllBlocks);
211
212 // -write-all
213 } else if (argument.CompareTo("-write-all")==0) {
214 SetMode(kWriteAllEvents);
215 SetMode(kWriteAllBlocks);
216
4b31e06b 217 // -burst-buffer
218 } else if (argument.CompareTo("-burst-buffer")==0) {
219 if ((bMissingParam=(++i>=argc))) break;
220 fBurstBufferSize = strtoul( argv[i], &cpErr ,0);
221 if ( *cpErr ) break;
222
2cb9ea42 223 // -skip-datatype
224 } else if(argument.CompareTo("-skip-datatype")==0){
225 SetMode(kSkipDataType);
226
4b31e06b 227 // check for selection arguments (AliHLTBlockDataCollection)
228 } else if (fpBlockDataCollection &&
229 (iResult=fpBlockDataCollection->ScanArgument(argc-i, &argv[i]))>0) {
230 i+=iResult-1;
231 iResult=0;
e74abd18 232 } else {
233 if ((iResult=ScanArgument(argc-i, &argv[i]))==-EINVAL) {
234 HLTError("unknown argument %s", argument.Data());
235 break;
236 } else if (iResult==-EPROTO) {
237 bMissingParam=1;
238 break;
13ce8aae 239 } else if (iResult>0) {
240 i+=iResult-1;
e74abd18 241 iResult=0;
242 }
243 }
244 }
4b31e06b 245
246 if (cpErr && *cpErr) {
247 HLTError("Cannot convert specifier '%s' for argument '%s'", argv[i], argument.Data());
248 iResult=-EINVAL;
249 } else if (bMissingParam) {
e74abd18 250 HLTError("missing parameter for argument %s", argument.Data());
251 iResult=-EINVAL;
252 }
4b31e06b 253 if (fpBlockDataCollection &&
254 (iResult<0 || fpBlockDataCollection->IsEmpty())) {
255 delete fpBlockDataCollection;
256 fpBlockDataCollection=NULL;
257 }
258 if (iResult>=0 && fBurstBufferSize>0) {
259 if (!CheckMode(kConcatenateBlocks) || !CheckMode(kConcatenateEvents)) {
260 HLTError("burst write currently only supported for mode kConcatenateBlocks AND kConcatenateEvents");
261 iResult=-EINVAL;
262 } else {
263 fpBurstBuffer=new AliHLTUInt8_t[fBurstBufferSize];
264 if (!fpBurstBuffer) {
265 iResult=-ENOMEM;
266 fBurstBufferSize=0;
267 }
268 }
269 }
270
e74abd18 271 if (iResult>=0) {
272 iResult=InitWriter();
07cd8230 273 if (!fDirectory.IsNull()) {
274 gSystem->mkdir(fDirectory);
275 }
e74abd18 276 }
277
278 return iResult;
279}
280
281int AliHLTFileWriter::InitWriter()
282{
283 // see header file for class documentation
5df0cbb9 284
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
289 fCurrentFileName="";
e74abd18 290 return 0; // note: this doesn't mean 'error'
291}
292
6daf06e2 293int AliHLTFileWriter::ScanArgument(int /*argc*/, const char** /*argv*/)
e74abd18 294{
295 // see header file for class documentation
296
297 // there are no other arguments than the standard ones
5df0cbb9 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
302 fCurrentFileName="";
e74abd18 303 return -EINVAL;
304}
305
306int AliHLTFileWriter::DoDeinit()
307{
308 // see header file for class documentation
4b31e06b 309 int iResult=0;
310 if (fpBurstBuffer) {
311 if ((iResult=BurstWrite())<0) {
312 HLTError("failed BurstWrite");
313 }
314 delete [] fpBurstBuffer;
315 fpBurstBuffer=NULL;
316 fBurstBufferSize=0;
317 fBurstBlocks.clear();
318 fBurstBlockEvents.clear();
319 }
320
321 iResult=CloseWriter();
e74abd18 322 ClearMode(kEnumerate);
4b31e06b 323
324 if (fpBlockDataCollection) delete fpBlockDataCollection;
325 fpBlockDataCollection=NULL;
326
327 SetDefaults();
e74abd18 328 return iResult;
329}
330
331int AliHLTFileWriter::CloseWriter()
332{
333 // see header file for class documentation
5df0cbb9 334
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
339 fCurrentFileName="";
6daf06e2 340 return 0;
e74abd18 341}
342
343int AliHLTFileWriter::DumpEvent( const AliHLTComponentEventData& evtData,
fdb4ca9e 344 AliHLTComponentTriggerData& /*trigData*/ )
e74abd18 345{
346 // see header file for class documentation
347 int iResult=0;
6b7f77cf 348 if (!IsDataEvent() && !CheckMode(kWriteAllEvents)) return 0;
349
e74abd18 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.
354 fCurrentFileName="";
355 }
fdb4ca9e 356 const AliHLTComponentBlockData* pDesc=NULL;
357
358 int blockno=0;
6daf06e2 359 for (pDesc=GetFirstInputBlock(); pDesc!=NULL; pDesc=GetNextInputBlock(), blockno++) {
4b31e06b 360 if (fpBlockDataCollection) {
361 if (!fpBlockDataCollection->IsSelected(*pDesc)) continue;
362 } else if (pDesc->fDataType==(kAliHLTAnyDataType|kAliHLTDataOriginPrivate) && !CheckMode(kWriteAllBlocks))
6b7f77cf 363 continue;
fdb4ca9e 364 HLTDebug("block %d out of %d", blockno, evtData.fBlockCnt);
4b31e06b 365 iResult=ScheduleBlock(blockno, evtData.fEventID, pDesc);
e74abd18 366 }
e74abd18 367 return iResult;
368}
369
5ab95e9a 370int AliHLTFileWriter::BuildFileName(const AliHLTEventID_t eventID, const int blockID,
371 const AliHLTComponentDataType& dataType,
372 const AliHLTUInt32_t specification,
373 TString& filename)
e74abd18 374{
375 // see header file for class documentation
376 int iResult=0;
377 //HLTDebug("build file name for event %d block %d", eventID, blockID);
378 filename="";
6b7f77cf 379
380 AliHLTUInt32_t eventType=gkAliEventTypeUnknown;
6b7f77cf 381
e74abd18 382 if (!fDirectory.IsNull()) {
383 filename+=fDirectory;
5ab95e9a 384 if (!filename.EndsWith("/"))
e74abd18 385 filename+="/";
386 }
5ab95e9a 387 if (!fSubDirFormat.IsNull()) {
388 filename+=Form(fSubDirFormat, eventID);
389 if (!filename.EndsWith("/"))
390 filename+="/";
391 }
392 if (filename.EndsWith("/")) {
393 gSystem->mkdir(filename);
394 }
488eca05 395
396 IsDataEvent(&eventType);
8516ea4c 397 if (CheckMode(kWriteAllEvents) && !CheckMode(kConcatenateEvents)) {
398 if (eventType==gkAliEventTypeStartOfRun) filename+="SOR_";
399 else if (eventType==gkAliEventTypeEndOfRun) filename+="EOR_";
400 }
488eca05 401
e74abd18 402 if (!fBaseName.IsNull())
403 filename+=fBaseName;
404 else
405 filename+="event";
406 if (!CheckMode(kConcatenateEvents)) {
407 if (!CheckMode(kEnumerate)) {
5ab95e9a 408 if (eventID!=kAliHLTVoidEventID && !fIdFormat.IsNull()) {
409 filename+=Form(fIdFormat, eventID);
e74abd18 410 }
411 } else {
412 filename+=Form("_%d", GetEventCount());
413 }
414 }
415 if (blockID>=0 && !CheckMode(kConcatenateBlocks)) {
5ab95e9a 416 if (!fBlcknoFormat.IsNull())
417 filename+=Form(fBlcknoFormat, blockID);
2cb9ea42 418 if (dataType!=kAliHLTVoidDataType &&
419 !CheckMode(kSkipDataType)) {
e74abd18 420 filename+="_";
421 filename+=AliHLTComponent::DataType2Text(dataType).data();
422 }
5ab95e9a 423 if (!fSpecFormat.IsNull())
424 filename+=Form(fSpecFormat, specification);
e74abd18 425 }
426 if (!fExtension.IsNull())
427 filename+="." + fExtension;
428 filename.ReplaceAll(" ", "");
429 return iResult;
430}
431
432int AliHLTFileWriter::SetMode(Short_t mode)
433{
434 // see header file for class documentation
435 fMode|=mode;
436 //HLTDebug("mode set to 0x%x", fMode);
437 return fMode;
438}
439
440int AliHLTFileWriter::ClearMode(Short_t mode)
441{
442 // see header file for class documentation
443 fMode&=~mode;
444 //HLTDebug("mode set to 0x%x", fMode);
445 return fMode;
446}
447
5df0cbb9 448int AliHLTFileWriter::CheckMode(Short_t mode) const
e74abd18 449{
450 // see header file for class documentation
451
452 //HLTDebug("check mode 0x%x for flag 0x%x: %d", fMode, mode, (fMode&mode)!=0);
453 return (fMode&mode)!=0;
454}
4b31e06b 455
456int AliHLTFileWriter::ScheduleBlock(int blockno, const AliHLTEventID_t& eventID,
457 const AliHLTComponentBlockData* pDesc)
458{
459 // see header file for class documentation
460 int iResult=0;
461 if (fpBurstBuffer==NULL ||
bb7774d6 462 (fBurstBlocks.size()==0 && pDesc->fSize>fBurstBufferSize) ) {
4b31e06b 463 return WriteBlock(blockno, eventID, pDesc);
464 }
465 AliHLTComponentBlockData bd=*pDesc;
466 bd.fPtr=NULL;
467 if (fBurstBlocks.size()>0) {
468 bd.fOffset=fBurstBlocks.back().fOffset+fBurstBlocks.back().fSize;
469 } else {
470 bd.fOffset=0;
471 }
472 if (bd.fOffset+bd.fSize>fBurstBufferSize) {
473 if ((iResult=BurstWrite())>=0) {
474 iResult=WriteBlock(blockno, eventID, pDesc);
475 }
476 } else {
477 memcpy(fpBurstBuffer+bd.fOffset, pDesc->fPtr, bd.fSize);
478 fBurstBlocks.push_back(bd);
479 fBurstBlockEvents.push_back(eventID);
480 }
481
482 return iResult;
483}
484
485int AliHLTFileWriter::BurstWrite()
486{
487 // see header file for class documentation
488 int iResult=0;
489 if (fBurstBlocks.size()==0) return 0;
490 assert(fBurstBlocks.size()==fBurstBlockEvents.size());
491 HLTDebug("writing %d postponed blocks", fBurstBlocks.size());
492 int blockno=0;
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;
499 }
500 for (; block!=fBurstBlocks.end() && iResult>=0; block++, event++, blockno++) {
501 if (event!=fBurstBlockEvents.begin() && *event!=*(event-1)) {
502 blockno=0;
503 }
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;
516 firstBlock=block+1;
517 } else {
518 // coninue if it wasn't the last block of this event
519 continue;
520 }
521 } else {
522 (*block).fPtr=fpBurstBuffer+(*block).fOffset;
523 }
524 (*block).fOffset=0;
525 iResult=WriteBlock(blockno, *event, &(*block));
526 }
527 fBurstBlocks.clear();
528 fBurstBlockEvents.clear();
529
530 return iResult;
531}
532
533int AliHLTFileWriter::WriteBlock(int blockno, const AliHLTEventID_t& eventID,
534 const AliHLTComponentBlockData* pDesc)
535{
536 // see header file for class documentation
537 int iResult=0;
538 TString filename;
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
544 filemode=ios::app;
545 } else {
546 // store the file for the next block
547 fCurrentFileName=filename;
548 }
549 if (iResult>=0) {
550 ofstream dump(filename.Data(), filemode);
551 if (dump.good()) {
552 dump.write((static_cast<const char*>(pDesc->fPtr)), pDesc->fSize);
553 HLTDebug("wrote %d byte(s) to file %s", pDesc->fSize, filename.Data());
554 } else {
555 HLTError("can not open file %s for writing", filename.Data());
556 iResult=-EBADF;
557 }
558 dump.close();
559 }
560 return iResult;
561}