3f2a1b1c |
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 | |
b22e91eb |
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 | */ |
3f2a1b1c |
14 | |
15 | #include <cerrno> |
8ede8717 |
16 | #include <vector> |
3f2a1b1c |
17 | #include "AliHLTLogging.h" |
18 | #include "AliHLTDataTypes.h" |
19 | #include "AliHLTDefinitions.h" |
3f2a1b1c |
20 | #include "TObject.h" |
70ed7d01 |
21 | //#include "TList.h" |
3f2a1b1c |
22 | |
b22e91eb |
23 | class AliHLTComponent; |
0c0c9d99 |
24 | /* @name internal data structures |
25 | */ |
26 | |
b22e91eb |
27 | /** |
28 | * @struct AliHLTDataSegment |
29 | * @brief Descriptor of a data segment within the buffer. |
30 | * @ingroup alihlt_system |
3f2a1b1c |
31 | */ |
32 | struct AliHLTDataSegment { |
0c0c9d99 |
33 | AliHLTDataSegment() |
85869391 |
34 | : |
35 | fDataType(), |
36 | fSegmentOffset(0), |
37 | fSegmentSize(0), |
38 | fSpecification(0) |
0c0c9d99 |
39 | { |
8ede8717 |
40 | memset(&fDataType, 0, sizeof(AliHLTComponentDataType)); |
0c0c9d99 |
41 | } |
42 | AliHLTDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size) |
85869391 |
43 | : |
44 | fDataType(), |
45 | fSegmentOffset(offset), |
46 | fSegmentSize(size), |
47 | fSpecification(0) |
0c0c9d99 |
48 | { |
8ede8717 |
49 | memset(&fDataType, 0, sizeof(AliHLTComponentDataType)); |
0c0c9d99 |
50 | } |
b22e91eb |
51 | /** the data type of this segment */ |
70ed7d01 |
52 | AliHLTComponentDataType fDataType; // see above |
b22e91eb |
53 | /** offset in byte within the data buffer */ |
70ed7d01 |
54 | AliHLTUInt32_t fSegmentOffset; // see above |
b22e91eb |
55 | /** size of the actual content */ |
70ed7d01 |
56 | AliHLTUInt32_t fSegmentSize; // see above |
b22e91eb |
57 | /** data specification */ |
70ed7d01 |
58 | AliHLTUInt32_t fSpecification; // see above |
3f2a1b1c |
59 | }; |
60 | |
b22e91eb |
61 | /** |
62 | * @struct AliHLTRawBuffer |
63 | * @brief Descriptor of the raw data buffer which can host several segments. |
64 | * @ingroup alihlt_system |
3f2a1b1c |
65 | */ |
66 | struct AliHLTRawBuffer { |
b22e91eb |
67 | /** size of the currently occupied partition of the buffer */ |
70ed7d01 |
68 | AliHLTUInt32_t fSize; // see above |
b22e91eb |
69 | /** total size of the buffer, including safety margin */ |
70ed7d01 |
70 | AliHLTUInt32_t fTotalSize; // see above |
b22e91eb |
71 | /** the buffer */ |
70ed7d01 |
72 | void* fPtr; //! transient |
3f2a1b1c |
73 | }; |
74 | |
b22e91eb |
75 | /** |
76 | * @class AliHLTConsumerDescriptor |
77 | * @brief Helper class to describe a consumer component. |
78 | * |
70ed7d01 |
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. |
b22e91eb |
83 | * |
84 | * @note This class is only used for the @ref alihlt_system. |
85 | * |
86 | * @ingroup alihlt_system |
3f2a1b1c |
87 | */ |
53feaef5 |
88 | class AliHLTConsumerDescriptor : public TObject, public AliHLTLogging { |
3f2a1b1c |
89 | public: |
0c0c9d99 |
90 | /** standard constructur */ |
3f2a1b1c |
91 | AliHLTConsumerDescriptor(); |
0c0c9d99 |
92 | /** constructur |
93 | * @param pConsumer pointer to the consumer component |
94 | */ |
95 | AliHLTConsumerDescriptor(AliHLTComponent* pConsumer); |
85869391 |
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 */ |
3f2a1b1c |
101 | ~AliHLTConsumerDescriptor(); |
102 | |
0c0c9d99 |
103 | /** |
70ed7d01 |
104 | * Get the component of this descriptor. |
0c0c9d99 |
105 | * @return pointer to the component |
106 | */ |
3f2a1b1c |
107 | AliHLTComponent* GetComponent() {return fpConsumer;} |
3f2a1b1c |
108 | |
0c0c9d99 |
109 | /** |
70ed7d01 |
110 | * Set an active data segment. |
111 | * the pointer will be handled in a container, no allocation, copy or |
112 | * cleanup. |
bfccbf68 |
113 | * @param offset offset of the segment in the buffer |
114 | * @param size size of the segment in the buffer |
0c0c9d99 |
115 | * @return >=0 if succeeded |
116 | */ |
117 | int SetActiveDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size); |
118 | |
119 | /** |
70ed7d01 |
120 | * Check whether there is an active data segment of certain size with |
121 | * certain offset. |
0c0c9d99 |
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 | */ |
3f2a1b1c |
126 | int CheckActiveDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size); |
0c0c9d99 |
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 | |
70ed7d01 |
145 | private: |
146 | /** consumer object */ |
147 | AliHLTComponent* fpConsumer; //! transient |
148 | |
149 | /** list of data segments */ |
150 | vector<AliHLTDataSegment> fSegments; // see above |
151 | |
0c0c9d99 |
152 | //ClassDef(AliHLTConsumerDescriptor, 0) |
3f2a1b1c |
153 | }; |
154 | |
0c0c9d99 |
155 | /** |
bfccbf68 |
156 | * @class AliHLTDataBuffer |
157 | * @brief Handling of data buffers for the HLT. |
b22e91eb |
158 | * |
70ed7d01 |
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. |
b22e91eb |
168 | * |
169 | * @note This class is only used for the @ref alihlt_system. |
170 | * |
171 | * @ingroup alihlt_system |
0c0c9d99 |
172 | */ |
53feaef5 |
173 | class AliHLTDataBuffer : public TObject, public AliHLTLogging { |
3f2a1b1c |
174 | public: |
70ed7d01 |
175 | ////////////////////////////////////////////////////////////////////////////// |
0c0c9d99 |
176 | // condtructors and destructors |
177 | |
178 | /* standard constructor |
179 | */ |
3f2a1b1c |
180 | AliHLTDataBuffer(); |
85869391 |
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 */ |
3f2a1b1c |
186 | virtual ~AliHLTDataBuffer(); |
187 | |
70ed7d01 |
188 | ////////////////////////////////////////////////////////////////////////////// |
3f2a1b1c |
189 | // initialization |
190 | |
0c0c9d99 |
191 | /** |
192 | * Add component to the list of consumers |
193 | * @param pConsumer - a consumer of type AliHLTComponent |
3f2a1b1c |
194 | */ |
0c0c9d99 |
195 | int SetConsumer(AliHLTComponent* pConsumer); |
3f2a1b1c |
196 | |
70ed7d01 |
197 | ////////////////////////////////////////////////////////////////////////////// |
3f2a1b1c |
198 | // component to component communication |
199 | |
0c0c9d99 |
200 | /** |
70ed7d01 |
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. |
0c0c9d99 |
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> |
3f2a1b1c |
210 | */ |
70ed7d01 |
211 | int FindMatchingDataBlocks(const AliHLTComponent* pConsumer, |
212 | vector<AliHLTComponentDataType>* tgtList=NULL); |
0c0c9d99 |
213 | |
214 | /** |
215 | * Subscribe to a segment of the data buffer. |
70ed7d01 |
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> |
0c0c9d99 |
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 |
70ed7d01 |
225 | * @return: number of matching data blocks, neg. error code if failed<br> |
226 | * -EACCESS the consumer state can't be changed (activated) |
0c0c9d99 |
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 | */ |
70ed7d01 |
232 | int Subscribe(const AliHLTComponent* pConsumer, |
233 | AliHLTComponentBlockData* arrayBlockDesc, |
234 | int iArraySize); |
0c0c9d99 |
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> |
70ed7d01 |
245 | * -EACCESS the consumer state can not be changed (de-activated) |
246 | * -ENOENT consumer has not subscribed to the buffer <br> |
0c0c9d99 |
247 | * -EINVAL invalid parameter <br> |
3f2a1b1c |
248 | */ |
8ede8717 |
249 | int Release(AliHLTComponentBlockData* pBlockDesc, const AliHLTComponent* pConsumer); |
3f2a1b1c |
250 | |
0c0c9d99 |
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 |
3f2a1b1c |
257 | */ |
258 | AliHLTUInt8_t* GetTargetBuffer(int iMinSize); |
259 | |
0c0c9d99 |
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 |
2d7ff710 |
265 | * which describes the data inside the buffer.<br> |
70ed7d01 |
266 | * The @ref AliHLTComponentBlockData segment descriptor comes directly from |
267 | * the @ref AliHLTComponent::ProcessEvent method. |
0c0c9d99 |
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 |
3f2a1b1c |
271 | */ |
8ede8717 |
272 | int SetSegments(AliHLTUInt8_t* pTgt, AliHLTComponentBlockData* arraySegments, int iSize); |
3f2a1b1c |
273 | |
0c0c9d99 |
274 | /** |
275 | * Check if the data buffer is empty. |
276 | * @return 1 if empty, 0 if not |
3f2a1b1c |
277 | */ |
278 | int IsEmpty(); |
279 | |
0c0c9d99 |
280 | /** |
281 | * Get the total and maximum size of the buffer. |
282 | * Lets see if this is needed later |
3f2a1b1c |
283 | */ |
284 | //int GetTotalSize(); |
285 | |
0c0c9d99 |
286 | /** |
287 | * Get the number of segments |
288 | * @return number of segments |
3f2a1b1c |
289 | */ |
290 | int GetNofSegments(); |
291 | |
0c0c9d99 |
292 | /** |
293 | * Get the number of consumers |
294 | * @return number of consumers |
3f2a1b1c |
295 | */ |
296 | int GetNofConsumers(); |
297 | |
0c0c9d99 |
298 | /** |
299 | * Get the number of active consumers |
300 | * @return number of active consumers |
3f2a1b1c |
301 | */ |
302 | int GetNofActiveConsumers(); |
303 | |
9ce4bf4a |
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 | |
3f2a1b1c |
320 | private: |
0c0c9d99 |
321 | /* lets see if this is needed |
8ede8717 |
322 | AliHLTDataSegment* FindDataSegment(AliHLTComponentDataType datatype); |
0c0c9d99 |
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); |
3f2a1b1c |
334 | |
0c0c9d99 |
335 | /** |
336 | * Reset the data buffer. |
9ce4bf4a |
337 | * Removes all consumers back to the @ref fConsumers list, deletes |
338 | * segments and releases the Raw Buffer. |
3f2a1b1c |
339 | */ |
340 | int ResetDataBuffer(); |
341 | |
70ed7d01 |
342 | ////////////////////////////////////////////////////////////////////////////// |
343 | |
3f2a1b1c |
344 | // the data description |
3f2a1b1c |
345 | |
0c0c9d99 |
346 | // the data segments within this buffer |
70ed7d01 |
347 | vector<AliHLTDataSegment> fSegments; // see above |
3f2a1b1c |
348 | |
0c0c9d99 |
349 | // the list of all consumers which are going to subscribe to the buffer |
70ed7d01 |
350 | vector<AliHLTConsumerDescriptor*> fConsumers; // see above |
0c0c9d99 |
351 | // the list of all consumers which are currently subscribed to the buffer |
70ed7d01 |
352 | vector<AliHLTConsumerDescriptor*> fActiveConsumers; // see above |
0c0c9d99 |
353 | // the list of all consumers which are already released for the current event |
70ed7d01 |
354 | vector<AliHLTConsumerDescriptor*> fReleasedConsumers; // see above |
3f2a1b1c |
355 | |
0c0c9d99 |
356 | // the buffer instance |
70ed7d01 |
357 | AliHLTRawBuffer* fpBuffer; //! transient |
3f2a1b1c |
358 | |
0c0c9d99 |
359 | // flags indicating the state of the buffer |
70ed7d01 |
360 | AliHLTUInt32_t fFlags; // see above |
3f2a1b1c |
361 | |
70ed7d01 |
362 | ////////////////////////////////////////////////////////////////////////////// |
0c0c9d99 |
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 |
9ddaea75 |
368 | * certain margin @ref fgMargin) from the list of free buffers. |
0c0c9d99 |
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 |
3f2a1b1c |
372 | */ |
373 | static AliHLTRawBuffer* CreateRawBuffer(AliHLTUInt32_t size); |
374 | |
0c0c9d99 |
375 | /** |
376 | * Mark a buffer as free. |
70ed7d01 |
377 | * After the Data Buffer has finnished using the raw buffer, it is released |
378 | * and added to the list of available buffers. |
0c0c9d99 |
379 | * @param pBuffer the raw buffer to release |
380 | * @return >=0 if succeeded, neg. error code if failed |
3f2a1b1c |
381 | */ |
382 | static int ReleaseRawBuffer(AliHLTRawBuffer* pBuffer); |
383 | |
0c0c9d99 |
384 | /** |
385 | * Deletes all the raw buffers. |
70ed7d01 |
386 | * When the last Data Buffer object is destructed, all raw data buffers are |
387 | * relesed. |
3f2a1b1c |
388 | */ |
389 | static int DeleteRawBuffers(); |
390 | |
0c0c9d99 |
391 | /** |
392 | * Number of instances of AliHLTDataBuffer. |
70ed7d01 |
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. |
0c0c9d99 |
396 | */ |
70ed7d01 |
397 | static int fgNofInstances; // see above |
0c0c9d99 |
398 | /** global list of free raw buffers */ |
70ed7d01 |
399 | static vector<AliHLTRawBuffer*> fgFreeBuffers; // see above |
0c0c9d99 |
400 | /** global list of currently active raw buffers */ |
70ed7d01 |
401 | static vector<AliHLTRawBuffer*> fgActiveBuffers; // see above |
0c0c9d99 |
402 | /** determines the raw buffer size margin at buffer requests */ |
70ed7d01 |
403 | static AliHLTUInt32_t fgMargin; // see above |
3f2a1b1c |
404 | |
0c0c9d99 |
405 | /** global instance to HLT logging class for static methods */ |
70ed7d01 |
406 | static AliHLTLogging fgLogging; // see above |
3f2a1b1c |
407 | |
70ed7d01 |
408 | ////////////////////////////////////////////////////////////////////////////// |
0c0c9d99 |
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> |
70ed7d01 |
414 | * <b>Note:</b> There are three lists which contain the consumers in the |
415 | * different states. |
0c0c9d99 |
416 | * @param pConsumer pointer to consumer component |
417 | * @param list list where to search for the consumer |
418 | */ |
70ed7d01 |
419 | AliHLTConsumerDescriptor* FindConsumer(const AliHLTComponent* pConsumer, |
420 | vector<AliHLTConsumerDescriptor*> &list) const; |
0c0c9d99 |
421 | |
422 | /** |
423 | * Change the state of a consumer. |
70ed7d01 |
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. |
0c0c9d99 |
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 | */ |
70ed7d01 |
430 | int ChangeConsumerState(AliHLTConsumerDescriptor* pDesc, |
431 | vector<AliHLTConsumerDescriptor*> &srcList, |
432 | vector<AliHLTConsumerDescriptor*> &tgtList); |
3f2a1b1c |
433 | |
0c0c9d99 |
434 | /** |
435 | * Cleanup a consumer list. |
436 | * Release all allocated data structures. <b>Note:</b> Not the component itself! |
437 | */ |
3f2a1b1c |
438 | int CleanupConsumerList(); |
439 | |
440 | ClassDef(AliHLTDataBuffer, 0) |
441 | }; |
442 | #endif // ALIHLTDATABUFFER_H |