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