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