Added code to allow sending back of EventDoneData from the DoEvent methods of AliHLTP...
[u/mrichter/AliRoot.git] / HLT / rec / AliHLTEsdManagerImplementation.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
f1207f29 19/** @file AliHLTEsdManagerImplementation.cxx
c5123824 20 @author Matthias Richter
21 @date
22 @brief Manager for merging and writing of HLT ESDs
23*/
24
f1207f29 25#include "AliHLTEsdManagerImplementation.h"
c5123824 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 */
f1207f29 40ClassImp(AliHLTEsdManagerImplementation)
c5123824 41
f1207f29 42AliHLTEsdManagerImplementation::AliHLTEsdManagerImplementation()
c5123824 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
f1207f29 54AliHLTEsdManagerImplementation::~AliHLTEsdManagerImplementation()
c5123824 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
f1207f29 65AliHLTEsdManagerImplementation::AliHLTEsdListEntry* AliHLTEsdManagerImplementation::Find(AliHLTComponentDataType dt) const
c5123824 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
f1207f29 77int AliHLTEsdManagerImplementation::WriteESD(const AliHLTUInt8_t* pBuffer, AliHLTUInt32_t size,
c5123824 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
f1207f29 155int AliHLTEsdManagerImplementation::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
f1207f29 168void AliHLTEsdManagerImplementation::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
f1207f29 180TString AliHLTEsdManagerImplementation::GetFileNames(AliHLTComponentDataType dt) const
90c37647 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
f1207f29 192TTree* AliHLTEsdManagerImplementation::EmbedIntoTree(AliESDEvent* pESD, const char* name, const char* title)
90c37647 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
f1207f29 213AliHLTEsdManagerImplementation::AliHLTEsdListEntry::AliHLTEsdListEntry(AliHLTComponentDataType dt)
90c37647 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
f1207f29 225AliHLTEsdManagerImplementation::AliHLTEsdListEntry::~AliHLTEsdListEntry()
90c37647 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
ba93bdb0 234 if (fpFile) {
235 fpFile->Close();
236 delete fpFile;
237 }
242e6536 238 fpFile=NULL;
c5123824 239}
240
f1207f29 241bool AliHLTEsdManagerImplementation::AliHLTEsdListEntry::operator==(AliHLTComponentDataType dt) const
c5123824 242{
243 // see header file for class documentation
244 return fDt==dt;
245}
246
f1207f29 247int AliHLTEsdManagerImplementation::AliHLTEsdListEntry::WriteESD(AliESDEvent* pSrcESD, int eventno)
c5123824 248{
83cb7e1d 249 // see header file for class documentation
250 int iResult=0;
9877121c 251#ifndef HAVE_NOT_ESD_COPY
83cb7e1d 252 if (fName.IsNull()) {
253 // this is the first event, create the file name
254 TString origin;
255 origin.Insert(0, fDt.fOrigin, kAliHLTComponentDataTypefOriginSize);
256 origin.Remove(TString::kTrailing, ' ');
257 origin.ToUpper();
258 fName="";
259 if (!fDirectory.IsNull()) {
260 fName+=fDirectory; fName+="/";
261 }
262 fName+="AliHLT"; fName+=origin;
263 if (fDt!=kAliHLTDataTypeESDObject &&
264 fDt!=kAliHLTDataTypeESDTree) {
265
266 HLTWarning("non-standard ESD type %s", AliHLTComponent::DataType2Text(fDt).c_str());
267 TString id;
268 id.Insert(0, fDt.fID, kAliHLTComponentDataTypefIDsize);
269 id.Remove(TString::kTrailing, ' ');
270 id.ToUpper();
271 fName+="_"; fName+=id; fName+=".root";
272 } else {
273 fName+="ESDs.root";
274 }
275
276 fpFile=new TFile(fName, "RECREATE");
277 fpTree=new TTree("esdTree", "Tree with HLT ESD objects");
278 fpEsd=new AliESDEvent;
279 if (fpEsd) {
280 fpEsd->CreateStdContent();
281 if (fpTree) {
282 fpEsd->WriteToTree(fpTree);
283 }
284 }
285 }
286
287 if (fpFile && fpTree && fpEsd) {
288 // synchronize and add empty events
289 fpEsd->Reset();
290 int nofCurrentEvents=fpTree->GetEntries();
291 if (nofCurrentEvents<eventno) {
292 iResult=1; // indicate tree to be written
293 HLTDebug("adding %d empty events to file %s", eventno-nofCurrentEvents, fName.Data());
294 for (int i=nofCurrentEvents; i<eventno; i++) {
295 fpTree->Fill();
296 }
297 }
298
299 if (iResult>=0 && pSrcESD) {
300 *fpEsd=*pSrcESD;
301 fpTree->Fill();
302 iResult=1; // indicate tree to be written
303 }
304
305 if (iResult>0) {
306 fpFile->cd();
307 fpTree->GetUserInfo()->Add(fpEsd);
308 fpTree->Write(fpTree->GetName(),TObject::kOverwrite);
309 fpTree->GetUserInfo()->Clear();
310 }
311 }
9877121c 312#else //HAVE_NOT_ESD_COPY
83cb7e1d 313 // this is the old workaround, necessary for older AliRoot versions
314 // version<=v4-12-Release
315
90c37647 316 // we need to copy the ESD, I did not find an approptiate
317 // method, the workaround is to save the ESD in a temporary
318 // tree, read the content back into the ESD structure
319 // used for filling.
320 // Unfortunately the following code crashes at the second event.
321 // The expert on the ESD (Christian Klein Boesig) does not have
322 // a solution either. It seems to be a problem in ROOT.
323 // TTree* dummy=new TTree("dummy","dummy");
324 // dummy->SetDirectory(0);
325 // pESD->WriteToTree(dummy);
326 // dummy->Fill();
327 // dummy->GetUserInfo()->Add(pESD);
328 // fpEsd->ReadFromTree(dummy);
329 // dummy->GetEvent(0);
330 // fpEsd->WriteToTree(fpTree);
331 // fpTree->Fill();
332 // dummy->GetUserInfo()->Clear();
333 // delete dummy;
334 //
335 // The only way is via TChain, which is working on files only at the
336 // time of writing.
337 // We use temporary files for the new event to be copied into the
338 // existing tree.
339 //
90c37647 340 if (fName.IsNull()) {
341 // this is the first event, create the file on disk and write ESD
c5123824 342 TString origin;
343 origin.Insert(0, fDt.fOrigin, kAliHLTComponentDataTypefOriginSize);
344 origin.Remove(TString::kTrailing, ' ');
345 origin.ToUpper();
90c37647 346 fName="";
347 if (!fDirectory.IsNull()) {
348 fName+=fDirectory; fName+="/";
349 }
350 fName+="AliHLT"; fName+=origin;
c5123824 351 if (fDt!=kAliHLTDataTypeESDObject &&
352 fDt!=kAliHLTDataTypeESDTree) {
353
354 HLTWarning("non-standard ESD type %s", AliHLTComponent::DataType2Text(fDt).c_str());
355 TString id;
356 id.Insert(0, fDt.fID, kAliHLTComponentDataTypefIDsize);
357 id.Remove(TString::kTrailing, ' ');
358 id.ToUpper();
359 fName+="_"; fName+=id; fName+=".root";
360 } else {
361 fName+="ESDs.root";
90c37647 362 }
363
364 if (!gSystem->AccessPathName(fName)) {
365 // file exists, delete
366 TString shellcmd="rm -f ";
367 shellcmd+=fName;
368 gSystem->Exec(shellcmd);
c5123824 369 }
370 }
90c37647 371
372 TChain chain("esdTree");
373 TList cleanup;
374 cleanup.SetOwner();
375
376 int nofCurrentEvents=0;
377 if (iResult>=0) {
378 if (!gSystem->AccessPathName(fName)) {
379 // these are the other events, use the target file and temporary files to merge
380 // with TChain
381 chain.Add(fName);
382
383 if (eventno>=0) {
384 TFile file(fName);
385 if (!file.IsZombie()) {
386 TTree* pSrcTree;
387 file.GetObject("esdTree", pSrcTree);
388 if (pSrcTree) {
389 nofCurrentEvents=pSrcTree->GetEntries();
390 }
391 file.Close();
392 }
c5123824 393 }
394 }
90c37647 395 }
396
397 // synchronize and add empty events
398 if (nofCurrentEvents<eventno) {
399 iResult=1; // indicate files to merge
400 TTree* pTgtTree=new TTree("esdTree", "Tree with HLT ESD objects");
401 if (pTgtTree) {
402 pTgtTree->SetDirectory(0);
403 AliESDEvent* pTmpESD=new AliESDEvent;
404 if (pTmpESD) {
405 TString tmpfilename;
406 FILE* pTmpFile=gSystem->TempFileName(tmpfilename);
407 if (pTmpFile) {
408 fclose(pTmpFile);
409 pTmpFile=NULL;
410 cleanup.Add(new TObjString(tmpfilename));
411 TFile emptyevents(tmpfilename, "RECREATE");
412 if (!emptyevents.IsZombie()) {
413 pTmpESD->CreateStdContent();
414 pTmpESD->WriteToTree(pTgtTree);
415 HLTDebug("adding %d empty events to file %s", eventno-nofCurrentEvents, fName.Data());
416 for (int i=nofCurrentEvents; i<eventno; i++) {
417 pTgtTree->Fill();
418 }
419 pTgtTree->GetUserInfo()->Add(pTmpESD);
420 emptyevents.cd();
421 pTgtTree->Write();
422 emptyevents.Close();
423 chain.Add(tmpfilename);
424 pTgtTree->GetUserInfo()->Clear();
425 }
c5123824 426 }
90c37647 427 delete pTmpESD;
c5123824 428 } else {
90c37647 429 iResult=-ENOMEM;
c5123824 430 }
90c37647 431 delete pTgtTree;
432 } else {
433 iResult=-ENOMEM;
434 }
435 }
436
437 if (iResult>=0 && pSrcESD) {
438 // add the new event to the chain
439 iResult=1; // indicate files to merge
440 TString tmpfilename=WriteTempFile(pSrcESD);
441 if (!tmpfilename.IsNull()) {
442 chain.Add(tmpfilename);
443 cleanup.Add(new TObjString(tmpfilename));
444 }
445 }
446
447 if (iResult>0) {
448 // build temporary file name for chain output
449 TString tgtName;
450 FILE* pTmpFile=gSystem->TempFileName(tgtName);
451 if (pTmpFile) {
452 fclose(pTmpFile);
453 pTmpFile=NULL;
454
41b5c1b6 455 // there have been problems with the memory consumption when using
456 // TChain::Merge
83cb7e1d 457 // but using a separate loop soemtimes crashes in AliESDEvent::ReadFromTree
458 // since this is for backward compatiblity only, we take the TChain::Merge
459 chain.Merge(tgtName);
460// TFile tgtFile(tgtName, "RECREATE");
461// TTree* pTgtTree=new TTree("esdTree", "Tree with HLT ESD objects");
462// AliESDEvent* pTgtESD=new AliESDEvent;
463// if (pTgtTree && pTgtESD) {
464// pTgtESD->ReadFromTree(&chain);
465// pTgtESD->WriteToTree(pTgtTree);
466
467// int nofEvents=chain.GetEntries();
468// for (int event=0; event<nofEvents; event++) {
469// chain.GetEntry(event);
470// pTgtTree->Fill();
471// }
472
473// pTgtTree->GetUserInfo()->Add(pTgtESD);
474// tgtFile.cd();
475// pTgtTree->Write();
476// pTgtTree->GetUserInfo()->Clear();
477// } else {
478// iResult=-ENOMEM;
479// }
480
481// if (pTgtTree) delete pTgtTree;
482// if (pTgtESD) delete pTgtESD;
483// tgtFile.Close();
41b5c1b6 484
90c37647 485 // rename the merged file to the original file
486 TString shellcmd="mv ";
487 shellcmd+=tgtName + " " + fName;
488 if (gSystem->Exec(shellcmd)==0) {
489 HLTDebug("renaming %s to %s", tgtName.Data(), fName.Data());
490 } else {
491 HLTError("can not rename temporary file %s to %s", tgtName.Data(), fName.Data());
c5123824 492 }
90c37647 493 } else {
494 HLTError("can not get temporary file name from system");
495 iResult=-EBADF;
496 }
497 }
498
499 // delete temporary files
41b5c1b6 500 // the list objects are cleaned up by the TList destructor as the
90c37647 501 // list is owner
502 TIter entry(&cleanup);
503 while (TObject* pObj=entry.Next()) {
504 if (dynamic_cast<TObjString*>(pObj)) {
505 TString shellcmd="rm -f ";
506 shellcmd+=(dynamic_cast<TObjString*>(pObj))->GetString();
507 gSystem->Exec(shellcmd);
508 }
509 }
9877121c 510#endif //HAVE_NOT_ESD_COPY
90c37647 511
512 return iResult;
513}
514
f1207f29 515TString AliHLTEsdManagerImplementation::AliHLTEsdListEntry::WriteTempFile(AliESDEvent* pESD) const
90c37647 516{
517 // see header file for class documentation
f7561f8d 518 int iResult=0;
90c37647 519 TString tmpfilename;
520 FILE* pTmpFile=gSystem->TempFileName(tmpfilename);
521 if (pTmpFile) {
522 fclose(pTmpFile);
523 pTmpFile=NULL;
524
525 TFile file(tmpfilename, "RECREATE");
526 if (!file.IsZombie()) {
f1207f29 527 TTree* pTree=AliHLTEsdManagerImplementation::EmbedIntoTree(pESD);
90c37647 528 if (pTree) {
529 file.cd();
530 if (pTree->Write()>0) {
c5123824 531 } else {
90c37647 532 HLTError("can not write esd tree to temporary file %s", tmpfilename.Data());
c5123824 533 }
90c37647 534
535 pTree->GetUserInfo()->Clear();
536 delete pTree;
c5123824 537 } else {
538 iResult=-ENOMEM;
539 }
90c37647 540 file.Close();
541 } else {
542 HLTError("can not open file %s", tmpfilename.Data());
3dd8541e 543 iResult=-EBADF;
c5123824 544 }
90c37647 545 } else {
546 HLTError("can not get temporary file name from system");
547 iResult=-EBADF;
c5123824 548 }
90c37647 549
550 if (iResult<0) {
551 if (gSystem->AccessPathName(tmpfilename)==0) {
552 TString shellcmd="rm -f ";
553 shellcmd+=tmpfilename;
554 gSystem->Exec(shellcmd);
555 }
556 tmpfilename="";
557 }
558 return tmpfilename;
559}
560
f1207f29 561void AliHLTEsdManagerImplementation::AliHLTEsdListEntry::SetDirectory(const char* directory)
90c37647 562{
563 // see header file for class documentation
564 if (!directory) return;
565 if (!fName.IsNull()) {
566 HLTWarning("ESD entry already in writing mode (%s), ignoring directory", fName.Data());
567 return;
568 }
569 fDirectory=directory;
570}
571
f1207f29 572void AliHLTEsdManagerImplementation::AliHLTEsdListEntry::Delete()
90c37647 573{
574 // see header file for class documentation
575 if (fName.IsNull()) return;
576 if (gSystem->AccessPathName(fName)!=0) return;
577
578 TString shellcmd="rm -f ";
579 shellcmd+=fName;
580 gSystem->Exec(shellcmd);
581 fName="";
582}
583
f1207f29 584const char* AliHLTEsdManagerImplementation::AliHLTEsdListEntry::GetFileName() const
90c37647 585{
586 // see header file for class documentation
587 return fName.Data();
c5123824 588}