]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTOUT.cxx
Bug Fix.
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTOUT.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   AliHLTOUT.cxx
20     @author Matthias Richter
21     @date   
22     @brief  The control class for HLTOUT data.
23 */
24
25 #include <cerrno>
26 #include <cassert>
27 #include "AliHLTOUT.h"
28 #include "AliHLTMessage.h"
29 #include "AliHLTMisc.h"
30 #include "TSystem.h"
31 #include "TClass.h"
32 #include "TROOT.h"
33
34 /** ROOT macro for the implementation of ROOT specific class methods */
35 ClassImp(AliHLTOUT)
36
37 AliHLTOUT::AliHLTOUT()
38   :
39   fSearchDataType(kAliHLTVoidDataType),
40   fSearchSpecification(kAliHLTVoidDataSpec),
41   fSearchHandlerType(AliHLTModuleAgent::kUnknownOutput),
42   fFlags(kSkipProcessed),
43   fBlockDescList(),
44   fCurrent(0),
45   fpBuffer(NULL),
46   fDataHandlers(),
47   fbVerbose(true),
48   fLog()
49   , fpDataObject(NULL)
50   , fpObjectBuffer(NULL)
51   , fObjectBufferSize(0)
52   , fCurrentEventId(kAliHLTVoidEventID)
53 {
54   // see header file for class documentation
55   // or
56   // refer to README to build package
57   // or
58   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
59 }
60
61 AliHLTOUT::~AliHLTOUT()
62 {
63   // see header file for class documentation
64   if (CheckStatusFlag(kIsSubCollection)) {
65     fLog.LoggingVarargs(kHLTLogWarning, "AliHLTOUT", "~AliHLTOUT" , __FILE__ , __LINE__ , "severe internal error: collection has not been released, potential crash due to invalid pointer");
66   }
67
68   if (fpDataObject) {
69     fLog.LoggingVarargs(kHLTLogWarning, "AliHLTOUT", "GetDataObject" , __FILE__ , __LINE__ , "data object has not been released, potential memory leak");
70   }
71   fpDataObject=NULL;
72 }
73 AliHLTOUT* AliHLTOUT::fgGlobalInstance=NULL;
74
75 int AliHLTOUT::Init()
76 {
77   // see header file for class documentation
78   int iResult=0;
79
80   // ignore if already initialized
81   if (fBlockDescList.size()>0) {
82     fLog.LoggingVarargs(kHLTLogWarning, "AliHLTOUT", "Init" , __FILE__ , __LINE__ , "instance %p already initialized, skipping ...", this);
83     return 0;
84   }
85
86   SetStatusFlag(kCollecting);
87   if ((iResult=GenerateIndex())>=0) {
88     if ((iResult=InitHandlers())>=0) {
89     }
90   }
91   ClearStatusFlag(kCollecting);
92   return iResult;
93 }
94
95 int AliHLTOUT::GetNofDataBlocks()
96 {
97   // see header file for class documentation
98   return fBlockDescList.size();
99 }
100
101 int AliHLTOUT::SelectFirstDataBlock(AliHLTComponentDataType dt, AliHLTUInt32_t spec,
102                                     AliHLTModuleAgent::AliHLTOUTHandlerType handlerType,
103                                     bool skipProcessed)
104 {
105   // see header file for class documentation
106   fCurrent=0;
107   fSearchDataType=dt;
108   fSearchSpecification=spec;
109   fSearchHandlerType=handlerType;
110   if (skipProcessed) SetStatusFlag(kSkipProcessed);
111   else ClearStatusFlag(kSkipProcessed);
112   return FindAndSelectDataBlock();
113 }
114
115 int AliHLTOUT::SelectNextDataBlock()
116 {
117   // see header file for class documentation
118   if (fCurrent>=fBlockDescList.size()) return -ENOENT;
119   fCurrent++;
120   return FindAndSelectDataBlock();
121 }
122
123 int AliHLTOUT::FindAndSelectDataBlock()
124 {
125   // see header file for class documentation
126   if (CheckStatusFlag(kLocked)) return -EPERM;
127   int iResult=-ENOENT;
128   while (fCurrent<fBlockDescList.size() && iResult==-ENOENT) {
129     if (fBlockDescList[fCurrent]==fSearchDataType &&
130         (fSearchSpecification==kAliHLTVoidDataSpec || fBlockDescList[fCurrent]==fSearchSpecification) &&
131         (fSearchHandlerType==AliHLTModuleAgent::kUnknownOutput || FindHandlerDesc(fCurrent)==fSearchHandlerType) &&
132         (!CheckStatusFlag(kBlockSelection) || fBlockDescList[fCurrent].IsSelected()) &&
133         (!CheckStatusFlag(kSkipProcessed) || !fBlockDescList[fCurrent].IsProcessed())) {
134       iResult=fBlockDescList[fCurrent].GetIndex();
135       // TODO: check the byte order on the current system and the byte order of the
136       // data block, print warning when mismatch and user did not check
137       //AliHLTOUTByteOrder blockBO=CheckByteOrder();
138       CheckByteOrder();
139       /*
140         if (blockBO!=fByteOrder) {
141         SetStatusFlag(kByteOrderWarning);
142
143         }
144        */
145       ClearStatusFlag(kByteOrderChecked);
146
147       // TODO: check the alignment on the current system and the alignment of the
148       // data block, print warning when mismatch and user did not check
149       ClearStatusFlag(kAlignmentChecked);
150
151       break;
152     }
153     fCurrent++;
154   }
155   return iResult;
156 }
157
158 int AliHLTOUT::GetDataBlockDescription(AliHLTComponentDataType& dt, AliHLTUInt32_t& spec)
159 {
160   // see header file for class documentation
161   int iResult=-ENOENT;
162   if (fCurrent<fBlockDescList.size()) {
163     iResult=0;
164     dt=fBlockDescList[fCurrent];
165     spec=fBlockDescList[fCurrent];
166   }
167   return iResult;
168 }
169
170 const AliHLTOUT::AliHLTOUTHandlerListEntry& AliHLTOUT::GetDataBlockHandlerDesc()
171 {
172   // see header file for class documentation
173   return FindHandlerDesc(fCurrent);
174 }
175
176 AliHLTModuleAgent::AliHLTOUTHandlerType AliHLTOUT::GetDataBlockHandlerType()
177 {
178   // see header file for class documentation
179   AliHLTModuleAgent::AliHLTOUTHandlerDesc desc=FindHandlerDesc(fCurrent);
180   AliHLTModuleAgent::AliHLTOUTHandlerType type=desc;
181   return type;
182 }
183
184 AliHLTUInt32_t AliHLTOUT::GetDataBlockIndex()
185 {
186   // see header file for class documentation
187   if (fCurrent>=fBlockDescList.size()) return AliHLTOUTInvalidIndex;
188   return fBlockDescList[fCurrent].GetIndex();
189 }
190
191 int AliHLTOUT::GetDataBuffer(const AliHLTUInt8_t* &pBuffer, AliHLTUInt32_t& size)
192 {
193   // see header file for class documentation
194   int iResult=-ENOENT;
195   pBuffer=NULL;
196   size=0;
197   if (fCurrent<fBlockDescList.size()) {
198     if ((iResult=fBlockDescList[fCurrent].GetDataBuffer(pBuffer, size))>=0) {
199       fpBuffer=pBuffer;
200     }
201   }
202   return iResult;  
203 }
204
205 int AliHLTOUT::ReleaseDataBuffer(const AliHLTUInt8_t* pBuffer)
206 {
207   // see header file for class documentation
208   int iResult=0;
209   if (pBuffer==fpBuffer) {
210     fpBuffer=NULL;
211   } else {
212     fLog.LoggingVarargs(kHLTLogWarning, "AliHLTOUT", "ReleaseDataBuffer" , __FILE__ , __LINE__ , "buffer %p does not match the provided one %p", pBuffer, fpBuffer);
213   }
214   return iResult;  
215 }
216
217 AliHLTModuleAgent* AliHLTOUT::GetAgent()
218 {
219   // see header file for class documentation
220   AliHLTModuleAgent* pAgent=NULL;
221   pAgent=FindHandlerDesc(fCurrent);
222   return pAgent;
223 }
224
225 AliHLTOUTHandler* AliHLTOUT::GetHandler()
226 {
227   // see header file for class documentation
228   AliHLTOUTHandler* pHandler=NULL;
229   pHandler=FindHandlerDesc(fCurrent);
230   return pHandler;
231 }
232
233 int AliHLTOUT::WriteESD(const AliHLTUInt8_t* /*pBuffer*/, AliHLTUInt32_t /*size*/, AliHLTComponentDataType /*dt*/, AliESDEvent* /*tgtesd*/) const
234 {
235   // see header file for class documentation
236   fLog.LoggingVarargs(kHLTLogWarning, "AliHLTOUT", "WriteESD" , __FILE__ , __LINE__ , "method not implemented in base class");
237   return -ENOSYS;
238 }
239
240 int AliHLTOUT::AddBlockDescriptor(const AliHLTOUTBlockDescriptor desc)
241 {
242   // see header file for class documentation
243   if (!CheckStatusFlag(kCollecting)) return -EPERM;
244   int iResult=0;
245   fBlockDescList.push_back(desc);
246   return iResult;  
247 }
248
249 AliHLTOUT::AliHLTOUTByteOrder AliHLTOUT::CheckByteOrder()
250 {
251   // see header file for class documentation
252   if (fCurrent<fBlockDescList.size()) {
253     SetStatusFlag(kByteOrderChecked);
254     AliHLTOUT::AliHLTOUTByteOrder order=CheckBlockByteOrder(fBlockDescList[fCurrent].GetIndex());
255     return order;
256   }
257   return kInvalidByteOrder;
258 }
259
260 int AliHLTOUT::CheckAlignment(AliHLTOUT::AliHLTOUTDataType type)
261 {
262   // see header file for class documentation
263   if (fCurrent<fBlockDescList.size()) {
264     SetStatusFlag(kAlignmentChecked);
265     int alignment=CheckBlockAlignment(fBlockDescList[fCurrent].GetIndex(), type);
266     return alignment;
267   }
268   return -ENOENT;
269 }
270
271 int AliHLTOUT::InitHandlers()
272 {
273   // see header file for class documentation
274   int iResult=0;
275   AliHLTOUTIndexList remnants;
276   int iCount=0;
277   for (int havedata=SelectFirstDataBlock(kAliHLTAnyDataType, kAliHLTVoidDataSpec); havedata>=0; havedata=SelectNextDataBlock()) {
278     iCount++;
279     remnants.push_back(GetDataBlockIndex());
280     AliHLTComponentDataType dt=kAliHLTVoidDataType;
281     AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
282     if (GetDataBlockDescription(dt, spec)<0) break;
283     bool bHaveHandler=false;
284     for (AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent(); pAgent && iResult>=0; pAgent=AliHLTModuleAgent::GetNextAgent()) {
285       AliHLTModuleAgent::AliHLTOUTHandlerDesc handlerDesc;
286       if (pAgent->GetHandlerDescription(dt, spec, handlerDesc)>0) {
287         AliHLTOUTHandlerListEntry entry(pAgent->GetOutputHandler(dt, spec), handlerDesc, pAgent, GetDataBlockIndex());
288         InsertHandler(fDataHandlers, entry);
289         remnants.pop_back();
290         bHaveHandler=true;
291         break;
292       }
293     }
294     if (!bHaveHandler && (dt==kAliHLTDataTypeESDObject || dt==kAliHLTDataTypeESDTree)) {
295       // ESDs are handled by the framework
296       remnants.pop_back();
297     }
298   }
299
300   // warning if some of the data blocks are not selected by the kAliHLTAnyDataType
301   // criterion
302   if (GetNofDataBlocks()>iCount) {
303     fLog.LoggingVarargs(kHLTLogWarning, "AliHLTOUT", "InitHandlers" , __FILE__ , __LINE__ , "incomplete data type in %d out of %d data block(s)", GetNofDataBlocks()-iCount, GetNofDataBlocks());
304   }
305
306   // warning if handler not found
307   if (remnants.size()>0) {
308     fLog.LoggingVarargs(kHLTLogWarning, "AliHLTOUT", "InitHandlers" , __FILE__ , __LINE__ , "no handlers found for %d data blocks out of %d", remnants.size(), iCount);
309     AliHLTOUTBlockDescriptorVector::iterator block=fBlockDescList.begin();
310     for (AliHLTOUTIndexList::iterator element=remnants.begin(); element!=remnants.end(); element++) {
311       for (int trials=0; trials<2; trials++) {
312         do {
313           // we start searching the index from the current position in the block list
314           if ((*block).GetIndex()==*element) break;
315         } while ((++block)!=fBlockDescList.end());
316         if (block==fBlockDescList.end()) {
317           // rewind and try again
318           block=fBlockDescList.begin();
319         }
320       }
321       assert(block!=fBlockDescList.end());
322       if (block!=fBlockDescList.end()) {
323         //HLTDebug("   %s", AliHLTComponent::DataType2Text((AliHLTComponentDataType)*block).c_str());
324       }
325     }
326   }
327   return iResult;
328 }
329
330 int AliHLTOUT::InsertHandler(AliHLTOUTHandlerListEntryVector& list, const AliHLTOUTHandlerListEntry &entry)
331 {
332   // see header file for class documentation
333   int iResult=0;
334   AliHLTOUTHandlerListEntryVector::iterator element=list.begin();
335   for (; element!=list.end();
336          element++) {
337     if (entry==(*element)) break;
338   }
339   if (element==list.end()) {
340     list.push_back(entry);
341   } else {
342     element->AddIndex(const_cast<AliHLTOUTHandlerListEntry&>(entry));
343   }
344   return iResult;
345 }
346
347 int AliHLTOUT::FillHandlerList(AliHLTOUTHandlerListEntryVector& list, AliHLTModuleAgent::AliHLTOUTHandlerType handlerType)
348 {
349   // see header file for class documentation
350   int iResult=0;
351   for (iResult=SelectFirstDataBlock(kAliHLTAnyDataType, kAliHLTVoidDataSpec, handlerType);
352        iResult>=0;
353        iResult=SelectNextDataBlock()) {
354     AliHLTComponentDataType dt=kAliHLTVoidDataType;
355     AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
356     GetDataBlockDescription(dt, spec);
357     AliHLTOUTHandler* pHandler=GetHandler();
358     if (!pHandler) {
359       fLog.LoggingVarargs(kHLTLogWarning, "AliHLTOUT", "FillHandlerList" , __FILE__ , __LINE__ , 
360                          "missing HLTOUT handler for block of type kChain: agent %s, data type %s, specification %#x, ... skipping data block",
361                          GetAgent()?GetAgent()->GetModuleId():"invalid",
362                          AliHLTComponent::DataType2Text(dt).c_str(), spec);
363     } else {
364       InsertHandler(list, GetDataBlockHandlerDesc());
365     }
366   }
367   // TODO: the return value of SelectFirst/NextDataBlock must be
368   // changed in order to avoid this check
369   if (iResult==-ENOENT) iResult=0;
370
371   return iResult;
372 }
373
374 int AliHLTOUT::RemoveEmptyDuplicateHandlers(AliHLTOUTHandlerListEntryVector& list)
375 {
376   // see header file for class documentation
377   int iResult=0;
378   AliHLTOUTHandlerListEntryVector::iterator element=list.begin();
379   while (element!=list.end()) {
380     if (element->IsEmpty()) {
381       AliHLTOUTHandler* pHandler=*element;
382       AliHLTModuleAgent* pAgent=*element;
383       AliHLTModuleAgent::AliHLTOUTHandlerDesc desc=*element;
384       if (FindHandler(list, desc)>=0) {
385         element=list.erase(element);
386         if (pAgent) {
387           pAgent->DeleteOutputHandler(pHandler);
388         }
389         // we are already at the next element
390         continue;
391       }
392     }
393     element++;
394   }
395   return iResult;
396 }
397
398 int AliHLTOUT::FindHandler(AliHLTOUTHandlerListEntryVector& list, const AliHLTModuleAgent::AliHLTOUTHandlerDesc desc)
399 {
400   // see header file for class documentation
401   for (int i=0; i<(int)list.size(); i++) {
402     if (list[i]==desc) return i;
403   }
404   return -ENOENT;
405 }
406
407 int AliHLTOUT::InvalidateBlocks(AliHLTOUTHandlerListEntryVector& list)
408 {
409   // see header file for class documentation
410   for (AliHLTOUTHandlerListEntryVector::iterator element=list.begin();
411          element!=list.end();
412          element++) {
413     element->InvalidateBlocks();
414   }
415   return 0;
416 }
417
418 const AliHLTOUT::AliHLTOUTHandlerListEntry& AliHLTOUT::FindHandlerDesc(AliHLTUInt32_t blockIndex)
419 {
420   // see header file for class documentation
421   if (blockIndex<fBlockDescList.size()) {
422     return fBlockDescList[blockIndex].GetHandlerDesc();
423   }
424   return const_cast<AliHLTOUT::AliHLTOUTHandlerListEntry&>(AliHLTOUT::AliHLTOUTHandlerListEntry::fgkVoidHandlerListEntry);
425 }
426
427 AliHLTOUT::AliHLTOUTHandlerListEntry::AliHLTOUTHandlerListEntry()
428   :
429   fpHandler(NULL),
430   fpHandlerDesc(NULL),
431   fpAgent(NULL),
432   fBlocks()
433 {
434   // see header file for class documentation
435 }
436
437 AliHLTOUT::AliHLTOUTHandlerListEntry::AliHLTOUTHandlerListEntry(AliHLTOUTHandler* pHandler, 
438                                                                 AliHLTModuleAgent::AliHLTOUTHandlerDesc& handlerDesc,
439                                                                 AliHLTModuleAgent* pAgent,
440                                                                 AliHLTUInt32_t index)
441   :
442   fpHandler(pHandler),
443   fpHandlerDesc(new AliHLTModuleAgent::AliHLTOUTHandlerDesc),
444   fpAgent(pAgent),
445   fBlocks()
446 {
447   // see header file for class documentation
448   *fpHandlerDesc=handlerDesc;
449   fBlocks.push_back(index);
450 }
451
452 AliHLTOUT::AliHLTOUTHandlerListEntry::AliHLTOUTHandlerListEntry(const AliHLTOUTHandlerListEntry& src)
453   :
454   fpHandler(src.fpHandler),
455   fpHandlerDesc(new AliHLTModuleAgent::AliHLTOUTHandlerDesc),
456   fpAgent(src.fpAgent),
457   fBlocks()
458 {
459   // see header file for class documentation
460   *fpHandlerDesc=*src.fpHandlerDesc;
461   fBlocks.assign(src.fBlocks.begin(), src.fBlocks.end());
462 }
463
464 AliHLTOUT::AliHLTOUTHandlerListEntry::~AliHLTOUTHandlerListEntry()
465 {
466   // see header file for class documentation
467   if (fpHandlerDesc) delete fpHandlerDesc;
468   fpHandlerDesc=NULL;
469 }
470
471 AliHLTOUT::AliHLTOUTHandlerListEntry& AliHLTOUT::AliHLTOUTHandlerListEntry::operator=(const AliHLTOUTHandlerListEntry& src)
472 {
473   // see header file for class documentation
474   fpHandler=src.fpHandler;
475   if (src.fpHandlerDesc)
476     *fpHandlerDesc=*src.fpHandlerDesc;
477   fpAgent=src.fpAgent;
478   fBlocks.assign(src.fBlocks.begin(), src.fBlocks.end());
479   return *this;
480 }
481
482 AliHLTUInt32_t AliHLTOUT::AliHLTOUTHandlerListEntry::operator[](int i) const
483 {
484   // see header file for class documentation
485   return (int)fBlocks.size()>i?fBlocks[i]:AliHLTOUTInvalidIndex;
486 }
487
488 bool AliHLTOUT::AliHLTOUTHandlerListEntry::operator==(const AliHLTOUTHandlerListEntry& entry) const
489 {
490   // see header file for class documentation
491   if (entry.fpHandler!=fpHandler || fpHandler==NULL) return false;
492   assert(entry.fpAgent==fpAgent);
493   if (entry.fpAgent!=fpAgent) return false;
494   return true;
495 }
496
497 bool AliHLTOUT::AliHLTOUTHandlerListEntry::operator==(const AliHLTModuleAgent::AliHLTOUTHandlerType handlerType) const
498 {
499   // see header file for class documentation
500   if (!fpHandlerDesc) return false;
501   return *fpHandlerDesc==handlerType;
502 }
503
504 bool AliHLTOUT::AliHLTOUTHandlerListEntry::operator==(const AliHLTModuleAgent::AliHLTOUTHandlerDesc desc) const
505 {
506   // see header file for class documentation
507   if (!fpHandlerDesc) return false;
508   return *fpHandlerDesc==desc;
509 }
510
511 void AliHLTOUT::AliHLTOUTHandlerListEntry::AddIndex(AliHLTOUT::AliHLTOUTHandlerListEntry &desc)
512 {
513   // see header file for class documentation
514   AliHLTOUTIndexList::iterator element;
515   for (element=desc.fBlocks.begin(); element!=desc.fBlocks.end(); element++) {
516     AddIndex(*element);
517   }  
518 }
519
520 void AliHLTOUT::AliHLTOUTHandlerListEntry::AddIndex(AliHLTUInt32_t index)
521 {
522   // see header file for class documentation
523   fBlocks.push_back(index);
524 }
525
526 bool AliHLTOUT::AliHLTOUTHandlerListEntry::HasIndex(AliHLTUInt32_t index) const
527 {
528   // see header file for class documentation
529   AliHLTOUTIndexList::iterator element;
530   for (unsigned int i=0; i<fBlocks.size(); i++) {
531     if (fBlocks[i]==index) return true;
532   }
533   return false;
534 }
535
536 const AliHLTOUT::AliHLTOUTHandlerListEntry AliHLTOUT::AliHLTOUTHandlerListEntry::fgkVoidHandlerListEntry;
537
538 AliHLTUInt64_t AliHLTOUT::ByteSwap64(AliHLTUInt64_t src)
539 {
540   // see header file for class documentation
541   return ((src & 0xFFULL) << 56) | 
542     ((src & 0xFF00ULL) << 40) | 
543     ((src & 0xFF0000ULL) << 24) | 
544     ((src & 0xFF000000ULL) << 8) | 
545     ((src & 0xFF00000000ULL) >> 8) | 
546     ((src & 0xFF0000000000ULL) >> 24) | 
547     ((src & 0xFF000000000000ULL) >>  40) | 
548     ((src & 0xFF00000000000000ULL) >> 56);
549 }
550
551 AliHLTUInt32_t AliHLTOUT::ByteSwap32(AliHLTUInt32_t src)
552 {
553   // see header file for class documentation
554   return ((src & 0xFFULL) << 24) | 
555     ((src & 0xFF00ULL) << 8) | 
556     ((src & 0xFF0000ULL) >> 8) | 
557     ((src & 0xFF000000ULL) >> 24);
558 }
559
560 AliHLTOUT* AliHLTOUT::New(AliRawReader* pRawReader)
561 {
562   // see header file for class documentation
563   AliHLTOUT* instance=AliHLTMisc::LoadInstance((AliHLTOUT*)0, "AliHLTOUTRawReader", "libHLTrec.so");
564   if (instance) {
565     instance->SetParam(pRawReader);
566   }
567   return instance;
568 }
569
570 AliHLTOUT* AliHLTOUT::New(TTree* pDigitTree, int event)
571 {
572   // see header file for class documentation
573   AliHLTOUT* instance=AliHLTMisc::LoadInstance((AliHLTOUT*)0, "AliHLTOUTDigitReader", "libHLTrec.so");
574   if (instance) {
575     instance->SetParam(pDigitTree, event);
576   }
577   return instance;
578 }
579
580 AliHLTOUT* AliHLTOUT::New(const char* filename, int event)
581 {
582   // see header file for class documentation
583   AliHLTOUT* instance=AliHLTMisc::LoadInstance((AliHLTOUT*)0, "AliHLTOUTDigitReader", "libHLTrec.so");
584   if (instance) {
585     instance->SetParam(filename, event);
586   }
587   return instance;
588 }
589
590 void AliHLTOUT::Delete(AliHLTOUT* pInstance)
591 {
592   // see header file for class documentation
593   if (!pInstance) return;
594   if (pInstance==fgGlobalInstance) return;
595
596   // check if the library is still there in order to have the
597   // destructor available
598   TClass* pCl1=TClass::GetClass("AliHLTOUTRawReader");
599   TClass* pCl2=TClass::GetClass("AliHLTOUTDigitReader");
600   if (!pCl1 && !pCl2) {
601     AliHLTLogging log;
602     log.Logging(kHLTLogError, "AliHLTOUT::Delete", "HLTOUT handling", "potential memory leak: libHLTrec library not available, skipping destruction %p", pInstance);    
603     return;
604   }
605
606   delete pInstance;  
607 }
608
609 void AliHLTOUT::SetParam(AliRawReader* /*pRawReader*/)
610 {
611   // see header file for class documentation
612   // default implementation, we should never get here
613   // this function can only be called from the class itsself and
614   // is intended to be used with the New functions. If we get into
615   // the default implementation there is a class mismatch.
616   assert(0);
617   fLog.LoggingVarargs(kHLTLogFatal, "AliHLTOUT", "SetParam" , __FILE__ , __LINE__ , "severe internal error: class mismatch");
618 }
619
620 void AliHLTOUT::SetParam(TTree* /*pDigitTree*/, int /*event*/)
621 {
622   // see header file for class documentation
623   // default implementation, we should never get here
624   // this function can only be called from the class itsself and
625   // is intended to be used with the New functions. If we get into
626   // the default implementation there is a class mismatch.
627   assert(0);
628   fLog.LoggingVarargs(kHLTLogFatal, "AliHLTOUT", "SetParam" , __FILE__ , __LINE__ , "severe internal error: class mismatch");
629 }
630
631 void AliHLTOUT::SetParam(const char* /*filename*/, int /*event*/)
632 {
633   // see header file for class documentation
634   // default implementation, we should never get here
635   // this function can only be called from the class itsself and
636   // is intended to be used with the New functions. If we get into
637   // the default implementation there is a class mismatch.
638   assert(0);
639   fLog.LoggingVarargs(kHLTLogFatal, "AliHLTOUT", "SetParam" , __FILE__ , __LINE__ , "severe internal error: class mismatch");
640 }
641
642 int AliHLTOUT::SelectDataBlock()
643 {
644   // see header file for class documentation
645   int iResult=0;
646   if (fCurrent>=fBlockDescList.size()) return 0;
647   fBlockDescList[fCurrent].Select(true);
648   EnableBlockSelection();
649   return iResult;
650 }
651
652 int AliHLTOUT::SelectDataBlocks(const AliHLTOUTHandlerListEntry* pHandlerEntry)
653 {
654   // see header file for class documentation
655   int iResult=0;
656   if (!pHandlerEntry) return 0;
657
658   AliHLTModuleAgent* pAgent=*pHandlerEntry;
659   AliHLTLogging log;
660   log.Logging(kHLTLogDebug, "AliHLTOUT::SelectDataBlocks", "HLTOUT handling", "selecting blocks for handler %s", pAgent->GetModuleId());
661   AliHLTOUTBlockDescriptorVector::iterator element;
662   for (AliHLTOUTBlockDescriptorVector::iterator block=fBlockDescList.begin();
663        block!=fBlockDescList.end();
664        block++) {
665     if (block->GetHandlerDesc()==*pHandlerEntry && pHandlerEntry->HasIndex(block->GetIndex())) {
666       block->Select(true);
667       log.Logging(kHLTLogDebug, "AliHLTOUT::SelectDataBlocks", "HLTOUT handling", "   select block %s", AliHLTComponent::DataType2Text(*block).c_str());
668     } else {
669       log.Logging(kHLTLogDebug, "AliHLTOUT::SelectDataBlocks", "HLTOUT handling", "   skip block %s", AliHLTComponent::DataType2Text(*block).c_str());
670       block->Select(false);
671     }
672   }
673   EnableBlockSelection();
674
675   // Matthias 2009-07-03 bugfix: the fCurrent position was not reset at that
676   // place. Also I think the data type and specification must be set in order
677   // to make SelectFirst/NextDataBlock working on the selected collection
678   // of data blocks
679   AliHLTModuleAgent::AliHLTOUTHandlerDesc pHandlerDesc=*pHandlerEntry; 
680   fSearchDataType=pHandlerDesc;
681   fSearchSpecification=kAliHLTVoidDataSpec;
682   fSearchHandlerType=pHandlerDesc;
683   fCurrent=0;
684   
685   return iResult;
686 }
687
688 int AliHLTOUT::EnableBlockSelection()
689 {
690   // see header file for class documentation
691   SetStatusFlag(kBlockSelection);
692   return 0;
693 }
694
695 int AliHLTOUT::DisableBlockSelection()
696 {
697   // see header file for class documentation
698   ClearStatusFlag(kBlockSelection);
699   return 0;
700 }
701
702 int AliHLTOUT::ResetBlockSelection()
703 {
704   // see header file for class documentation
705   for (AliHLTOUTBlockDescriptorVector::iterator block=fBlockDescList.begin();
706        block!=fBlockDescList.end();
707        block++) {
708     block->Select(false);
709   }
710   return 0;
711 }
712
713 int AliHLTOUT::MarkDataBlockProcessed()
714 {
715   // see header file for class documentation
716   int iResult=0;
717   if (fCurrent>=fBlockDescList.size()) return 0;
718   fBlockDescList[fCurrent].MarkProcessed();
719   return iResult;
720 }
721
722 int AliHLTOUT::MarkDataBlocksProcessed(const AliHLTOUTHandlerListEntry* pHandlerDesc)
723 {
724   // see header file for class documentation
725   int iResult=0;
726   if (!pHandlerDesc) return 0;
727
728   AliHLTOUTBlockDescriptorVector::iterator element;
729   for (AliHLTOUTBlockDescriptorVector::iterator block=fBlockDescList.begin();
730        block!=fBlockDescList.end();
731        block++) {
732     if (block->GetHandlerDesc()==*pHandlerDesc && pHandlerDesc->HasIndex(block->GetIndex()))
733       block->MarkProcessed();
734   }
735   
736   return iResult;
737 }
738
739 int AliHLTOUT::AddSubCollection(AliHLTOUT* pCollection)
740 {
741   // see header file for class documentation
742   int iResult=0;
743   if (!pCollection) return 0;
744
745   SetStatusFlag(kCollecting);  
746   int index=-1;
747   for (index=pCollection->SelectFirstDataBlock();
748        index>=0;
749        index=pCollection->SelectNextDataBlock()) {
750     AliHLTComponentDataType dt=kAliHLTVoidDataType;
751     AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
752     pCollection->GetDataBlockDescription(dt, spec);  
753     AliHLTOUTBlockDescriptor desc(dt, spec, index, pCollection);
754     AddBlockDescriptor(desc);
755     iResult++;
756   }
757   if (iResult>0) {
758     if (CheckStatusFlag(kIsSubCollection)) {
759       fLog.LoggingVarargs(kHLTLogWarning, "AliHLTOUT", "AddSubCollection" , __FILE__ , __LINE__ , "HLTOUT object %p has already been added as sub-collection", pCollection);
760     } else {
761       pCollection->SetStatusFlag(kIsSubCollection);
762     }
763   }
764   ClearStatusFlag(kCollecting);  
765
766   return iResult;
767 }
768
769 int AliHLTOUT::ReleaseSubCollection(AliHLTOUT* pCollection)
770 {
771   // see header file for class documentation
772   int iResult=0;
773   if (!pCollection) return 0;
774
775   AliHLTOUTBlockDescriptorVector::iterator block=fBlockDescList.begin();
776   while (block!=fBlockDescList.end()) {
777     if ((*block)==pCollection) {
778       block=fBlockDescList.erase(block);
779       continue;
780     }
781     block++;
782   }
783   pCollection->ClearStatusFlag(kIsSubCollection);
784
785   return iResult;
786 }
787
788 int AliHLTOUT::Reset()
789 {
790   // see header file for class documentation
791   int iResult=0;
792   AliHLTOUTPVector subCollections;
793   AliHLTOUTBlockDescriptorVector::iterator block=fBlockDescList.begin();
794   while (block!=fBlockDescList.end()) {
795     if (!((*block)==this)) {
796       AliHLTOUTPVector::iterator collection=subCollections.begin();
797       for (; collection!=subCollections.end(); collection++)
798         if((*block)==*collection) break;
799       if (collection==subCollections.end())
800         subCollections.push_back(block->GetCollection());
801     }
802     block=fBlockDescList.erase(block);
803   }
804
805   for (AliHLTOUTPVector::iterator collection=subCollections.begin(); 
806        collection!=subCollections.end(); collection++) {
807     (*collection)->Reset();
808     (*collection)->ClearStatusFlag(kIsSubCollection);
809   }
810
811   ResetInput();
812   fCurrentEventId=kAliHLTVoidEventID;
813
814   return iResult;
815 }
816
817 int AliHLTOUT::ResetInput()
818 {
819   // default implementation, nothing to do
820   return 0;
821 }
822
823 const AliHLTOUT::AliHLTOUTHandlerListEntry& AliHLTOUT::AliHLTOUTBlockDescriptor::GetHandlerDesc()
824 {
825   // see header file for class documentation
826   if (fpCollection) {
827     AliHLTOUTHandlerListEntryVector::iterator element=fpCollection->fDataHandlers.begin();
828     while (element!=fpCollection->fDataHandlers.end()) {
829       if (element->HasIndex(GetIndex())) {
830         return *element;
831       }
832       element++;
833     }
834   }
835   return const_cast<AliHLTOUT::AliHLTOUTHandlerListEntry&>(AliHLTOUT::AliHLTOUTHandlerListEntry::fgkVoidHandlerListEntry);
836 }
837
838 TObject* AliHLTOUT::GetDataObject()
839 {
840   // see header file for class documentation
841   if (fpDataObject) {
842     fLog.LoggingVarargs(kHLTLogWarning, "AliHLTOUT", "GetDataObject" , __FILE__ , __LINE__ , "data object has not been released, potential memory leak");
843     ReleaseDataBuffer(fpObjectBuffer);
844   }
845   fpObjectBuffer=NULL;
846   fObjectBufferSize=0;
847   fpDataObject=NULL;
848
849   if (GetDataBuffer(fpObjectBuffer, fObjectBufferSize)>=0) {
850     fpDataObject=AliHLTMessage::Extract(fpObjectBuffer, fObjectBufferSize);
851   } else {
852     fLog.LoggingVarargs(kHLTLogError, "AliHLTOUT", "GetDataObject" , __FILE__ , __LINE__ , "can not fetch data buffer");    
853   }
854
855   return fpDataObject;
856 }
857
858 int AliHLTOUT::ReleaseDataObject(TObject* pObject)
859 {
860   // see header file for class documentation
861   if (!pObject) return -EINVAL;
862   if (pObject!=fpDataObject) {
863     fLog.LoggingVarargs(kHLTLogError, "AliHLTOUT", "GetDataObject" , __FILE__ , __LINE__ , "attempt to release wrong data object %p, expected %p", pObject, fpDataObject);
864     return -EINVAL;
865   }
866
867   delete fpDataObject;
868   fpDataObject=NULL;
869   ReleaseDataBuffer(fpObjectBuffer);
870   fpObjectBuffer=NULL;
871   fObjectBufferSize=0;
872
873   return 0;
874 }
875
876 void AliHLTOUT::SetEventId(AliHLTUInt64_t id)
877 {
878   // see header file for class documentation
879   if (fCurrentEventId!=kAliHLTVoidEventID && fCurrentEventId!=id) {
880     fLog.LoggingVarargs(kHLTLogWarning, "AliHLTOUT", "SetEventId" , __FILE__ , __LINE__ , "event id was already set to 0x%llx, setting now to 0x%llx", fCurrentEventId, id);
881   }
882   fCurrentEventId=id;
883 }