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