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