Fixing typo
[u/mrichter/AliRoot.git] / HLT / rec / AliHLTEsdManager.cxx
CommitLineData
c5123824 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 AliHLTEsdManager.cxx
20 @author Matthias Richter
21 @date
22 @brief Manager for merging and writing of HLT ESDs
23*/
24
25#include "AliHLTEsdManager.h"
26#include "AliHLTComponent.h"
27#include "AliESDEvent.h"
28#include "AliHLTMessage.h"
29#include "AliESDEvent.h"
30#include "TFile.h"
31#include "TTree.h"
32#include "TClass.h"
33#include "TObject.h"
62ff1e23 34#include "TObjectTable.h"
90c37647 35#include "TSystem.h"
36#include "TChain.h"
37#include "TList.h"
c5123824 38
39/** ROOT macro for the implementation of ROOT specific class methods */
40ClassImp(AliHLTEsdManager)
41
42AliHLTEsdManager::AliHLTEsdManager()
43 :
90c37647 44 fESDs(),
45 fDirectory()
c5123824 46{
47 // see header file for class documentation
48 // or
49 // refer to README to build package
50 // or
51 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
52}
53
54AliHLTEsdManager::~AliHLTEsdManager()
55{
56 // see header file for class documentation
62ff1e23 57 for (unsigned int i=0; i<fESDs.size(); i++) {
58 if (fESDs[i]) {
59 delete fESDs[i];
60 }
61 fESDs[i]=NULL;
62 }
c5123824 63}
64
65AliHLTEsdManager::AliHLTEsdListEntry* AliHLTEsdManager::Find(AliHLTComponentDataType dt) const
66{
67 // see header file for class documentation
68 AliHLTEsdListEntry* pEntry=NULL;
69 for (unsigned int i=0; i<fESDs.size(); i++) {
62ff1e23 70 if (fESDs[i] && *(fESDs[i])==dt) {
71 pEntry=const_cast<AliHLTEsdListEntry*>(fESDs[i]);
c5123824 72 }
73 }
74 return pEntry;
75}
76
77int AliHLTEsdManager::WriteESD(const AliHLTUInt8_t* pBuffer, AliHLTUInt32_t size,
78 AliHLTComponentDataType dt, AliESDEvent* tgtesd, int eventno)
79{
80 // see header file for class documentation
81 if (!pBuffer && size<=0) return -EINVAL;
82 int iResult=0;
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);
92 TTree* pTree=NULL;
93 if (!pESD) {
94 pTree=dynamic_cast<TTree*>(pObj);
95 if (pTree) {
96 pESD=new AliESDEvent;
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());
102 }
103 pESD->ReadFromTree(pTree);
104 pTree->GetEvent(0);
105 }
106 } else {
107 HLTWarning("tree of data block %s has no events, skipping data block", AliHLTComponent::DataType2Text(dt).c_str());
108 }
109 }
110 if (pESD) {
111 AliHLTEsdListEntry* entry=Find(dt);
112 if (!entry) {
62ff1e23 113 AliHLTEsdListEntry* newEntry=new AliHLTEsdListEntry(dt);
90c37647 114 if (!fDirectory.IsNull()) {
115 newEntry->SetDirectory(fDirectory);
116 }
c5123824 117 fESDs.push_back(newEntry);
118 }
119 if (tgtesd) {
9877121c 120#ifndef HAVE_NOT_ESD_COPY
83cb7e1d 121 *tgtesd=*pESD;
9877121c 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");
90c37647 126 }
9877121c 127 warningPrinted=true;
128#endif //HAVE_NOT_ESD_COPY
90c37647 129 } else {
c5123824 130 entry=Find(dt);
131 if (entry) {
132 entry->WriteESD(pESD, eventno);
133 } else {
134 HLTError("internal mismatch, can not create list entry");
135 iResult=-ENOMEM;
136 }
90c37647 137 }
c5123824 138 } else {
139 HLTWarning("data block %s is not of class type AliESDEvent, ignoring ...", AliHLTComponent::DataType2Text(dt).c_str());
140 }
141 if (pTree) {
142 // ESD has been created and must be cleaned up
242e6536 143 pESD->Reset();
c5123824 144 delete pESD;
145 pESD=NULL;
146 }
147 delete pObj;
148 pObj=NULL;
149 } else {
150 }
151 }
152 return iResult;
153}
154
90c37647 155int AliHLTEsdManager::PadESDs(int eventno)
c5123824 156{
157 // see header file for class documentation
90c37647 158 int iResult=0;
159 for (unsigned int i=0; i<fESDs.size(); i++) {
160 if (fESDs[i]) {
161 int res=fESDs[i]->WriteESD(NULL, eventno);
162 if (res<0 && iResult>=0) iResult=res;
163 }
164 }
165 return iResult;
c5123824 166}
167
90c37647 168void AliHLTEsdManager::SetDirectory(const char* directory)
c5123824 169{
170 // see header file for class documentation
90c37647 171 if (!directory) return;
172 fDirectory=directory;
173 for (unsigned int i=0; i<fESDs.size(); i++) {
174 if (fESDs[i]) {
175 fESDs[i]->SetDirectory(directory);
176 }
177 }
178}
179
180TString AliHLTEsdManager::GetFileNames(AliHLTComponentDataType dt) const
181{
182 TString result;
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();
187 }
c5123824 188 }
90c37647 189 return result;
190}
c5123824 191
90c37647 192TTree* AliHLTEsdManager::EmbedIntoTree(AliESDEvent* pESD, const char* name, const char* title)
193{
194 // see header file for class documentation
195 int iResult=0;
196 TTree* pTree=new TTree(name, title);
197 if (pTree) {
198 pESD->WriteToTree(pTree);
199 pTree->Fill();
200 pTree->GetUserInfo()->Add(pESD);
201 } else {
202 iResult=-ENOMEM;
c5123824 203 }
204
90c37647 205 if (iResult<0) {
206 pTree->GetUserInfo()->Clear();
207 delete pTree;
c5123824 208 }
90c37647 209
210 return pTree;
211}
212
213AliHLTEsdManager::AliHLTEsdListEntry::AliHLTEsdListEntry(AliHLTComponentDataType dt)
214 :
215 fName(),
216 fDirectory(),
83cb7e1d 217 fDt(dt),
218 fpFile(NULL),
219 fpTree(NULL),
220 fpEsd(NULL)
90c37647 221{
222 // see header file for class documentation
223}
224
225AliHLTEsdManager::AliHLTEsdListEntry::~AliHLTEsdListEntry()
226{
227 // see header file for class documentation
242e6536 228 if (fpEsd) delete fpEsd;
229 fpEsd=NULL;
230
231 if (fpTree) delete fpTree;
232 fpTree=NULL;
233
234 if (fpFile) delete fpFile;
235 fpFile=NULL;
c5123824 236}
237
238bool AliHLTEsdManager::AliHLTEsdListEntry::operator==(AliHLTComponentDataType dt) const
239{
240 // see header file for class documentation
241 return fDt==dt;
242}
243
90c37647 244int AliHLTEsdManager::AliHLTEsdListEntry::WriteESD(AliESDEvent* pSrcESD, int eventno)
c5123824 245{
83cb7e1d 246 // see header file for class documentation
247 int iResult=0;
9877121c 248#ifndef HAVE_NOT_ESD_COPY
83cb7e1d 249 if (fName.IsNull()) {
250 // this is the first event, create the file name
251 TString origin;
252 origin.Insert(0, fDt.fOrigin, kAliHLTComponentDataTypefOriginSize);
253 origin.Remove(TString::kTrailing, ' ');
254 origin.ToUpper();
255 fName="";
256 if (!fDirectory.IsNull()) {
257 fName+=fDirectory; fName+="/";
258 }
259 fName+="AliHLT"; fName+=origin;
260 if (fDt!=kAliHLTDataTypeESDObject &&
261 fDt!=kAliHLTDataTypeESDTree) {
262
263 HLTWarning("non-standard ESD type %s", AliHLTComponent::DataType2Text(fDt).c_str());
264 TString id;
265 id.Insert(0, fDt.fID, kAliHLTComponentDataTypefIDsize);
266 id.Remove(TString::kTrailing, ' ');
267 id.ToUpper();
268 fName+="_"; fName+=id; fName+=".root";
269 } else {
270 fName+="ESDs.root";
271 }
272
273 fpFile=new TFile(fName, "RECREATE");
274 fpTree=new TTree("esdTree", "Tree with HLT ESD objects");
275 fpEsd=new AliESDEvent;
276 if (fpEsd) {
277 fpEsd->CreateStdContent();
278 if (fpTree) {
279 fpEsd->WriteToTree(fpTree);
280 }
281 }
282 }
283
284 if (fpFile && fpTree && fpEsd) {
285 // synchronize and add empty events
286 fpEsd->Reset();
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++) {
292 fpTree->Fill();
293 }
294 }
295
296 if (iResult>=0 && pSrcESD) {
297 *fpEsd=*pSrcESD;
298 fpTree->Fill();
299 iResult=1; // indicate tree to be written
300 }
301
302 if (iResult>0) {
303 fpFile->cd();
304 fpTree->GetUserInfo()->Add(fpEsd);
305 fpTree->Write(fpTree->GetName(),TObject::kOverwrite);
306 fpTree->GetUserInfo()->Clear();
307 }
308 }
9877121c 309#else //HAVE_NOT_ESD_COPY
83cb7e1d 310 // this is the old workaround, necessary for older AliRoot versions
311 // version<=v4-12-Release
312
90c37647 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
316 // used for filling.
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);
323 // dummy->Fill();
324 // dummy->GetUserInfo()->Add(pESD);
325 // fpEsd->ReadFromTree(dummy);
326 // dummy->GetEvent(0);
327 // fpEsd->WriteToTree(fpTree);
328 // fpTree->Fill();
329 // dummy->GetUserInfo()->Clear();
330 // delete dummy;
331 //
332 // The only way is via TChain, which is working on files only at the
333 // time of writing.
334 // We use temporary files for the new event to be copied into the
335 // existing tree.
336 //
90c37647 337 if (fName.IsNull()) {
338 // this is the first event, create the file on disk and write ESD
c5123824 339 TString origin;
340 origin.Insert(0, fDt.fOrigin, kAliHLTComponentDataTypefOriginSize);
341 origin.Remove(TString::kTrailing, ' ');
342 origin.ToUpper();
90c37647 343 fName="";
344 if (!fDirectory.IsNull()) {
345 fName+=fDirectory; fName+="/";
346 }
347 fName+="AliHLT"; fName+=origin;
c5123824 348 if (fDt!=kAliHLTDataTypeESDObject &&
349 fDt!=kAliHLTDataTypeESDTree) {
350
351 HLTWarning("non-standard ESD type %s", AliHLTComponent::DataType2Text(fDt).c_str());
352 TString id;
353 id.Insert(0, fDt.fID, kAliHLTComponentDataTypefIDsize);
354 id.Remove(TString::kTrailing, ' ');
355 id.ToUpper();
356 fName+="_"; fName+=id; fName+=".root";
357 } else {
358 fName+="ESDs.root";
90c37647 359 }
360
361 if (!gSystem->AccessPathName(fName)) {
362 // file exists, delete
363 TString shellcmd="rm -f ";
364 shellcmd+=fName;
365 gSystem->Exec(shellcmd);
c5123824 366 }
367 }
90c37647 368
369 TChain chain("esdTree");
370 TList cleanup;
371 cleanup.SetOwner();
372
373 int nofCurrentEvents=0;
374 if (iResult>=0) {
375 if (!gSystem->AccessPathName(fName)) {
376 // these are the other events, use the target file and temporary files to merge
377 // with TChain
378 chain.Add(fName);
379
380 if (eventno>=0) {
381 TFile file(fName);
382 if (!file.IsZombie()) {
383 TTree* pSrcTree;
384 file.GetObject("esdTree", pSrcTree);
385 if (pSrcTree) {
386 nofCurrentEvents=pSrcTree->GetEntries();
387 }
388 file.Close();
389 }
c5123824 390 }
391 }
90c37647 392 }
393
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");
398 if (pTgtTree) {
399 pTgtTree->SetDirectory(0);
400 AliESDEvent* pTmpESD=new AliESDEvent;
401 if (pTmpESD) {
402 TString tmpfilename;
403 FILE* pTmpFile=gSystem->TempFileName(tmpfilename);
404 if (pTmpFile) {
405 fclose(pTmpFile);
406 pTmpFile=NULL;
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++) {
414 pTgtTree->Fill();
415 }
416 pTgtTree->GetUserInfo()->Add(pTmpESD);
417 emptyevents.cd();
418 pTgtTree->Write();
419 emptyevents.Close();
420 chain.Add(tmpfilename);
421 pTgtTree->GetUserInfo()->Clear();
422 }
c5123824 423 }
90c37647 424 delete pTmpESD;
c5123824 425 } else {
90c37647 426 iResult=-ENOMEM;
c5123824 427 }
90c37647 428 delete pTgtTree;
429 } else {
430 iResult=-ENOMEM;
431 }
432 }
433
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));
441 }
442 }
443
444 if (iResult>0) {
445 // build temporary file name for chain output
446 TString tgtName;
447 FILE* pTmpFile=gSystem->TempFileName(tgtName);
448 if (pTmpFile) {
449 fclose(pTmpFile);
450 pTmpFile=NULL;
451
41b5c1b6 452 // there have been problems with the memory consumption when using
453 // TChain::Merge
83cb7e1d 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);
463
464// int nofEvents=chain.GetEntries();
465// for (int event=0; event<nofEvents; event++) {
466// chain.GetEntry(event);
467// pTgtTree->Fill();
468// }
469
470// pTgtTree->GetUserInfo()->Add(pTgtESD);
471// tgtFile.cd();
472// pTgtTree->Write();
473// pTgtTree->GetUserInfo()->Clear();
474// } else {
475// iResult=-ENOMEM;
476// }
477
478// if (pTgtTree) delete pTgtTree;
479// if (pTgtESD) delete pTgtESD;
480// tgtFile.Close();
41b5c1b6 481
90c37647 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());
487 } else {
488 HLTError("can not rename temporary file %s to %s", tgtName.Data(), fName.Data());
c5123824 489 }
90c37647 490 } else {
491 HLTError("can not get temporary file name from system");
492 iResult=-EBADF;
493 }
494 }
495
496 // delete temporary files
41b5c1b6 497 // the list objects are cleaned up by the TList destructor as the
90c37647 498 // list is owner
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);
505 }
506 }
9877121c 507#endif //HAVE_NOT_ESD_COPY
90c37647 508
509 return iResult;
510}
511
512TString AliHLTEsdManager::AliHLTEsdListEntry::WriteTempFile(AliESDEvent* pESD) const
513{
514 // see header file for class documentation
f7561f8d 515 int iResult=0;
90c37647 516 TString tmpfilename;
517 FILE* pTmpFile=gSystem->TempFileName(tmpfilename);
518 if (pTmpFile) {
519 fclose(pTmpFile);
520 pTmpFile=NULL;
521
522 TFile file(tmpfilename, "RECREATE");
523 if (!file.IsZombie()) {
524 TTree* pTree=AliHLTEsdManager::EmbedIntoTree(pESD);
525 if (pTree) {
526 file.cd();
527 if (pTree->Write()>0) {
c5123824 528 } else {
90c37647 529 HLTError("can not write esd tree to temporary file %s", tmpfilename.Data());
c5123824 530 }
90c37647 531
532 pTree->GetUserInfo()->Clear();
533 delete pTree;
c5123824 534 } else {
535 iResult=-ENOMEM;
536 }
90c37647 537 file.Close();
538 } else {
539 HLTError("can not open file %s", tmpfilename.Data());
3dd8541e 540 iResult=-EBADF;
c5123824 541 }
90c37647 542 } else {
543 HLTError("can not get temporary file name from system");
544 iResult=-EBADF;
c5123824 545 }
90c37647 546
547 if (iResult<0) {
548 if (gSystem->AccessPathName(tmpfilename)==0) {
549 TString shellcmd="rm -f ";
550 shellcmd+=tmpfilename;
551 gSystem->Exec(shellcmd);
552 }
553 tmpfilename="";
554 }
555 return tmpfilename;
556}
557
558void AliHLTEsdManager::AliHLTEsdListEntry::SetDirectory(const char* directory)
559{
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());
564 return;
565 }
566 fDirectory=directory;
567}
568
569void AliHLTEsdManager::AliHLTEsdListEntry::Delete()
570{
571 // see header file for class documentation
572 if (fName.IsNull()) return;
573 if (gSystem->AccessPathName(fName)!=0) return;
574
575 TString shellcmd="rm -f ";
576 shellcmd+=fName;
577 gSystem->Exec(shellcmd);
578 fName="";
579}
580
581const char* AliHLTEsdManager::AliHLTEsdListEntry::GetFileName() const
582{
583 // see header file for class documentation
584 return fName.Data();
c5123824 585}