// $Id$ //************************************************************************** //* This file is property of and copyright by the ALICE HLT Project * //* ALICE Experiment at CERN, All rights reserved. * //* * //* Primary Authors: Matthias Richter * //* 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 AliHLTOUT.cxx @author Matthias Richter @date @brief The control class for HLTOUT data. */ #include #include #include "AliHLTOUT.h" #include "TSystem.h" #include "TClass.h" #include "TROOT.h" /** ROOT macro for the implementation of ROOT specific class methods */ ClassImp(AliHLTOUT) AliHLTOUT::AliHLTOUT() : fSearchDataType(kAliHLTVoidDataType), fSearchSpecification(kAliHLTVoidDataSpec), fSearchHandlerType(AliHLTModuleAgent::kUnknownOutput), fFlags(kSkipProcessed), fBlockDescList(), fCurrent(0), fpBuffer(NULL), fDataHandlers(), fbVerbose(true) { // see header file for class documentation // or // refer to README to build package // or // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt } AliHLTOUT::~AliHLTOUT() { // see header file for class documentation if (CheckStatusFlag(kIsSubCollection)) { HLTWarning("severe internal error: collection has not been released, potential crash due to invalid pointer"); } } int AliHLTOUT::Init() { // see header file for class documentation int iResult=0; SetStatusFlag(kCollecting); if ((iResult=GenerateIndex())>=0) { if ((iResult=InitHandlers())>=0) { } } ClearStatusFlag(kCollecting); return iResult; } int AliHLTOUT::GetNofDataBlocks() { // see header file for class documentation return fBlockDescList.size(); } int AliHLTOUT::SelectFirstDataBlock(AliHLTComponentDataType dt, AliHLTUInt32_t spec, AliHLTModuleAgent::AliHLTOUTHandlerType handlerType, bool skipProcessed) { // see header file for class documentation fCurrent=0; fSearchDataType=dt; fSearchSpecification=spec; fSearchHandlerType=handlerType; if (skipProcessed) SetStatusFlag(kSkipProcessed); else ClearStatusFlag(kSkipProcessed); return FindAndSelectDataBlock(); } int AliHLTOUT::SelectNextDataBlock() { // see header file for class documentation if (fCurrent>=fBlockDescList.size()) return -ENOENT; fCurrent++; return FindAndSelectDataBlock(); } int AliHLTOUT::FindAndSelectDataBlock() { // see header file for class documentation if (CheckStatusFlag(kLocked)) return -EPERM; int iResult=-ENOENT; while (fCurrent=fBlockDescList.size()) return AliHLTOUTInvalidIndex; return fBlockDescList[fCurrent].GetIndex(); } int AliHLTOUT::GetDataBuffer(const AliHLTUInt8_t* &pBuffer, AliHLTUInt32_t& size) { // see header file for class documentation int iResult=-ENOENT; pBuffer=NULL; size=0; if (fCurrent=0) { fpBuffer=pBuffer; } } return iResult; } int AliHLTOUT::ReleaseDataBuffer(const AliHLTUInt8_t* pBuffer) { // see header file for class documentation int iResult=0; if (pBuffer==fpBuffer) { fpBuffer=NULL; } else { HLTWarning("buffer %p does not match the provided one %p", pBuffer, fpBuffer); } return iResult; } AliHLTModuleAgent* AliHLTOUT::GetAgent() { // see header file for class documentation AliHLTModuleAgent* pAgent=NULL; pAgent=FindHandlerDesc(GetDataBlockIndex()); return pAgent; } AliHLTOUTHandler* AliHLTOUT::GetHandler() { // see header file for class documentation AliHLTOUTHandler* pHandler=NULL; pHandler=FindHandlerDesc(GetDataBlockIndex()); return pHandler; } int AliHLTOUT::WriteESD(const AliHLTUInt8_t* /*pBuffer*/, AliHLTUInt32_t /*size*/, AliHLTComponentDataType /*dt*/, AliESDEvent* /*tgtesd*/) const { // see header file for class documentation HLTWarning("method not implemented in base class"); return -ENOSYS; } int AliHLTOUT::AddBlockDescriptor(const AliHLTOUTBlockDescriptor desc) { // see header file for class documentation if (!CheckStatusFlag(kCollecting)) return -EPERM; int iResult=0; fBlockDescList.push_back(desc); return iResult; } AliHLTOUT::AliHLTOUTByteOrder AliHLTOUT::CheckByteOrder() { // see header file for class documentation if (fCurrent=0; havedata=SelectNextDataBlock()) { iCount++; remnants.push_back(GetDataBlockIndex()); AliHLTComponentDataType dt=kAliHLTVoidDataType; AliHLTUInt32_t spec=kAliHLTVoidDataSpec; if (GetDataBlockDescription(dt, spec)<0) break; bool bHaveHandler=false; for (AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent(); pAgent && iResult>=0; pAgent=AliHLTModuleAgent::GetNextAgent()) { AliHLTModuleAgent::AliHLTOUTHandlerDesc handlerDesc; if (pAgent->GetHandlerDescription(dt, spec, handlerDesc)>0) { AliHLTOUTHandlerListEntry entry(pAgent->GetOutputHandler(dt, spec), handlerDesc, pAgent, GetDataBlockIndex()); InsertHandler(fDataHandlers, entry); remnants.pop_back(); bHaveHandler=true; break; } } if (!bHaveHandler && (dt==kAliHLTDataTypeESDObject || dt==kAliHLTDataTypeESDTree)) { // ESDs are handled by the framework remnants.pop_back(); } } // warning if some of the data blocks are not selected by the kAliHLTAnyDataType // criterion if (GetNofDataBlocks()>iCount) { HLTWarning("incomplete data type in %d out of %d data block(s)", GetNofDataBlocks()-iCount, iCount); } // warning if handler not found if (remnants.size()>0) { HLTWarning("no handlers found for %d data blocks out of %d", remnants.size(), iCount); AliHLTOUTBlockDescriptorVector::iterator block=fBlockDescList.begin(); for (AliHLTOUTIndexList::iterator element=remnants.begin(); element!=remnants.end(); element++) { for (int trials=0; trials<2; trials++) { do { // we start searching the index from the current position in the block list if ((*block).GetIndex()==*element) break; } while ((++block)!=fBlockDescList.end()); if (block==fBlockDescList.end()) { // rewind and try again block=fBlockDescList.begin(); } } assert(block!=fBlockDescList.end()); if (block!=fBlockDescList.end()) { HLTDebug(" %s", AliHLTComponent::DataType2Text((AliHLTComponentDataType)*block).c_str()); } } } return iResult; } int AliHLTOUT::InsertHandler(AliHLTOUTHandlerListEntryVector& list, const AliHLTOUTHandlerListEntry &entry) { // see header file for class documentation int iResult=0; AliHLTOUTHandlerListEntryVector::iterator element=list.begin(); while (element!=list.end()) { if (entry==(*element)) break; element++; } if (element==list.end()) { list.push_back(entry); } else { element->AddIndex(const_cast(entry)); } return iResult; } const AliHLTOUT::AliHLTOUTHandlerListEntry& AliHLTOUT::FindHandlerDesc(AliHLTUInt32_t blockIndex) { // see header file for class documentation AliHLTOUTHandlerListEntryVector::iterator element=fDataHandlers.begin(); while (element!=fDataHandlers.end()) { if (element->HasIndex(blockIndex)) { return *element; } element++; } return const_cast(AliHLTOUT::AliHLTOUTHandlerListEntry::fgkVoidHandlerListEntry); } AliHLTOUT::AliHLTOUTHandlerListEntry::AliHLTOUTHandlerListEntry() : fpHandler(NULL), fpHandlerDesc(NULL), fpAgent(NULL), fBlocks() { // see header file for class documentation } AliHLTOUT::AliHLTOUTHandlerListEntry::AliHLTOUTHandlerListEntry(AliHLTOUTHandler* pHandler, AliHLTModuleAgent::AliHLTOUTHandlerDesc& handlerDesc, AliHLTModuleAgent* pAgent, AliHLTUInt32_t index) : fpHandler(pHandler), fpHandlerDesc(new AliHLTModuleAgent::AliHLTOUTHandlerDesc), fpAgent(pAgent), fBlocks() { // see header file for class documentation *fpHandlerDesc=handlerDesc; fBlocks.push_back(index); } AliHLTOUT::AliHLTOUTHandlerListEntry::AliHLTOUTHandlerListEntry(const AliHLTOUTHandlerListEntry& src) : fpHandler(src.fpHandler), fpHandlerDesc(new AliHLTModuleAgent::AliHLTOUTHandlerDesc), fpAgent(src.fpAgent), fBlocks() { // see header file for class documentation *fpHandlerDesc=*src.fpHandlerDesc; fBlocks.assign(src.fBlocks.begin(), src.fBlocks.end()); } AliHLTOUT::AliHLTOUTHandlerListEntry::~AliHLTOUTHandlerListEntry() { // see header file for class documentation if (fpHandlerDesc) delete fpHandlerDesc; fpHandlerDesc=NULL; } AliHLTOUT::AliHLTOUTHandlerListEntry& AliHLTOUT::AliHLTOUTHandlerListEntry::operator=(const AliHLTOUTHandlerListEntry& src) { // see header file for class documentation fpHandler=src.fpHandler; if (src.fpHandlerDesc) *fpHandlerDesc=*src.fpHandlerDesc; fpAgent=src.fpAgent; fBlocks.assign(src.fBlocks.begin(), src.fBlocks.end()); return *this; } AliHLTUInt32_t AliHLTOUT::AliHLTOUTHandlerListEntry::operator[](int i) const { // see header file for class documentation return (int)fBlocks.size()>i?fBlocks[i]:AliHLTOUTInvalidIndex; } bool AliHLTOUT::AliHLTOUTHandlerListEntry::operator==(const AliHLTOUTHandlerListEntry& entry) const { // see header file for class documentation if (entry.fpHandler!=fpHandler || fpHandler==NULL) return false; assert(entry.fpAgent==fpAgent); if (entry.fpAgent!=fpAgent) return false; return true; } bool AliHLTOUT::AliHLTOUTHandlerListEntry::operator==(const AliHLTModuleAgent::AliHLTOUTHandlerType handlerType) const { // see header file for class documentation if (!fpHandlerDesc) return false; return *fpHandlerDesc==handlerType; } void AliHLTOUT::AliHLTOUTHandlerListEntry::AddIndex(AliHLTOUT::AliHLTOUTHandlerListEntry &desc) { // see header file for class documentation AliHLTOUTIndexList::iterator element; for (element=desc.fBlocks.begin(); element!=desc.fBlocks.end(); element++) { AddIndex(*element); } } void AliHLTOUT::AliHLTOUTHandlerListEntry::AddIndex(AliHLTUInt32_t index) { // see header file for class documentation fBlocks.push_back(index); } bool AliHLTOUT::AliHLTOUTHandlerListEntry::HasIndex(AliHLTUInt32_t index) const { // see header file for class documentation AliHLTOUTIndexList::iterator element; for (unsigned int i=0; i> 8) | ((src & 0xFF0000000000ULL) >> 24) | ((src & 0xFF000000000000ULL) >> 40) | ((src & 0xFF00000000000000ULL) >> 56); } AliHLTUInt32_t AliHLTOUT::ByteSwap32(AliHLTUInt32_t src) { // see header file for class documentation return ((src & 0xFFULL) << 24) | ((src & 0xFF00ULL) << 8) | ((src & 0xFF0000ULL) >> 8) | ((src & 0xFF000000ULL) >> 24); } AliHLTOUT* AliHLTOUT::New(AliRawReader* pRawReader) { // see header file for class documentation AliHLTOUT* instance=New("AliHLTOUTRawReader"); if (instance) { instance->SetParam(pRawReader); } return instance; } AliHLTOUT* AliHLTOUT::New(TTree* pDigitTree, int event) { // see header file for class documentation AliHLTOUT* instance=New("AliHLTOUTDigitReader"); if (instance) { instance->SetParam(pDigitTree, event); } return instance; } AliHLTOUT* AliHLTOUT::New(const char* classname) { // see header file for class documentation int iLibResult=0; AliHLTOUT* instance=NULL; AliHLTLogging log; TClass* pCl=NULL; ROOT::NewFunc_t pNewFunc=NULL; do { pCl=TClass::GetClass(classname); } while (!pCl && (iLibResult=gSystem->Load("libHLTRec.so"))==0); if (iLibResult>=0) { if (pCl && (pNewFunc=pCl->GetNew())!=NULL) { void* p=(*pNewFunc)(NULL); if (p) { instance=reinterpret_cast(p); if (!instance) { log.Logging(kHLTLogError, "AliHLTOUT::New", "HLTOUT handling", "type cast to AliHLTOUT instance failed"); } } else { log.Logging(kHLTLogError, "AliHLTOUT::New", "HLTOUT handling", "can not create AliHLTOUT instance from class descriptor"); } } else { log.Logging(kHLTLogError, "AliHLTOUT::New", "HLTOUT handling", "can not find AliHLTOUT class descriptor"); } } else { log.Logging(kHLTLogError, "AliHLTOUT::New", "HLTOUT handling", "can not load libHLTrec library"); } return instance; } void AliHLTOUT::Delete(AliHLTOUT* pInstance) { // see header file for class documentation if (!pInstance) return; // check if the library is still there in order to have the // destructor available TClass* pCl1=TClass::GetClass("AliHLTOUTRawReader"); TClass* pCl2=TClass::GetClass("AliHLTOUTDigitReader"); if (!pCl1 && !pCl2) { AliHLTLogging log; log.Logging(kHLTLogError, "AliHLTOUT::Delete", "HLTOUT handling", "potential memory leak: libHLTrec library not available, skipping destruction %p", pInstance); return; } delete pInstance; } void AliHLTOUT::SetParam(AliRawReader* /*pRawReader*/) { // see header file for class documentation // default implementation, we should never get here // this function can only be called from the class itsself and // is intended to be used with the New functions. If we get into // the default implementation there is a class mismatch. assert(0); HLTFatal("severe internal error: class mismatch"); } void AliHLTOUT::SetParam(TTree* /*pDigitTree*/, int /*event*/) { // see header file for class documentation // default implementation, we should never get here // this function can only be called from the class itsself and // is intended to be used with the New functions. If we get into // the default implementation there is a class mismatch. assert(0); HLTFatal("severe internal error: class mismatch"); } int AliHLTOUT::SelectDataBlock() { // see header file for class documentation int iResult=0; if (fCurrent>=fBlockDescList.size()) return 0; fBlockDescList[fCurrent].Select(true); EnableBlockSelection(); return iResult; } int AliHLTOUT::SelectDataBlocks(const AliHLTOUTHandlerListEntry* pHandlerDesc) { // see header file for class documentation int iResult=0; if (!pHandlerDesc) return 0; AliHLTOUTBlockDescriptorVector::iterator element; for (AliHLTOUTBlockDescriptorVector::iterator block=fBlockDescList.begin(); block!=fBlockDescList.end(); block++) { if (pHandlerDesc->HasIndex(block->GetIndex())) block->Select(true); else block->Select(false); } EnableBlockSelection(); return iResult; } int AliHLTOUT::EnableBlockSelection() { // see header file for class documentation SetStatusFlag(kBlockSelection); return 0; } int AliHLTOUT::DisableBlockSelection() { // see header file for class documentation ClearStatusFlag(kBlockSelection); return 0; } int AliHLTOUT::ResetBlockSelection() { // see header file for class documentation for (AliHLTOUTBlockDescriptorVector::iterator block=fBlockDescList.begin(); block!=fBlockDescList.end(); block++) { block->Select(false); } return 0; } int AliHLTOUT::MarkDataBlockProcessed() { // see header file for class documentation int iResult=0; if (fCurrent>=fBlockDescList.size()) return 0; fBlockDescList[fCurrent].MarkProcessed(); return iResult; } int AliHLTOUT::MarkDataBlocksProcessed(const AliHLTOUTHandlerListEntry* pHandlerDesc) { // see header file for class documentation int iResult=0; if (!pHandlerDesc) return 0; AliHLTOUTBlockDescriptorVector::iterator element; for (AliHLTOUTBlockDescriptorVector::iterator block=fBlockDescList.begin(); block!=fBlockDescList.end(); block++) { if (pHandlerDesc->HasIndex(block->GetIndex())) block->MarkProcessed(); } return iResult; } int AliHLTOUT::AddSubCollection(AliHLTOUT* pCollection) { // see header file for class documentation int iResult=0; if (!pCollection) return 0; int index=-1; for (index=pCollection->SelectFirstDataBlock(); index>=0; index=pCollection->SelectNextDataBlock()) { AliHLTComponentDataType dt=kAliHLTVoidDataType; AliHLTUInt32_t spec=kAliHLTVoidDataSpec; pCollection->GetDataBlockDescription(dt, spec); AliHLTOUTBlockDescriptor desc(dt, spec, index, pCollection); AddBlockDescriptor(desc); iResult++; } if (iResult>0) { pCollection->SetStatusFlag(kIsSubCollection); } return iResult; } int AliHLTOUT::ReleaseSubCollection(AliHLTOUT* pCollection) { // see header file for class documentation int iResult=0; if (!pCollection) return 0; AliHLTOUTBlockDescriptorVector::iterator element; for (AliHLTOUTBlockDescriptorVector::iterator block=fBlockDescList.begin(); block!=fBlockDescList.end(); block++) { if ((*block)==pCollection) { element=fBlockDescList.erase(element); } } return iResult; }