added new helper components to libAliHLTUtil (EsdCollector and AliHLTOUTPublisher...
[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 // see header file for class documentation
25 // or
26 // refer to README to build package
27 // or
28 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
29
30 #include <cerrno>
31 #include <cassert>
32 #include "AliHLTOUT.h"
33 #include "TSystem.h"
34 #include "TClass.h"
35 #include "TROOT.h"
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(0),
46   fBlockDescList(),
47   fCurrent(fBlockDescList.begin()),
48   fpBuffer(NULL),
49   fDataHandlers(),
50   fbVerbose(true)
51 {
52   // see header file for class documentation
53   // or
54   // refer to README to build package
55   // or
56   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
57 }
58
59 AliHLTOUT::~AliHLTOUT()
60 {
61   // see header file for class documentation
62 }
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 {
86   // see header file for class documentation
87   if (CheckStatusFlag(kLocked)) return -EPERM;
88   fCurrent=fBlockDescList.begin();
89   fSearchDataType=dt;
90   fSearchSpecification=spec;
91   fSearchHandlerType=handlerType;
92   return FindAndSelectDataBlock();
93 }
94
95 int AliHLTOUT::SelectNextDataBlock()
96 {
97   // see header file for class documentation
98   if (CheckStatusFlag(kLocked)) return -EPERM;
99   if (fCurrent==fBlockDescList.end()) return -ENOENT;
100   fCurrent++;
101   return FindAndSelectDataBlock();
102 }
103
104 int AliHLTOUT::FindAndSelectDataBlock()
105 {
106   // see header file for class documentation
107   if (CheckStatusFlag(kLocked)) return -EPERM;
108   int iResult=-ENOENT;
109   while (fCurrent!=fBlockDescList.end() && iResult==-ENOENT) {
110     if ((*fCurrent)==fSearchDataType &&
111         (fSearchSpecification==kAliHLTVoidDataSpec || (*fCurrent)==fSearchSpecification) &&
112         (fSearchHandlerType==AliHLTModuleAgent::kUnknownOutput || FindHandlerDesc(fCurrent->GetIndex())==fSearchHandlerType)) {
113       iResult=fCurrent->GetIndex();
114       // TODO: check the byte order on the current system and the byte order of the
115       // data block, print warning when mismatch and user did not check
116       //AliHLTOUTByteOrder blockBO=CheckByteOrder();
117       CheckByteOrder();
118       /*
119         if (blockBO!=fByteOrder) {
120         SetStatusFlag(kByteOrderWarning);
121
122         }
123        */
124       ClearStatusFlag(kByteOrderChecked);
125
126       // TODO: check the alignment on the current system and the alignment of the
127       // data block, print warning when mismatch and user did not check
128       ClearStatusFlag(kAlignmentChecked);
129
130       break;
131     }
132     fCurrent++;
133   }
134   return iResult;
135 }
136
137 int AliHLTOUT::GetDataBlockDescription(AliHLTComponentDataType& dt, AliHLTUInt32_t& spec)
138 {
139   // see header file for class documentation
140   int iResult=-ENOENT;
141   if (fCurrent!=fBlockDescList.end()) {
142     iResult=0;
143     dt=(*fCurrent);
144     spec=(*fCurrent);
145   }
146   return iResult;
147 }
148
149 const AliHLTOUT::AliHLTOUTHandlerListEntry& AliHLTOUT::GetDataBlockHandlerDesc()
150 {
151   // see header file for class documentation
152   return FindHandlerDesc(GetDataBlockIndex());
153 }
154
155 AliHLTModuleAgent::AliHLTOUTHandlerType AliHLTOUT::GetDataBlockHandlerType()
156 {
157   // see header file for class documentation
158   AliHLTModuleAgent::AliHLTOUTHandlerDesc desc=FindHandlerDesc(GetDataBlockIndex());
159   AliHLTModuleAgent::AliHLTOUTHandlerType type=desc;
160   return type;
161 }
162
163 AliHLTUInt32_t AliHLTOUT::GetDataBlockIndex()
164 {
165   // see header file for class documentation
166   if (fCurrent==fBlockDescList.end()) return AliHLTOUTInvalidIndex;
167   return fCurrent->GetIndex();
168 }
169
170 int AliHLTOUT::GetDataBuffer(const AliHLTUInt8_t* &pBuffer, AliHLTUInt32_t& size)
171 {
172   // see header file for class documentation
173   int iResult=-ENOENT;
174   pBuffer=NULL;
175   size=0;
176   if (fCurrent!=fBlockDescList.end()) {
177     if ((iResult=GetDataBuffer(fCurrent->GetIndex(), pBuffer, size))>=0) {
178       fpBuffer=pBuffer;
179     }
180   }
181   return iResult;  
182 }
183
184 int AliHLTOUT::ReleaseDataBuffer(const AliHLTUInt8_t* pBuffer)
185 {
186   // see header file for class documentation
187   int iResult=0;
188   if (pBuffer==fpBuffer) {
189     fpBuffer=NULL;
190   } else {
191     HLTWarning("buffer %p does not match the provided one %p", pBuffer, fpBuffer);
192   }
193   return iResult;  
194 }
195
196 AliHLTModuleAgent* AliHLTOUT::GetAgent()
197 {
198   // see header file for class documentation
199   AliHLTModuleAgent* pAgent=NULL;
200   pAgent=FindHandlerDesc(GetDataBlockIndex());
201   return pAgent;
202 }
203
204 AliHLTOUTHandler* AliHLTOUT::GetHandler()
205 {
206   // see header file for class documentation
207   AliHLTOUTHandler* pHandler=NULL;
208   pHandler=FindHandlerDesc(GetDataBlockIndex());
209   return pHandler;
210 }
211
212 int AliHLTOUT::WriteESD(const AliHLTUInt8_t* /*pBuffer*/, AliHLTUInt32_t /*size*/, AliHLTComponentDataType /*dt*/, AliESDEvent* /*tgtesd*/) const
213 {
214   // see header file for class documentation
215   HLTWarning("method not implemented in base class");
216   return -ENOSYS;
217 }
218
219 int AliHLTOUT::AddBlockDescriptor(const AliHLTOUTBlockDescriptor desc)
220 {
221   // see header file for class documentation
222   if (!CheckStatusFlag(kCollecting)) return -EPERM;
223   int iResult=0;
224   fBlockDescList.push_back(desc);
225   return iResult;  
226 }
227
228 AliHLTOUT::AliHLTOUTByteOrder AliHLTOUT::CheckByteOrder()
229 {
230   // see header file for class documentation
231   if (fCurrent!=fBlockDescList.end()) {
232     SetStatusFlag(kByteOrderChecked);
233     AliHLTOUT::AliHLTOUTByteOrder order=CheckBlockByteOrder((*fCurrent).GetIndex());
234     return order;
235   }
236   return kInvalidByteOrder;
237 }
238
239 int AliHLTOUT::CheckAlignment(AliHLTOUT::AliHLTOUTDataType type)
240 {
241   // see header file for class documentation
242   if (fCurrent!=fBlockDescList.end()) {
243     SetStatusFlag(kAlignmentChecked);
244     int alignment=CheckBlockAlignment((*fCurrent).GetIndex(), type);
245     return alignment;
246   }
247   return -ENOENT;
248 }
249
250 int AliHLTOUT::InitHandlers()
251 {
252   // see header file for class documentation
253   int iResult=0;
254   AliHLTOUTIndexList remnants;
255   int iCount=0;
256   for (int havedata=SelectFirstDataBlock(kAliHLTAnyDataType, kAliHLTVoidDataSpec); havedata>=0; havedata=SelectNextDataBlock()) {
257     iCount++;
258     remnants.push_back(GetDataBlockIndex());
259     AliHLTComponentDataType dt=kAliHLTVoidDataType;
260     AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
261     if (GetDataBlockDescription(dt, spec)<0) break;
262     bool bHaveHandler=false;
263     for (AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent(); pAgent && iResult>=0; pAgent=AliHLTModuleAgent::GetNextAgent()) {
264       AliHLTModuleAgent::AliHLTOUTHandlerDesc handlerDesc;
265       if (pAgent->GetHandlerDescription(dt, spec, handlerDesc)>0) {
266         AliHLTOUTHandlerListEntry entry(pAgent->GetOutputHandler(dt, spec), handlerDesc, pAgent, GetDataBlockIndex());
267         InsertHandler(fDataHandlers, entry);
268         remnants.pop_back();
269         bHaveHandler=true;
270         break;
271       }
272     }
273     if (!bHaveHandler && (dt==kAliHLTDataTypeESDObject || dt==kAliHLTDataTypeESDTree)) {
274       // ESDs are handled by the framework
275       remnants.pop_back();
276     }
277   }
278
279   // warning if some of the data blocks are not selected by the kAliHLTAnyDataType
280   // criterion
281   if (GetNofDataBlocks()>iCount) {
282     HLTWarning("incomplete data type in %d out of %d data block(s)", GetNofDataBlocks()-iCount, iCount);
283   }
284
285   // warning if handler not found
286   if (remnants.size()>0) {
287     HLTWarning("no handlers found for %d data blocks out of %d", remnants.size(), iCount);
288     AliHLTOUTBlockDescriptorVector::iterator block=fBlockDescList.begin();
289     for (AliHLTOUTIndexList::iterator element=remnants.begin(); element!=remnants.end(); element++) {
290       for (int trials=0; trials<2; trials++) {
291         do {
292           // we start searching the index from the current position in the block list
293           if ((*block).GetIndex()==*element) break;
294         } while ((++block)!=fBlockDescList.end());
295         if (block==fBlockDescList.end()) {
296           // rewind and try again
297           block=fBlockDescList.begin();
298         }
299       }
300       assert(block!=fBlockDescList.end());
301       if (block!=fBlockDescList.end()) {
302         HLTDebug("   %s", AliHLTComponent::DataType2Text((AliHLTComponentDataType)*block).c_str());
303       }
304     }
305   }
306   return iResult;
307 }
308
309 int AliHLTOUT::InsertHandler(AliHLTOUTHandlerListEntryVector& list, const AliHLTOUTHandlerListEntry &entry)
310 {
311   // see header file for class documentation
312   int iResult=0;
313   AliHLTOUTHandlerListEntryVector::iterator element=list.begin();
314   while (element!=list.end()) {
315     if (entry==(*element)) break;
316     element++;
317   }
318   if (element==list.end()) {
319     list.push_back(entry);
320   } else {
321     element->AddIndex(const_cast<AliHLTOUTHandlerListEntry&>(entry));
322   }
323   return iResult;
324 }
325
326 const AliHLTOUT::AliHLTOUTHandlerListEntry& AliHLTOUT::FindHandlerDesc(AliHLTUInt32_t blockIndex)
327 {
328   // see header file for class documentation
329   AliHLTOUTHandlerListEntryVector::iterator element=fDataHandlers.begin();
330   while (element!=fDataHandlers.end()) {
331     if (element->HasIndex(blockIndex)) {
332       return *element;
333     }
334     element++;
335   }
336   return const_cast<AliHLTOUT::AliHLTOUTHandlerListEntry&>(AliHLTOUT::AliHLTOUTHandlerListEntry::fgkVoidHandlerListEntry);
337 }
338
339 AliHLTOUT::AliHLTOUTHandlerListEntry::AliHLTOUTHandlerListEntry()
340   :
341   fpHandler(NULL),
342   fpHandlerDesc(NULL),
343   fpAgent(NULL),
344   fBlocks()
345 {
346   // see header file for class documentation
347 }
348
349 AliHLTOUT::AliHLTOUTHandlerListEntry::AliHLTOUTHandlerListEntry(AliHLTOUTHandler* pHandler, 
350                                                                 AliHLTModuleAgent::AliHLTOUTHandlerDesc& handlerDesc,
351                                                                 AliHLTModuleAgent* pAgent,
352                                                                 AliHLTUInt32_t index)
353   :
354   fpHandler(pHandler),
355   fpHandlerDesc(new AliHLTModuleAgent::AliHLTOUTHandlerDesc),
356   fpAgent(pAgent),
357   fBlocks()
358 {
359   // see header file for class documentation
360   *fpHandlerDesc=handlerDesc;
361   fBlocks.push_back(index);
362 }
363
364 AliHLTOUT::AliHLTOUTHandlerListEntry::AliHLTOUTHandlerListEntry(const AliHLTOUTHandlerListEntry& src)
365   :
366   fpHandler(src.fpHandler),
367   fpHandlerDesc(new AliHLTModuleAgent::AliHLTOUTHandlerDesc),
368   fpAgent(src.fpAgent),
369   fBlocks()
370 {
371   // see header file for class documentation
372   *fpHandlerDesc=*src.fpHandlerDesc;
373   fBlocks.assign(src.fBlocks.begin(), src.fBlocks.end());
374 }
375
376 AliHLTOUT::AliHLTOUTHandlerListEntry::~AliHLTOUTHandlerListEntry()
377 {
378   // see header file for class documentation
379   if (fpHandlerDesc) delete fpHandlerDesc;
380   fpHandlerDesc=NULL;
381 }
382
383 AliHLTOUT::AliHLTOUTHandlerListEntry& AliHLTOUT::AliHLTOUTHandlerListEntry::operator=(const AliHLTOUTHandlerListEntry& src)
384 {
385   // see header file for class documentation
386   fpHandler=src.fpHandler;
387   if (src.fpHandlerDesc)
388     *fpHandlerDesc=*src.fpHandlerDesc;
389   fpAgent=src.fpAgent;
390   fBlocks.assign(src.fBlocks.begin(), src.fBlocks.end());
391   return *this;
392 }
393
394 AliHLTUInt32_t AliHLTOUT::AliHLTOUTHandlerListEntry::operator[](int i) const
395 {
396   // see header file for class documentation
397   return (int)fBlocks.size()>i?fBlocks[i]:AliHLTOUTInvalidIndex;
398 }
399
400 bool AliHLTOUT::AliHLTOUTHandlerListEntry::operator==(const AliHLTOUTHandlerListEntry& entry) const
401 {
402   // see header file for class documentation
403   if (entry.fpHandler!=fpHandler || fpHandler==NULL) return false;
404   assert(entry.fpAgent==fpAgent);
405   if (entry.fpAgent!=fpAgent) return false;
406   return true;
407 }
408
409 bool AliHLTOUT::AliHLTOUTHandlerListEntry::operator==(const AliHLTModuleAgent::AliHLTOUTHandlerType handlerType) const
410 {
411   // see header file for class documentation
412   if (!fpHandlerDesc) return false;
413   return *fpHandlerDesc==handlerType;
414 }
415
416 void AliHLTOUT::AliHLTOUTHandlerListEntry::AddIndex(AliHLTOUT::AliHLTOUTHandlerListEntry &desc)
417 {
418   // see header file for class documentation
419   AliHLTOUTIndexList::iterator element;
420   for (element=desc.fBlocks.begin(); element!=desc.fBlocks.end(); element++) {
421     AddIndex(*element);
422   }  
423 }
424
425 void AliHLTOUT::AliHLTOUTHandlerListEntry::AddIndex(AliHLTUInt32_t index)
426 {
427   // see header file for class documentation
428   fBlocks.push_back(index);
429 }
430
431 bool AliHLTOUT::AliHLTOUTHandlerListEntry::HasIndex(AliHLTUInt32_t index)
432 {
433   // see header file for class documentation
434   AliHLTOUTIndexList::iterator element;
435   for (element=fBlocks.begin(); element!=fBlocks.end(); element++) {
436     if (*element==index) return true;
437   }
438   return false;
439 }
440
441 const AliHLTOUT::AliHLTOUTHandlerListEntry AliHLTOUT::AliHLTOUTHandlerListEntry::fgkVoidHandlerListEntry;
442
443 AliHLTUInt64_t AliHLTOUT::ByteSwap64(AliHLTUInt64_t src)
444 {
445   // see header file for class documentation
446   return ((src & 0xFFULL) << 56) | 
447     ((src & 0xFF00ULL) << 40) | 
448     ((src & 0xFF0000ULL) << 24) | 
449     ((src & 0xFF000000ULL) << 8) | 
450     ((src & 0xFF00000000ULL) >> 8) | 
451     ((src & 0xFF0000000000ULL) >> 24) | 
452     ((src & 0xFF000000000000ULL) >>  40) | 
453     ((src & 0xFF00000000000000ULL) >> 56);
454 }
455
456 AliHLTUInt32_t AliHLTOUT::ByteSwap32(AliHLTUInt32_t src)
457 {
458   // see header file for class documentation
459   return ((src & 0xFFULL) << 24) | 
460     ((src & 0xFF00ULL) << 8) | 
461     ((src & 0xFF0000ULL) >> 8) | 
462     ((src & 0xFF000000ULL) >> 24);
463 }
464
465 AliHLTOUT* AliHLTOUT::New(AliRawReader* pRawReader)
466 {
467   // see header file for class documentation
468   AliHLTOUT* instance=New("AliHLTOUTRawReader");
469   if (instance) {
470     instance->SetParam(pRawReader);
471   }
472   return instance;
473 }
474
475 AliHLTOUT* AliHLTOUT::New(TTree* pDigitTree, int event)
476 {
477   // see header file for class documentation
478   AliHLTOUT* instance=New("AliHLTOUTDigitReader");
479   if (instance) {
480     instance->SetParam(pDigitTree, event);
481   }
482   return instance;
483 }
484
485 AliHLTOUT* AliHLTOUT::New(const char* classname)
486 {
487   // see header file for class documentation
488   int iLibResult=0;
489   AliHLTOUT* instance=NULL;
490   AliHLTLogging log;
491   TClass* pCl=NULL;
492   ROOT::NewFunc_t pNewFunc=NULL;
493   do {
494     pCl=TClass::GetClass(classname);
495   } while (!pCl && (iLibResult=gSystem->Load("libHLTRec.so"))==0);
496   if (iLibResult>=0) {
497     if (pCl && (pNewFunc=pCl->GetNew())!=NULL) {
498       void* p=(*pNewFunc)(NULL);
499       if (p) {
500         instance=reinterpret_cast<AliHLTOUT*>(p);
501         if (!instance) {
502           log.Logging(kHLTLogError, "AliHLTOUT::New", "HLTOUT handling", "type cast to AliHLTOUT instance failed");
503         }
504       } else {
505         log.Logging(kHLTLogError, "AliHLTOUT::New", "HLTOUT handling", "can not create AliHLTOUT instance from class descriptor");
506       }
507     } else {
508       log.Logging(kHLTLogError, "AliHLTOUT::New", "HLTOUT handling", "can not find AliHLTOUT class descriptor");
509     }
510   } else {
511     log.Logging(kHLTLogError, "AliHLTOUT::New", "HLTOUT handling", "can not load libHLTrec library");
512   }
513   return instance;
514 }
515
516 void AliHLTOUT::Delete(AliHLTOUT* pInstance)
517 {
518   // see header file for class documentation
519   if (!pInstance) return;
520
521   // check if the library is still there in order to have the
522   // destructor available
523   TClass* pCl1=TClass::GetClass("AliHLTOUTRawReader");
524   TClass* pCl2=TClass::GetClass("AliHLTOUTDigitReader");
525   if (!pCl1 && !pCl2) {
526     AliHLTLogging log;
527     log.Logging(kHLTLogError, "AliHLTOUT::Delete", "HLTOUT handling", "potential memory leak: libHLTrec library not available, skipping destruction %p", pInstance);    
528     return;
529   }
530
531   delete pInstance;  
532 }
533
534 void AliHLTOUT::SetParam(AliRawReader* /*pRawReader*/)
535 {
536   // see header file for class documentation
537   // default implementation, we should never get here
538   // this function can only be called from the class itsself and
539   // is intended to be used with the New functions. If we get into
540   // the default implementation there is a class mismatch.
541   assert(0);
542   HLTFatal("severe internal error: class mismatch");
543 }
544
545 void AliHLTOUT::SetParam(TTree* /*pDigitTree*/, int /*event*/)
546 {
547   // see header file for class documentation
548   // default implementation, we should never get here
549   // this function can only be called from the class itsself and
550   // is intended to be used with the New functions. If we get into
551   // the default implementation there is a class mismatch.
552   assert(0);
553   HLTFatal("severe internal error: class mismatch");
554 }