#include "AliHLTTPCEsdWriterComponent.h"
#include "AliESDEvent.h"
#include "AliESDtrack.h"
+#include "AliCDBEntry.h"
+#include "AliCDBManager.h"
#include "TTree.h"
#include "TList.h"
#include "AliHLTTPCTrack.h"
ClassImp(AliHLTTPCEsdWriterComponent)
AliHLTTPCEsdWriterComponent::AliHLTTPCEsdWriterComponent()
+ :
+ fSolenoidBz(0)
{
// see header file for class documentation
// or
if (fTree==NULL) {
iResult=-ENOMEM;
}
+
+ if (iResult>=0) {
+ iResult=fBase->Reconfigure(NULL, NULL);
+ }
+
return iResult;
}
// see header file for class documentation
int iResult=0;
if (pESD && blocks) {
+ pESD->SetMagneticField(fSolenoidBz);
const AliHLTComponentBlockData* iter = NULL;
AliHLTTPCTrackletData* inPtr=NULL;
int bIsTrackSegs=0;
return iResult;
}
+int AliHLTTPCEsdWriterComponent::Configure(const char* arguments)
+{
+ // see header file for class documentation
+ int iResult=0;
+ if (!arguments) return iResult;
+
+ TString allArgs=arguments;
+ TString argument;
+ int bMissingParam=0;
+
+ TObjArray* pTokens=allArgs.Tokenize(" ");
+ if (pTokens) {
+ for (int i=0; i<pTokens->GetEntries() && iResult>=0; i++) {
+ argument=((TObjString*)pTokens->At(i))->GetString();
+ if (argument.IsNull()) continue;
+
+ if (argument.CompareTo("-solenoidBz")==0) {
+ if ((bMissingParam=(++i>=pTokens->GetEntries()))) break;
+ HLTInfo("Magnetic Field set to: %s", ((TObjString*)pTokens->At(i))->GetString().Data());
+ fSolenoidBz=((TObjString*)pTokens->At(i))->GetString().Atof();
+ continue;
+ } else {
+ HLTError("unknown argument %s", argument.Data());
+ iResult=-EINVAL;
+ break;
+ }
+ }
+ delete pTokens;
+ }
+ if (bMissingParam) {
+ HLTError("missing parameter for argument %s", argument.Data());
+ iResult=-EINVAL;
+ }
+
+ return iResult;
+}
+
+int AliHLTTPCEsdWriterComponent::Reconfigure(const char* cdbEntry, const char* chainId)
+{
+ // see header file for class documentation
+ int iResult=0;
+ const char* path="HLT/ConfigHLT/SolenoidBz";
+ const char* defaultNotify="";
+ if (cdbEntry) {
+ path=cdbEntry;
+ defaultNotify=" (default)";
+ }
+ if (path) {
+ HLTInfo("reconfigure from entry %s%s, chain id %s", path, defaultNotify,(chainId!=NULL && chainId[0]!=0)?chainId:"<none>");
+ AliCDBEntry *pEntry = AliCDBManager::Instance()->Get(path/*,GetRunNo()*/);
+ if (pEntry) {
+ TObjString* pString=dynamic_cast<TObjString*>(pEntry->GetObject());
+ if (pString) {
+ HLTInfo("received configuration object string: \'%s\'", pString->GetString().Data());
+ iResult=Configure(pString->GetString().Data());
+ } else {
+ HLTError("configuration object \"%s\" has wrong type, required TObjString", path);
+ }
+ } else {
+ HLTError("can not fetch object \"%s\" from CDB", path);
+ }
+ }
+
+ return iResult;
+}
+
AliHLTTPCEsdWriterComponent::AliConverter::AliConverter()
:
fBase(new AliHLTTPCEsdWriterComponent),
iResult=-EINVAL;
}
+ if (iResult>=0) {
+ iResult=fBase->Reconfigure(NULL, NULL);
+ }
+
return iResult;
}
#include "TClass.h"
#include "TObject.h"
#include "TObjectTable.h"
+#include "TSystem.h"
+#include "TChain.h"
+#include "TList.h"
/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTEsdManager)
AliHLTEsdManager::AliHLTEsdManager()
:
- fESDs()
+ fESDs(),
+ fDirectory()
{
// see header file for class documentation
// or
AliHLTEsdListEntry* entry=Find(dt);
if (!entry) {
AliHLTEsdListEntry* newEntry=new AliHLTEsdListEntry(dt);
+ if (!fDirectory.IsNull()) {
+ newEntry->SetDirectory(fDirectory);
+ }
fESDs.push_back(newEntry);
}
if (tgtesd) {
- }
+ TTree* pTmpTree=AliHLTEsdManager::EmbedIntoTree(pESD);
+ if (pTmpTree) {
+ tgtesd->ReadFromTree(pTmpTree);
+ pTmpTree->GetEvent(0);
+ pTmpTree->GetUserInfo()->Clear();
+ delete pTmpTree;
+ HLTDebug("data block %s written to target ESD", AliHLTComponent::DataType2Text(dt).c_str());
+ } else {
+ iResult=-ENOMEM;
+ }
+ } else {
entry=Find(dt);
if (entry) {
entry->WriteESD(pESD, eventno);
HLTError("internal mismatch, can not create list entry");
iResult=-ENOMEM;
}
+ }
} else {
HLTWarning("data block %s is not of class type AliESDEvent, ignoring ...", AliHLTComponent::DataType2Text(dt).c_str());
}
return iResult;
}
-AliHLTEsdManager::AliHLTEsdListEntry::AliHLTEsdListEntry(AliHLTComponentDataType dt)
- :
- fName(),
- fpFile(NULL),
- fpTree(NULL),
- fpEsd(NULL),
- fDt(dt)
+int AliHLTEsdManager::PadESDs(int eventno)
{
// see header file for class documentation
+ int iResult=0;
+ for (unsigned int i=0; i<fESDs.size(); i++) {
+ if (fESDs[i]) {
+ int res=fESDs[i]->WriteESD(NULL, eventno);
+ if (res<0 && iResult>=0) iResult=res;
+ }
+ }
+ return iResult;
}
-AliHLTEsdManager::AliHLTEsdListEntry::~AliHLTEsdListEntry()
+void AliHLTEsdManager::SetDirectory(const char* directory)
{
// see header file for class documentation
- if (fpTree) {
- fpTree->GetUserInfo()->Clear();
- delete fpTree;
- fpTree=NULL;
+ if (!directory) return;
+ fDirectory=directory;
+ for (unsigned int i=0; i<fESDs.size(); i++) {
+ if (fESDs[i]) {
+ fESDs[i]->SetDirectory(directory);
+ }
+ }
+}
+
+TString AliHLTEsdManager::GetFileNames(AliHLTComponentDataType dt) const
+{
+ TString result;
+ for (unsigned int i=0; i<fESDs.size(); i++) {
+ if (fESDs[i] && *(fESDs[i])==dt) {
+ if (!result.IsNull()) result+=" ";
+ result+=fESDs[i]->GetFileName();
+ }
}
+ return result;
+}
- // due to the Root garbage collection the ESD object might already be
- // deleted since the pTree->GetUserInfo()->Add(pESD) adds the ESD object to
- // an internal list which is cleaned when the tree is deleted
- if (fpEsd && gObjectTable->PtrIsValid(fpEsd)) {
- delete fpEsd;
+TTree* AliHLTEsdManager::EmbedIntoTree(AliESDEvent* pESD, const char* name, const char* title)
+{
+ // see header file for class documentation
+ int iResult=0;
+ TTree* pTree=new TTree(name, title);
+ if (pTree) {
+ pESD->WriteToTree(pTree);
+ pTree->Fill();
+ pTree->GetUserInfo()->Add(pESD);
+ } else {
+ iResult=-ENOMEM;
}
- fpEsd=NULL;
- if (fpFile) {
- fpFile->Close();
- delete fpFile;
- fpFile=NULL;
+ if (iResult<0) {
+ pTree->GetUserInfo()->Clear();
+ delete pTree;
}
+
+ return pTree;
+}
+
+AliHLTEsdManager::AliHLTEsdListEntry::AliHLTEsdListEntry(AliHLTComponentDataType dt)
+ :
+ fName(),
+ fDirectory(),
+ fDt(dt)
+{
+ // see header file for class documentation
+}
+
+AliHLTEsdManager::AliHLTEsdListEntry::~AliHLTEsdListEntry()
+{
+ // see header file for class documentation
}
bool AliHLTEsdManager::AliHLTEsdListEntry::operator==(AliHLTComponentDataType dt) const
return fDt==dt;
}
-int AliHLTEsdManager::AliHLTEsdListEntry::WriteESD(AliESDEvent* pESD, int eventno)
+int AliHLTEsdManager::AliHLTEsdListEntry::WriteESD(AliESDEvent* pSrcESD, int eventno)
{
- // see header file for class documentation
- if (!pESD) return -EINVAL;
+ // we need to copy the ESD, I did not find an approptiate
+ // method, the workaround is to save the ESD in a temporary
+ // tree, read the content back into the ESD structure
+ // used for filling.
+ // Unfortunately the following code crashes at the second event.
+ // The expert on the ESD (Christian Klein Boesig) does not have
+ // a solution either. It seems to be a problem in ROOT.
+ // TTree* dummy=new TTree("dummy","dummy");
+ // dummy->SetDirectory(0);
+ // pESD->WriteToTree(dummy);
+ // dummy->Fill();
+ // dummy->GetUserInfo()->Add(pESD);
+ // fpEsd->ReadFromTree(dummy);
+ // dummy->GetEvent(0);
+ // fpEsd->WriteToTree(fpTree);
+ // fpTree->Fill();
+ // dummy->GetUserInfo()->Clear();
+ // delete dummy;
+ //
+ // The only way is via TChain, which is working on files only at the
+ // time of writing.
+ // We use temporary files for the new event to be copied into the
+ // existing tree.
+ //
int iResult=0;
- if (!fpFile) {
+ if (fName.IsNull()) {
+ // this is the first event, create the file on disk and write ESD
TString origin;
origin.Insert(0, fDt.fOrigin, kAliHLTComponentDataTypefOriginSize);
origin.Remove(TString::kTrailing, ' ');
origin.ToUpper();
- fName="AliHLT"; fName+=origin;
+ fName="";
+ if (!fDirectory.IsNull()) {
+ fName+=fDirectory; fName+="/";
+ }
+ fName+="AliHLT"; fName+=origin;
if (fDt!=kAliHLTDataTypeESDObject &&
fDt!=kAliHLTDataTypeESDTree) {
fName+="_"; fName+=id; fName+=".root";
} else {
fName+="ESDs.root";
- fpFile=new TFile(fName, "RECREATE");
+ }
+
+ if (!gSystem->AccessPathName(fName)) {
+ // file exists, delete
+ TString shellcmd="rm -f ";
+ shellcmd+=fName;
+ gSystem->Exec(shellcmd);
}
}
- if (fpFile && !fpFile->IsZombie() && iResult>=0) {
- if (!fpTree) {
- fpTree=new TTree("esdTree", "Tree with HLT ESD objects");
- if (!fpTree) {
- iResult=-ENOMEM;
- } else {
- fpTree->SetDirectory(0);
+
+ TChain chain("esdTree");
+ TList cleanup;
+ cleanup.SetOwner();
+
+ int nofCurrentEvents=0;
+ if (iResult>=0) {
+ if (!gSystem->AccessPathName(fName)) {
+ // these are the other events, use the target file and temporary files to merge
+ // with TChain
+ chain.Add(fName);
+
+ if (eventno>=0) {
+ TFile file(fName);
+ if (!file.IsZombie()) {
+ TTree* pSrcTree;
+ file.GetObject("esdTree", pSrcTree);
+ if (pSrcTree) {
+ nofCurrentEvents=pSrcTree->GetEntries();
+ }
+ file.Close();
+ }
}
}
- if (fpTree && iResult>=0) {
- if (!fpEsd) {
- // create the ESD structure for filling into the tree
- fpEsd=new AliESDEvent;
- if (fpEsd) {
- fpEsd->CreateStdContent();
- fpTree->GetUserInfo()->Add(fpEsd);
- } else {
- iResult=-ENOMEM;
+ }
+
+ // synchronize and add empty events
+ if (nofCurrentEvents<eventno) {
+ iResult=1; // indicate files to merge
+ TTree* pTgtTree=new TTree("esdTree", "Tree with HLT ESD objects");
+ if (pTgtTree) {
+ pTgtTree->SetDirectory(0);
+ AliESDEvent* pTmpESD=new AliESDEvent;
+ if (pTmpESD) {
+ TString tmpfilename;
+ FILE* pTmpFile=gSystem->TempFileName(tmpfilename);
+ if (pTmpFile) {
+ fclose(pTmpFile);
+ pTmpFile=NULL;
+ cleanup.Add(new TObjString(tmpfilename));
+ TFile emptyevents(tmpfilename, "RECREATE");
+ if (!emptyevents.IsZombie()) {
+ pTmpESD->CreateStdContent();
+ pTmpESD->WriteToTree(pTgtTree);
+ HLTDebug("adding %d empty events to file %s", eventno-nofCurrentEvents, fName.Data());
+ for (int i=nofCurrentEvents; i<eventno; i++) {
+ pTgtTree->Fill();
+ }
+ pTgtTree->GetUserInfo()->Add(pTmpESD);
+ emptyevents.cd();
+ pTgtTree->Write();
+ emptyevents.Close();
+ chain.Add(tmpfilename);
+ pTgtTree->GetUserInfo()->Clear();
+ }
}
+ delete pTmpESD;
} else {
- fpEsd->ResetStdContent();
+ iResult=-ENOMEM;
}
- if (eventno>=0) {
- // synchronize and add empty events
- for (int i=fpTree->GetEntries(); i<eventno; i++) {
- fpTree->Fill();
- }
- if (fpTree->GetEntries()>eventno) {
- HLTWarning("event %d ESD of type %s already written, skipping additional data block", eventno, AliHLTComponent::DataType2Text(fDt).c_str());
- }
+ delete pTgtTree;
+ } else {
+ iResult=-ENOMEM;
+ }
+ }
+
+ if (iResult>=0 && pSrcESD) {
+ // add the new event to the chain
+ iResult=1; // indicate files to merge
+ TString tmpfilename=WriteTempFile(pSrcESD);
+ if (!tmpfilename.IsNull()) {
+ chain.Add(tmpfilename);
+ cleanup.Add(new TObjString(tmpfilename));
+ }
+ }
+
+ if (iResult>0) {
+ // build temporary file name for chain output
+ TString tgtName;
+ FILE* pTmpFile=gSystem->TempFileName(tgtName);
+ if (pTmpFile) {
+ fclose(pTmpFile);
+ pTmpFile=NULL;
+
+ chain.Merge(tgtName);
+ // rename the merged file to the original file
+ TString shellcmd="mv ";
+ shellcmd+=tgtName + " " + fName;
+ if (gSystem->Exec(shellcmd)==0) {
+ HLTDebug("renaming %s to %s", tgtName.Data(), fName.Data());
+ } else {
+ HLTError("can not rename temporary file %s to %s", tgtName.Data(), fName.Data());
}
- if (fpEsd) {
- // we need to copy the ESD, I did not find an approptiate
- // method, the workaround is to save the ESD in a temporary
- // tree, read the content back into the ESD structure
- // used for filling
- TTree* dummy=new TTree("dummy","dummy");
- if (dummy) {
- /*
- dummy->SetDirectory(0);
- pESD->WriteToTree(dummy);
- dummy->Fill();
- dummy->GetUserInfo()->Add(pESD);
- fpEsd->ReadFromTree(dummy);
- dummy->GetEvent(0);
- */
- fpEsd->WriteToTree(fpTree);
- fpTree->Fill();
- dummy->GetUserInfo()->Clear();
- delete dummy;
+ } else {
+ HLTError("can not get temporary file name from system");
+ iResult=-EBADF;
+ }
+ }
+
+ // delete temporary files
+ // the list objects are cleaned up be the TList destructor as the
+ // list is owner
+ TIter entry(&cleanup);
+ while (TObject* pObj=entry.Next()) {
+ if (dynamic_cast<TObjString*>(pObj)) {
+ TString shellcmd="rm -f ";
+ shellcmd+=(dynamic_cast<TObjString*>(pObj))->GetString();
+ gSystem->Exec(shellcmd);
+ }
+ }
+
+ return iResult;
+}
+
+TString AliHLTEsdManager::AliHLTEsdListEntry::WriteTempFile(AliESDEvent* pESD) const
+{
+ // see header file for class documentation
+ int iResult;
+ TString tmpfilename;
+ FILE* pTmpFile=gSystem->TempFileName(tmpfilename);
+ if (pTmpFile) {
+ fclose(pTmpFile);
+ pTmpFile=NULL;
+
+ TFile file(tmpfilename, "RECREATE");
+ if (!file.IsZombie()) {
+ TTree* pTree=AliHLTEsdManager::EmbedIntoTree(pESD);
+ if (pTree) {
+ file.cd();
+ if (pTree->Write()>0) {
} else {
- iResult=-ENOMEM;
+ HLTError("can not write esd tree to temporary file %s", tmpfilename.Data());
}
+
+ pTree->GetUserInfo()->Clear();
+ delete pTree;
} else {
iResult=-ENOMEM;
}
- if (iResult>=0) {
- fpTree->Write("",TObject::kOverwrite);
- }
+ file.Close();
+ } else {
+ HLTError("can not open file %s", tmpfilename.Data());
}
+ } else {
+ HLTError("can not get temporary file name from system");
+ iResult=-EBADF;
}
- return iResult;
+
+ if (iResult<0) {
+ if (gSystem->AccessPathName(tmpfilename)==0) {
+ TString shellcmd="rm -f ";
+ shellcmd+=tmpfilename;
+ gSystem->Exec(shellcmd);
+ }
+ tmpfilename="";
+ }
+ return tmpfilename;
+}
+
+void AliHLTEsdManager::AliHLTEsdListEntry::SetDirectory(const char* directory)
+{
+ // see header file for class documentation
+ if (!directory) return;
+ if (!fName.IsNull()) {
+ HLTWarning("ESD entry already in writing mode (%s), ignoring directory", fName.Data());
+ return;
+ }
+ fDirectory=directory;
+}
+
+void AliHLTEsdManager::AliHLTEsdListEntry::Delete()
+{
+ // see header file for class documentation
+ if (fName.IsNull()) return;
+ if (gSystem->AccessPathName(fName)!=0) return;
+
+ TString shellcmd="rm -f ";
+ shellcmd+=fName;
+ gSystem->Exec(shellcmd);
+ fName="";
+}
+
+const char* AliHLTEsdManager::AliHLTEsdListEntry::GetFileName() const
+{
+ // see header file for class documentation
+ return fName.Data();
}
#include "AliHLTDataTypes.h"
#include "AliHLTLogging.h"
+#include "TString.h"
#include <vector>
class AliESDEvent;
int WriteESD(const AliHLTUInt8_t* pBuffer, AliHLTUInt32_t size, AliHLTComponentDataType dt,
AliESDEvent* tgtesd=NULL, int eventno=-1);
+ /**
+ * Align all ESD to the same number of events.
+ * The function adds empty events to all ESD files if their event number
+ * does not match the specified one.
+ * @param eventno the desired event no
+ * @return neg. error code if failed
+ */
+ int PadESDs(int eventno);
+
+ /**
+ * Set the target directory for the ESD files.
+ */
+ void SetDirectory(const char* directory);
+
+ /**
+ * Get the list of the internally created files.
+ * Returns a blank separated list of the file names.
+ */
+ TString GetFileNames(AliHLTComponentDataType dt=kAliHLTAnyDataType) const;
+
+ /**
+ * Embed an ESD into a TTree object.
+ * The tree object needs to be deleted by the caller.
+ */
+ static TTree* EmbedIntoTree(AliESDEvent* pESD, const char* name="esdTree", const char* title="Tree with HLT ESD objects");
+
protected:
private:
*/
int WriteESD(AliESDEvent* pESD, int eventno=-1);
+ /**
+ * Set the target directory for the ESD file.
+ */
+ void SetDirectory(const char* directory);
+
+ /**
+ * Delete the ESD file.
+ */
+ void Delete();
+
+ /**
+ * Get name of the ESD file.
+ */
+ const char* GetFileName() const;
+
bool operator==(AliHLTComponentDataType dt) const;
private:
/** assignment operator prohibited */
AliHLTEsdListEntry& operator=(const AliHLTEsdListEntry& src);
+ /**
+ * Write ESD to temporary file.
+ * The ESD is embedded into a tree and saved to a temporary file.
+ * The file name is retrieved by TSystem::GetTempFileName and returned
+ * on success.
+ * @return file name, empty on failure
+ */
+ TString WriteTempFile(AliESDEvent* pESD) const;
+
/** root file name */
TString fName; //!transient
- /** the root file for this esd */
- TFile* fpFile; //!transient
- /** the tree for this esd */
- TTree* fpTree; //!transient
- /** the esd to fill into the tree */
- AliESDEvent* fpEsd; //!transient
+ /** target directory */
+ TString fDirectory; //!transient
/** data type of the corresponding block */
AliHLTComponentDataType fDt; //!transient
};
/** the list of the ESDs */
AliHLTEsdPList fESDs; //!transient
+ /** target directory */
+ TString fDirectory; //!transient
+
ClassDef(AliHLTEsdManager, 0)
};
+
#endif