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