- make selection functionality and parsing of arguments from AliHLTBlockFilteirComponent commonly available: AliHLTBlockDataCollection
- AliHLTFileWriter: adding support for data block selection and postpone burst write
--- /dev/null
+// $Id$
+
+//**************************************************************************
+//* This file is property of and copyright by the ALICE HLT Project *
+//* ALICE Experiment at CERN, All rights reserved. *
+//* *
+//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
+//* for The ALICE HLT Project. *
+//* *
+//* Permission to use, copy, modify and distribute this software and its *
+//* documentation strictly for non-commercial purposes is hereby granted *
+//* without fee, provided that the above copyright notice appears in all *
+//* copies and that both the copyright notice and this permission notice *
+//* appear in the supporting documentation. The authors make no claims *
+//* about the suitability of this software for any purpose. It is *
+//* provided "as is" without express or implied warranty. *
+//**************************************************************************
+
+/** @file AliHLTBlockDataCollection.cxx
+ @author Matthias Richter
+ @date
+ @brief A collection of AliHLTComponentBlockData descriptors providing
+ argument parsing and basic selection.
+*/
+
+#include <cstdlib>
+#include "AliHLTBlockDataCollection.h"
+#include "AliHLTComponent.h"
+#include "TString.h"
+
+/** ROOT macro for the implementation of ROOT specific class methods */
+ClassImp(AliHLTBlockDataCollection)
+
+AliHLTBlockDataCollection::AliHLTBlockDataCollection()
+ : TObject()
+ , AliHLTLogging()
+ , fFilterRules()
+{
+ // see header file for class documentation
+ // or
+ // refer to README to build package
+ // or
+ // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
+}
+
+AliHLTBlockDataCollection::~AliHLTBlockDataCollection()
+{
+ // see header file for class documentation
+}
+
+int AliHLTBlockDataCollection::Add(const AliHLTComponentBlockData& block)
+{
+ // see header file for class documentation
+ fFilterRules.push_back(block);
+ return fFilterRules.size();
+}
+
+int AliHLTBlockDataCollection::ScanArgument( int argc, const char** argv )
+{
+ // see header file for class documentation
+ int iResult=0;
+ TString argument="";
+ int bMissingParam=0;
+ AliHLTComponentBlockData rule;
+ AliHLTComponent::FillBlockData(rule);
+ int i=0;
+ for (; i<argc && iResult>=0; i++) {
+ argument=argv[i];
+ if (argument.IsNull()) continue;
+
+ // -datatype
+ if (argument.CompareTo("-datatype")==0) {
+ if ((bMissingParam=(i+2>=argc))) break;
+
+ if (!MatchExactly(rule.fDataType,kAliHLTAnyDataType)) {
+ // the data type has already been set, add to list
+ // and reset
+ fFilterRules.push_back(rule);
+ AliHLTComponent::FillBlockData(rule);
+ }
+
+ AliHLTComponent::SetDataType(rule.fDataType, argv[i+1], argv[i+2]);
+ i+=2;
+
+ // -origin
+ } else if (argument.CompareTo("-origin")==0) {
+ if ((bMissingParam=(i+1>=argc))) break;
+
+ if (!MatchExactly(rule.fDataType,kAliHLTAnyDataType)) {
+ // the data type has already been set, add to list
+ // and reset
+ fFilterRules.push_back(rule);
+ AliHLTComponent::FillBlockData(rule);
+ }
+
+ AliHLTComponent::SetDataType(rule.fDataType, NULL, argv[i+1]);
+ i+=1;
+
+ // -typeid
+ } else if (argument.CompareTo("-typeid")==0) {
+ if ((bMissingParam=(i+1>=argc))) break;
+
+ if (!MatchExactly(rule.fDataType,kAliHLTAnyDataType)) {
+ // the data type has already been set, add to list
+ // and reset
+ fFilterRules.push_back(rule);
+ AliHLTComponent::FillBlockData(rule);
+ }
+
+ AliHLTComponent::SetDataType(rule.fDataType, argv[i+1], NULL);
+ i+=1;
+
+ // -dataspec
+ } else if (argument.CompareTo("-dataspec")==0) {
+ if ((bMissingParam=(++i>=argc))) break;
+
+ if (rule.fSpecification!=kAliHLTVoidDataSpec) {
+ // the specification has already been set, add to list
+ // and reset
+ fFilterRules.push_back(rule);
+ AliHLTComponent::FillBlockData(rule);
+ }
+
+ TString parameter(argv[i]);
+ parameter.Remove(TString::kLeading, ' '); // remove all blanks
+ char* pRemnant=NULL;
+ rule.fSpecification=strtoul(parameter.Data(), &pRemnant, 0);
+ if (pRemnant!=NULL && pRemnant[0]!=0) {
+ HLTError("invalid parameter/remnant (%s) for argument %s, number expected", pRemnant, argument.Data());
+ iResult=-EINVAL;
+ }
+ } else {
+ // terminate at the first unknown argument
+ break;
+ }
+ }
+
+ if (bMissingParam) {
+ HLTError("missing parameter for argument %s", argument.Data());
+ iResult=-EPROTO;
+ }
+ if (iResult>=0) {
+ if (rule.fSpecification!=kAliHLTVoidDataSpec || !MatchExactly(rule.fDataType,kAliHLTAnyDataType)) {
+ // add the pending rule
+ fFilterRules.push_back(rule);
+ AliHLTComponent::FillBlockData(rule);
+ }
+ iResult=i;
+ }
+
+ return iResult;
+}
+
+int AliHLTBlockDataCollection::IsSelected(const AliHLTComponentBlockData& block)
+{
+ // see header file for class documentation
+ AliHLTComponentBlockDataList::iterator desc=fFilterRules.begin();
+ //HLTDebug("check block: %s spec %#x", DataType2Text(block.fDataType, 1).c_str(), block.fSpecification);
+ if (desc==fFilterRules.end()) return 1; // no filter rules
+ do {
+ // match if
+ // 1. data types match or filter data type not set
+ // 2. data spec match or filter data wpec not set
+ // 3. either filter data type or spec is set
+ //HLTDebug("check rule : %s spec %#x", DataType2Text((*desc).fDataType, 2).c_str(), block.fSpecification);
+ if (((*desc).fDataType==block.fDataType) &&
+ ((*desc).fSpecification==block.fSpecification || (*desc).fSpecification==kAliHLTVoidDataSpec) &&
+ (!MatchExactly((*desc).fDataType,kAliHLTAnyDataType) || (*desc).fSpecification!=kAliHLTVoidDataSpec)) {
+ return 1;
+ }
+ } while (++desc!=fFilterRules.end());
+
+ return 0;
+}
+
+int AliHLTBlockDataCollection::IsEmpty()
+{
+ // see header file for class documentation
+ if (fFilterRules.size()==0) return 1;
+ return 0;
+}
--- /dev/null
+// -*- Mode: C++ -*-
+// $Id$
+
+#ifndef ALIHLTBLOCKDATACOLLECTION_H
+#define ALIHLTBLOCKDATACOLLECTION_H
+//* This file is property of and copyright by the ALICE HLT Project *
+//* ALICE Experiment at CERN, All rights reserved. *
+//* See cxx source for full Copyright notice *
+
+/** @file AliHLTBlockDataCollection.h
+ @author Matthias Richter
+ @date
+ @brief A collection of AliHLTComponentBlockData descriptors providing
+ argument parsing and basic selection.
+*/
+
+#include "AliHLTLogging.h"
+#include "vector"
+#include "TObject.h"
+
+/**
+ * @class AliHLTBlockDataCollection
+ * Class handles a list of AliHLTComponentBlockData entries and parsing of
+ * argument list to fill it. Originally taken from AliHLTBlickFilterComponent,
+ * but decided to be commonly of benefit.
+ *
+ * See ScanArgument() function for description of available arguments
+ * <pre>
+ * -datatype ID ORIGIN
+ * -typeid ID
+ * -origin ORIGIN
+ * -dataspec SPEC
+ * </pre>
+ *
+ * @ingroup alihlt_base
+ */
+class AliHLTBlockDataCollection : public TObject, public AliHLTLogging
+{
+ public:
+ /** standard constructor */
+ AliHLTBlockDataCollection();
+ /** destructor */
+ virtual ~AliHLTBlockDataCollection();
+
+ /**
+ * Add data block descriptor.
+ */
+ int Add(const AliHLTComponentBlockData& block);
+
+ /**
+ * Check if the data block is selected by the filter rules.
+ * @return 1 if selected
+ */
+ int IsSelected(const AliHLTComponentBlockData& block);
+
+ /**
+ * Scan argument and read block descriptor data.
+ * The function is invoked by components in the course of argument
+ * scan.
+ *
+ * Scan the list for known arguments, terminates at the first unknown argument.
+ * Recognized arguments:
+ * \li -datatype <i> id origin </i> <br>
+ * e.g. <tt> -datatype 'ESD_TREE' 'TPC ' </tt> <br>
+ * \b Note: due to the 4-character data origin it might be necessary to
+ * append a blank to the detectorname, e.g. <tt>TPC -> 'TPC '</tt>
+ *
+ * \li -origin <i> origin </i> <br>
+ * e.g. -origin 'TPC ', \b Note: the filter rule has type id 'ANY'
+ *
+ * \li -typeid <i> id </i> <br>
+ * e.g. -typeid ESD_TREE, \b Note: the filter rule has origin 'ANY'
+ *
+ * \li -dataspec <i> specification </i> <br>
+ * data specification treated as decimal number or hex number if
+ * prepended by '0x'
+ *
+ * @return number of arguments which have been treated.
+ */
+ int ScanArgument(int argc, const char** argv );
+
+ /**
+ * Check collection for content.
+ * @return 1 if empty, 0 if content available
+ */
+ int IsEmpty();
+ protected:
+
+ private:
+ /** copy constructor prohibited */
+ AliHLTBlockDataCollection(const AliHLTBlockDataCollection&);
+ /** assignment operator prohibited */
+ AliHLTBlockDataCollection& operator=(const AliHLTBlockDataCollection&);
+
+ /** filtering rules, only the data type and specification members are use */
+ vector<AliHLTComponentBlockData> fFilterRules; //! transient
+
+ ClassDef(AliHLTBlockDataCollection, 0)
+};
+#endif
return iResult;
}
-int AliHLTConfiguration::InterpreteString(const char* arg, vector<char*>& argList) const
+int AliHLTConfiguration::InterpreteString(const char* arg, vector<char*>& argList)
{
// see header file for function documentation
int iResult=0;
return !(*this==c);
}
+ /**
+ * Helper function to build a vector from an argument string.
+ * The function allocates memory for each token. The caller is responsible
+ * for cleaning the strings recursively.
+ * @param arg pointer to argument string
+ * @param argList target to receive the argument list
+ */
+ static int InterpreteString(const char* arg, vector<char*>& argList);
+
protected:
*/
int ExtractArguments();
- /**
- * Helper function to build a vector from an argument string
- * @param arg pointer to argument string
- * @param argList target to receive the argument list
- */
- int InterpreteString(const char* arg, vector<char*>& argList) const;
-
/**
* Convert buffer size string to number
*/
EXTRA_DIST =
-check_PROGRAMS = dtOperators \
+check_PROGRAMS = testAliHLTBlockDataCollection \
+ dtOperators \
testDefaultDataTypes
# testAliHLT_C_Component_WrapperInterface
+testAliHLTBlockDataCollection_SOURCES = testAliHLTBlockDataCollection.cxx
+testAliHLTBlockDataCollection_LDADD = $(top_builddir)/BASE/libHLTbase.la
+
dtOperators_SOURCES = dtOperators.cxx
dtOperators_LDADD = $(top_builddir)/BASE/libHLTbase.la
testDefaultDataTypes_SOURCES = testDefaultDataTypes.C
testDefaultDataTypes_LDADD = $(top_builddir)/BASE/libHLTbase.la
-TESTS = $(check_PROGRAMS)
\ No newline at end of file
+TESTS = $(check_PROGRAMS)
--- /dev/null
+// $Id$
+
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project *
+ * ALICE Experiment at CERN, All rights reserved. *
+ * *
+ * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
+ * for The ALICE HLT Project. *
+ * *
+ * Permission to use, copy, modify and distribute this software and its *
+ * documentation strictly for non-commercial purposes is hereby granted *
+ * without fee, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission notice *
+ * appear in the supporting documentation. The authors make no claims *
+ * about the suitability of this software for any purpose. It is *
+ * provided "as is" without express or implied warranty. *
+ **************************************************************************/
+
+/** @file testAliHLTBlockDataCollection.C
+ @author Matthias Richter
+ @date
+ @brief Test macro/program for the AliHLTBlockDataCollection
+ */
+
+#ifndef __CINT__
+#include <ostream>
+#include <vector>
+#include "AliHLTBlockDataCollection.h"
+#include "AliHLTComponent.h"
+#else
+#define EINVAL 22
+#define EPROTO 71
+#endif //__CINT__
+
+typedef struct init_t {
+ const char* arguments;
+ int result;
+} init_t;
+
+typedef struct select_t {
+ const char* id;
+ const char* origin;
+ UInt_t specification;
+ int result;
+} select_t;
+
+init_t gInits[]={
+ {"-datatype 'ESD_TREE' 'TPC ' ", 3},
+ {"-datatype 'ESD_TREE' 'TPC ' "
+ "-origin PHOS "
+ "-verbosity "
+ "-origin 'TRD ' "
+ "-dataspec 0xdeadbeef ", 9},
+ {"-datatype 'ESD_TREE'", -EPROTO},
+ {NULL, 0}
+};
+
+select_t gSelections[]={
+ {"ESD_TREE", "TPC ", 0, 1},
+ {"DDL_RAW ", "TPC ", 0xaffe, 0},
+ {"ESD_TREE", "TRD ", 0xaffe, 0},
+ {"ESD_TREE", "TRD ", 0xdeadbeef, 1},
+ {NULL, NULL, 0, 0}
+};
+
+int gVerbosity=0;
+
+int InitCollection(AliHLTBlockDataCollection& collection, const char* init)
+{
+ // build argument vector
+ int iResult=0;
+ char* arguments=new char[strlen(init)+1];
+ strcpy(arguments, init);
+ vector<int> positions;
+ bool bQuote=false;
+ int i=0;
+ int iStart=0;
+ for (;arguments[i]!=0; i++) {
+ if (arguments[i]=='\'') {
+ if (bQuote=!bQuote) {
+ // opening quote, set start
+ } else {
+ // closing quote, add argument
+ arguments[i]=0;
+ if (i-iStart>0) positions.push_back(iStart);
+ }
+ iStart=i+1;
+ } else if ((arguments[i]==' ' && !bQuote) ||
+ arguments[i]==0) {
+ arguments[i]=0;
+ if (i-iStart>0) positions.push_back(iStart);
+ iStart=i+1;
+ }
+ }
+ if (i-iStart>0) positions.push_back(iStart);
+
+ int argc=positions.size();
+ const char** argv=new const char*[argc];
+ for (int j=0; j<argc ; j++) {
+ argv[j]=&arguments[positions[j]];
+ }
+
+ // test argument scan
+ for (i=0; i<argc; i++) {
+ if (gVerbosity>1) cout << "scanning " << argc-i << " arguments: " << argv[i] << endl;
+ int result=collection.ScanArgument(argc-i, &argv[i]);
+ if (result>0) {
+ iResult+=result;
+ i+=result-1;
+ } else if (result<0) {
+ iResult=result;
+ break;
+ }
+ }
+
+ // cleanup
+ delete [] argv;
+ delete [] arguments;
+
+ return iResult;
+}
+
+int testAliHLTBlockDataCollection(int verbosity=0)
+{
+ gVerbosity=verbosity;
+ AliHLTBlockDataCollection collection;
+ for (int initNo=0; gInits[initNo].arguments!=NULL; initNo++) {
+ if (gVerbosity>0) cout << "checking: " << gInits[initNo].arguments << endl;
+ int result=InitCollection(collection, gInits[initNo].arguments);
+ if (result!=gInits[initNo].result) {
+ cerr << "failed: " << initNo << " (" << gInits[initNo].arguments << ") " << ": result " << result << ", expected " << gInits[initNo].result << endl;
+ return -1;
+ } else {
+ if (gVerbosity>1) cout << "init " << initNo << " (" << gInits[initNo].arguments << ") " << "succeeded: result " << result << endl;
+ }
+ }
+
+ AliHLTComponentBlockData bd;
+ AliHLTComponent::FillBlockData(bd);
+
+ for (int selectNo=0; gSelections[selectNo].id!=NULL; selectNo++) {
+ AliHLTComponent::SetDataType(bd.fDataType, gSelections[selectNo].id, gSelections[selectNo].origin );
+ bd.fSpecification=gSelections[selectNo].specification;
+ int result=collection.IsSelected(bd);
+ if (result!=gSelections[selectNo].result) {
+ cerr << "failed: block " << gSelections[selectNo].id << ":" << gSelections[selectNo].origin << " 0x" << hex << gSelections[selectNo].specification << ": result " << result << ", expected " << gSelections[selectNo].result << endl;
+ return -1;
+ } else {
+ if (gVerbosity>0) cout << "checking: block " << gSelections[selectNo].id << ":" << gSelections[selectNo].origin << " 0x" << hex << gSelections[selectNo].specification << (result==1?" selected":" not selected") << " (correctly)" << endl;
+ }
+ }
+
+ return 0;
+}
+
+int main(int /*argc*/, const char** /*argv*/)
+{
+ int iResult=0;
+ if ((iResult=testAliHLTBlockDataCollection(1))<0) {
+ cerr << "<<<<< re-run with higher verbosity >>>>>>>" << endl;
+ testAliHLTBlockDataCollection(2);
+ }
+ return iResult;
+}
-// @(#) $Id$
+// $Id$
//**************************************************************************
//* This file is property of and copyright by the ALICE HLT Project *
// -*- Mode: C++ -*-
-// @(#) $Id$
+// $Id$
#ifndef ALIHLTBLOCKFILTERCOMPONENT_H
#define ALIHLTBLOCKFILTERCOMPONENT_H
#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)
AliHLTFileWriter::AliHLTFileWriter()
:
AliHLTDataSink(),
+ fpBlockDataCollection(NULL),
fBaseName(""),
fExtension(""),
fDirectory(""),
fBlcknoFormat("_0x%02x"),
fCurrentFileName(""),
fMode(0)
+ , fpBurstBuffer(NULL)
+ , fBurstBufferSize(0)
+ , fBurstBlocks()
+ , fBurstBlockEvents()
{
// see header file for class documentation
// or
// 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
{
// 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;
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());
}
}
}
- 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 (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()) {
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;
}
int blockno=0;
for (pDesc=GetFirstInputBlock(); pDesc!=NULL; pDesc=GetNextInputBlock(), blockno++) {
- if (pDesc->fDataType==(kAliHLTAnyDataType|kAliHLTDataOriginPrivate) && !CheckMode(kWriteAllBlocks))
+ 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);
- TString filename;
- HLTDebug("dataspec 0x%x", pDesc->fSpecification);
- iResult=BuildFileName(evtData.fEventID, 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();
- }
+ iResult=ScheduleBlock(blockno, evtData.fEventID, pDesc);
}
return iResult;
}
//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;
+}
-// @(#) $Id$
+// $Id$
#ifndef ALIHLTFILEWRITER_H
#define ALIHLTFILEWRITER_H
#include "AliHLTDataSink.h"
#include <TString.h>
+class AliHLTBlockDataCollection;
+
/**
* @class AliHLTFileWriter
* An HLT data sink component which writes data to file(s).
* the beginning.
* \li -write-all <br>
* combines both -write-all-events and -write-all-blocks
+ * \li -burst-buffer <size> <br>
+ * size of burst buffer, blocks are written to buffer until it is filled
+ * and written in one burst (though to different files according to conf)<br>
+ * \b Note: burst write is currently only supported for mode
+ * -concatenate-events AND -concatenate-blocks (both enabled).
+ * \li -datatype <i> id origin </i> <br>
+ * data block selection by AliHLTBlockDataCollection
+ * \li -origin <i> origin </i> <br>
+ * data block selection by AliHLTBlockDataCollection
+ * \li -typeid <i> id </i> <br>
+ * data block selection by AliHLTBlockDataCollection
+ * \li -dataspec <i> specification </i> <br>
+ * data block selection by AliHLTBlockDataCollection
*
* <h2>Configuration:</h2>
* <!-- NOTE: ignore the \li. <i> and </i>: it's just doxygen formatting -->
kSkipDataType = 0x20
};
+ /** argument scan concerning block descriptor selections */
+ AliHLTBlockDataCollection* fpBlockDataCollection; //!transient
+
private:
/** copy constructor prohibited */
AliHLTFileWriter(const AliHLTFileWriter&);
/** assignment operator prohibited */
AliHLTFileWriter& operator=(const AliHLTFileWriter&);
+ /**
+ * Set defaults for all internal properties
+ */
+ int SetDefaults();
+
+ /**
+ * Schedule block for writing.
+ * The block is written immediately unless burst mode is activated.
+ * In burst mode, the block is buffered in the burst buffer until it is filled.
+ * Content of the burst buffer is then written in one burst.
+ *
+ * In the first implementation, burst write is only foreseen for the base
+ * file writer.
+ */
+ int ScheduleBlock(int blockno, const AliHLTEventID_t& eventID,
+ const AliHLTComponentBlockData* pDesc);
+
+ /**
+ * Flush burst buffer.
+ */
+ int BurstWrite();
+
+ /**
+ * Write data block;
+ * Build file name from the block attributes and compare with the
+ * lat file name in order to correctly append data or not.
+ */
+ int WriteBlock(int blockno, const AliHLTEventID_t& eventID,
+ const AliHLTComponentBlockData* pDesc);
+
/** the basename of the output file */
TString fBaseName; // see above
/** the extension of the output file */
/** mode specifier, see @ref TWriterMode */
Short_t fMode; // see above
- ClassDef(AliHLTFileWriter, 2)
+ /** burst buffer for postponed data write */
+ AliHLTUInt8_t* fpBurstBuffer; //!transient
+
+ /** size of burst buffer */
+ AliHLTUInt32_t fBurstBufferSize; //!transient
+
+ /** block descriptor list for postponed burst write*/
+ AliHLTComponentBlockDataList fBurstBlocks; //!transient
+
+ /** event ids for the burst blocks */
+ vector<AliHLTEventID_t> fBurstBlockEvents; //!transient
+
+ ClassDef(AliHLTFileWriter, 3)
};
#endif
# e.g. for libAliHLTUtil, MODULE=AliHLTUtil
MODULE = AliHLTUtil
+SUBDIRS = . test
+
EXTRA_DIST =
# library definition
--- /dev/null
+# $Id$
+# Makefile template for Alice HLT libAliHLTUtil test programs
+
+AM_CPPFLAGS = -I$(top_srcdir)/BASE \
+ -I$(top_srcdir)/BASE/util
+
+EXTRA_DIST =
+
+check_PROGRAMS = testAliHLTFileWriter
+
+testAliHLTFileWriter_SOURCES = testAliHLTFileWriter.C
+testAliHLTFileWriter_LDADD = $(top_builddir)/BASE/libHLTbase.la
+
+TESTS = $(check_PROGRAMS)
--- /dev/null
+// $Id$
+
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project *
+ * ALICE Experiment at CERN, All rights reserved. *
+ * *
+ * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
+ * for The ALICE HLT Project. *
+ * *
+ * Permission to use, copy, modify and distribute this software and its *
+ * documentation strictly for non-commercial purposes is hereby granted *
+ * without fee, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission notice *
+ * appear in the supporting documentation. The authors make no claims *
+ * about the suitability of this software for any purpose. It is *
+ * provided "as is" without express or implied warranty. *
+ **************************************************************************/
+
+/** @file testAliHLTFileWriter.C
+ @author Matthias Richter
+ @date
+ @brief Test macro/program for the AliHLTFileWriter
+ */
+
+#ifndef __CINT__
+#include <ostream>
+#include <vector>
+#include "AliHLTComponent.h"
+#include "AliHLTComponentHandler.h"
+#include "AliHLTConfiguration.h"
+#include "TString.h"
+#include "TFile.h"
+#include "TSystem.h"
+#else
+#define EINVAL 22
+#define EPROTO 71
+#endif //__CINT__
+
+typedef AliHLTUInt32_t TestElement_t;
+const char* testDirectory="/tmp/testAliHLTFileWriter";
+
+int SetEvent(unsigned eventNo, vector<TestElement_t>& testData)
+{
+ unsigned shift=(sizeof(TestElement_t)-1)*8;
+ AliHLTUInt32_t mask=0xf<<shift;
+ for (unsigned i=0; i<testData.size(); i++) {
+ testData[i]&=~mask;
+ testData[i]|=eventNo<<shift;
+ }
+ return 0;
+}
+
+int TestCycle(AliHLTComponent* pComponent, const char* arguments, AliHLTComponentBlockDataList blocks,
+ vector<TestElement_t>& testData, unsigned int nofEvents=1)
+{
+ int iResult=0;
+ vector<char*> argList;
+ if ((iResult=AliHLTConfiguration::InterpreteString(arguments, argList))<0) {
+ cerr << "failed: chopping arguments \"" << arguments << "\"" << endl;
+ }
+
+ // notepad for generalized unit test class
+ // - test component for outputsize==0 if no blocks are added
+
+ // init FileWriter component
+ if ((iResult=pComponent->Init(NULL, NULL, argList.size(), const_cast<const char**>(&(argList[0]))))!=0) {
+ cerr << "failed: initializing component" << endl;
+ return iResult;
+ }
+
+ // process event
+ AliHLTComponentBlockData eventTypeBlock;
+ AliHLTComponent::FillBlockData(eventTypeBlock);
+ eventTypeBlock.fDataType=kAliHLTDataTypeEvent;
+ eventTypeBlock.fSpecification=gkAliEventTypeData;
+ blocks.push_back(eventTypeBlock);
+
+ AliHLTComponentEventData evtData;
+ memset(&evtData, 0, sizeof(AliHLTComponentEventData));
+ evtData.fStructSize=sizeof(AliHLTComponentEventData);
+ evtData.fEventID=0;
+ evtData.fBlockCnt=blocks.size();
+
+ AliHLTComponentTriggerData trigData;
+ memset(&trigData, 0, sizeof(AliHLTComponentTriggerData));
+ trigData.fStructSize=sizeof(AliHLTComponentTriggerData);
+
+ AliHLTUInt32_t size=0;
+ AliHLTUInt32_t outputBlockCnt=0;
+ AliHLTComponentBlockData* outputBlocks=NULL;
+ AliHLTComponentEventDoneData* edd=NULL;
+
+ for (unsigned eventNo=0; eventNo<nofEvents; eventNo++) {
+ SetEvent(eventNo, testData);
+ evtData.fEventID=eventNo;
+ if ((iResult=pComponent->ProcessEvent(evtData, &(blocks[0]), trigData, NULL, size, outputBlockCnt, outputBlocks, edd))!=0) {
+ cerr << "failed: event processing" << endl;
+ break;
+ }
+ }
+ blocks.pop_back();
+
+ // cleanup FileWriter component
+ if ((iResult=pComponent->Deinit())!=0) {
+ cerr << "failed: deinit component" << endl;
+ }
+
+ // cleanup argument vector
+ for (vector<char*>::iterator element=argList.begin();
+ element!=argList.end(); element++) {
+ delete *element;
+ }
+ argList.clear();
+
+ return iResult;
+}
+
+int BuildFileName(unsigned eventNo, unsigned blockID,
+ const AliHLTComponentDataType& dataType,
+ const AliHLTUInt32_t /*specification*/,
+ bool bConcatenateEvents, bool bConcatenateBlocks,
+ TString& filename)
+{
+ int iResult=0;
+ filename="";
+
+ filename+=testDirectory;
+ if (!filename.EndsWith("/")) {
+ filename+="/";
+ }
+
+ filename+="event";
+ if (!bConcatenateEvents) {
+ filename+=Form("_0x%08x", eventNo);
+ }
+ if (!bConcatenateBlocks && !bConcatenateEvents) {
+ filename+=Form("_0x%02x", blockID);
+ if (dataType!=kAliHLTVoidDataType) {
+ filename+="_";
+ filename+=AliHLTComponent::DataType2Text(dataType).data();
+ }
+ //filename+=Form("", specification);
+ }
+ return iResult;
+}
+
+int CheckOutputFiles(AliHLTComponentBlockDataList blocks, vector<TestElement_t>& testData,
+ bool bConcatenateEvents, bool bConcatenateBlocks,
+ unsigned int nofEvents=1)
+{
+ int iResult=0;
+ AliHLTUInt32_t fileOffset=0;
+ TString lastFileName;
+ TFile* pFile=NULL;
+ TArrayC buffer;
+ for (unsigned eventNo=0; eventNo<nofEvents && iResult>=0; eventNo++) {
+ SetEvent(eventNo, testData);
+ for (unsigned blockNo=0; blockNo<blocks.size(); blockNo++) {
+ TString fileName;
+ BuildFileName(eventNo, blockNo, blocks[blockNo].fDataType, blocks[blockNo].fSpecification, bConcatenateEvents, bConcatenateBlocks, fileName);
+ if (pFile && !fileName.IsNull() && fileName!=lastFileName) {
+ pFile->Close();
+ delete pFile;
+ pFile=NULL;
+ fileOffset=0;
+ }
+ lastFileName=fileName;
+ fileName+="?filetype=raw";
+ if (!pFile) pFile=new TFile(fileName);
+ if (!pFile || pFile->IsZombie()) {
+ cerr << "failed: can not open file " << fileName.ReplaceAll("?filetype=raw", "") << endl;
+ iResult=-ENOENT;
+ break;
+ }
+ if (buffer.GetSize()<(int)blocks[blockNo].fSize) {
+ buffer.Set(blocks[blockNo].fSize);
+ }
+ if ((pFile->ReadBuffer((char*)buffer.GetArray(), blocks[blockNo].fSize))!=0) {
+ cerr << "failed: reading " << blocks[blockNo].fSize << " at offset " << fileOffset << " from file " << fileName.ReplaceAll("?filetype=raw", "") << endl;
+ iResult=-EIO;
+ break;
+ }
+ AliHLTUInt8_t* origin=(AliHLTUInt8_t*)blocks[blockNo].fPtr;
+ AliHLTUInt8_t* processed=(AliHLTUInt8_t*)buffer.GetArray();
+ if (memcmp(origin, processed, blocks[blockNo].fSize)!=0) {
+ cerr << "failed: data missmatch in event " << eventNo << " block " << blockNo << endl;
+ iResult=-EFAULT;
+ break;
+ }
+ cout << "checked: file " << fileName.ReplaceAll("?filetype=raw", "") << " offset " << fileOffset << endl;
+ fileOffset+=blocks[blockNo].fSize;
+ }
+ }
+ if (pFile) {
+ pFile->Close();
+ delete pFile;
+ pFile=NULL;
+ }
+ return iResult;
+}
+
+int testAliHLTFileWriter()
+{
+ int iResult=0;
+ AliHLTComponentHandler chandler;
+ if ((iResult=chandler.LoadLibrary("../.libs/libAliHLTUtil.so"))<0) {
+ cerr << "failed: loading libAliHLTUtil" << endl;
+ return iResult;
+ }
+
+ // create FileWriter component
+ AliHLTComponent* pComponent=NULL;
+ if ((iResult=chandler.CreateComponent("FileWriter", pComponent))<0) {
+ cerr << "failed: can not create component \"FileWriter\"" << endl;
+ return iResult;
+ }
+
+ AliHLTComponentBlockDataList blocks;
+ const unsigned testDataSize=500;
+ vector<TestElement_t> testData;
+ testData.assign(testDataSize, 0);
+ unsigned int i=0;
+ for (; i<testDataSize; i++) testData[i]=i;
+
+ const unsigned elementsPerBlock=100;
+ AliHLTComponentBlockData bd;
+ AliHLTComponent::FillBlockData(bd);
+ for (i=0; i*elementsPerBlock<testData.size(); i++) {
+ bd.fPtr=&(testData[i*elementsPerBlock]);
+ bd.fSize=elementsPerBlock*sizeof(TestElement_t);
+ bd.fSpecification=i;
+ AliHLTComponent::SetDataType(bd.fDataType, "DUMMYDAT", "TEST");
+ blocks.push_back(bd);
+ }
+
+ const char* testArguments[]={
+ "",
+ "-concatenate-blocks ",
+ "-concatenate-blocks -concatenate-events ",
+ // not currently working "-burst-buffer 10000 ",
+ // not currently working "-burst-buffer 5000 ",
+ // not currently working "-burst-buffer 10000 -concatenate-blocks ",
+ "-burst-buffer 10000 -concatenate-blocks -concatenate-events ",
+ "-burst-buffer 5000 -concatenate-blocks -concatenate-events ",
+ NULL
+ };
+
+ for (const char** currentTest=testArguments; *currentTest!=NULL; currentTest++) {
+ TString arguments=*currentTest;
+ arguments+=" -directory "; arguments+=testDirectory;
+ if (!gSystem->AccessPathName(testDirectory)) {
+ TString command="rm -r "; command+=testDirectory;
+ gSystem->Exec(command);
+ }
+ cout << arguments.Data() << endl;
+ if ((iResult=TestCycle(pComponent, arguments.Data(), blocks, testData, 4))<0) {
+ break;
+ }
+ if ((iResult=CheckOutputFiles(blocks, testData, arguments.Contains("-concatenate-events "), arguments.Contains("-concatenate-blocks"), 4))<0) {
+ break;
+ }
+ };
+
+ delete pComponent;
+
+ return iResult;
+}
+
+int main(int /*argc*/, const char** /*argv*/)
+{
+ int iResult=0;
+ if ((iResult=testAliHLTFileWriter())<0) {
+ }
+ return iResult;
+}
BASE/setenv.csh
BASE/HOMER/Makefile
BASE/util/Makefile
+ BASE/util/test/Makefile
BASE/interface/Makefile
BASE/test/Makefile
BASE/interface/test/Makefile
AliHLTMemoryFile.h \
AliHLTMessage.h \
AliHLTEventStatistics.h \
+ AliHLTBlockDataCollection.h \
AliHLTRunStatistics.h