]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - HLT/BASE/util/AliHLTFileWriter.cxx
- break up of argument string into argument list: making static method of AliHLTConfi...
[u/mrichter/AliRoot.git] / HLT / BASE / util / AliHLTFileWriter.cxx
index 4ee692087337888f4298338e00b1400ddbd1668a..73d3e38a086262cdc41aa75314727e2d6b2d563b 100644 (file)
@@ -26,11 +26,13 @@ using namespace std;
 #endif
 
 #include "AliHLTFileWriter.h"
+#include "AliHLTBlockDataCollection.h"
 #include <TObjArray.h>
 #include <TObjString.h>
 #include <TSystem.h>
 //#include <TMath.h>
 //#include <TFile.h>
+#include <cassert>
 
 /** ROOT macro for the implementation of ROOT specific class methods */
 ClassImp(AliHLTFileWriter)
@@ -38,15 +40,20 @@ ClassImp(AliHLTFileWriter)
 AliHLTFileWriter::AliHLTFileWriter()
   :
   AliHLTDataSink(),
+  fpBlockDataCollection(NULL),
   fBaseName(""),
   fExtension(""),
   fDirectory(""),
   fSubDirFormat(""),
-  fIdFormat(""),
+  fIdFormat("_0x%08x"),
   fSpecFormat(""),
-  fBlcknoFormat(""),
+  fBlcknoFormat("_0x%02x"),
   fCurrentFileName(""),
   fMode(0)
+  , fpBurstBuffer(NULL)
+  , fBurstBufferSize(0)
+  , fBurstBlocks()
+  , fBurstBlockEvents()
 {
   // see header file for class documentation
   // or
@@ -63,6 +70,25 @@ AliHLTFileWriter::~AliHLTFileWriter()
   // delete all the objects
 }
 
