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