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