added new helper components to libAliHLTUtil (EsdCollector and AliHLTOUTPublisher...
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTOUT.h
1 //-*- Mode: C++ -*-
2 // @(#) $Id$
3
4 #ifndef ALIHLTOUT_H
5 #define ALIHLTOUT_H
6 //* This file is property of and copyright by the ALICE HLT Project        * 
7 //* ALICE Experiment at CERN, All rights reserved.                         *
8 //* See cxx source for full Copyright notice                               *
9
10 /** @file   AliHLTOUT.h
11     @author Matthias Richter
12     @date   
13     @brief  The control class for HLTOUT data.
14 */
15
16 #include <vector>
17 #include "AliHLTLogging.h"
18 #include "AliHLTModuleAgent.h"
19
20 class AliHLTOUTHandler;
21 class AliHLTOUTHandlerDesc; // AliHLTModuleAgent.h
22 class AliESDEvent;
23 class AliHLTReconstructor;
24 class AliRawReader;
25 class TTree;
26
27 #define AliHLTOUTInvalidIndex (~(AliHLTUInt32_t)0)
28
29 typedef vector<AliHLTUInt32_t> AliHLTOUTIndexList;
30
31 /**
32  * @class AliHLTOUT
33  * The control class for HLTOUT data.
34  * The output of the HLT, either from the HLTOUT nodes or simulated output,
35  * is transferred and stored in the HOMER format. The AliHLTOUT class 
36  * implements scanning of the HOMER data for all HLTOUT DDL links and
37  * abstracts access to the complete HLTOUT data.
38  * 
39  */
40 class AliHLTOUT : public AliHLTLogging {
41  public:
42   /** standard constructor */
43   AliHLTOUT();
44   /** standard destructor */
45   virtual ~AliHLTOUT();
46
47   /**
48    * Create an AliHLTOUTRawReader instance.
49    * Helper function to transparently access classes from the
50    * libHLTrec library.
51    */
52   static AliHLTOUT* New(AliRawReader* pRawReader);
53
54   /**
55    * Create an AliHLTOUTDigitReader instance
56    * Helper function to transparently access classes from the
57    * libHLTrec library.
58    */
59   static AliHLTOUT* New(TTree* pDigitTree, int event=-1);
60
61   /**
62    * Delete an instance of the HLTOUT.
63    * Helper function to transparently access classes from the
64    * libHLTrec library. Before deleting, the availability of the
65    * library is checked.
66    */
67   static void Delete(AliHLTOUT* pInstance);
68
69   /**
70    * Locking guard for the AliHLTOUT object.
71    * If the object is locked, the selection of data blocks can not be changed.
72    */
73   class AliHLTOUTLockGuard {
74   public:
75     /** constructor */
76     AliHLTOUTLockGuard(AliHLTOUT* pInstance) : fpInstance(pInstance)
77     {if (fpInstance) fpInstance->SetStatusFlag(kLocked);}
78     /** destructor */
79     ~AliHLTOUTLockGuard()
80     {if (fpInstance) fpInstance->ClearStatusFlag(kLocked);}
81
82   private:
83     /** standard constructor prohibited */
84     AliHLTOUTLockGuard();
85     /** copy constructor prohibited */
86     AliHLTOUTLockGuard(const AliHLTOUTLockGuard&);
87     /** assignment operator prohibited */
88     AliHLTOUTLockGuard& operator=(const AliHLTOUTLockGuard&);
89
90     /** the AliHLTOUT instance the guard is locking */
91     AliHLTOUT* fpInstance; //!transient
92   };
93
94   /**
95    * The HLT OUT Event Header.
96    * Defined between HLT and DAQ.
97    */
98   struct AliHLTOUTEventHeader {
99     /**Total length of the data in bytes, including HLT event header, excluding CDH. */
100     AliHLTUInt32_t fLength; //! see above
101     /** version of the header */
102     AliHLTUInt32_t fVersion; //! see above
103     /** High 32 bit word of event id */
104     AliHLTUInt32_t fEventIDHigh; //! see above
105     /** Low 32 bit word of event id */
106     AliHLTUInt32_t fEventIDLow; //! see above
107   };
108
109   enum {
110     /// versions 1 of the HLT header
111     kVersion1 = 1,
112     /// versions 2 of the HLT header
113     kVersion2 = 2
114   };
115
116   enum {
117     /// size of HLT decision in data format version 1: 29x4
118     kSizeDecisionVersion1 = 116,
119     /// size of HLT decision in data format version 2: 30x4
120     kSizeDecisionVersion2 = 120
121   };
122
123   // definitions from ALICE internal notes ALICE-INT-2002-010 and
124   // ALICE-INT-2006-XXX
125   enum {
126     /** the 32bit word in the CDH containing the status flags */
127     kCDHStatusWord=4, //! see above
128     /** start of the flags in word fgkCDHStatusWord */
129     kCDHStatusFlagsOffset=12, //! see above
130     /** bit indicating HLT decision in the HLTOUT*/
131     kCDHFlagsHLTDecision=6, //! see above
132     /** bit indicating HLT payload in the HLTOUT*/
133     kCDHFlagsHLTPayload=7 //! see above
134   };
135
136   /**
137    * Block descriptor.
138    */
139   class AliHLTOUTBlockDescriptor {
140   public:
141     AliHLTOUTBlockDescriptor(AliHLTComponentDataType dt, AliHLTUInt32_t spec, AliHLTUInt32_t index)
142       : fDataType(dt), fSpecification(spec), fIndex(index) {};
143     ~AliHLTOUTBlockDescriptor() {}
144
145     operator AliHLTComponentDataType() const {return fDataType;}
146     operator AliHLTUInt32_t() const {return fSpecification;}
147     int operator==(AliHLTComponentDataType dt) const {return dt==fDataType;}
148     int operator==(AliHLTUInt32_t spec) const {return spec==fSpecification;}
149
150     AliHLTUInt32_t GetIndex() const {return fIndex;}
151   private:
152     /** data type of the block */
153     AliHLTComponentDataType fDataType; //!transient
154     /** data specification of the block */
155     AliHLTUInt32_t          fSpecification; //!transient
156     /** index in the data stream */
157     AliHLTUInt32_t          fIndex; //!transient
158   };
159
160   class AliHLTOUTHandlerListEntry {
161   public:
162     AliHLTOUTHandlerListEntry(AliHLTOUTHandler* pHandler, 
163                               AliHLTModuleAgent::AliHLTOUTHandlerDesc& handlerDesc,
164                               AliHLTModuleAgent* pAgent,
165                               AliHLTUInt32_t index);
166
167     /** copy constructor for vector handling */
168     AliHLTOUTHandlerListEntry(const AliHLTOUTHandlerListEntry& src);
169
170     /** assignment operator for vector handling */
171     AliHLTOUTHandlerListEntry& operator=(const AliHLTOUTHandlerListEntry& src);
172
173     ~AliHLTOUTHandlerListEntry();
174
175     static const AliHLTOUTHandlerListEntry fgkVoidHandlerListEntry; //! initializer
176
177     operator AliHLTOUTHandler*() const {return fpHandler;}
178
179     // please note that fpHandlerDesc is really a pointer and is created
180     // in the constructor. Thats why it is dereferenced here. The pointer
181     // type is on purpose, even though it is a bit confusing with the 
182     // argument by reference in the AliHLTOUTHandlerListEntry constructor.
183     operator const AliHLTModuleAgent::AliHLTOUTHandlerDesc&() const 
184     {return fpHandlerDesc?*fpHandlerDesc:AliHLTModuleAgent::fgkVoidHandlerDesc;}
185     operator AliHLTModuleAgent*() const {return fpAgent;}
186
187     /**
188      * Two list entries are considered to be equal if the handlers
189      * are equal.
190      */
191     bool operator==(const AliHLTOUTHandlerListEntry& entry) const;
192
193     bool operator==(const AliHLTModuleAgent::AliHLTOUTHandlerType handlerType) const;
194
195     AliHLTUInt32_t operator[](int i) const;
196
197     /**
198      * Add a block index to this descriptor.
199      * One descriptor can serve multiple blocks if the agent returns the
200      * same handler for all of the blocks. Instead of creating a new entry
201      * the block index ist just added
202      */
203     void AddIndex(AliHLTUInt32_t index);
204
205     /**
206      * Add all indexes of the descriptor.
207      */
208     void AddIndex(AliHLTOUTHandlerListEntry &desc);
209
210     /**
211      * Check if an index is served by this descriptor.
212      * @return true if the index is in the table
213      */
214     bool HasIndex(AliHLTUInt32_t index);
215
216   private:
217     /** standard constructor prohibited */
218     AliHLTOUTHandlerListEntry();
219
220     /** pointer to the handler */
221     AliHLTOUTHandler* fpHandler; //! transient
222
223     /** pointer to handler description */
224     AliHLTModuleAgent::AliHLTOUTHandlerDesc* fpHandlerDesc; //! transient
225
226     /** pointer to module agent */
227     AliHLTModuleAgent* fpAgent; //! transient
228
229     /** list of block indexes */
230     AliHLTOUTIndexList fBlocks; //!transient
231   };
232
233   typedef vector<AliHLTOUTHandlerListEntry> AliHLTOUTHandlerListEntryVector;
234   typedef vector<AliHLTOUTBlockDescriptor>  AliHLTOUTBlockDescriptorVector;
235
236   /**
237    * Init for processing.
238    * The HLTOUT is scanned for all available data blocks and the
239    * AliHLTOUTHandler objects for the data blocks are created according
240    * to the module agents (see AliHLTModuleAgent).
241    */
242   int Init();
243
244   /**
245    * Get number of data blocks in the HLTOUT data
246    */
247   int GetNofDataBlocks();
248
249   /**
250    * Select the first data block of a certain data type and specification.
251    * The selection criteria can be of kAliHLTAnyDataType and/or
252    * kAliHLTVoidDataSpec in order to be ignored and just match any data block.
253    *
254    * The search criteria can be combined with a handler type (e.g. kRawReader)
255    * @param dt    [in]  data type to match                                <br>
256    * @param spec  [in]  data specification to match                       <br>
257    * @param handlerType [in]  type of the handler
258    * @return block index: >= 0 if success, -ENOENT if no block found      <br>
259    *         neg. error code if failed                                    <br>
260    *                        -EPERM if access denied (object locked)
261    */
262   int SelectFirstDataBlock(AliHLTComponentDataType dt=kAliHLTAnyDataType,
263                            AliHLTUInt32_t spec=kAliHLTVoidDataSpec,
264                            AliHLTModuleAgent::AliHLTOUTHandlerType handlerType=AliHLTModuleAgent::kUnknownOutput);
265
266   /**
267    * Select the next data block of data type and specification of the previous
268    * call to @ref SelectFirstDataBlock.
269    * @return block index: >= 0 if success, -ENOENT if no block found      <br>
270    *         neg. error code if failed                                    <br>
271    *                        -EPERM if access denied (object locked)
272    */
273   int SelectNextDataBlock();
274
275   /**
276    * Get properties of the selected data block.
277    * @param dt    [out] data type of the selected block
278    * @param spec  [out] data specification of the selected block
279    */
280   int GetDataBlockDescription(AliHLTComponentDataType& dt, AliHLTUInt32_t& spec);
281
282   /**
283    * Get handler description of the current data block.
284    */
285   const AliHLTOUTHandlerListEntry& GetDataBlockHandlerDesc();
286
287   /**
288    * Get handler type of the selected data block.
289    * @return handler type for the selected data block
290    */
291   AliHLTModuleAgent::AliHLTOUTHandlerType GetDataBlockHandlerType();
292
293   /**
294    * Get the index of the current data block.
295    * @return index, AliHLTOUTInvalidIndex if no block selected
296    */
297   AliHLTUInt32_t GetDataBlockIndex();
298
299   /**
300    * Get buffer of the selected data block.
301    * @param pBuffer [out] buffer of the selected data block
302    * @param size    [out] size of the selected data block
303    */
304   int GetDataBuffer(const AliHLTUInt8_t* &pBuffer, AliHLTUInt32_t& size);
305
306   /**
307    * Release buffer after use.
308    * @param pBuffer [in]  buffer of the selected data block
309    */
310   int ReleaseDataBuffer(const AliHLTUInt8_t* pBuffer);
311
312   /**
313    * Get module agent for the selected data block.
314    */
315   AliHLTModuleAgent* GetAgent();
316
317   /**
318    * Get handler for the selected data block.
319    */
320   AliHLTOUTHandler* GetHandler();
321
322   /**
323    * Convert data buffer to ESD.
324    * The buffer is supposed to describe a streamed AliESDEvent object.
325    * If no target object is specified, the ESD is written to a file AliHLTdetESDs.root,
326    * where 'det' is derived from the data type origin. Each time the function is invoked
327    * a new event is created. Dummy events are added if the previous events did not contain
328    *
329    * The function needs AliRoot and might not be implemented by all AliHLTOUT
330    * implementations.
331    * a data block of this specification.
332    * @param pBuffer  [in] the data buffer
333    * @param size     [in] data buffer size
334    * @param dt       [in] data type of the block
335    * @param tgtesd   [out] optional target
336    */
337   virtual int WriteESD(const AliHLTUInt8_t* pBuffer, AliHLTUInt32_t size, AliHLTComponentDataType dt, AliESDEvent* tgtesd=NULL) const;
338
339   enum AliHLTOUTByteOrder {
340     /** no data block selected */
341     kInvalidByteOrder=-1,
342     kUnknownByteOrder=0,
343     kLittleEndian,
344     kBigEndian
345   };
346
347   enum AliHLTOUTDataType {
348     kUint64 = 0,
349     kUint32 = 1,
350     kUint16 = 2,
351     kUint8  = 3,
352     kDouble = 4,
353     kFloat  = 5
354   };
355
356   /**
357    * Check byte order of selected block
358    */
359   AliHLTOUTByteOrder CheckByteOrder();
360
361   /**
362    * Check alignment of selected block
363    */
364   int CheckAlignment(AliHLTOUT::AliHLTOUTDataType type);
365
366   /**
367    * Helper function to byte swap a 64 bit value.
368    */
369   static AliHLTUInt64_t ByteSwap64(AliHLTUInt64_t src);
370
371   /**
372    * Helper function to byte swap a 32 bit value.
373    */
374   static AliHLTUInt32_t ByteSwap32(AliHLTUInt32_t src);
375
376   /**
377    * Insert a handler item.
378    * The current list entries are checked if the handler is already in
379    * the list. It is added if not in the list, otherwise the block index
380    * is added to the existing entry.
381    * @param list     the handler list
382    * @param entry    handler list entry
383    * @return 0 if added, EEXIST (non negative!) if merged with existing entry <br>
384    *         neg. error code if failed
385    */
386   static int InsertHandler(AliHLTOUTHandlerListEntryVector& list, const AliHLTOUTHandlerListEntry &entry);
387   
388  protected:
389   /**
390    * Add a block descriptor.
391    * This is done by the child classes generating the index. The AliHLTOUT
392    * object must be locked for index generation.
393    * @param desc    the block descriptor
394    * @return 0 if success, -EPERM if access denied
395    */
396   int AddBlockDescriptor(const AliHLTOUTBlockDescriptor desc);
397
398   /**
399    * Print output or suppress.
400    */
401   bool BeVerbose() {return fbVerbose;}
402
403   /**
404    * Switch output.
405    */
406   void SwitchVerbosity(bool verbose) {fbVerbose=verbose;}
407
408  private:
409   /** copy constructor prohibited */
410   AliHLTOUT(const AliHLTOUT&);
411   /** assignment operator prohibited */
412   AliHLTOUT& operator=(const AliHLTOUT&);
413
414   /**
415    * Internal status flags
416    */
417   enum {
418     /** the HLTOUT object is locked with the current data block */
419     kLocked = 0x1,
420     /** childs can add block descriptors */
421     kCollecting = 0x2,
422     /** user of the data block has checked the byte order */
423     kByteOrderChecked = 0x4,
424     /** warning on byte order missmatch has been printed */
425     kByteOrderWarning = 0x8,
426     /** user of the data block has checked the alignment */
427     kAlignmentChecked = 0x10,
428     /** warning on alignment missmatch has been printed */
429     kAlignmentWarning = 0x20
430   };
431
432   /**
433    * Generate the index of the HLTOUT data.
434    * Must be implemented by the child classes.
435    */
436   virtual int GenerateIndex()=0;
437
438   /**
439    * Find AliHLTOUTHandler objects for the data blocks.
440    * The available AliHLTModuleAgents are probed whether they provide
441    * handlers for data processing.
442    */
443   int InitHandlers();
444
445   /**
446    * Get the data buffer
447    * @param index   [in]  index of the block
448    * @param pBuffer [out] buffer of the selected data block
449    * @param size    [out] size of the selected data block
450    */
451   virtual int GetDataBuffer(AliHLTUInt32_t index, const AliHLTUInt8_t* &pBuffer, 
452                             AliHLTUInt32_t& size)=0;
453
454   /**
455    * Check byte order of data block
456    */
457   virtual AliHLTOUTByteOrder CheckBlockByteOrder(AliHLTUInt32_t index)=0;
458
459   /**
460    * Check alignment of data block
461    */
462   virtual int CheckBlockAlignment(AliHLTUInt32_t index, AliHLTOUT::AliHLTOUTDataType type)=0;
463
464   /**
465    * Select the data block of data type and specification of the previous
466    * call to @ref SelectFirstDataBlock. Core function of @ref SelectFirstDataBlock
467    * and @ref SelectNextDataBlock, starts to find a block at the current list
468    * position. 
469    * @return identifier >=0 if success, neg. error code if failed         <br>
470    *                        -ENOENT if no block found                     <br>
471    *                        -EPERM if access denied (object locked)
472    */
473   int FindAndSelectDataBlock();
474
475   /**
476    * Set status flag.
477    * @param flag     flag to set
478    * @return current status flags
479    */
480   unsigned int SetStatusFlag(unsigned int flag) {return fFlags|=flag;}
481
482   /**
483    * Clear status flag.
484    * @param flag     flag to clear
485    * @return current status flags
486    */
487   unsigned int ClearStatusFlag(unsigned int flag) {return fFlags&=~flag;}
488
489   /**
490    * Check status flag.
491    * @param flag     flag to check
492    * @return 1 if flag is set
493    */
494   int CheckStatusFlag(unsigned int flag) const {return (fFlags&flag)==flag;}
495
496   /**
497    * Find handler description for a certain block index.
498    */
499   const AliHLTOUTHandlerListEntry& FindHandlerDesc(AliHLTUInt32_t blockIndex);
500
501   /**
502    * Internal New function for the external HLTOUT instances.
503    * Currently supported classes are AliHLTOUTRawReader and
504    * AliHLTOUTDigitReader, both implemented in libHLTrec.so.
505    */
506   static AliHLTOUT* New(const char* classname);
507
508   /**
509    * Set the RawReader as parameter.
510    * The function is for internal use only in conjunction with the
511    * New() functions.
512    */
513   virtual void SetParam(AliRawReader* pRawReader);
514
515   /**
516    * Set the RunLoader as parameter
517    * The function is for internal use only in conjunction with the
518    * New() functions.
519    */
520   virtual void SetParam(TTree* pDigitTree, int event=-1);
521
522   /** data type for the current block search, set from @ref SelectFirstDataBlock */
523   AliHLTComponentDataType fSearchDataType; //!transient
524
525   /** data specification for the current block search */
526   AliHLTUInt32_t fSearchSpecification; //!transient
527
528   /** handler type for the current block search */
529   AliHLTModuleAgent::AliHLTOUTHandlerType fSearchHandlerType; // !transient
530
531   /** instance flags: locked, collecting, ... */
532   unsigned int fFlags; //!transient
533
534   /** list of block descriptors */
535   AliHLTOUTBlockDescriptorVector fBlockDescList; //!transient
536
537   /** current position in the list */
538   AliHLTOUTBlockDescriptorVector::iterator fCurrent; //!transient
539
540   /** data buffer under processing */
541   const AliHLTUInt8_t* fpBuffer; //!transient
542
543   /** list of AliHLTOUTHandlers */
544   AliHLTOUTHandlerListEntryVector fDataHandlers; // !transient
545
546   /** verbose or silent output */
547   bool fbVerbose; //!transient
548
549   ClassDef(AliHLTOUT, 2)
550 };
551 #endif