3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project *
5 //* ALICE Experiment at CERN, All rights reserved. *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 //* for The ALICE HLT Project. *
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 //**************************************************************************
19 /** @file AliHLTEsdManager.cxx
20 @author Matthias Richter
22 @brief Manager for merging and writing of HLT ESDs
25 #include "AliHLTEsdManager.h"
26 #include "AliHLTComponent.h"
27 #include "AliESDEvent.h"
28 #include "AliHLTMessage.h"
29 #include "AliESDEvent.h"
34 #include "TObjectTable.h"
39 /** ROOT macro for the implementation of ROOT specific class methods */
40 ClassImp(AliHLTEsdManager)
42 AliHLTEsdManager::AliHLTEsdManager()
47 // see header file for class documentation
49 // refer to README to build package
51 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
54 AliHLTEsdManager::~AliHLTEsdManager()
56 // see header file for class documentation
57 for (unsigned int i=0; i<fESDs.size(); i++) {
65 AliHLTEsdManager::AliHLTEsdListEntry* AliHLTEsdManager::Find(AliHLTComponentDataType dt) const
67 // see header file for class documentation
68 AliHLTEsdListEntry* pEntry=NULL;
69 for (unsigned int i=0; i<fESDs.size(); i++) {
70 if (fESDs[i] && *(fESDs[i])==dt) {
71 pEntry=const_cast<AliHLTEsdListEntry*>(fESDs[i]);
77 int AliHLTEsdManager::WriteESD(const AliHLTUInt8_t* pBuffer, AliHLTUInt32_t size,
78 AliHLTComponentDataType dt, AliESDEvent* tgtesd, int eventno)
80 // see header file for class documentation
81 if (!pBuffer && size<=0) return -EINVAL;
83 AliHLTUInt32_t firstWord=*((AliHLTUInt32_t*)pBuffer);
84 if (firstWord==size-sizeof(AliHLTUInt32_t)) {
85 HLTDebug("create object from block %s size %d", AliHLTComponent::DataType2Text(dt).c_str(), size);
86 AliHLTMessage msg(const_cast<AliHLTUInt8_t*>(pBuffer), size);
87 TClass* objclass=msg.GetClass();
88 TObject* pObj=msg.ReadObject(objclass);
89 if (pObj && objclass) {
90 HLTDebug("object %p type %s created", pObj, objclass->GetName());
91 AliESDEvent* pESD=dynamic_cast<AliESDEvent*>(pObj);
94 pTree=dynamic_cast<TTree*>(pObj);
97 pESD->CreateStdContent();
98 if (pTree->GetEntries()>0) {
99 if (pTree->GetEntries()>1) {
100 HLTWarning("only one entry allowed for ESD embedded into tree, data block %s contains tree with %d entires, taking first entry",
101 AliHLTComponent::DataType2Text(dt).c_str(), pTree->GetEntries());
103 pESD->ReadFromTree(pTree);
107 HLTWarning("tree of data block %s has no events, skipping data block", AliHLTComponent::DataType2Text(dt).c_str());
111 AliHLTEsdListEntry* entry=Find(dt);
113 AliHLTEsdListEntry* newEntry=new AliHLTEsdListEntry(dt);
114 if (!fDirectory.IsNull()) {
115 newEntry->SetDirectory(fDirectory);
117 fESDs.push_back(newEntry);
120 TTree* pTmpTree=AliHLTEsdManager::EmbedIntoTree(pESD);
122 tgtesd->ReadFromTree(pTmpTree);
123 pTmpTree->GetEvent(0);
124 pTmpTree->GetUserInfo()->Clear();
126 HLTDebug("data block %s written to target ESD", AliHLTComponent::DataType2Text(dt).c_str());
133 entry->WriteESD(pESD, eventno);
135 HLTError("internal mismatch, can not create list entry");
140 HLTWarning("data block %s is not of class type AliESDEvent, ignoring ...", AliHLTComponent::DataType2Text(dt).c_str());
143 // ESD has been created and must be cleaned up
155 int AliHLTEsdManager::PadESDs(int eventno)
157 // see header file for class documentation
159 for (unsigned int i=0; i<fESDs.size(); i++) {
161 int res=fESDs[i]->WriteESD(NULL, eventno);
162 if (res<0 && iResult>=0) iResult=res;
168 void AliHLTEsdManager::SetDirectory(const char* directory)
170 // see header file for class documentation
171 if (!directory) return;
172 fDirectory=directory;
173 for (unsigned int i=0; i<fESDs.size(); i++) {
175 fESDs[i]->SetDirectory(directory);
180 TString AliHLTEsdManager::GetFileNames(AliHLTComponentDataType dt) const
183 for (unsigned int i=0; i<fESDs.size(); i++) {
184 if (fESDs[i] && *(fESDs[i])==dt) {
185 if (!result.IsNull()) result+=" ";
186 result+=fESDs[i]->GetFileName();
192 TTree* AliHLTEsdManager::EmbedIntoTree(AliESDEvent* pESD, const char* name, const char* title)
194 // see header file for class documentation
196 TTree* pTree=new TTree(name, title);
198 pESD->WriteToTree(pTree);
200 pTree->GetUserInfo()->Add(pESD);
206 pTree->GetUserInfo()->Clear();
213 AliHLTEsdManager::AliHLTEsdListEntry::AliHLTEsdListEntry(AliHLTComponentDataType dt)
219 // see header file for class documentation
222 AliHLTEsdManager::AliHLTEsdListEntry::~AliHLTEsdListEntry()
224 // see header file for class documentation
227 bool AliHLTEsdManager::AliHLTEsdListEntry::operator==(AliHLTComponentDataType dt) const
229 // see header file for class documentation
233 int AliHLTEsdManager::AliHLTEsdListEntry::WriteESD(AliESDEvent* pSrcESD, int eventno)
235 // we need to copy the ESD, I did not find an approptiate
236 // method, the workaround is to save the ESD in a temporary
237 // tree, read the content back into the ESD structure
239 // Unfortunately the following code crashes at the second event.
240 // The expert on the ESD (Christian Klein Boesig) does not have
241 // a solution either. It seems to be a problem in ROOT.
242 // TTree* dummy=new TTree("dummy","dummy");
243 // dummy->SetDirectory(0);
244 // pESD->WriteToTree(dummy);
246 // dummy->GetUserInfo()->Add(pESD);
247 // fpEsd->ReadFromTree(dummy);
248 // dummy->GetEvent(0);
249 // fpEsd->WriteToTree(fpTree);
251 // dummy->GetUserInfo()->Clear();
254 // The only way is via TChain, which is working on files only at the
256 // We use temporary files for the new event to be copied into the
260 if (fName.IsNull()) {
261 // this is the first event, create the file on disk and write ESD
263 origin.Insert(0, fDt.fOrigin, kAliHLTComponentDataTypefOriginSize);
264 origin.Remove(TString::kTrailing, ' ');
267 if (!fDirectory.IsNull()) {
268 fName+=fDirectory; fName+="/";
270 fName+="AliHLT"; fName+=origin;
271 if (fDt!=kAliHLTDataTypeESDObject &&
272 fDt!=kAliHLTDataTypeESDTree) {
274 HLTWarning("non-standard ESD type %s", AliHLTComponent::DataType2Text(fDt).c_str());
276 id.Insert(0, fDt.fID, kAliHLTComponentDataTypefIDsize);
277 id.Remove(TString::kTrailing, ' ');
279 fName+="_"; fName+=id; fName+=".root";
284 if (!gSystem->AccessPathName(fName)) {
285 // file exists, delete
286 TString shellcmd="rm -f ";
288 gSystem->Exec(shellcmd);
292 TChain chain("esdTree");
296 int nofCurrentEvents=0;
298 if (!gSystem->AccessPathName(fName)) {
299 // these are the other events, use the target file and temporary files to merge
305 if (!file.IsZombie()) {
307 file.GetObject("esdTree", pSrcTree);
309 nofCurrentEvents=pSrcTree->GetEntries();
317 // synchronize and add empty events
318 if (nofCurrentEvents<eventno) {
319 iResult=1; // indicate files to merge
320 TTree* pTgtTree=new TTree("esdTree", "Tree with HLT ESD objects");
322 pTgtTree->SetDirectory(0);
323 AliESDEvent* pTmpESD=new AliESDEvent;
326 FILE* pTmpFile=gSystem->TempFileName(tmpfilename);
330 cleanup.Add(new TObjString(tmpfilename));
331 TFile emptyevents(tmpfilename, "RECREATE");
332 if (!emptyevents.IsZombie()) {
333 pTmpESD->CreateStdContent();
334 pTmpESD->WriteToTree(pTgtTree);
335 HLTDebug("adding %d empty events to file %s", eventno-nofCurrentEvents, fName.Data());
336 for (int i=nofCurrentEvents; i<eventno; i++) {
339 pTgtTree->GetUserInfo()->Add(pTmpESD);
343 chain.Add(tmpfilename);
344 pTgtTree->GetUserInfo()->Clear();
357 if (iResult>=0 && pSrcESD) {
358 // add the new event to the chain
359 iResult=1; // indicate files to merge
360 TString tmpfilename=WriteTempFile(pSrcESD);
361 if (!tmpfilename.IsNull()) {
362 chain.Add(tmpfilename);
363 cleanup.Add(new TObjString(tmpfilename));
368 // build temporary file name for chain output
370 FILE* pTmpFile=gSystem->TempFileName(tgtName);
375 chain.Merge(tgtName);
376 // rename the merged file to the original file
377 TString shellcmd="mv ";
378 shellcmd+=tgtName + " " + fName;
379 if (gSystem->Exec(shellcmd)==0) {
380 HLTDebug("renaming %s to %s", tgtName.Data(), fName.Data());
382 HLTError("can not rename temporary file %s to %s", tgtName.Data(), fName.Data());
385 HLTError("can not get temporary file name from system");
390 // delete temporary files
391 // the list objects are cleaned up be the TList destructor as the
393 TIter entry(&cleanup);
394 while (TObject* pObj=entry.Next()) {
395 if (dynamic_cast<TObjString*>(pObj)) {
396 TString shellcmd="rm -f ";
397 shellcmd+=(dynamic_cast<TObjString*>(pObj))->GetString();
398 gSystem->Exec(shellcmd);
405 TString AliHLTEsdManager::AliHLTEsdListEntry::WriteTempFile(AliESDEvent* pESD) const
407 // see header file for class documentation
410 FILE* pTmpFile=gSystem->TempFileName(tmpfilename);
415 TFile file(tmpfilename, "RECREATE");
416 if (!file.IsZombie()) {
417 TTree* pTree=AliHLTEsdManager::EmbedIntoTree(pESD);
420 if (pTree->Write()>0) {
422 HLTError("can not write esd tree to temporary file %s", tmpfilename.Data());
425 pTree->GetUserInfo()->Clear();
432 HLTError("can not open file %s", tmpfilename.Data());
435 HLTError("can not get temporary file name from system");
440 if (gSystem->AccessPathName(tmpfilename)==0) {
441 TString shellcmd="rm -f ";
442 shellcmd+=tmpfilename;
443 gSystem->Exec(shellcmd);
450 void AliHLTEsdManager::AliHLTEsdListEntry::SetDirectory(const char* directory)
452 // see header file for class documentation
453 if (!directory) return;
454 if (!fName.IsNull()) {
455 HLTWarning("ESD entry already in writing mode (%s), ignoring directory", fName.Data());
458 fDirectory=directory;
461 void AliHLTEsdManager::AliHLTEsdListEntry::Delete()
463 // see header file for class documentation
464 if (fName.IsNull()) return;
465 if (gSystem->AccessPathName(fName)!=0) return;
467 TString shellcmd="rm -f ";
469 gSystem->Exec(shellcmd);
473 const char* AliHLTEsdManager::AliHLTEsdListEntry::GetFileName() const
475 // see header file for class documentation