]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTDataBuffer.h
minor changes according to coding conventions
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTDataBuffer.h
1 // @(#) $Id$
2
3 #ifndef ALIHLTDATABUFFER_H
4 #define ALIHLTDATABUFFER_H
5 /* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
6  * See cxx source for full Copyright notice                               */
7
8 /** @file   AliHLTDataBuffer.h
9     @author Matthias Richter
10     @date   
11     @brief  Handling of Data Buffers for HLT components.
12     @note   The class is used in Offline (AliRoot) context
13 */
14
15 #include <cerrno>
16 #include <vector>
17 #include "AliHLTLogging.h"
18 #include "AliHLTDataTypes.h"
19 #include "AliHLTDefinitions.h"
20 #include "TObject.h"
21 //#include "TList.h"
22
23 class AliHLTComponent;
24 /* @name internal data structures
25  */
26
27 /**
28  * @struct AliHLTDataSegment
29  * @brief  Descriptor of a data segment within the buffer.
30  * @ingroup alihlt_system
31  */
32 struct AliHLTDataSegment {
33   AliHLTDataSegment()
34     :
35     fDataType(),
36     fSegmentOffset(0),
37     fSegmentSize(0),
38     fSpecification(0)
39   {
40     memset(&fDataType, 0, sizeof(AliHLTComponentDataType));
41   }
42   AliHLTDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size) 
43     :
44     fDataType(),
45     fSegmentOffset(offset),
46     fSegmentSize(size),
47     fSpecification(0)
48   {
49     memset(&fDataType, 0, sizeof(AliHLTComponentDataType));
50   }
51   /** the data type of this segment */
52   AliHLTComponentDataType fDataType;                               // see above
53   /** offset in byte within the data buffer */
54   AliHLTUInt32_t fSegmentOffset;                                   // see above
55   /** size of the actual content */
56   AliHLTUInt32_t fSegmentSize;                                     // see above
57   /** data specification */
58   AliHLTUInt32_t fSpecification;                                   // see above
59 };
60
61 /**
62  * @struct AliHLTRawBuffer
63  * @brief  Descriptor of the raw data buffer which can host several segments.
64  * @ingroup alihlt_system
65  */
66 struct AliHLTRawBuffer {
67   /** size of the currently occupied partition of the buffer */
68   AliHLTUInt32_t fSize;                                            // see above
69   /** total size of the buffer, including safety margin */
70   AliHLTUInt32_t fTotalSize;                                       // see above
71   /** the buffer */
72   void* fPtr;                                                      //! transient
73 };
74
75 /**
76  * @class AliHLTConsumerDescriptor
77  * @brief Helper class to describe a consumer component.
78  *
79  * There is unfortunately no unique determination of the data type from the
80  * component itself possible, thats why both component and data type have to
81  * be initialized and are stored in a compound. The class is intended to make
82  * bookkeeping easier.
83  *
84  * @note This class is only used for the @ref alihlt_system.
85  *
86  * @ingroup alihlt_system
87  */
88 class AliHLTConsumerDescriptor : public TObject, public AliHLTLogging {
89  public:
90   /** standard constructur */
91   AliHLTConsumerDescriptor();
92   /** constructur 
93    * @param pConsumer pointer to the consumer component
94    */
95   AliHLTConsumerDescriptor(AliHLTComponent* pConsumer);
96   /** not a valid copy constructor, defined according to effective C++ style */
97   AliHLTConsumerDescriptor(const AliHLTConsumerDescriptor&);
98   /** not a valid assignment op, but defined according to effective C++ style */
99   AliHLTConsumerDescriptor& operator=(const AliHLTConsumerDescriptor&);
100   /** destructor */
101   ~AliHLTConsumerDescriptor();
102
103   /**
104    * Get the component of this descriptor.
105    * @return pointer to the component
106    */
107   AliHLTComponent* GetComponent() {return fpConsumer;}
108
109   /**
110    * Set an active data segment.
111    * the pointer will be handled in a container, no allocation, copy or
112    * cleanup.
113    * @param offset  offset of the segment in the buffer
114    * @param size    size of the segment in the buffer
115    * @return >=0 if succeeded
116    */
117   int SetActiveDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size);
118
119   /**
120    * Check whether there is an active data segment of certain size with
121    * certain offset.
122    * @param offset  offset of the data segment in the data buffer
123    * @param size    size of the data segment in the data buffer
124    * @return > if existend, 0 if not
125    */
126   int CheckActiveDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size);
127
128   /** find an active data segment of certain size with certain offset
129    * will see if this is necessary
130    * @param offset  offset of the data segment in the data buffer
131    * @param size    size of the data segment in the data buffer
132    * @return offset of the data segment
133    */
134   //AliHLTUInt32_t FindActiveDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size);
135
136   /** get the number of active segments for this consumer
137    * @return number of active segments
138    */
139   int GetNofActiveSegments() {return fSegments.size();};
140
141   /**
142    */
143   int ReleaseActiveDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size);
144
145  private:
146   /** consumer object */
147   AliHLTComponent* fpConsumer;                                     //! transient
148
149   /** list of data segments */
150   vector<AliHLTDataSegment> fSegments;                             // see above
151
152   //ClassDef(AliHLTConsumerDescriptor, 0)
153 };
154
155 /**
156  * @class AliHLTDataBuffer
157  * @brief  Handling of data buffers for the HLT.
158  * 
159  * The class provides handling of data buffers for HLT tasks. Each task gets
160  * its own Data Buffer instance. The buffer is grouped into different data
161  * segments according to the output of the component.<br>
162  * The Data Buffer keeps control over the data requests of the 'child'
163  * components. Each component can subscribe to a certain segment of the data
164  * buffer. It's state is then changed from 'reserved' to 'active'. After the
165  * data processing, the component has to release the segment and it's state is
166  * set to 'processed'. If all components have requested and released their data,
167  * the Raw Buffer is released and pushed back in the list of available buffers.
168  *
169  * @note This class is only used for the @ref alihlt_system.
170  *
171  * @ingroup alihlt_system
172  */
173 class AliHLTDataBuffer : public TObject, public AliHLTLogging {
174  public:
175   //////////////////////////////////////////////////////////////////////////////
176   // condtructors and destructors
177
178   /* standard constructor
179    */
180   AliHLTDataBuffer();
181   /** not a valid copy constructor, defined according to effective C++ style */
182   AliHLTDataBuffer(const AliHLTDataBuffer&);
183   /** not a valid assignment op, but defined according to effective C++ style */
184   AliHLTDataBuffer& operator=(const AliHLTDataBuffer&);
185   /** destructor */
186   virtual ~AliHLTDataBuffer();
187
188   //////////////////////////////////////////////////////////////////////////////
189   // initialization
190
191   /**
192    * Add component to the list of consumers
193    * @param pConsumer - a consumer of type AliHLTComponent
194    */
195   int SetConsumer(AliHLTComponent* pConsumer);
196
197   //////////////////////////////////////////////////////////////////////////////
198   // component to component communication
199
200   /**
201    * Determine the number of matching data blocks for the component and a
202    * consumer component. <br>
203    * The first approach will support only one output data type for processing
204    * components.
205    * @param pConsumer       the component which subscribes to the buffer
206    * @param tgtList         (optional) the list to receive the data types
207    * @return: number of data blocks which match the input data types 
208    *          of the consumer, neg. error code if failed <br>
209    *          -EINVAL       invalid parameter <br>
210    */
211   int FindMatchingDataBlocks(const AliHLTComponent* pConsumer,
212                              vector<AliHLTComponentDataType>* tgtList=NULL);
213
214   /**
215    * Subscribe to a segment of the data buffer.
216    * The function prepares the block descriptor for subsequent use with the
217    * AliHLTComponent::ProcessEvent method, the method can prepare several block
218    * descriptors up to the array size specified by iArraySize. The return value
219    * is independent from the array size the number of block descriptors which
220    * would have been prepared if there was enough space in the array<br>
221    * The method is used by the consumer component.
222    * @param pConsumer       the component which subscribes to the buffer
223    * @param arrayBlockDesc  pointer to block descriptor to be filled
224    * @param iArraySize      size of the block descriptor array
225    * @return: number of matching data blocks, neg. error code if failed<br>
226    *          -EACCESS      the consumer state can't be changed (activated)
227    *          -EBADF        unresolved data segments <br>
228    *          -ENOENT       consumer component not found <br>
229    *          -ENODATA      data buffer does not have raw data <br>
230    *          -EINVAL       invalid parameter <br>
231    */
232   int Subscribe(const AliHLTComponent* pConsumer,
233                 AliHLTComponentBlockData* arrayBlockDesc,
234                 int iArraySize);
235
236   /**
237    * Release an instance of the data buffer.
238    * Resets the variables of the block descriptor.
239    * If all buffer segments are released, the Data Buffer is reseted
240    * and the Raw Buffer released.<br>
241    * The method is used by the consumer component.
242    * @param pBlockDesc      descriptor of the data segment
243    * @param pConsumer       the component which subscribes to the buffer
244    * @return: >0 if success, negative error code if failed <br>
245    *          -EACCESS      the consumer state can not be changed (de-activated)
246    *          -ENOENT       consumer has not subscribed to the buffer <br>
247    *          -EINVAL       invalid parameter <br>
248    */
249   int Release(AliHLTComponentBlockData* pBlockDesc, const AliHLTComponent* pConsumer);
250
251   /**
252    * Get a target buffer of minimum size iMinSize.
253    * The method is used by the component which owns the Data Buffer to 
254    * allocate a buffer for the data it is going to produce.
255    * @param iMinSize        minumum size of the requested buffer
256    * @return: pointer to target buffer if 
257    */
258   AliHLTUInt8_t* GetTargetBuffer(int iMinSize);
259
260   /**
261    * Set the segments for the data buffer.
262    * This is usually done after the component has written the data to the buffer, 
263    * which was requested by the @ref GetTargetBuffer method. The component might
264    * produce different types of data, for each type a segment has to be defined
265    * which describes the data inside the buffer.<br>
266    * The @ref AliHLTComponentBlockData segment descriptor comes directly from
267    * the @ref AliHLTComponent::ProcessEvent method.
268    * @param pTgt            the target buffer which the segments refer to
269    * @param arraySegments   the output block descriptors of the component
270    * @param iSize           size of the array
271    */
272   int SetSegments(AliHLTUInt8_t* pTgt, AliHLTComponentBlockData* arraySegments, int iSize);
273
274   /**
275    * Check if the data buffer is empty.
276    * @return 1 if empty, 0 if not
277    */
278   int IsEmpty();
279
280   /**
281    * Get the total and maximum size of the buffer.
282    * Lets see if this is needed later
283    */
284   //int GetTotalSize();
285
286   /**
287    * Get the number of segments
288    * @return number of segments
289    */
290   int GetNofSegments();
291
292   /**
293    * Get the number of consumers
294    * @return number of consumers
295    */
296   int GetNofConsumers();
297
298   /**
299    * Get the number of active consumers
300    * @return number of active consumers
301    */
302   int GetNofActiveConsumers();
303
304   /**
305    * Check if a consumer is already in the list
306    * @param pConsumer   pointer to consumer component
307    * @param bAllLists   search in all lists if 1
308    *                    search only in fConsumer list if 0
309    * @return 1 if found, 0 if not
310    */
311   int FindConsumer(AliHLTComponent* pConsumer, int bAllLists=1);
312
313   /**
314    * Public method to reset the buffer.
315    * Eventually with some additional checks. In normal operation,
316    * an external reset should not be necessary.
317    */
318   int Reset();
319
320  private:
321   /* lets see if this is needed
322   AliHLTDataSegment* FindDataSegment(AliHLTComponentDataType datatype);
323   */
324
325   /**
326    * Find those data segments which match the input types of a component.
327    * @param pConsumer       the component which subscribes to the buffer
328    * @param tgtList         the list to receive the data segment descriptors
329    * @return: number of data blocks which match the input data types 
330    *          of the consumer, neg. error code if failed <br>
331    *          -EINVAL       invalid parameter <br>
332    */
333   int FindMatchingDataSegments(const AliHLTComponent* pConsumer, vector<AliHLTDataSegment>& tgtList);
334
335   /**
336    * Reset the data buffer.
337    * Removes all consumers back to the @ref fConsumers list, deletes
338    * segments and releases the Raw Buffer.
339    */
340   int ResetDataBuffer();
341
342   //////////////////////////////////////////////////////////////////////////////
343
344   // the data description
345
346   // the data segments within this buffer
347   vector<AliHLTDataSegment> fSegments;                             // see above
348
349   // the list of all consumers which are going to subscribe to the buffer
350   vector<AliHLTConsumerDescriptor*> fConsumers;                    // see above
351   // the list of all consumers which are currently subscribed to the buffer
352   vector<AliHLTConsumerDescriptor*> fActiveConsumers;              // see above
353   // the list of all consumers which are already released for the current event
354   vector<AliHLTConsumerDescriptor*> fReleasedConsumers;            // see above
355
356   // the buffer instance
357   AliHLTRawBuffer* fpBuffer;                                       //! transient
358
359   // flags indicating the state of the buffer
360   AliHLTUInt32_t fFlags;                                           // see above
361
362   //////////////////////////////////////////////////////////////////////////////
363   // global buffer handling, internal use only
364
365   /**
366    * Create a raw buffer of a certain size.
367    * The function tries to find a buffer of the given size (or a bit bigger by a 
368    * certain margin @ref fgMargin) from the list of free buffers.
369    * If no buffer is available, a new one is created and added to the buffer handling.
370    * @param size            min. size of the requested buffer
371    * @return pointer to raw buffer
372    */
373   static AliHLTRawBuffer* CreateRawBuffer(AliHLTUInt32_t size);
374
375   /**
376    * Mark a buffer as free.
377    * After the Data Buffer has finnished using the raw buffer, it is released
378    * and added to the list of available buffers.
379    * @param pBuffer         the raw buffer to release
380    * @return >=0 if succeeded, neg. error code if failed
381    */
382   static int ReleaseRawBuffer(AliHLTRawBuffer* pBuffer);
383
384   /**
385    * Deletes all the raw buffers.
386    * When the last Data Buffer object is destructed, all raw data buffers are
387    * relesed.
388    */
389   static int DeleteRawBuffers();
390
391   /**
392    * Number of instances of AliHLTDataBuffer.
393    * The statice variable is incremented and decremented in the constructor/
394    * destructor. All internal data structures are cleaned up when the last
395    * instance is exiting.
396    */
397   static int fgNofInstances;                                       // see above
398   /** global list of free raw buffers */
399   static vector<AliHLTRawBuffer*> fgFreeBuffers;                   // see above
400   /** global list of currently active raw buffers */
401   static vector<AliHLTRawBuffer*> fgActiveBuffers;                 // see above
402   /** determines the raw buffer size margin at buffer requests */
403   static AliHLTUInt32_t fgMargin;                                  // see above
404
405   /** global instance to HLT logging class for static methods */
406   static AliHLTLogging fgLogging;                                  // see above
407
408   //////////////////////////////////////////////////////////////////////////////
409   // internal helper functions
410
411   /**
412    * Find the consumer descriptor for a certain component and data type in 
413    * a list of consumers.<br>
414    * <b>Note:</b> There are three lists which contain the consumers in the
415    * different states.
416    * @param pConsumer       pointer to consumer component
417    * @param list            list where to search for the consumer
418    */
419   AliHLTConsumerDescriptor* FindConsumer(const AliHLTComponent* pConsumer,
420                                          vector<AliHLTConsumerDescriptor*> &list) const;
421
422   /**
423    * Change the state of a consumer.
424    * The state of a consumer is determined by the list it is strored in, the
425    * method moves a consumer from the source to the target list.
426    * @param pDesc           pointer to consumer descriptor
427    * @param srcList         list where the consumer is currently to be found
428    * @param tgtList         list where to move the consumer
429    */
430   int ChangeConsumerState(AliHLTConsumerDescriptor* pDesc,
431                           vector<AliHLTConsumerDescriptor*> &srcList,
432                           vector<AliHLTConsumerDescriptor*> &tgtList);
433
434   /**
435    * Cleanup a consumer list.
436    * Release all allocated data structures. <b>Note:</b> Not the component itself!
437    */
438   int CleanupConsumerList();
439
440   ClassDef(AliHLTDataBuffer, 0)
441 };
442 #endif // ALIHLTDATABUFFER_H