+int AliHLTFileWriter::SetDefaults()
+{
+  // see header file for class documentation
+  fBaseName="";
+  fExtension="";
+  fDirectory="";
+  fSubDirFormat="";
+  fIdFormat="_0x%08x";
+  fSpecFormat="";
+  fBlcknoFormat="_0x%02x";
+  fCurrentFileName="";
+  fMode=0;
+  fpBurstBuffer=NULL;
+  fBurstBufferSize=0;
+  fBurstBlocks.clear();
+  fBurstBlockEvents.clear();
+  return 0;
+}
+
 const char* AliHLTFileWriter::GetComponentID()
 {
   // see header file for class documentation
@@ -73,7 +99,7 @@ void AliHLTFileWriter::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
 {
   // see header file for class documentation
   list.clear();
-  list.push_back(kAliHLTAnyDataType);
+  list.push_back(kAliHLTAllDataTypes);
 }
 
 AliHLTComponent* AliHLTFileWriter::Spawn()
@@ -86,9 +112,13 @@ int AliHLTFileWriter::DoInit( int argc, const char** argv )
 {
   // see header file for class documentation
   int iResult=0;
+  fpBlockDataCollection=new AliHLTBlockDataCollection;
   TString argument="";
   int bMissingParam=0;
-  for (int i=0; i<argc && iResult>=0; i++) {
+  char* cpErr=NULL;
+  int i=0;
+  for (; i<argc && iResult>=0; i++) {
+    cpErr=NULL;
     argument=argv[i];
     if (argument.IsNull()) continue;
 
@@ -100,12 +130,12 @@ int AliHLTFileWriter::DoInit( int argc, const char** argv )
       if (pTokens) {
        int iEntries=pTokens->GetEntries();
        if (iEntries>1) {
-         int i=0;
-         fBaseName=((TObjString*)pTokens->At(i++))->GetString();
-         while (i<iEntries-1) {
-           fBaseName+="." + ((TObjString*)pTokens->At(i++))->GetString();
+         int n=0;
+         fBaseName=((TObjString*)pTokens->At(n++))->GetString();
+         while (n<iEntries-1) {
+           fBaseName+="." + ((TObjString*)pTokens->At(n++))->GetString();
          }
-         fExtension=((TObjString*)pTokens->At(i))->GetString();
+         fExtension=((TObjString*)pTokens->At(n))->GetString();
        }
        delete pTokens;
       }
@@ -120,9 +150,15 @@ int AliHLTFileWriter::DoInit( int argc, const char** argv )
       argument.ReplaceAll("-subdir", "");
       if (argument.BeginsWith("=")) {
        fSubDirFormat=argument.Replace(0,1,"");
+       if (strchr(fSubDirFormat.Data(), '%')==NULL) {
+         fSubDirFormat+="%lu";
+       }
       } else {
-       fSubDirFormat="event%03d";
+       fSubDirFormat="event%03lu";
       }
+      // no additional eventno in the filename unless set again
+      // the sub dir contains the id
+      fIdFormat="";
 
       // -idfmt
     } else if (argument.BeginsWith("-idfmt")) {
@@ -140,9 +176,13 @@ int AliHLTFileWriter::DoInit( int argc, const char** argv )
        fSpecFormat="_0x%08x";
       }
 
-      // -blcknofmt
-    } else if (argument.BeginsWith("-blcknofmt")) {
+      // -blocknofmt
+    } else if (argument.BeginsWith("-blcknofmt") || 
+              argument.BeginsWith("-blocknofmt")) {
+      // for the sake of backward compatibility we consider also the
+      // old argument with typo for a while
       argument.ReplaceAll("-blcknofmt", "");
+      argument.ReplaceAll("-blocknofmt", "");
       if (argument.BeginsWith("=")) {
        fBlcknoFormat=argument.Replace(0,1,"");
       } else {
@@ -161,6 +201,34 @@ int AliHLTFileWriter::DoInit( int argc, const char** argv )
     } else if (argument.CompareTo("-concatenate-events")==0) {
       SetMode(kConcatenateEvents);
 
+      // -write-all-events
+    } else if (argument.CompareTo("-write-all-events")==0) {
+      SetMode(kWriteAllEvents);
+
+      // -write-all-blocks
+    } else if (argument.CompareTo("-write-all-blocks")==0) {
+      SetMode(kWriteAllBlocks);
+
+      // -write-all
+    } else if (argument.CompareTo("-write-all")==0) {
+      SetMode(kWriteAllEvents);
+      SetMode(kWriteAllBlocks);
+
+      // -burst-buffer
+    } else if (argument.CompareTo("-burst-buffer")==0) {
+      if ((bMissingParam=(++i>=argc))) break;
+      fBurstBufferSize = strtoul( argv[i], &cpErr ,0);
+      if ( *cpErr ) break;
+
+      // -skip-datatype
+    } else if(argument.CompareTo("-skip-datatype")==0){
+      SetMode(kSkipDataType);
+
+      // check for selection arguments (AliHLTBlockDataCollection)
+    } else if (fpBlockDataCollection && 
+              (iResult=fpBlockDataCollection->ScanArgument(argc-i, &argv[i]))>0) {
+       i+=iResult-1;
+       iResult=0;
     } else {
       if ((iResult=ScanArgument(argc-i, &argv[i]))==-EINVAL) {
        HLTError("unknown argument %s", argument.Data());
@@ -168,23 +236,43 @@ int AliHLTFileWriter::DoInit( int argc, const char** argv )
       } else if (iResult==-EPROTO) {
        bMissingParam=1;
        break;
-      } else if (iResult>=0) {
-       i+=iResult;
+      } else if (iResult>0) {
+       i+=iResult-1;
        iResult=0;
       }
     }
   }
-  if (bMissingParam) {
+
+  if (cpErr && *cpErr) {
+    HLTError("Cannot convert specifier '%s' for argument '%s'", argv[i], argument.Data());
+    iResult=-EINVAL;
+  } else if (bMissingParam) {
     HLTError("missing parameter for argument %s", argument.Data());
     iResult=-EINVAL;
   }
-  if (iResult>=0) {
-    if (fIdFormat.IsNull() && fSubDirFormat.IsNull()) {
-      // set the default format string for the id if it is not set and
-      // no sub dirs set (the sub dir than contains the id)
-      fIdFormat="_0x%08x";
+  if (fpBlockDataCollection &&
+      (iResult<0 || fpBlockDataCollection->IsEmpty())) {
+    delete fpBlockDataCollection;
+    fpBlockDataCollection=NULL;
+  }
+  if (iResult>=0 && fBurstBufferSize>0) {
+    if (!CheckMode(kConcatenateBlocks) || !CheckMode(kConcatenateEvents)) {
+      HLTError("burst write currently only supported for mode kConcatenateBlocks AND kConcatenateEvents");
+      iResult=-EINVAL;
+    } else {
+    fpBurstBuffer=new AliHLTUInt8_t[fBurstBufferSize];
+    if (!fpBurstBuffer) {
+      iResult=-ENOMEM;
+      fBurstBufferSize=0;
     }
+    }
+  }
+
+  if (iResult>=0) {
     iResult=InitWriter();
+    if (!fDirectory.IsNull()) {
+      gSystem->mkdir(fDirectory);
+    }
   }
 
   return iResult;
@@ -202,14 +290,11 @@ int AliHLTFileWriter::InitWriter()
   return 0; // note: this doesn't mean 'error'
 }
 
-int AliHLTFileWriter::ScanArgument(int argc, const char** argv)
+int AliHLTFileWriter::ScanArgument(int /*argc*/, const char** /*argv*/)
 {
   // see header file for class documentation
 
   // there are no other arguments than the standard ones
-  if (argc==0 && argv==NULL) {
-    // this is just to get rid of the warning "unused parameter"
-  }
   // fCurrentFileName is used in dump event, just touched her to avoid
   // coding convention violation RC11. The function can not be declared
   // const since it is just the default implementation, overloaded
@@ -221,8 +306,25 @@ int AliHLTFileWriter::ScanArgument(int argc, const char** argv)
 int AliHLTFileWriter::DoDeinit()
 {
   // see header file for class documentation
-  int iResult=CloseWriter();
+  int iResult=0;
+  if (fpBurstBuffer) {
+    if ((iResult=BurstWrite())<0) {
+      HLTError("failed BurstWrite");
+    }
+    delete [] fpBurstBuffer;
+    fpBurstBuffer=NULL;
+    fBurstBufferSize=0;
+    fBurstBlocks.clear();
+    fBurstBlockEvents.clear();
+  }
+
+  iResult=CloseWriter();
   ClearMode(kEnumerate);
+
+  if (fpBlockDataCollection) delete fpBlockDataCollection;
+  fpBlockDataCollection=NULL;
+
+  SetDefaults();
   return iResult;
 }
 
@@ -235,48 +337,32 @@ int AliHLTFileWriter::CloseWriter()
   // const since it is just the default implementation, overloaded
   // virtual function might not be const
   fCurrentFileName="";
-  return 0; // note: this doesn't mean 'error'
+  return 0;
 }
 
 int AliHLTFileWriter::DumpEvent( const AliHLTComponentEventData& evtData,
-                        const AliHLTComponentBlockData* blocks, 
-                        AliHLTComponentTriggerData& trigData )
+                        AliHLTComponentTriggerData& /*trigData*/ )
 {
   // see header file for class documentation
   int iResult=0;
+  if (!IsDataEvent() && !CheckMode(kWriteAllEvents)) return 0;
+
   if (CheckMode(kConcatenateEvents)==0) {
     // reset the current file name in order to open a new file
     // for the first block. If events are concatenated, the current
     // file name stays in order to be opended in append mode.
     fCurrentFileName="";
   }
-  for (int n=0; n<(int)evtData.fBlockCnt; n++ ) {
-    //HLTDebug("block %d out of %d", n, evtData.fBlockCnt);
-    TString filename;
-    //HLTDebug("dataspec 0x%x", blocks[n].fSpecification);
-    iResult=BuildFileName(evtData.fEventID, n, blocks[n].fDataType, blocks[n].fSpecification, filename);
-    ios::openmode filemode=(ios::openmode)0;
-    if (fCurrentFileName.CompareTo(filename)==0) {
-      // append to the file
-      filemode=ios::app;
-    } else {
-      // store the file for the next block
-      fCurrentFileName=filename;
-    }
-    if (iResult>=0) {
-      ofstream dump(filename.Data(), filemode);
-      if (dump.good()) {
-       dump.write((static_cast<const char*>(blocks[n].fPtr)), blocks[n].fSize);
-       HLTDebug("wrote %d byte(s) to file %s", blocks[n].fSize, filename.Data());
-      } else {
-       HLTError("can not open file %s for writing", filename.Data());
-       iResult=-EBADF;
-      }
-      dump.close();
-    }
-  }
-  if (trigData.fStructSize==0) {
-    // this is just to get rid of the warning "unused parameter"
+  const AliHLTComponentBlockData* pDesc=NULL;
+
+  int blockno=0;
+  for (pDesc=GetFirstInputBlock(); pDesc!=NULL; pDesc=GetNextInputBlock(), blockno++) {
+    if (fpBlockDataCollection) {
+      if (!fpBlockDataCollection->IsSelected(*pDesc)) continue;
+    } else if (pDesc->fDataType==(kAliHLTAnyDataType|kAliHLTDataOriginPrivate) && !CheckMode(kWriteAllBlocks))
+      continue;
+    HLTDebug("block %d out of %d", blockno, evtData.fBlockCnt);
+    iResult=ScheduleBlock(blockno, evtData.fEventID, pDesc);
   }
   return iResult;
 }
@@ -290,6 +376,9 @@ int AliHLTFileWriter::BuildFileName(const AliHLTEventID_t eventID, const int blo
   int iResult=0;
   //HLTDebug("build file name for event %d block %d", eventID, blockID);
   filename="";
+
+  AliHLTUInt32_t eventType=gkAliEventTypeUnknown;
+
   if (!fDirectory.IsNull()) {
     filename+=fDirectory;
     if (!filename.EndsWith("/"))
@@ -303,6 +392,11 @@ int AliHLTFileWriter::BuildFileName(const AliHLTEventID_t eventID, const int blo
   if (filename.EndsWith("/")) {
     gSystem->mkdir(filename);
   }
+
+  IsDataEvent(&eventType);
+  if (eventType==gkAliEventTypeStartOfRun && CheckMode(kWriteAllEvents)) filename+="SOR_";
+  else if (eventType==gkAliEventTypeEndOfRun && CheckMode(kWriteAllEvents)) filename+="EOR_";
+
   if (!fBaseName.IsNull())
     filename+=fBaseName;
   else
@@ -319,7 +413,8 @@ int AliHLTFileWriter::BuildFileName(const AliHLTEventID_t eventID, const int blo
   if (blockID>=0 && !CheckMode(kConcatenateBlocks)) {
     if (!fBlcknoFormat.IsNull())
       filename+=Form(fBlcknoFormat, blockID);
-    if (dataType!=kAliHLTVoidDataType) {
+    if (dataType!=kAliHLTVoidDataType &&
+       !CheckMode(kSkipDataType)) {
       filename+="_";
       filename+=AliHLTComponent::DataType2Text(dataType).data();
     }
@@ -355,3 +450,110 @@ int AliHLTFileWriter::CheckMode(Short_t mode) const
   //HLTDebug("check mode 0x%x for flag 0x%x: %d", fMode, mode, (fMode&mode)!=0);
   return (fMode&mode)!=0;
 }
+
+int AliHLTFileWriter::ScheduleBlock(int blockno, const AliHLTEventID_t& eventID,
+                                   const AliHLTComponentBlockData* pDesc)
+{
+  // see header file for class documentation
+  int iResult=0;
+  if (fpBurstBuffer==NULL ||
+      fBurstBlocks.size()==0 && pDesc->fSize>fBurstBufferSize) {
+    return WriteBlock(blockno, eventID, pDesc);
+  }
+  AliHLTComponentBlockData bd=*pDesc;
+  bd.fPtr=NULL;
+  if (fBurstBlocks.size()>0) {
+    bd.fOffset=fBurstBlocks.back().fOffset+fBurstBlocks.back().fSize;
+  } else {
+    bd.fOffset=0;
+  }
+  if (bd.fOffset+bd.fSize>fBurstBufferSize) {
+    if ((iResult=BurstWrite())>=0) {
+      iResult=WriteBlock(blockno, eventID, pDesc);
+    }
+  } else {
+    memcpy(fpBurstBuffer+bd.fOffset, pDesc->fPtr, bd.fSize);
+    fBurstBlocks.push_back(bd);
+    fBurstBlockEvents.push_back(eventID);
+  }
+
+  return iResult;
+}
+
+int AliHLTFileWriter::BurstWrite()
+{
+  // see header file for class documentation
+  int iResult=0;
+  if (fBurstBlocks.size()==0) return 0;
+  assert(fBurstBlocks.size()==fBurstBlockEvents.size());
+  HLTDebug("writing %d postponed blocks", fBurstBlocks.size());
+  int blockno=0;
+  AliHLTComponentBlockDataList::iterator block=fBurstBlocks.begin();
+  AliHLTComponentBlockDataList::iterator firstBlock=block;
+  vector<AliHLTEventID_t>::iterator event=fBurstBlockEvents.begin();
+  if (CheckMode(kConcatenateEvents)) {
+    block=fBurstBlocks.end()-1;
+    event=fBurstBlockEvents.end()-1;
+  }
+  for (; block!=fBurstBlocks.end() && iResult>=0; block++, event++, blockno++) {
+    if (event!=fBurstBlockEvents.begin() && *event!=*(event-1)) {
+      blockno=0;
+    }
+    if (CheckMode(kConcatenateEvents)) {
+      // all blocks in the burst buffer are written in one go
+      // just the block descriptor is updated appropriately
+      (*block).fSize+=(*block).fOffset;
+      (*block).fPtr=fpBurstBuffer;
+    } else if (CheckMode(kConcatenateBlocks)) {
+      // all blocks of the same event are written in one go
+      // just the block descriptor is updated appropriately
+      if (event+1==fBurstBlockEvents.end() ||
+         *event!=*(event+1)) {
+       (*block).fSize+=(*block).fOffset-(*firstBlock).fOffset;
+       (*block).fPtr=fpBurstBuffer+(*firstBlock).fOffset;
+       firstBlock=block+1;
+      } else {
+       // coninue if it wasn't the last block of this event
+       continue;
+      }
+    } else {
+      (*block).fPtr=fpBurstBuffer+(*block).fOffset;
+    }
+    (*block).fOffset=0;
+    iResult=WriteBlock(blockno, *event, &(*block));
+  }
+  fBurstBlocks.clear();
+  fBurstBlockEvents.clear();
+
+  return iResult;
+}
+
+int AliHLTFileWriter::WriteBlock(int blockno, const AliHLTEventID_t& eventID,
+                                const AliHLTComponentBlockData* pDesc)
+{
+  // see header file for class documentation
+  int iResult=0;
+  TString filename;
+  HLTDebug("dataspec 0x%x", pDesc->fSpecification);
+  iResult=BuildFileName(eventID, blockno, pDesc->fDataType, pDesc->fSpecification, filename);
+  ios::openmode filemode=(ios::openmode)0;
+  if (fCurrentFileName.CompareTo(filename)==0) {
+    // append to the file
+    filemode=ios::app;
+  } else {
+    // store the file for the next block
+    fCurrentFileName=filename;
+  }
+  if (iResult>=0) {
+    ofstream dump(filename.Data(), filemode);
+    if (dump.good()) {
+      dump.write((static_cast<const char*>(pDesc->fPtr)), pDesc->fSize);
+      HLTDebug("wrote %d byte(s) to file %s", pDesc->fSize, filename.Data());
+    } else {
+      HLTError("can not open file %s for writing", filename.Data());
+      iResult=-EBADF;
+    }
+    dump.close();
+  }
+  return iResult;
+}