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 AliHLTEsdManagerImplementation.cxx
20 @author Matthias Richter
22 @brief Manager for merging and writing of HLT ESDs
25 #include "AliHLTEsdManagerImplementation.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(AliHLTEsdManagerImplementation)
42 AliHLTEsdManagerImplementation::AliHLTEsdManagerImplementation()
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 AliHLTEsdManagerImplementation::~AliHLTEsdManagerImplementation()
56 // see header file for class documentation
57 for (unsigned int i=0; i<fESDs.size(); i++) {
65 AliHLTEsdManagerImplementation::AliHLTEsdListEntry* AliHLTEsdManagerImplementation::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 AliHLTEsdManagerImplementation::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 #ifndef HAVE_NOT_ESD_COPY
122 #else //HAVE_NOT_ESD_COPY
123 static bool warningPrinted=false;
124 if (!warningPrinted) {
125 HLTWarning("old version of AliESDEvent does not provide assignment operator, skip merging to global hltEsd");
128 #endif //HAVE_NOT_ESD_COPY
132 entry->WriteESD(pESD, eventno);
134 HLTError("internal mismatch, can not create list entry");
139 HLTWarning("data block %s is not of class type AliESDEvent, ignoring ...", AliHLTComponent::DataType2Text(dt).c_str());
142 // ESD has been created and must be cleaned up
155 int AliHLTEsdManagerImplementation::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 AliHLTEsdManagerImplementation::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 AliHLTEsdManagerImplementation::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* AliHLTEsdManagerImplementation::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 AliHLTEsdManagerImplementation::AliHLTEsdListEntry::AliHLTEsdListEntry(AliHLTComponentDataType dt)
222 // see header file for class documentation
225 AliHLTEsdManagerImplementation::AliHLTEsdListEntry::~AliHLTEsdListEntry()
227 // see header file for class documentation
228 if (fpEsd) delete fpEsd;
231 if (fpTree) delete fpTree;
234 if (fpFile) delete fpFile;
238 bool AliHLTEsdManagerImplementation::AliHLTEsdListEntry::operator==(AliHLTComponentDataType dt) const
240 // see header file for class documentation
244 int AliHLTEsdManagerImplementation::AliHLTEsdListEntry::WriteESD(AliESDEvent* pSrcESD, int eventno)
246 // see header file for class documentation
248 #ifndef HAVE_NOT_ESD_COPY
249 if (fName.IsNull()) {
250 // this is the first event, create the file name
252 origin.Insert(0, fDt.fOrigin, kAliHLTComponentDataTypefOriginSize);
253 origin.Remove(TString::kTrailing, ' ');
256 if (!fDirectory.IsNull()) {
257 fName+=fDirectory; fName+="/";
259 fName+="AliHLT"; fName+=origin;
260 if (fDt!=kAliHLTDataTypeESDObject &&
261 fDt!=kAliHLTDataTypeESDTree) {
263 HLTWarning("non-standard ESD type %s", AliHLTComponent::DataType2Text(fDt).c_str());
265 id.Insert(0, fDt.fID, kAliHLTComponentDataTypefIDsize);
266 id.Remove(TString::kTrailing, ' ');
268 fName+="_"; fName+=id; fName+=".root";
273 fpFile=new TFile(fName, "RECREATE");
274 fpTree=new TTree("esdTree", "Tree with HLT ESD objects");
275 fpEsd=new AliESDEvent;
277 fpEsd->CreateStdContent();
279 fpEsd->WriteToTree(fpTree);
284 if (fpFile && fpTree && fpEsd) {
285 // synchronize and add empty events
287 int nofCurrentEvents=fpTree->GetEntries();
288 if (nofCurrentEvents<eventno) {
289 iResult=1; // indicate tree to be written
290 HLTDebug("adding %d empty events to file %s", eventno-nofCurrentEvents, fName.Data());
291 for (int i=nofCurrentEvents; i<eventno; i++) {
296 if (iResult>=0 && pSrcESD) {
299 iResult=1; // indicate tree to be written
304 fpTree->GetUserInfo()->Add(fpEsd);
305 fpTree->Write(fpTree->GetName(),TObject::kOverwrite);
306 fpTree->GetUserInfo()->Clear();
309 #else //HAVE_NOT_ESD_COPY
310 // this is the old workaround, necessary for older AliRoot versions
311 // version<=v4-12-Release
313 // we need to copy the ESD, I did not find an approptiate
314 // method, the workaround is to save the ESD in a temporary
315 // tree, read the content back into the ESD structure
317 // Unfortunately the following code crashes at the second event.
318 // The expert on the ESD (Christian Klein Boesig) does not have
319 // a solution either. It seems to be a problem in ROOT.
320 // TTree* dummy=new TTree("dummy","dummy");
321 // dummy->SetDirectory(0);
322 // pESD->WriteToTree(dummy);
324 // dummy->GetUserInfo()->Add(pESD);
325 // fpEsd->ReadFromTree(dummy);
326 // dummy->GetEvent(0);
327 // fpEsd->WriteToTree(fpTree);
329 // dummy->GetUserInfo()->Clear();
332 // The only way is via TChain, which is working on files only at the
334 // We use temporary files for the new event to be copied into the
337 if (fName.IsNull()) {
338 // this is the first event, create the file on disk and write ESD
340 origin.Insert(0, fDt.fOrigin, kAliHLTComponentDataTypefOriginSize);
341 origin.Remove(TString::kTrailing, ' ');
344 if (!fDirectory.IsNull()) {
345 fName+=fDirectory; fName+="/";
347 fName+="AliHLT"; fName+=origin;
348 if (fDt!=kAliHLTDataTypeESDObject &&
349 fDt!=kAliHLTDataTypeESDTree) {
351 HLTWarning("non-standard ESD type %s", AliHLTComponent::DataType2Text(fDt).c_str());
353 id.Insert(0, fDt.fID, kAliHLTComponentDataTypefIDsize);
354 id.Remove(TString::kTrailing, ' ');
356 fName+="_"; fName+=id; fName+=".root";
361 if (!gSystem->AccessPathName(fName)) {
362 // file exists, delete
363 TString shellcmd="rm -f ";
365 gSystem->Exec(shellcmd);
369 TChain chain("esdTree");
373 int nofCurrentEvents=0;
375 if (!gSystem->AccessPathName(fName)) {
376 // these are the other events, use the target file and temporary files to merge
382 if (!file.IsZombie()) {
384 file.GetObject("esdTree", pSrcTree);
386 nofCurrentEvents=pSrcTree->GetEntries();
394 // synchronize and add empty events
395 if (nofCurrentEvents<eventno) {
396 iResult=1; // indicate files to merge
397 TTree* pTgtTree=new TTree("esdTree", "Tree with HLT ESD objects");
399 pTgtTree->SetDirectory(0);
400 AliESDEvent* pTmpESD=new AliESDEvent;
403 FILE* pTmpFile=gSystem->TempFileName(tmpfilename);
407 cleanup.Add(new TObjString(tmpfilename));
408 TFile emptyevents(tmpfilename, "RECREATE");
409 if (!emptyevents.IsZombie()) {
410 pTmpESD->CreateStdContent();
411 pTmpESD->WriteToTree(pTgtTree);
412 HLTDebug("adding %d empty events to file %s", eventno-nofCurrentEvents, fName.Data());
413 for (int i=nofCurrentEvents; i<eventno; i++) {
416 pTgtTree->GetUserInfo()->Add(pTmpESD);
420 chain.Add(tmpfilename);
421 pTgtTree->GetUserInfo()->Clear();
434 if (iResult>=0 && pSrcESD) {
435 // add the new event to the chain
436 iResult=1; // indicate files to merge
437 TString tmpfilename=WriteTempFile(pSrcESD);
438 if (!tmpfilename.IsNull()) {
439 chain.Add(tmpfilename);
440 cleanup.Add(new TObjString(tmpfilename));
445 // build temporary file name for chain output
447 FILE* pTmpFile=gSystem->TempFileName(tgtName);
452 // there have been problems with the memory consumption when using
454 // but using a separate loop soemtimes crashes in AliESDEvent::ReadFromTree
455 // since this is for backward compatiblity only, we take the TChain::Merge
456 chain.Merge(tgtName);
457 // TFile tgtFile(tgtName, "RECREATE");
458 // TTree* pTgtTree=new TTree("esdTree", "Tree with HLT ESD objects");
459 // AliESDEvent* pTgtESD=new AliESDEvent;
460 // if (pTgtTree && pTgtESD) {
461 // pTgtESD->ReadFromTree(&chain);
462 // pTgtESD->WriteToTree(pTgtTree);
464 // int nofEvents=chain.GetEntries();
465 // for (int event=0; event<nofEvents; event++) {
466 // chain.GetEntry(event);
470 // pTgtTree->GetUserInfo()->Add(pTgtESD);
472 // pTgtTree->Write();
473 // pTgtTree->GetUserInfo()->Clear();
478 // if (pTgtTree) delete pTgtTree;
479 // if (pTgtESD) delete pTgtESD;
482 // rename the merged file to the original file
483 TString shellcmd="mv ";
484 shellcmd+=tgtName + " " + fName;
485 if (gSystem->Exec(shellcmd)==0) {
486 HLTDebug("renaming %s to %s", tgtName.Data(), fName.Data());
488 HLTError("can not rename temporary file %s to %s", tgtName.Data(), fName.Data());
491 HLTError("can not get temporary file name from system");
496 // delete temporary files
497 // the list objects are cleaned up by the TList destructor as the
499 TIter entry(&cleanup);
500 while (TObject* pObj=entry.Next()) {
501 if (dynamic_cast<TObjString*>(pObj)) {
502 TString shellcmd="rm -f ";
503 shellcmd+=(dynamic_cast<TObjString*>(pObj))->GetString();
504 gSystem->Exec(shellcmd);
507 #endif //HAVE_NOT_ESD_COPY
512 TString AliHLTEsdManagerImplementation::AliHLTEsdListEntry::WriteTempFile(AliESDEvent* pESD) const
514 // see header file for class documentation
517 FILE* pTmpFile=gSystem->TempFileName(tmpfilename);
522 TFile file(tmpfilename, "RECREATE");
523 if (!file.IsZombie()) {
524 TTree* pTree=AliHLTEsdManagerImplementation::EmbedIntoTree(pESD);
527 if (pTree->Write()>0) {
529 HLTError("can not write esd tree to temporary file %s", tmpfilename.Data());
532 pTree->GetUserInfo()->Clear();
539 HLTError("can not open file %s", tmpfilename.Data());
543 HLTError("can not get temporary file name from system");
548 if (gSystem->AccessPathName(tmpfilename)==0) {
549 TString shellcmd="rm -f ";
550 shellcmd+=tmpfilename;
551 gSystem->Exec(shellcmd);
558 void AliHLTEsdManagerImplementation::AliHLTEsdListEntry::SetDirectory(const char* directory)
560 // see header file for class documentation
561 if (!directory) return;
562 if (!fName.IsNull()) {
563 HLTWarning("ESD entry already in writing mode (%s), ignoring directory", fName.Data());
566 fDirectory=directory;
569 void AliHLTEsdManagerImplementation::AliHLTEsdListEntry::Delete()
571 // see header file for class documentation
572 if (fName.IsNull()) return;
573 if (gSystem->AccessPathName(fName)!=0) return;
575 TString shellcmd="rm -f ";
577 gSystem->Exec(shellcmd);
581 const char* AliHLTEsdManagerImplementation::AliHLTEsdListEntry::GetFileName() const
583 // see header file for class documentation