]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/rec/AliHLTEsdManagerImplementation.cxx
handling of non-std ESD content
[u/mrichter/AliRoot.git] / HLT / rec / AliHLTEsdManagerImplementation.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8 //*                  for The ALICE HLT Project.                            *
9 //*                                                                        *
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 //**************************************************************************
18
19 /** @file   AliHLTEsdManagerImplementation.cxx
20     @author Matthias Richter
21     @date   
22     @brief  Manager for merging and writing of HLT ESDs
23 */
24
25 #include "AliHLTEsdManagerImplementation.h"
26 #include "AliHLTComponent.h"
27 #include "AliESDEvent.h"
28 #include "AliHLTMessage.h"
29 #include "AliESDEvent.h"
30 #include "AliESDtrack.h"
31 #include "TFile.h"
32 #include "TTree.h"
33 #include "TClass.h"
34 #include "TObject.h"
35 #include "TObjectTable.h"
36 #include "TSystem.h"
37 #include "TChain.h"
38 #include "TList.h"
39
40 /** ROOT macro for the implementation of ROOT specific class methods */
41 ClassImp(AliHLTEsdManagerImplementation)
42
43 AliHLTEsdManagerImplementation::AliHLTEsdManagerImplementation()
44   :
45   fESDs(),
46   fDirectory()
47 {
48   // see header file for class documentation
49   // or
50   // refer to README to build package
51   // or
52   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
53 }
54
55 AliHLTEsdManagerImplementation::~AliHLTEsdManagerImplementation()
56 {
57   // see header file for class documentation
58   for (unsigned int i=0; i<fESDs.size(); i++) {
59     if (fESDs[i]) {
60       delete fESDs[i];
61     }
62     fESDs[i]=NULL;
63   }
64 }
65
66 AliHLTEsdManagerImplementation::AliHLTEsdListEntry* AliHLTEsdManagerImplementation::Find(AliHLTComponentDataType dt) const
67 {
68   // see header file for class documentation
69   AliHLTEsdListEntry* pEntry=NULL;
70   for (unsigned int i=0; i<fESDs.size(); i++) {
71     if (fESDs[i] && *(fESDs[i])==dt) {
72       pEntry=const_cast<AliHLTEsdListEntry*>(fESDs[i]);
73     }
74   }
75   return pEntry;
76 }
77
78 int AliHLTEsdManagerImplementation::WriteESD(const AliHLTUInt8_t* pBuffer, AliHLTUInt32_t size,
79                                AliHLTComponentDataType dt, AliESDEvent* tgtesd, int eventno)
80 {
81   // see header file for class documentation
82   if (!pBuffer && size<=0) return -EINVAL;
83   int iResult=0;
84   AliHLTUInt32_t firstWord=*((AliHLTUInt32_t*)pBuffer);
85   if (firstWord==size-sizeof(AliHLTUInt32_t)) {
86     HLTDebug("create object from block %s size %d", AliHLTComponent::DataType2Text(dt).c_str(), size);
87     AliHLTMessage msg(const_cast<AliHLTUInt8_t*>(pBuffer), size);
88     TClass* objclass=msg.GetClass();
89     TObject* pObj=msg.ReadObject(objclass);
90     if (pObj && objclass) {
91       HLTDebug("object %p type %s created", pObj, objclass->GetName());
92       AliESDEvent* pESD=dynamic_cast<AliESDEvent*>(pObj);
93       TTree* pTree=NULL;
94       if (!pESD) {
95         pTree=dynamic_cast<TTree*>(pObj);
96         if (pTree) {
97           pESD=new AliESDEvent;
98           pESD->CreateStdContent();
99           if (pTree->GetEntries()>0) {
100             if (pTree->GetEntries()>1) {
101               HLTWarning("only one entry allowed for ESD embedded into tree, data block %s contains tree with %d entires, taking first entry",
102                          AliHLTComponent::DataType2Text(dt).c_str(), pTree->GetEntries());
103             }
104             pESD->ReadFromTree(pTree);
105             pTree->GetEvent(0);
106           }
107         } else {
108           HLTWarning("tree of data block %s has no events, skipping data block", AliHLTComponent::DataType2Text(dt).c_str());
109         }
110       }
111       if (pESD) {
112         AliHLTEsdListEntry* entry=Find(dt);
113         if (!entry) {
114           AliHLTEsdListEntry* newEntry=new AliHLTEsdListEntry(dt);
115           if (!fDirectory.IsNull()) {
116             newEntry->SetDirectory(fDirectory);
117           }
118           fESDs.push_back(newEntry);
119         }
120         if (tgtesd) {
121 #if 0 // later extension !defined(HAVE_NOT_ESD_NONSTD)
122           entry=Find(dt);
123           if (entry) {
124             entry->CopyNonEmptyObjects(tgtesd, pESD);
125           } else {
126             HLTError("internal mismatch, can not create list entry");
127             iResult=-ENOMEM;
128           }
129 #elif !defined(HAVE_NOT_ESD_COPY)
130           *tgtesd=*pESD;
131 #else //HAVE_NOT_ESD_COPY
132           static bool warningPrinted=false;
133           if (!warningPrinted) {
134             HLTWarning("old version of AliESDEvent does not provide assignment operator, skip merging to global hltEsd");
135           }
136           warningPrinted=true;
137 #endif //HAVE_NOT_ESD_COPY
138         } else {
139         entry=Find(dt);
140         if (entry) {
141           entry->WriteESD(pESD, eventno);
142         } else {
143           HLTError("internal mismatch, can not create list entry");
144           iResult=-ENOMEM;
145         }
146         }
147       } else {
148         HLTWarning("data block %s is not of class type AliESDEvent, ignoring ...", AliHLTComponent::DataType2Text(dt).c_str());
149       }
150       if (pTree) {
151         // ESD has been created and must be cleaned up
152         pESD->Reset();
153         delete pESD;
154         pESD=NULL;
155       }
156       delete pObj;
157       pObj=NULL;
158     } else {
159     }
160   }
161   return iResult;
162 }
163
164 int AliHLTEsdManagerImplementation::PadESDs(int eventno)
165 {
166   // see header file for class documentation
167   int iResult=0;
168   for (unsigned int i=0; i<fESDs.size(); i++) {
169     if (fESDs[i]) {
170       int res=fESDs[i]->WriteESD(NULL, eventno);
171       if (res<0 && iResult>=0) iResult=res;
172     }
173   }
174   return iResult;
175 }
176
177 void AliHLTEsdManagerImplementation::SetDirectory(const char* directory)
178 {
179   // see header file for class documentation
180   if (!directory) return;
181   fDirectory=directory;
182   for (unsigned int i=0; i<fESDs.size(); i++) {
183     if (fESDs[i]) {
184       fESDs[i]->SetDirectory(directory);
185     }
186   }
187 }
188
189 TString AliHLTEsdManagerImplementation::GetFileNames(AliHLTComponentDataType dt) const
190 {
191   TString result;
192   for (unsigned int i=0; i<fESDs.size(); i++) {
193     if (fESDs[i] && *(fESDs[i])==dt) {
194       if (!result.IsNull()) result+=" ";
195       result+=fESDs[i]->GetFileName();
196     }
197   }
198   return result;
199 }
200
201 TTree* AliHLTEsdManagerImplementation::EmbedIntoTree(AliESDEvent* pESD, const char* name, const char* title)
202 {
203   // see header file for class documentation
204   int iResult=0;
205   TTree* pTree=new TTree(name, title);
206   if (pTree) {
207     pESD->WriteToTree(pTree);
208     pTree->Fill();
209     pTree->GetUserInfo()->Add(pESD);
210   } else {
211     iResult=-ENOMEM;
212   }
213
214   if (iResult<0) {
215     pTree->GetUserInfo()->Clear();
216     delete pTree;
217   }
218
219   return pTree;
220 }
221
222 AliHLTEsdManagerImplementation::AliHLTEsdListEntry::AliHLTEsdListEntry(AliHLTComponentDataType dt)
223   :
224   fName(),
225   fDirectory(),
226   fDt(dt),
227   fpFile(NULL),
228   fpTree(NULL),
229   fpEsd(NULL),
230   fPrefix()
231 {
232   // see header file for class documentation
233 }
234
235 AliHLTEsdManagerImplementation::AliHLTEsdListEntry::~AliHLTEsdListEntry()
236 {
237   // see header file for class documentation
238   if (fpEsd) delete fpEsd;
239   fpEsd=NULL;
240
241   if (fpTree) delete fpTree;
242   fpTree=NULL;
243
244   if (fpFile) {
245     fpFile->Close();
246     delete fpFile;
247   }
248   fpFile=NULL;
249 }
250
251 bool AliHLTEsdManagerImplementation::AliHLTEsdListEntry::operator==(AliHLTComponentDataType dt) const
252 {
253   // see header file for class documentation
254   return fDt==dt;
255 }
256
257 int AliHLTEsdManagerImplementation::AliHLTEsdListEntry::WriteESD(AliESDEvent* pSrcESD, int eventno)
258 {
259   // see header file for class documentation
260   int iResult=0;
261 #ifndef HAVE_NOT_ESD_COPY
262   if (fName.IsNull()) {
263     // this is the first event, create the file name
264     fName="";
265     if (!fDirectory.IsNull()) {
266       fName+=fDirectory; fName+="/";
267     }
268     fName+="Ali"; fName+=GetPrefix();
269     if (fDt!=kAliHLTDataTypeESDObject &&
270         fDt!=kAliHLTDataTypeESDTree) {
271
272       HLTWarning("non-standard ESD type %s", AliHLTComponent::DataType2Text(fDt).c_str());
273       TString id;
274       id.Insert(0, fDt.fID, kAliHLTComponentDataTypefIDsize);
275       id.Remove(TString::kTrailing, ' ');
276       id.ToUpper();
277       fName+="_"; fName+=id; fName+=".root";
278     } else {
279       fName+="ESDs.root";
280     }
281
282     fpFile=new TFile(fName, "RECREATE");
283     fpTree=new TTree("esdTree", "Tree with HLT ESD objects");
284     fpTree->SetDirectory(0);
285     fpEsd=new AliESDEvent;
286     if (fpEsd) {
287       fpEsd->CreateStdContent();
288       *fpEsd=*pSrcESD;
289       if (fpTree) {
290         fpEsd->WriteToTree(fpTree);
291       }
292     }
293   }
294
295   if (fpFile && fpTree && fpEsd) {
296     // synchronize and add empty events
297     fpEsd->Reset();
298     int nofCurrentEvents=fpTree->GetEntries();
299     if (nofCurrentEvents<eventno) {
300       iResult=1; // indicate tree to be written
301       HLTDebug("adding %d empty events to file %s", eventno-nofCurrentEvents, fName.Data());
302       for (int i=nofCurrentEvents; i<eventno; i++) {
303         fpTree->Fill();
304       }
305     }
306
307     if (iResult>=0 && pSrcESD) {
308       int nofObjects=fpEsd->GetList()->GetEntries();
309       *fpEsd=*pSrcESD;
310       if (nofObjects!=fpEsd->GetList()->GetEntries()) {
311         // The source ESD contains object not present in the target ESD
312         // before. Those objects will not be written to the tree since
313         // the branch layout has been created earlier.
314         // Create new tree with the additional branches, copy the entries
315         // of the current tree into the new tree, and continue.
316         TTree* pNewTree=new TTree("esdTree", "Tree with HLT ESD objects");
317         pNewTree->SetDirectory(0);
318         AliESDEvent* readESD=new AliESDEvent;
319         readESD->CreateStdContent();
320         readESD->ReadFromTree(fpTree);
321         fpEsd->Reset();
322         fpEsd->WriteToTree(pNewTree);
323         HLTDebug("cloning tree with %d entries", fpTree->GetEntries());
324         for (int event=0; event<fpTree->GetEntries(); event++) {
325           fpTree->GetEntry(event);
326           *fpEsd=*readESD;
327           pNewTree->Fill();
328           fpEsd->Reset();
329         }
330         fpFile->Close();
331         delete fpFile;
332         delete readESD;
333         delete fpTree;
334         fpFile=new TFile(fName, "RECREATE");
335         fpTree=pNewTree;
336         *fpEsd=*pSrcESD;
337         HLTDebug("new ESD with %d objects", fpEsd->GetList()->GetEntries());
338       }
339       fpTree->Fill();
340       iResult=1; // indicate tree to be written
341     }
342
343     if (iResult>0) {
344       fpFile->cd();
345       fpTree->GetUserInfo()->Add(fpEsd);
346       fpTree->Write(fpTree->GetName(),TObject::kOverwrite);
347       fpTree->GetUserInfo()->Clear();
348     }
349   }
350 #else //HAVE_NOT_ESD_COPY
351   // this is the old workaround, necessary for older AliRoot versions
352   // version<=v4-12-Release
353
354   // we need to copy the ESD, I did not find an approptiate
355   // method, the workaround is to save the ESD in a temporary
356   // tree, read the content back into the ESD structure
357   // used for filling.
358   // Unfortunately the following code crashes at the second event.
359   // The expert on the ESD (Christian Klein Boesig) does not have
360   // a solution either. It seems to be a problem in ROOT.
361   //  TTree* dummy=new TTree("dummy","dummy");
362   //  dummy->SetDirectory(0);
363   //  pESD->WriteToTree(dummy);
364   //  dummy->Fill();
365   //  dummy->GetUserInfo()->Add(pESD);
366   //  fpEsd->ReadFromTree(dummy);
367   //  dummy->GetEvent(0);
368   //  fpEsd->WriteToTree(fpTree);
369   //  fpTree->Fill();
370   //  dummy->GetUserInfo()->Clear();
371   //  delete dummy;
372   //
373   // The only way is via TChain, which is working on files only at the
374   // time of writing.
375   // We use temporary files for the new event to be copied into the
376   // existing tree.
377   //
378   if (fName.IsNull()) {
379     // this is the first event, create the file on disk and write ESD
380     TString origin;
381     origin.Insert(0, fDt.fOrigin, kAliHLTComponentDataTypefOriginSize);
382     origin.Remove(TString::kTrailing, ' ');
383     origin.ToUpper();
384     fName="";
385     if (!fDirectory.IsNull()) {
386       fName+=fDirectory; fName+="/";
387     }
388     fName+="AliHLT"; fName+=origin;
389     if (fDt!=kAliHLTDataTypeESDObject &&
390         fDt!=kAliHLTDataTypeESDTree) {
391
392       HLTWarning("non-standard ESD type %s", AliHLTComponent::DataType2Text(fDt).c_str());
393       TString id;
394       id.Insert(0, fDt.fID, kAliHLTComponentDataTypefIDsize);
395       id.Remove(TString::kTrailing, ' ');
396       id.ToUpper();
397       fName+="_"; fName+=id; fName+=".root";
398     } else {
399       fName+="ESDs.root";
400     }
401
402     if (!gSystem->AccessPathName(fName)) {
403       // file exists, delete
404       TString shellcmd="rm -f ";
405       shellcmd+=fName;
406       gSystem->Exec(shellcmd);
407     }
408   }
409
410   TChain chain("esdTree");
411   TList cleanup;
412   cleanup.SetOwner();
413
414   int nofCurrentEvents=0;
415   if (iResult>=0) {
416     if (!gSystem->AccessPathName(fName)) {
417       // these are the other events, use the target file and temporary files to merge
418       // with TChain
419       chain.Add(fName);
420
421       if (eventno>=0) {
422         TFile file(fName);
423         if (!file.IsZombie()) {
424           TTree* pSrcTree;
425           file.GetObject("esdTree", pSrcTree);
426           if (pSrcTree) {
427             nofCurrentEvents=pSrcTree->GetEntries();
428           }
429           file.Close();
430         }
431       }
432     }
433   }
434
435   // synchronize and add empty events
436   if (nofCurrentEvents<eventno) {
437     iResult=1; // indicate files to merge
438     TTree* pTgtTree=new TTree("esdTree", "Tree with HLT ESD objects");
439     if (pTgtTree) {
440       pTgtTree->SetDirectory(0);
441       AliESDEvent* pTmpESD=new AliESDEvent;
442       if (pTmpESD) {
443         TString tmpfilename;
444         FILE* pTmpFile=gSystem->TempFileName(tmpfilename);
445         if (pTmpFile) {
446           fclose(pTmpFile);
447           pTmpFile=NULL;
448           cleanup.Add(new TObjString(tmpfilename));
449           TFile emptyevents(tmpfilename, "RECREATE");
450           if (!emptyevents.IsZombie()) {
451             pTmpESD->CreateStdContent();
452             pTmpESD->WriteToTree(pTgtTree);
453             HLTDebug("adding %d empty events to file %s", eventno-nofCurrentEvents, fName.Data());
454             for (int i=nofCurrentEvents; i<eventno; i++) {
455               pTgtTree->Fill();
456             }
457             pTgtTree->GetUserInfo()->Add(pTmpESD);
458             emptyevents.cd();
459             pTgtTree->Write();
460             emptyevents.Close();
461             chain.Add(tmpfilename);
462             pTgtTree->GetUserInfo()->Clear();
463           }
464         }
465         delete pTmpESD;
466       } else {
467         iResult=-ENOMEM;
468       }
469       delete pTgtTree;
470     } else {
471       iResult=-ENOMEM;
472     }
473   }
474
475   if (iResult>=0 && pSrcESD) {
476     // add the new event to the chain
477     iResult=1; // indicate files to merge
478     TString tmpfilename=WriteTempFile(pSrcESD);
479     if (!tmpfilename.IsNull()) {
480       chain.Add(tmpfilename);
481       cleanup.Add(new TObjString(tmpfilename));
482     }
483   }
484
485   if (iResult>0) {
486     // build temporary file name for chain output
487     TString tgtName;
488     FILE* pTmpFile=gSystem->TempFileName(tgtName);
489     if (pTmpFile) {
490       fclose(pTmpFile);
491       pTmpFile=NULL;
492
493       // there have been problems with the memory consumption when using
494       // TChain::Merge
495       // but using a separate loop soemtimes crashes in AliESDEvent::ReadFromTree
496       // since this is for backward compatiblity only, we take the TChain::Merge
497       chain.Merge(tgtName);
498 //       TFile tgtFile(tgtName, "RECREATE");
499 //       TTree* pTgtTree=new TTree("esdTree", "Tree with HLT ESD objects");
500 //       AliESDEvent* pTgtESD=new AliESDEvent;
501 //       if (pTgtTree && pTgtESD) {
502 //      pTgtESD->ReadFromTree(&chain);
503 //      pTgtESD->WriteToTree(pTgtTree);
504
505 //      int nofEvents=chain.GetEntries();
506 //      for (int event=0; event<nofEvents; event++) {
507 //        chain.GetEntry(event);
508 //        pTgtTree->Fill();
509 //      }
510
511 //      pTgtTree->GetUserInfo()->Add(pTgtESD);
512 //      tgtFile.cd();
513 //      pTgtTree->Write();
514 //      pTgtTree->GetUserInfo()->Clear();
515 //       } else {
516 //      iResult=-ENOMEM;
517 //       }
518
519 //       if (pTgtTree) delete pTgtTree;
520 //       if (pTgtESD) delete pTgtESD;
521 //       tgtFile.Close();
522
523       // rename the merged file to the original file
524       TString shellcmd="mv ";
525       shellcmd+=tgtName + " " + fName;
526       if (gSystem->Exec(shellcmd)==0) {
527         HLTDebug("renaming %s to %s", tgtName.Data(), fName.Data());
528       } else {
529         HLTError("can not rename temporary file %s to %s", tgtName.Data(), fName.Data());
530       }
531     } else {
532       HLTError("can not get temporary file name from system");
533       iResult=-EBADF;
534     }
535   }
536
537   // delete temporary files
538   // the list objects are cleaned up by the TList destructor as the
539   // list is owner
540   TIter entry(&cleanup);
541   while (TObject* pObj=entry.Next()) {
542     if (dynamic_cast<TObjString*>(pObj)) {
543       TString shellcmd="rm -f ";
544       shellcmd+=(dynamic_cast<TObjString*>(pObj))->GetString();
545       gSystem->Exec(shellcmd);
546     }
547   }
548 #endif //HAVE_NOT_ESD_COPY
549
550   return iResult;
551 }
552
553 TString AliHLTEsdManagerImplementation::AliHLTEsdListEntry::WriteTempFile(AliESDEvent* pESD) const
554 {
555   // see header file for class documentation
556   int iResult=0;
557   TString tmpfilename;
558   FILE* pTmpFile=gSystem->TempFileName(tmpfilename);
559   if (pTmpFile) {
560     fclose(pTmpFile);
561     pTmpFile=NULL;
562
563     TFile file(tmpfilename, "RECREATE");
564     if (!file.IsZombie()) {
565       TTree* pTree=AliHLTEsdManagerImplementation::EmbedIntoTree(pESD);
566       if (pTree) {
567         file.cd();
568         if (pTree->Write()>0) {
569         } else {
570           HLTError("can not write esd tree to temporary file %s", tmpfilename.Data());
571         }
572
573         pTree->GetUserInfo()->Clear();
574         delete pTree;
575       } else {
576         iResult=-ENOMEM;
577       }
578       file.Close();
579     } else {
580       HLTError("can not open file %s", tmpfilename.Data());
581       iResult=-EBADF;
582     }
583   } else {
584     HLTError("can not get temporary file name from system");
585     iResult=-EBADF;
586   }
587
588   if (iResult<0) {
589     if (gSystem->AccessPathName(tmpfilename)==0) {
590       TString shellcmd="rm -f ";
591       shellcmd+=tmpfilename;
592       gSystem->Exec(shellcmd);
593     }
594     tmpfilename="";
595   }
596   return tmpfilename;
597 }
598
599 void AliHLTEsdManagerImplementation::AliHLTEsdListEntry::SetDirectory(const char* directory)
600 {
601   // see header file for class documentation
602   if (!directory) return;
603   if (!fName.IsNull()) {
604     HLTWarning("ESD entry already in writing mode (%s), ignoring directory", fName.Data());
605     return;
606   }
607   fDirectory=directory;
608 }
609
610 void AliHLTEsdManagerImplementation::AliHLTEsdListEntry::Delete()
611 {
612   // see header file for class documentation
613   if (fName.IsNull()) return;
614   if (gSystem->AccessPathName(fName)!=0) return;
615
616   TString shellcmd="rm -f ";
617   shellcmd+=fName;
618   gSystem->Exec(shellcmd);
619   fName="";
620 }
621
622 const char* AliHLTEsdManagerImplementation::AliHLTEsdListEntry::GetFileName() const
623 {
624   // see header file for class documentation
625   return fName.Data();
626 }
627
628 const char* AliHLTEsdManagerImplementation::AliHLTEsdListEntry::GetPrefix()
629 {
630   // see header file for class documentation
631   if (fPrefix.IsNull()) {
632     fPrefix.Insert(0, fDt.fOrigin, kAliHLTComponentDataTypefOriginSize);
633     fPrefix.Remove(TString::kTrailing, ' ');
634     fPrefix.ToUpper();
635     if (!fPrefix.Contains("HLT")) {
636       fPrefix.Insert(0, "HLT");
637     }
638   }
639   return fPrefix.Data();
640 }
641
642 int AliHLTEsdManagerImplementation::AliHLTEsdListEntry::CopyNonEmptyObjects(AliESDEvent* pTgt, AliESDEvent* pSrc)
643 {
644   // see header file for class documentation
645   int iResult=0;
646   if (!pTgt || !pSrc) return -EINVAL;
647
648   const char* defaultPrefix="HLT";
649   TIter next(pSrc->GetList());
650   TObject* pSrcObject=NULL;
651   TString name;
652   while ((pSrcObject=next())) {
653     if(!pSrcObject->InheritsFrom("TCollection")){
654       // simple objects
655     } else if(pSrcObject->InheritsFrom("TClonesArray")){
656       TClonesArray* pTClA=dynamic_cast<TClonesArray*>(pSrcObject);
657       if (pTClA!=NULL && pTClA->GetEntriesFast()>0) {
658         bool bMakeNewName=true;
659         name=defaultPrefix;
660         name+=pTClA->GetName();
661         TObject* pTgtObject=pTgt->GetList()->FindObject(name);
662         TClonesArray* pTgtArray=NULL;
663         if (bMakeNewName=(pTgtObject!=NULL) && pTgtObject->InheritsFrom("TClonesArray")){
664           pTgtArray=dynamic_cast<TClonesArray*>(pTgtObject);
665           if (pTgtArray) {
666             TString classType=pTClA->Class()->GetName();
667             if (classType.CompareTo(pTgtArray->Class()->GetName())==0) {
668               if (pTgtArray->GetEntries()==0) {
669                 bMakeNewName=false;
670               } else {
671                 HLTWarning("TClonesArray \"%s\"  in target ESD %p is already filled with %d entries",
672                            name.Data(), pTgt, pTgtArray->GetEntries());
673               }
674             } else {
675               HLTWarning("TClonesArray \"%s\" exists in target ESD %p, but describes incompatible class type %s instead of %s",
676                          name.Data(), pTgt, pTgtArray->GetClass()->GetName(), pTClA->GetClass()->GetName());
677             }
678           } else {
679             HLTError("internal error: dynamic cast failed for object %s %p", pTgtObject->GetName(), pTgtObject);
680           }
681         } else if (pTgtObject) {
682           HLTWarning("object \"%s\" does already exist in target ESD %p, but is %s rather than TClonesArray",
683                      name.Data(), pTgt, pTgtObject->Class()->GetName());
684           // TODO: temporary solution, think about a general naming scheme and add
685           // the name as property of AliHLTEsdListEntry
686         }
687
688         if (bMakeNewName) {
689           pTgtArray=NULL;
690           int count=1;
691           while (pTgt->GetList()->FindObject(name)) {
692             name.Form("%sESD_%s", GetPrefix(), pTClA->GetName());
693             if (count++>1) {
694               name+=Form("%d", count);
695             }
696           }
697           HLTWarning("adding new TClonesArray \"%s\" because of conflicts", name.Data());
698         }
699
700         if (pTgtArray) {
701           pTgtArray->ExpandCreate(pTClA->GetEntries());
702           HLTInfo("Expanding TClonesArray \"%s\" to %d elements", pTgtArray->GetClass()->GetName(), pTClA->GetEntries());
703         } else {
704           pTgtArray=new TClonesArray(pTClA->GetClass(), pTClA->GetEntries());
705           pTgtArray->ExpandCreate(pTClA->GetEntries());
706           pTgtArray->SetName(name);
707           pTgt->AddObject(pTgtArray);
708           HLTInfo("Adding TClonesArray \"%s\" with %d elements to ESD %p", name.Data(), pTClA->GetEntries(), pTgt);
709         }
710
711         if (pTgtArray) {
712           for(int i=0; i<pTClA->GetEntriesFast(); ++i){
713             (*pTClA)[i]->Copy(*((*pTgtArray)[i]));
714           }
715         } else {
716           iResult=-ENOMEM;
717         }
718       }
719     }
720   }
721   return iResult;
722 }