]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/BASE/AliHLTDataBuffer.cxx
bugfix: correcting sequence of DataBuffer cleanup in order to first release all consu...
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTDataBuffer.cxx
CommitLineData
3f2a1b1c 1// $Id$
2
c5123824 3//**************************************************************************
4//* This file is property of and copyright by the ALICE HLT Project *
5//* ALICE Experiment at CERN, All rights reserved. *
6//* *
7//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8//* for The ALICE HLT Project. *
9//* *
10//* Permission to use, copy, modify and distribute this software and its *
11//* documentation strictly for non-commercial purposes is hereby granted *
12//* without fee, provided that the above copyright notice appears in all *
13//* copies and that both the copyright notice and this permission notice *
14//* appear in the supporting documentation. The authors make no claims *
15//* about the suitability of this software for any purpose. It is *
16//* provided "as is" without express or implied warranty. *
17//**************************************************************************
3f2a1b1c 18
b22e91eb 19/** @file AliHLTDataBuffer.cxx
20 @author Matthias Richter
21 @date
22 @brief Handling of Data Buffers for HLT components.
23*/
3f2a1b1c 24
0c0c9d99 25#if __GNUC__>= 3
3f2a1b1c 26using namespace std;
27#endif
28
29#include "AliHLTDataBuffer.h"
6235cd38 30#include "AliHLTConsumerDescriptor.h"
b22e91eb 31#include "AliHLTComponent.h"
b46ca65e 32#include "AliHLTTask.h"
66043029 33#include <cerrno>
d6cbe999 34#include <cassert>
66043029 35//#include <string>
36//#include "AliHLTSystem.h"
3f2a1b1c 37
2be3f004 38typedef vector<AliHLTDataBuffer::AliHLTDataSegment> AliHLTDataSegmentList;
2be3f004 39
b22e91eb 40/** ROOT macro for the implementation of ROOT specific class methods */
3f2a1b1c 41ClassImp(AliHLTDataBuffer)
42
3f2a1b1c 43AliHLTDataBuffer::AliHLTDataBuffer()
85869391 44 :
45 fSegments(),
46 fConsumers(),
47 fActiveConsumers(),
48 fReleasedConsumers(),
49 fpBuffer(NULL),
b46ca65e 50 fFlags(0),
51 fForwardedSegmentSources(),
52 fForwardedSegments()
3f2a1b1c 53{
70ed7d01 54 // see header file for class documentation
55 // or
56 // refer to README to build package
57 // or
58 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
85869391 59 fSegments.empty();
60 fConsumers.empty();
61 fActiveConsumers.empty();
62 fReleasedConsumers.empty();
70ed7d01 63 fgNofInstances++;
3f2a1b1c 64}
65
70ed7d01 66int AliHLTDataBuffer::fgNofInstances=0;
545d509f 67AliHLTDataBuffer::AliHLTRawBufferPList AliHLTDataBuffer::fgFreeBuffers;
68AliHLTDataBuffer::AliHLTRawBufferPList AliHLTDataBuffer::fgActiveBuffers;
70ed7d01 69AliHLTUInt32_t AliHLTDataBuffer::fgMargin=1024;
b22e91eb 70AliHLTLogging AliHLTDataBuffer::fgLogging;
8451168b 71const Int_t AliHLTDataBuffer::fgkSafetyPatternSize=16;
72const char AliHLTDataBuffer::fgkSafetyPattern[]={0x28, 0x63, 0x29, 0x4d, 0x52, 0x49, 0x43, 0x48, 0x54, 0x45, 0x52, 0x20, 0x32, 0x30, 0x30, 0x37};
0a7afbf0 73AliHLTUInt32_t AliHLTDataBuffer::fgEventCount=0;
b22e91eb 74
3f2a1b1c 75AliHLTDataBuffer::~AliHLTDataBuffer()
76{
70ed7d01 77 // see header file for function documentation
5dc29c72 78 CleanupConsumerList();
79
70ed7d01 80 if (--fgNofInstances<=0) {
3f2a1b1c 81 DeleteRawBuffers();
82 }
3f2a1b1c 83}
84
0c0c9d99 85int AliHLTDataBuffer::SetConsumer(AliHLTComponent* pConsumer)
3f2a1b1c 86{
70ed7d01 87 // see header file for function documentation
3f2a1b1c 88 int iResult=0;
89 if (pConsumer) {
9ce4bf4a 90 if (FindConsumer(pConsumer)) {
91 HLTWarning("consumer %s (%p) already set to data buffer %p", pConsumer->GetComponentID(), pConsumer, this);
92 }
0c0c9d99 93 AliHLTConsumerDescriptor* pDesc=new AliHLTConsumerDescriptor(pConsumer);
3f2a1b1c 94 if (pDesc) {
95 fConsumers.push_back(pDesc);
9ce4bf4a 96 HLTDebug("set consumer %s (%p) to data buffer %p", pConsumer->GetComponentID(), pConsumer, this);
3f2a1b1c 97 } else {
98 HLTError("memory allocation failed");
99 iResult=-ENOMEM;
100 }
101 } else {
9ce4bf4a 102 HLTError("invalid parameter: consumer component (nil)");
3f2a1b1c 103 iResult=-EINVAL;
104 }
105 return iResult;
106}
107
2be3f004 108int AliHLTDataBuffer::FindMatchingDataBlocks(const AliHLTComponent* pConsumer, AliHLTComponentDataTypeList* tgtList)
0c0c9d99 109{
70ed7d01 110 // see header file for function documentation
0c0c9d99 111 int iResult=0;
112 if (pConsumer) {
2be3f004 113 AliHLTDataSegmentList segments;
0c0c9d99 114 if ((iResult=FindMatchingDataSegments(pConsumer, segments))>=0) {
115 if (tgtList) {
2be3f004 116 AliHLTDataSegmentList::iterator segment=segments.begin();
0c0c9d99 117 while (segment!=segments.end()) {
118 tgtList->push_back((*segment).fDataType);
119 segment++;
120 }
121 }
122 iResult=segments.size();
123 }
124 } else {
125 iResult=-EINVAL;
126 }
127 return iResult;
128}
129
6235cd38 130int AliHLTDataBuffer::FindMatchingDataSegments(const AliHLTComponent* pConsumer, vector<AliHLTDataBuffer::AliHLTDataSegment>& tgtList)
0c0c9d99 131{
70ed7d01 132 // see header file for function documentation
0c0c9d99 133 int iResult=0;
9b7fe12d 134
135 // Matthias 26.09.2007 relax the restriction to matching data blocks
136 // all blocks are passed to the consumer, which is the policy also in
137 // PubSub
138 tgtList.assign(fSegments.begin(), fSegments.end());
b46ca65e 139
140 // add all forwarded blocks
141 tgtList.insert(tgtList.begin(), fForwardedSegments.begin(), fForwardedSegments.end());
9b7fe12d 142 iResult=tgtList.size();
143 return iResult;
144
0c0c9d99 145 if (pConsumer) {
2be3f004 146 AliHLTComponentDataTypeList dtlist;
0c0c9d99 147 ((AliHLTComponent*)pConsumer)->GetInputDataTypes(dtlist);
2be3f004 148 AliHLTDataSegmentList::iterator segment=fSegments.begin();
0c0c9d99 149 while (segment!=fSegments.end()) {
2be3f004 150 AliHLTComponentDataTypeList::iterator type=dtlist.begin();
0c0c9d99 151 while (type!=dtlist.end()) {
d8f5c9fe 152 if ((*segment).fDataType==(*type)) {
0c0c9d99 153 tgtList.push_back(*segment);
154 iResult++;
155 break;
156 }
157 type++;
158 }
159 segment++;
160 }
161 } else {
162 iResult=-EINVAL;
163 }
164 return iResult;
165}
166
457ec821 167int AliHLTDataBuffer::Subscribe(const AliHLTComponent* pConsumer, AliHLTComponentBlockDataList& blockDescList)
3f2a1b1c 168{
70ed7d01 169 // see header file for function documentation
3f2a1b1c 170 int iResult=0;
457ec821 171 if (pConsumer) {
b46ca65e 172 if (1/*fpBuffer*/) {
0c0c9d99 173 AliHLTConsumerDescriptor* pDesc=FindConsumer(pConsumer, fConsumers);
3f2a1b1c 174 if (pDesc) {
2be3f004 175 AliHLTDataSegmentList tgtList;
9b7fe12d 176 // Matthias 26.07.2007 AliHLTSystem should behave the same way as PubSub
177 // so it does not matter if there are matching data types or not, unless
178 // we implement such a check in PubSub
179 if ((iResult=FindMatchingDataSegments(pConsumer, tgtList))>=0) {
2be3f004 180 AliHLTDataSegmentList::iterator segment=tgtList.begin();
457ec821 181 while (segment!=tgtList.end()) {
3f2a1b1c 182 // fill the block data descriptor
457ec821 183 AliHLTComponentBlockData bd;
184 AliHLTComponent::FillBlockData(bd);
3294f81a 185 // This models the behavior of PubSub.
186 // For incoming data blocks, fOffset must be ignored by the
187 // processing component. It is set for bookkeeping in the framework.
188 // fPtr always points to the beginning of the data.
457ec821 189 bd.fOffset=0;
b46ca65e 190 AliHLTUInt8_t* pTgt=*segment;
457ec821 191 bd.fPtr=reinterpret_cast<void*>(pTgt);
192 bd.fSize=(*segment).fSegmentSize;
193 bd.fDataType=(*segment).fDataType;
194 bd.fSpecification=(*segment).fSpecification;
195 blockDescList.push_back(bd);
b46ca65e 196 pDesc->SetActiveDataSegment(*segment);
457ec821 197 HLTDebug("component %p (%s) subscribed to segment offset %d size %d data type %s %#x",
198 pConsumer, ((AliHLTComponent*)pConsumer)->GetComponentID(), bd.fOffset,
199 bd.fSize, (AliHLTComponent::DataType2Text(bd.fDataType)).c_str(),
200 bd.fSpecification);
0c0c9d99 201 segment++;
202 }
203 // move this consumer to the active list
457ec821 204 if (tgtList.size()==0) {
b46ca65e 205 ChangeConsumerState(pDesc, fConsumers, fReleasedConsumers);
206 HLTDebug("no input data for component %p (%s) available", pConsumer, ((AliHLTComponent*)pConsumer)->GetComponentID());
207 } else if (ChangeConsumerState(pDesc, fConsumers, fActiveConsumers)>=0) {
0c0c9d99 208 HLTDebug("component %p (%s) subscribed to data buffer %p", pConsumer, ((AliHLTComponent*)pConsumer)->GetComponentID(), this);
3f2a1b1c 209 } else {
0c0c9d99 210 // TODO: cleanup the consumer descriptor correctly
457ec821 211 segment=tgtList.begin();
212 while (segment!=tgtList.end()) {
213 blockDescList.pop_back();
214 segment++;
215 }
3f2a1b1c 216 HLTError("can not activate consumer %p for data buffer %p", pConsumer, this);
217 iResult=-EACCES;
218 }
219 } else {
0c0c9d99 220 HLTError("unresolved data segment(s) for component %p (%s)", pConsumer, ((AliHLTComponent*)pConsumer)->GetComponentID());
3f2a1b1c 221 iResult=-EBADF;
222 }
223 } else {
d4a18597 224 if (!FindConsumer(pConsumer)) {
225 HLTError("component %p is not a data consumer of data buffer %p", pConsumer, this);
226 } else {
227 HLTError("component %p is a valid data consumer of data buffer %p, but did not release it's buffer subscription", pConsumer, this);
228 }
3f2a1b1c 229 iResult=-ENOENT;
230 }
231 } else {
9b7fe12d 232 // Matthias 26.07.2007 until now, data had to be present for successful subscription
233 // in order to be consistent with the PubSub framework, this restiction has been
234 // removed
235 //HLTError("data buffer %p is empty", this);
236 //iResult=-ENODATA;
3f2a1b1c 237 }
238 } else {
239 HLTError("invalid parameter");
240 iResult=-EINVAL;
241 }
242 return iResult;
243}
244
b46ca65e 245int AliHLTDataBuffer::Release(AliHLTComponentBlockData* pBlockDesc,
246 const AliHLTComponent* pConsumer,
247 const AliHLTTask* pOwnerTask)
3f2a1b1c 248{
70ed7d01 249 // see header file for function documentation
3f2a1b1c 250 int iResult=0;
251 if (pBlockDesc && pConsumer) {
0c0c9d99 252 AliHLTConsumerDescriptor* pDesc=FindConsumer(pConsumer, fActiveConsumers);
253 if (pDesc) {
b46ca65e 254 if ((iResult=pDesc->CheckActiveDataSegment(AliHLTDataSegment(pBlockDesc->fPtr, pBlockDesc->fOffset, pBlockDesc->fSize)))!=1) {
c5123824 255 HLTWarning("data segment mismatch, component %p has not subscribed to a segment with offset %#x and size %d", pConsumer, pBlockDesc->fOffset, pBlockDesc->fSize);
0c0c9d99 256 // TODO: appropriate error handling, but so far optional
257 iResult=0;
258 } else {
b46ca65e 259 pDesc->ReleaseActiveDataSegment(AliHLTDataSegment(pBlockDesc->fPtr, pBlockDesc->fOffset, pBlockDesc->fSize));
260 }
261 if (GetNofPendingConsumers()==0 && fForwardedSegments.size()>0) {
262 // last consumer, release forwarded segments
d4a18597 263 ReleaseForwardedBlock(pBlockDesc, pOwnerTask);
264 }
265 pBlockDesc->fOffset=0;
266 pBlockDesc->fPtr=NULL;
267 pBlockDesc->fSize=0;
268 if (pDesc->GetNofActiveSegments()==0) {
269 if ((iResult=ChangeConsumerState(pDesc, fActiveConsumers, fReleasedConsumers))>=0) {
270 if (GetNofActiveConsumers()==0 && GetNofPendingConsumers()==0) {
271 // this is the last consumer, reset the consumer list and release the raw buffer
272 ResetDataBuffer();
273 }
274 } else {
275 HLTError("can not deactivate consumer %p for data buffer %p", pConsumer, this);
276 iResult=-EACCES;
277 }
278 }
279 } else {
280 HLTWarning("component %p has currently not subscribed to the data buffer %p", pConsumer, this);
281 iResult=-ENOENT;
282 }
283 } else {
284 HLTError("inavalid parameter: pBlockDesc=%p pConsumer=%p", pBlockDesc, pConsumer);
285 iResult=-EINVAL;
286 }
287 return iResult;
288}
289
290int AliHLTDataBuffer::ReleaseForwardedBlock(AliHLTComponentBlockData* pBlockDesc,
291 const AliHLTTask* pOwnerTask)
292{
293 // see header file for function documentation
294 int iResult=0;
295 if (pBlockDesc && pOwnerTask) {
b46ca65e 296 assert(fForwardedSegments.size()==fForwardedSegmentSources.size());
297 AliHLTDataSegmentList::iterator segment=fForwardedSegments.begin();
298 AliHLTTaskPList::iterator src=fForwardedSegmentSources.begin();
299 //HLTDebug("%p checking forwarded segments", this);
300 for (; segment!=fForwardedSegments.end(); segment++, src++) {
301 //HLTDebug("segment ptr=%p offset=%d size=%d\n"
302 // "block ptr=%p offset=%d size=%d", (*segment).fPtr, (*segment).fSegmentOffset, (*segment).fSegmentSize, pBlockDesc->fPtr, pBlockDesc->fOffset, pBlockDesc->fSize);
303 if ((*segment)==AliHLTDataSegment(pBlockDesc->fPtr, pBlockDesc->fOffset, pBlockDesc->fSize)) {
304 //HLTDebug("release segment of task %p", *src);
305 assert((*src)!=NULL);
306 if ((*src)!=NULL) {
307 if ((*src)->Release(pBlockDesc, pOwnerTask)>=0) {
308 HLTDebug("task %s (%p) released forwarded segment %p size %d of task %s (%p)",
309 pOwnerTask->GetName(), pOwnerTask, (*segment).GetPtr(), (*segment).GetSize(),
310 (*src)->GetName(), *src);
311 } else {
312 HLTError("task %s (%p) failed releasing forwarded segment %p size %d of task %s (%p)",
313 pOwnerTask->GetName(), pOwnerTask, (*segment).GetPtr(), (*segment).GetSize(),
314 (*src)->GetName(), *src);
315 }
316 }
317 fForwardedSegments.erase(segment);
318 fForwardedSegmentSources.erase(src);
319 break;
320 }
321 }
3f2a1b1c 322 } else {
d4a18597 323 HLTError("inavalid parameter: pBlockDesc=%p pOwnerTask=%p", pBlockDesc, pOwnerTask);
3f2a1b1c 324 iResult=-EINVAL;
325 }
326 return iResult;
327}
328
b46ca65e 329int AliHLTDataBuffer::Forward(AliHLTTask* pSrcTask, AliHLTComponentBlockData* pBlockDesc)
330{
331 // see header file for function documentation
332 if (pSrcTask==NULL || pBlockDesc==NULL) return -EINVAL;
333 assert(fForwardedSegments.size()==fForwardedSegmentSources.size());
334 if (fForwardedSegments.size()!=fForwardedSegmentSources.size()) return -EFAULT;
335 fForwardedSegmentSources.push_back(pSrcTask);
457ec821 336 fForwardedSegments.push_back(AliHLTDataSegment(pBlockDesc->fPtr, pBlockDesc->fOffset, pBlockDesc->fSize, pBlockDesc->fDataType, pBlockDesc->fSpecification));
b46ca65e 337 return 0;
338}
339
3f2a1b1c 340AliHLTUInt8_t* AliHLTDataBuffer::GetTargetBuffer(int iMinSize)
341{
70ed7d01 342 // see header file for function documentation
3f2a1b1c 343 AliHLTUInt8_t* pTargetBuffer=NULL;
b6800be0 344 if (fpBuffer!=NULL) {
345 HLTWarning("data buffer not properly reset, possible memory leak\n");
346 }
3f2a1b1c 347 fpBuffer=CreateRawBuffer(iMinSize);
9ce4bf4a 348 if (fpBuffer) {
1e6e67ec 349 pTargetBuffer=*fpBuffer;
9ce4bf4a 350 } else {
351 HLTError("can not create raw buffer");
352 }
3f2a1b1c 353 return pTargetBuffer;
354}
355
8ede8717 356int AliHLTDataBuffer::SetSegments(AliHLTUInt8_t* pTgt, AliHLTComponentBlockData* arrayBlockData, int iSize)
3f2a1b1c 357{
70ed7d01 358 // see header file for function documentation
3f2a1b1c 359 int iResult=0;
360 if (pTgt && arrayBlockData && iSize>=0) {
0c0c9d99 361 if (fpBuffer) {
1e6e67ec 362 if (*fpBuffer==pTgt) {
6235cd38 363 AliHLTDataBuffer::AliHLTDataSegment segment;
48dedf26 364 AliHLTUInt32_t maxSize=0;
0c0c9d99 365 for (int i=0; i<iSize; i++) {
3294f81a 366 // This function has to model the behavior of PubSub
367 // For output blocks only the fOffset value is used, this must be the offset
368 // relative to the output pointer. fPtr must be either NULL or the output
b46ca65e 369 // pointer. In either case it is 'ignored' and set to the beginning of the
370 // data buffer
6434d28a 371 if (arrayBlockData[i].fPtr==NULL ||
3294f81a 372 arrayBlockData[i].fPtr==*fpBuffer) {
b46ca65e 373 arrayBlockData[i].fPtr=*fpBuffer;
0ad4ebd1 374 if ((arrayBlockData[i].fOffset+arrayBlockData[i].fSize<=fpBuffer->GetUsedSize()) ||
375 ((arrayBlockData[i].fOffset==~(AliHLTUInt32_t)0) && arrayBlockData[i].fSize==0)) {
3294f81a 376 segment.fSegmentOffset=arrayBlockData[i].fOffset;
b46ca65e 377 segment.fPtr=(AliHLTUInt8_t*)arrayBlockData[i].fPtr;
1e6e67ec 378 segment.fSegmentSize=arrayBlockData[i].fSize;
379 segment.fDataType=arrayBlockData[i].fDataType;
380 segment.fSpecification=arrayBlockData[i].fSpecification;
381 fSegments.push_back(segment);
382 HLTDebug("set segment %s with size %d at offset %d", AliHLTComponent::DataType2Text(segment.fDataType).data(), segment.fSegmentSize, segment.fSegmentOffset);
48dedf26 383
384 // find the actual size of the data
385 if ((arrayBlockData[i].fOffset!=~(AliHLTUInt32_t)0) &&
386 arrayBlockData[i].fOffset+arrayBlockData[i].fSize>maxSize) {
387 maxSize=arrayBlockData[i].fOffset+arrayBlockData[i].fSize;
388 }
1e6e67ec 389 } else {
390 HLTError("block data specification %#d (%s) exceeds size of data buffer", i, AliHLTComponent::DataType2Text(arrayBlockData[i].fDataType).data());
c0a2bfc2 391 HLTError("block offset=%d, block size=%d, buffer size=%d", arrayBlockData[i].fOffset, arrayBlockData[i].fSize, fpBuffer->GetUsedSize());
1e6e67ec 392 iResult=-E2BIG;
393 }
0c0c9d99 394 } else {
3294f81a 395 HLTError("invalid pointer (%p) in block data specification (buffer %p size %d)."
396 "please note: for output blocks only the fOffset value is valid and must "
c0a2bfc2 397 "be relative to the output buffer", arrayBlockData[i].fPtr, fpBuffer->GetPointer(), fpBuffer->GetUsedSize());
1e6e67ec 398 iResult=-ERANGE;
0c0c9d99 399 }
400 }
48dedf26 401 // to be enabled if unit test is ready
402 //iResult=SetRawBufferDataSize(fpBuffer, maxSize);
3f2a1b1c 403 } else {
c0a2bfc2 404 HLTError("this data buffer (%p) does not match the internal data buffer %p of raw buffer %p", pTgt, fpBuffer->GetPointer(), fpBuffer);
8451168b 405 iResult=-EINVAL;
3f2a1b1c 406 }
0c0c9d99 407 } else {
c5123824 408 HLTFatal("internal data structur mismatch");
0c0c9d99 409 iResult=-EFAULT;
3f2a1b1c 410 }
411 } else {
0c0c9d99 412 HLTError("invalid parameter: pTgtBuffer=%p arrayBlockData=%p", pTgt, arrayBlockData);
3f2a1b1c 413 iResult=-EINVAL;
414 }
415 return iResult;
416}
417
418int AliHLTDataBuffer::IsEmpty()
419{
70ed7d01 420 // see header file for function documentation
d4a18597 421 int iResult=(fpBuffer==NULL && fForwardedSegments.size()==0) || GetNofSegments()==0;
3f2a1b1c 422 return iResult;
423}
424
425int AliHLTDataBuffer::GetNofSegments()
426{
70ed7d01 427 // see header file for function documentation
d4a18597 428 int iResult=fSegments.size() + fForwardedSegments.size();
3f2a1b1c 429 return iResult;
430}
431
432int AliHLTDataBuffer::GetNofConsumers()
433{
70ed7d01 434 // see header file for function documentation
3f2a1b1c 435 int iResult=fConsumers.size() + GetNofActiveConsumers() + fReleasedConsumers.size();
436 return iResult;
437}
438
b426991e 439int AliHLTDataBuffer::GetNofPendingConsumers()
440{
441 // see header file for function documentation
442 int iResult=fConsumers.size();
443 return iResult;
444}
445
3f2a1b1c 446int AliHLTDataBuffer::GetNofActiveConsumers()
447{
70ed7d01 448 // see header file for function documentation
3f2a1b1c 449 int iResult=fActiveConsumers.size();
450 return iResult;
451}
452
6235cd38 453AliHLTDataBuffer::AliHLTRawBuffer* AliHLTDataBuffer::CreateRawBuffer(AliHLTUInt32_t size)
3f2a1b1c 454{
70ed7d01 455 // see header file for function documentation
3f2a1b1c 456 AliHLTRawBuffer* pRawBuffer=NULL;
7a5ccd96 457 unsigned int reqSize=size+fgkSafetyPatternSize;
2be3f004 458 AliHLTRawBufferPList::iterator buffer=fgFreeBuffers.begin();
70ed7d01 459 while (buffer!=fgFreeBuffers.end() && pRawBuffer==NULL) {
d6cbe999 460 if ((*buffer)->CheckSize(reqSize)) {
3f2a1b1c 461 // assign this element
462 pRawBuffer=*buffer;
d6cbe999 463 pRawBuffer->UseBuffer(size);
70ed7d01 464 fgFreeBuffers.erase(buffer);
c0a2bfc2 465 fgLogging.Logging(kHLTLogDebug, "AliHLTDataBuffer::CreateRawBuffer", "data buffer handling", "raw buffer container %p provided for request of %d bytes (total %d available in buffer %p)", pRawBuffer, size, pRawBuffer->GetTotalSize(), pRawBuffer->GetPointer());
70ed7d01 466 fgActiveBuffers.push_back(pRawBuffer);
0c0c9d99 467 break;
3f2a1b1c 468 }
0c0c9d99 469 buffer++;
3f2a1b1c 470 }
471 if (pRawBuffer==NULL) {
0c0c9d99 472 // no buffer found, create a new one
d6cbe999 473 pRawBuffer=new AliHLTRawBuffer(reqSize);
3f2a1b1c 474 if (pRawBuffer) {
c0a2bfc2 475 if (pRawBuffer->GetPointer()) {
d6cbe999 476 pRawBuffer->UseBuffer(size);
70ed7d01 477 fgActiveBuffers.push_back(pRawBuffer);
c0a2bfc2 478 fgLogging.Logging(kHLTLogDebug, "AliHLTDataBuffer::CreateRawBuffer", "data buffer handling", "new raw buffer %p of size %d created (container %p)", pRawBuffer->GetPointer(), pRawBuffer->GetTotalSize(), pRawBuffer);
3f2a1b1c 479 } else {
480 delete pRawBuffer;
481 pRawBuffer=NULL;
0c0c9d99 482 fgLogging.Logging(kHLTLogError, "AliHLTDataBuffer::CreateRawBuffer", "data buffer handling", "memory allocation failed");
3f2a1b1c 483 }
484 } else {
0c0c9d99 485 fgLogging.Logging(kHLTLogError, "AliHLTDataBuffer::CreateRawBuffer", "data buffer handling", "memory allocation failed");
3f2a1b1c 486 }
487 }
73ede1d3 488 if (pRawBuffer!=NULL && fgkSafetyPatternSize>0) {
c0a2bfc2 489 //fgLogging.Logging(kHLTLogDebug, "AliHLTDataBuffer::CreateRawBuffer", "data buffer handling", "writing safety pattern to %p offset %d", (*buffer)->GetPointer(), (*buffer)->GetUsedSize());
49b01d04 490 pRawBuffer->WritePattern(fgkSafetyPattern, fgkSafetyPatternSize);
73ede1d3 491 }
3f2a1b1c 492 return pRawBuffer;
493}
494
48dedf26 495int AliHLTDataBuffer::SetRawBufferDataSize(AliHLTRawBuffer* pBuffer, AliHLTUInt32_t size) const
496{
497 // see header file for function documentation
498 int iResult=0;
499 if (!pBuffer) return -EINVAL;
500 if (size>pBuffer->GetUsedSize()) {
501 HLTError("indicated data size %d exceeds data buffer %p (%d)", size, pBuffer->GetPointer(), pBuffer->GetUsedSize());
502 return -ENOSPC;
503 }
504 if (fgkSafetyPatternSize>0) {
505 if (pBuffer->CheckPattern(fgkSafetyPattern, fgkSafetyPatternSize)) {
506 HLTError("potential memory corruption: component has written beyond end of data buffer %p size %d", pBuffer->GetPointer(), pBuffer->GetUsedSize());
507 }
508 }
509 // shrink the buffer and write new pattern at the end
510 pBuffer->UseBuffer(size);
511 if (fgkSafetyPatternSize>0) {
512 pBuffer->WritePattern(fgkSafetyPattern, fgkSafetyPatternSize);
513 }
514 return iResult;
515}
516
3f2a1b1c 517int AliHLTDataBuffer::ReleaseRawBuffer(AliHLTRawBuffer* pBuffer)
518{
70ed7d01 519 // see header file for function documentation
3f2a1b1c 520 int iResult=0;
521 if (pBuffer) {
2be3f004 522 AliHLTRawBufferPList::iterator buffer=fgActiveBuffers.begin();
70ed7d01 523 while (buffer!=fgActiveBuffers.end() && (*buffer)!=pBuffer) {
3f2a1b1c 524 buffer++;
525 }
70ed7d01 526 if (buffer!=fgActiveBuffers.end()) {
8451168b 527 if (fgkSafetyPatternSize>0) {
c0a2bfc2 528 //fgLogging.Logging(kHLTLogDebug, "AliHLTDataBuffer::ReleaseRawBuffer", "data buffer handling", "comparing safety pattern at %p offset %d", (*buffer)->GetPointer(), reinterpret_cast<AliHLTUInt32_t>(*buffer));
d6cbe999 529 if ((*buffer)->CheckPattern(fgkSafetyPattern, fgkSafetyPatternSize)) {
c0a2bfc2 530 fgLogging.Logging(kHLTLogFatal, "AliHLTDataBuffer::ReleaseRawBuffer", "data buffer handling", "component has written beyond end of data buffer %p size %d", (*buffer)->GetPointer(), (*buffer)->GetUsedSize());
8451168b 531 }
532 }
d6cbe999 533 (*buffer)->Reset();
70ed7d01 534 fgFreeBuffers.push_back(*buffer);
535 fgActiveBuffers.erase(buffer);
3f2a1b1c 536 } else {
0c0c9d99 537 fgLogging.Logging(kHLTLogWarning, "AliHLTDataBuffer::ReleaseRawBuffer", "data buffer handling", "can not find raw buffer container %p in the list of active containers", pBuffer);
3f2a1b1c 538 iResult=-ENOENT;
539 }
540 } else {
0c0c9d99 541 fgLogging.Logging(kHLTLogError, "AliHLTDataBuffer::ReleaseRawBuffer", "data buffer handling", "invalid parameter");
3f2a1b1c 542 iResult=-EINVAL;
543 }
544 return iResult;
545}
546
547
548int AliHLTDataBuffer::DeleteRawBuffers()
549{
70ed7d01 550 // see header file for function documentation
3f2a1b1c 551 int iResult=0;
950a0e40 552#ifdef ALIHLTSYSTEM_PROFILING
553 int iTotalSize=0;
554 int iCount=fgFreeBuffers.size()+fgActiveBuffers.size();
555#endif //ALIHLTSYSTEM_PROFILING
dba03d72 556 AliHLTRawBufferPList::iterator buffer;;
557 while ((buffer=fgFreeBuffers.begin())!=fgFreeBuffers.end()) {
950a0e40 558#ifdef ALIHLTSYSTEM_PROFILING
559 iTotalSize+=(*buffer)->GetTotalSize();
560#endif //ALIHLTSYSTEM_PROFILING
3f2a1b1c 561 delete *buffer;
70ed7d01 562 fgFreeBuffers.erase(buffer);
3f2a1b1c 563 }
dba03d72 564 while ((buffer=fgActiveBuffers.begin())!=fgActiveBuffers.end()) {
950a0e40 565#ifdef ALIHLTSYSTEM_PROFILING
566 iTotalSize+=(*buffer)->GetTotalSize();
567#endif //ALIHLTSYSTEM_PROFILING
c0a2bfc2 568 fgLogging.Logging(kHLTLogWarning, "AliHLTDataBuffer::ReleaseRawBuffer", "data buffer handling", "request to delete active raw buffer container (raw buffer %p, size %d)", (*buffer)->GetPointer(), (*buffer)->GetTotalSize());
3f2a1b1c 569 delete *buffer;
70ed7d01 570 fgActiveBuffers.erase(buffer);
3f2a1b1c 571 }
950a0e40 572#ifdef ALIHLTSYSTEM_PROFILING
573 fgLogging.Logging(kHLTLogImportant, "AliHLTDataBuffer::ReleaseRawBuffer", "data buffer handling", "Total memory allocation: %d byte in %d buffers", iTotalSize, iCount);
574#endif //ALIHLTSYSTEM_PROFILING
3f2a1b1c 575 return iResult;
576}
577
0a7afbf0 578int AliHLTDataBuffer::PrintStatistics()
579{
580 // see header file for function documentation
581 int iResult=0;
582 int iFree=0;
583 int iActive=0;
584 AliHLTRawBufferPList::iterator buffer;;
585 for (buffer=fgFreeBuffers.begin(); buffer!=fgFreeBuffers.end(); buffer++) {
586 iFree+=(*buffer)->GetTotalSize();
587 }
588 for (buffer=fgActiveBuffers.begin(); buffer!=fgActiveBuffers.end(); buffer++) {
589 iActive+=(*buffer)->GetTotalSize();
590 }
591 fgLogging.Logging(kHLTLogInfo, "AliHLTDataBuffer::PrintStatistics", "data buffer handling", "Total memory allocation: %d byte; %d free buffers (%d byte) - %d active buffers (%d byte) ", iFree+iActive, fgFreeBuffers.size(), iFree, fgActiveBuffers.size(), iActive);
592 return iResult;
593}
594
2be3f004 595AliHLTConsumerDescriptor* AliHLTDataBuffer::FindConsumer(const AliHLTComponent* pConsumer, AliHLTConsumerDescriptorPList &list) const
3f2a1b1c 596{
70ed7d01 597 // see header file for function documentation
3f2a1b1c 598 AliHLTConsumerDescriptor* pDesc=NULL;
2be3f004 599 AliHLTConsumerDescriptorPList::iterator desc=list.begin();
3f2a1b1c 600 while (desc!=list.end() && pDesc==NULL) {
0c0c9d99 601 if ((pConsumer==NULL || (*desc)->GetComponent()==pConsumer)) {
3f2a1b1c 602 pDesc=*desc;
603 }
0c0c9d99 604 desc++;
3f2a1b1c 605 }
606 return pDesc;
607}
608
0c0c9d99 609int AliHLTDataBuffer::ResetDataBuffer()
610{
70ed7d01 611 // see header file for function documentation
3f2a1b1c 612 int iResult=0;
0c0c9d99 613 AliHLTRawBuffer* pBuffer=fpBuffer;
3f2a1b1c 614 fpBuffer=NULL;
9ce4bf4a 615
b46ca65e 616 // cleanup forwarded segment lists
617 assert(fForwardedSegments.size()==0);
618 fForwardedSegments.clear();
619 fForwardedSegmentSources.clear();
620
9ce4bf4a 621 // cleanup consumer states
2be3f004 622 AliHLTConsumerDescriptorPList::iterator desc;
b426991e 623// if (GetNofPendingConsumers()>0) {
624// desc=fConsumers.begin();
625// while (desc!=fConsumers.end()) {
626// AliHLTComponent* pComp=(*desc)->GetComponent();
627// HLTError("internal error: consumer %p (%s %p) did not get data from data buffer %p", *desc, pComp?pComp->GetComponentID():"", pComp, this);
628// desc++;
629// }
630// }
631 desc=fReleasedConsumers.begin();
3f2a1b1c 632 while (desc!=fReleasedConsumers.end()) {
633 AliHLTConsumerDescriptor* pDesc=*desc;
634 fReleasedConsumers.erase(desc);
635 desc=fReleasedConsumers.begin();
636 fConsumers.push_back(pDesc);
637 }
638 desc=fActiveConsumers.begin();
639 while (desc!=fActiveConsumers.end()) {
640 AliHLTConsumerDescriptor* pDesc=*desc;
48abe484 641 HLTWarning("consumer %p (%s) was not released", pDesc, pDesc->GetComponent()?pDesc->GetComponent()->GetComponentID():"### invalid component ###");
3f2a1b1c 642 fActiveConsumers.erase(desc);
643 desc=fActiveConsumers.begin();
644 fConsumers.push_back(pDesc);
645 }
9ce4bf4a 646
647 // cleanup segments
2be3f004 648 AliHLTDataSegmentList::iterator segment=fSegments.begin();
9ce4bf4a 649 while (segment!=fSegments.end()) {
650 fSegments.erase(segment);
651 segment=fSegments.begin();
652 }
653
654 // cleanup raw buffer
655 if (pBuffer) {
656 ReleaseRawBuffer(pBuffer);
657 }
3f2a1b1c 658 return iResult;
659}
660
9ce4bf4a 661int AliHLTDataBuffer::Reset()
662{
70ed7d01 663 // see header file for function documentation
9ce4bf4a 664 return ResetDataBuffer();
665}
666
0c0c9d99 667// this is the version which works on lists of components instead of consumer descriptors
2be3f004 668// int AliHLTDataBuffer::ChangeConsumerState(AliHLTComponent* pConsumer, AliHLTComponentPList &srcList, AliHLTComponentPList &tgtList)
0c0c9d99 669// {
670// int iResult=0;
671// if (pDesc) {
2be3f004 672// AliHLTComponentPList::iterator desc=srcList.begin();
0c0c9d99 673// while (desc!=srcList.end()) {
674// if ((*desc)==pConsumer) {
675// srcList.erase(desc);
676// tgtList.push_back(pConsumer);
677// break;
678// }
679// desc++;
680// }
681// if (desc==srcList.end()) {
682// HLTError("can not find consumer component %p in list", pConsumer);
683// iResult=-ENOENT;
684// }
685// } else {
686// HLTError("invalid parameter");
687// iResult=-EINVAL;
688// }
689// return iResult;
690// }
691
2be3f004 692int AliHLTDataBuffer::ChangeConsumerState(AliHLTConsumerDescriptor* pDesc, AliHLTConsumerDescriptorPList &srcList, AliHLTConsumerDescriptorPList &tgtList)
3f2a1b1c 693{
70ed7d01 694 // see header file for function documentation
9ce4bf4a 695 int iResult=-ENOENT;
3f2a1b1c 696 if (pDesc) {
2be3f004 697 AliHLTConsumerDescriptorPList::iterator desc=srcList.begin();
3f2a1b1c 698 while (desc!=srcList.end()) {
699 if ((*desc)==pDesc) {
700 srcList.erase(desc);
701 tgtList.push_back(pDesc);
9ce4bf4a 702 iResult=0;
3f2a1b1c 703 break;
704 }
0c0c9d99 705 desc++;
3f2a1b1c 706 }
9ce4bf4a 707 if (iResult<0) {
3f2a1b1c 708 HLTError("can not find consumer descriptor %p in list", pDesc);
3f2a1b1c 709 }
710 } else {
711 HLTError("invalid parameter");
712 iResult=-EINVAL;
713 }
714 return iResult;
715}
716
70ed7d01 717int AliHLTDataBuffer::CleanupConsumerList()
718{
719 // see header file for function documentation
3f2a1b1c 720 int iResult=0;
721 ResetDataBuffer();
2be3f004 722 AliHLTConsumerDescriptorPList::iterator desc=fConsumers.begin();
3f2a1b1c 723 while (desc!=fConsumers.end()) {
724 delete *desc;
725 fConsumers.erase(desc);
726 desc=fConsumers.begin();
727 }
728 return iResult;
729}
9ce4bf4a 730
d4a18597 731int AliHLTDataBuffer::FindConsumer(const AliHLTComponent* pConsumer, int bAllLists)
70ed7d01 732{
733 // see header file for function documentation
2be3f004 734 AliHLTConsumerDescriptorPList::iterator desc=fConsumers.begin();
9ce4bf4a 735 while (desc!=fConsumers.end()) {
736 if ((*desc)->GetComponent()==pConsumer)
737 return 1;
738 desc++;
739 }
740 if (bAllLists==0) return 0;
741
742 desc=fActiveConsumers.begin();
743 while (desc!=fActiveConsumers.end()) {
744 if ((*desc)->GetComponent()==pConsumer)
745 return 1;
746 desc++;
747 }
748 desc=fReleasedConsumers.begin();
749 while (desc!=fReleasedConsumers.end()) {
750 if ((*desc)->GetComponent()==pConsumer)
751 return 1;
752 desc++;
753 }
754 return 0;
755}
1e6e67ec 756
d6cbe999 757AliHLTDataBuffer::AliHLTRawBuffer::AliHLTRawBuffer(AliHLTUInt32_t size)
545d509f 758 : fSize(0)
759 , fTotalSize(size)
760 , fExternalPtr(NULL)
761 , fPtr(static_cast<AliHLTUInt8_t*>(malloc(size)))
762 , fLastEventCount(0)
d6cbe999 763{
764 // see header file for class documentation
765 // or
766 // refer to README to build package
767 // or
768 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
769 if (fPtr==NULL) {
770 fSize=0;
771 fTotalSize=0;
772 }
773}
774
545d509f 775AliHLTDataBuffer::AliHLTRawBuffer::AliHLTRawBuffer(AliHLTUInt32_t size, AliHLTUInt8_t* buffer)
776 : fSize(0)
777 , fTotalSize(size)
778 , fExternalPtr(buffer)
779 , fPtr(fExternalPtr)
780 , fLastEventCount(0)
781{
782 // see header file for class documentation
783}
784
d6cbe999 785AliHLTDataBuffer::AliHLTRawBuffer::~AliHLTRawBuffer()
786{
545d509f 787 if (fExternalPtr==NULL && fPtr) {
d6cbe999 788 free(fPtr);
789 }
790 fPtr=NULL;
791 fSize=0;
792 fTotalSize=0;
793}
794
3a7c0444 795int AliHLTDataBuffer::AliHLTRawBuffer::operator==(void* ptr) const
1e6e67ec 796{
3a7c0444 797 // see header file for function documentation
1e6e67ec 798 return fPtr == static_cast<AliHLTUInt8_t*>(ptr);
799}
800
545d509f 801int AliHLTDataBuffer::AliHLTRawBuffer::operator<(void* ptr) const
802{
803 // see header file for function documentation
804 int iResult=fPtr < static_cast<AliHLTUInt8_t*>(ptr);
805 //printf("%p: %p <= %p (%d)\n", this, fPtr, ptr, iResult);
806 return iResult;
807}
808
3a7c0444 809int AliHLTDataBuffer::AliHLTRawBuffer::operator<=(void* ptr) const
1e6e67ec 810{
3a7c0444 811 // see header file for function documentation
1e6e67ec 812 int iResult=fPtr <= static_cast<AliHLTUInt8_t*>(ptr);
813 //printf("%p: %p <= %p (%d)\n", this, fPtr, ptr, iResult);
814 return iResult;
815}
816
3a7c0444 817int AliHLTDataBuffer::AliHLTRawBuffer::operator>(void* ptr) const
1e6e67ec 818{
3a7c0444 819 // see header file for function documentation
1e6e67ec 820 int iResult=fPtr+fSize > static_cast<AliHLTUInt8_t*>(ptr);
821 //printf("%p: %p + %d > %p (%d)\n", this, fPtr, fSize, ptr, iResult);
822 return iResult;
823}
824
3a7c0444 825int AliHLTDataBuffer::AliHLTRawBuffer::operator-(void* ptr) const
1e6e67ec 826{
3a7c0444 827 // see header file for function documentation
1e6e67ec 828 return static_cast<int>(static_cast<AliHLTUInt8_t*>(ptr)-fPtr);
829}
d6cbe999 830
545d509f 831int AliHLTDataBuffer::AliHLTRawBuffer::operator<(const AliHLTRawBuffer& op) const
832{
833 // see header file for function documentation
834 return (fPtr+fSize < op.fPtr);
835}
836
837int AliHLTDataBuffer::AliHLTRawBuffer::operator<=(const AliHLTRawBuffer& op) const
d6cbe999 838{
839 // see header file for function documentation
545d509f 840 return (fPtr+fSize <= op.fPtr);
841}
842
843int AliHLTDataBuffer::AliHLTRawBuffer::operator>(const AliHLTRawBuffer& op) const
844{
845 // see header file for function documentation
775975be 846 return (fPtr >= op.fPtr+op.fSize);
545d509f 847}
848
849AliHLTUInt8_t* AliHLTDataBuffer::AliHLTRawBuffer::UseBuffer(AliHLTUInt32_t size)
850{
851 // mark a portion of the buffer as used
dba03d72 852 if (size>0 && fTotalSize>=size) {
d6cbe999 853 fSize=size;
0a7afbf0 854 fLastEventCount=AliHLTDataBuffer::fgEventCount;
d6cbe999 855 return fPtr;
856 }
857 return NULL;
858}
859
545d509f 860AliHLTDataBuffer::AliHLTRawBuffer* AliHLTDataBuffer::AliHLTRawBuffer::Split(AliHLTUInt32_t size)
861{
862 // split a buffer at specified size
863 // only possible for buffers with external memory
48dedf26 864 if (fTotalSize>size &&
545d509f 865 (fSize==0 || fSize<size) &&
866 fExternalPtr!=NULL) {
867 AliHLTRawBuffer* part2=new AliHLTRawBuffer(fTotalSize-size, fPtr+size);
868 if (part2) {
869 fTotalSize=size;
870 }
871 return part2;
872 }
873 return NULL;
874}
875
d6cbe999 876int AliHLTDataBuffer::AliHLTRawBuffer::CheckSize(AliHLTUInt32_t size) const
877{
878 // see header file for function documentation
0a7afbf0 879 if (fTotalSize<size) return 0;
880 unsigned adjust=0;
881 if (fLastEventCount+1<AliHLTDataBuffer::fgEventCount) {
882 adjust=AliHLTDataBuffer::fgEventCount-fLastEventCount;
883 }
884 return (adjust>2) || ((fTotalSize-size)<(fgMargin<<adjust));
d6cbe999 885}
886
887int AliHLTDataBuffer::AliHLTRawBuffer::Reset()
888{
889 // see header file for function documentation
890 fSize=0;
2be3f004 891 return 0;
d6cbe999 892}
893
894int AliHLTDataBuffer::AliHLTRawBuffer::WritePattern(const char* pattern, int size)
895{
896 // see header file for function documentation
897 int iResult=0;
898 if (pattern!=NULL && size>0) {
899 if (fSize+size<=fTotalSize) {
900 memcpy(((char*)fPtr)+fSize, pattern, size);
901 iResult=size;
902 } else {
903 iResult=-ENOSPC;
904 }
905 }
906 return iResult;
907}
908
909int AliHLTDataBuffer::AliHLTRawBuffer::CheckPattern(const char* pattern, int size) const
910{
911 // see header file for function documentation
912 int iResult=0;
913 if (pattern!=NULL && size>0) {
914 if (fSize+size<=fTotalSize) {
915 iResult=memcmp(((char*)fPtr)+fSize, pattern, size)!=0;
916 } else {
917 iResult=-ENOSPC;
918 }
919 }
920 return iResult;
921}
545d509f 922
923int AliHLTDataBuffer::AliHLTRawBuffer::Merge(const AliHLTDataBuffer::AliHLTRawBuffer& neighbor)
924{
925 // Merge buffer with neighboring buffer.
926 // Only possible if the buffers are consecutive with out any gap.
927
928 if (!fExternalPtr || !neighbor.fExternalPtr) return -EPERM;
929
48dedf26 930 if (neighbor.fTotalSize==0 &&
931 fPtr < neighbor.fPtr &&
932 fPtr+fTotalSize > neighbor.fPtr) {
933 // special case for a buffer of zero size embedded into this buffer
934 // nothing to do
935 return 0;
936 }
937 if (fTotalSize==0 &&
938 neighbor.fPtr < fPtr &&
939 neighbor.fPtr+neighbor.fTotalSize > fPtr) {
940 // special case for this buffer of size zero embedded into another buffer
941 fPtr=neighbor.fPtr;
942 fExternalPtr=fPtr;
943 fTotalSize+=neighbor.fTotalSize;
944 fSize=0;
945 return 0;
946 }
545d509f 947 if (fPtr+fTotalSize == neighbor.fPtr) {
948 fTotalSize+=neighbor.fTotalSize;
949 fSize=0;
950 return 0;
951 }
952 if (fPtr == neighbor.fPtr+neighbor.fTotalSize) {
953 fPtr=neighbor.fPtr;
954 fExternalPtr=fPtr;
955 fTotalSize+=neighbor.fTotalSize;
956 fSize=0;
957 return 0;
958 }
959 return -EINVAL;
960}
961
962void AliHLTDataBuffer::AliHLTRawBuffer::Print(const char* option)
963{
964 /// print buffer information
965 if (strcmp(option, "min")!=0) {
966 cout << "************* AliHLTRawBuffer status ***********" << endl;
967 }
775975be 968 printf(" %p: buffer %p%s size %d used %d\n", this, fPtr, fExternalPtr?" (external)":"", fTotalSize, fSize); fflush(stdout);
545d509f 969}
970
971AliHLTDataBuffer::AliHLTRawPage::AliHLTRawPage(AliHLTUInt32_t pagesize)
972 : fSize(pagesize)
973 , fPtr(static_cast<AliHLTUInt8_t*>(malloc(pagesize)))
974 , fFreeBuffers()
975 , fUsedBuffers()
976{
977 // constructor
978 if (fPtr) {
979 fFreeBuffers.push_back(new AliHLTRawBuffer(fSize, fPtr));
980 } else {
981 fSize=0;
982 }
983}
984
985AliHLTDataBuffer::AliHLTRawPage::~AliHLTRawPage()
986{
987 // destructor
48dedf26 988 if (IsUsed()) {
545d509f 989 // do not free if the resources have not been completely freed
990 HLTError("memory mismatch: not all allocated intances have been released");
991 } else {
48dedf26 992 if (IsFragmented()) {
545d509f 993 HLTWarning("page still fragmented");
994 }
995 AliHLTRawBufferPList::iterator element=fFreeBuffers.begin();
996 while (element!=fFreeBuffers.end()) {
997 if (*element) delete *element;
998 element=fFreeBuffers.erase(element);
999 }
1000 if (fPtr) {
1001 free(fPtr);
1002 }
1003 fPtr=NULL;
1004 fSize=0;
1005 }
1006}
1007
1008AliHLTDataBuffer::AliHLTRawBuffer* AliHLTDataBuffer::AliHLTRawPage::Alloc(AliHLTUInt32_t size)
1009{
1010 /// alloc a buffer of specified size
775975be 1011 if (fFreeBuffers.size()==0) return NULL;
545d509f 1012
545d509f 1013 for (AliHLTRawBufferPList::iterator iter=fFreeBuffers.begin();
775975be 1014 iter!=fFreeBuffers.end();
545d509f 1015 iter++) {
48dedf26 1016 if ((*iter)->GetTotalSize()==size) {
1017 AliHLTRawBuffer* thisbuffer=*iter;
1018 fFreeBuffers.erase(iter);
1019 fUsedBuffers.push_back(thisbuffer);
1020 return thisbuffer;
1021 } else if ((*iter)->GetTotalSize()>size) {
775975be 1022 AliHLTRawBuffer* thisbuffer=*iter;
1023 AliHLTRawBuffer* newbuffer=thisbuffer->Split(size);
1024 if (newbuffer) {
1025 *iter=newbuffer;
1026 fUsedBuffers.push_back(thisbuffer);
1027 return thisbuffer;
545d509f 1028 } else {
48dedf26 1029 HLTWarning("failed to alloc raw buffer: cannot split raw buffer %p of size %d (used %d) at size %d", *iter, (*iter)->GetTotalSize(), (*iter)->GetUsedSize(), size);
545d509f 1030 }
1031 }
1032 }
1033 return NULL;
1034}
1035
1036int AliHLTDataBuffer::AliHLTRawPage::Free(AliHLTRawBuffer* pBuffer)
1037{
1038 /// free a buffer and merge consecutive free buffers
1039 int iResult=0;
1040 for (AliHLTRawBufferPList::iterator iter=fUsedBuffers.begin();
1041 iter!=fUsedBuffers.end() && iResult>=0;
1042 iter++) {
1043 if ((*iter)==pBuffer) {
1044 fUsedBuffers.erase(iter);
775975be 1045 AliHLTRawBufferPList::iterator prev=fFreeBuffers.begin();
1046 for (; prev!=fFreeBuffers.end() && iResult>=0; prev++) {
48dedf26 1047 if ((*pBuffer)<(*(*prev)) ||
1048 ((*prev)->GetTotalSize()==0 && pBuffer->GetPointer()<=(*prev)->GetPointer() && (*prev)->GetPointer()<=pBuffer->GetPointer()+pBuffer->GetTotalSize())) {
545d509f 1049 // check consecutive buffers
48dedf26 1050 if ((*(*prev)) == (pBuffer->GetPointer()+pBuffer->GetTotalSize()) ||
1051 ((*prev)->GetTotalSize()==0 && pBuffer->GetPointer()<=(*prev)->GetPointer() && (*prev)->GetPointer()<=pBuffer->GetPointer()+pBuffer->GetTotalSize())) {
545d509f 1052 // the buffer to be released has a consecutive free buffer -> merge them
1053 if ((iResult=pBuffer->Merge(*(*prev)))>=0) {
545d509f 1054 delete *prev;
775975be 1055 *prev=pBuffer;
48dedf26 1056 } else {
1057 HLTError("failed to merge consecutive/overlapping buffers %p and %p", pBuffer, (*prev));
1058 pBuffer->Print("");
1059 (*prev)->Print("");
545d509f 1060 }
1061 break;
1062 }
775975be 1063 fFreeBuffers.insert(prev, pBuffer);
1064 break;
545d509f 1065 }
48dedf26 1066 if ((*pBuffer)>(*(*prev)) ||
1067 (pBuffer->GetTotalSize()==0 && (*prev)->GetPointer()<=pBuffer->GetPointer() && pBuffer->GetPointer()<=(*prev)->GetPointer()+(*prev)->GetTotalSize())) {
545d509f 1068 // check consecutive buffers
48dedf26 1069 if ((*pBuffer) == ((*prev)->GetPointer()+(*prev)->GetTotalSize())||
1070 (pBuffer->GetTotalSize()==0 && (*prev)->GetPointer()<=pBuffer->GetPointer() && pBuffer->GetPointer()<=(*prev)->GetPointer()+(*prev)->GetTotalSize())) {
545d509f 1071 // the buffer to be released is consecutive to a free buffer -> merge them
1072 if ((iResult=pBuffer->Merge(*(*prev)))>=0) {
775975be 1073 AliHLTRawBufferPList::iterator succ=prev+1;
545d509f 1074 delete *prev;
775975be 1075 *prev=pBuffer;
1076 // check if the buffer and the following one are consecutive
1077 if (succ!=fFreeBuffers.end() &&
1078 (*(*succ)) == (pBuffer->GetPointer()+pBuffer->GetTotalSize())) {
1079 if ((iResult=pBuffer->Merge(*(*succ)))>=0) {
1080 delete *succ;
1081 fFreeBuffers.erase(succ);
1082 }
1083 }
545d509f 1084 }
775975be 1085 break;
545d509f 1086 }
775975be 1087 }
1088 }
1089 if (prev==fFreeBuffers.end()) {
1090 fFreeBuffers.push_back(pBuffer);
1091 }
48dedf26 1092
1093 // merge consecutive free buffers
1094 prev=fFreeBuffers.begin();
1095 for (AliHLTRawBufferPList::iterator current=prev+1; current!=fFreeBuffers.end() && iResult>=0; ) {
1096 // check if the buffer is embedded into the previous one
1097 if ((*current)->GetTotalSize()==0 && (*prev)->GetPointer()<=(*current)->GetPointer() && (*current)->GetPointer()<(*prev)->GetPointer()+(*prev)->GetTotalSize()) {
1098 if ((iResult=(*prev)->Merge(*(*current)))>=0) {
1099 current=fFreeBuffers.erase(current);
1100 continue;
1101 } else {
1102 HLTError("failed to merge embedded zero length buffer into preceeding buffer");
1103 Print("");
1104 }
1105 }
1106 // check if the buffer is consecutive to the previous one
1107 if ((*(*current)) == ((*prev)->GetPointer()+(*prev)->GetTotalSize())) {
1108 if ((iResult=(*prev)->Merge(*(*current)))>=0) {
1109 current=fFreeBuffers.erase(current);
1110 continue;
1111 } else {
1112 HLTError("failed to merge consecutive free buffers");
1113 Print("");
1114 }
1115 }
1116 prev=current++;
1117 }
1118
775975be 1119 // buffer was part of this page
545d509f 1120 return 0;
1121 }
1122 }
775975be 1123 // buffer not found in this page
545d509f 1124 return 1;
1125}
1126
775975be 1127int AliHLTDataBuffer::AliHLTRawPage::SetSize(AliHLTDataBuffer::AliHLTRawBuffer* pBuffer, AliHLTUInt32_t size)
1128{
1129 /// set the size of a raw buffer and release the remaining part
1130 int iResult=0;
1131 for (AliHLTRawBufferPList::iterator iter=fUsedBuffers.begin();
1132 iter!=fUsedBuffers.end() && iResult>=0;
1133 iter++) {
1134 if ((*iter)==pBuffer) { // buffer was part of this page
48dedf26 1135 if ((*iter)->GetTotalSize()==size) return 0;
1136 if ((*iter)->GetTotalSize()<size) {
1137 HLTError("%d exceeds total size of buffer %p (%d used %d)\n", size, *iter, (*iter)->GetTotalSize(), (*iter)->GetUsedSize());
1138 return -ENOSPC;
1139 }
775975be 1140 AliHLTDataBuffer::AliHLTRawBuffer* freespace=(*iter)->Split(size);
1141 if (freespace) {
1142 fUsedBuffers.push_back(freespace);
1143 Free(freespace);
1144 } else {
48dedf26 1145 HLTWarning("failed to relase unused memory: cannot split raw buffer %p of size %d (used %d) at size %d", *iter, (*iter)->GetTotalSize(), (*iter)->GetUsedSize(), size);
775975be 1146 }
1147 return 0;
1148 }
1149 }
1150 // buffer not found in this page
1151 return 1;
1152}
1153
48dedf26 1154bool AliHLTDataBuffer::AliHLTRawPage::HasBuffer(AliHLTDataBuffer::AliHLTRawBuffer* pBuffer)
1155{
1156 /// check if the buffer is in this page
1157 for (AliHLTRawBufferPList::iterator iter=fUsedBuffers.begin();
1158 iter!=fUsedBuffers.end();
1159 iter++) {
1160 if ((*iter)==pBuffer) { // buffer was part of this page
1161 return true;
1162 }
1163 }
1164 // buffer not found in this page
1165 return false;
1166}
1167
775975be 1168AliHLTUInt32_t AliHLTDataBuffer::AliHLTRawPage::Capacity() const
1169{
1170 /// get max available contiguous buffer
1171 AliHLTUInt32_t capacity=0;
1172 for (unsigned i=0; i<fFreeBuffers.size(); i++) {
1173 if (fFreeBuffers[i]->GetTotalSize()>capacity)
1174 capacity=fFreeBuffers[i]->GetTotalSize();
1175 }
1176 return capacity;
1177}
1178
48dedf26 1179void AliHLTDataBuffer::AliHLTRawPage::Print(const char* option)
545d509f 1180{
1181 /// print page information
48dedf26 1182 if (strcmp(option, "global")==0) {
1183 cout << "number of global pages: " << fgGlobalPages.size() << endl;
1184 for (AliHLTRawPage* rawpage=NextPage(NULL);
1185 rawpage!=NULL;
1186 rawpage=NextPage(rawpage)) {
1187 rawpage->Print("");
1188 }
1189 return;
1190 }
545d509f 1191 cout << "************* AliHLTRawPage status ***********" << endl;
48dedf26 1192 cout << " instance " << this << endl;
775975be 1193 printf(" buffer %p size %d", fPtr, fSize);
1194 cout << " used buffers: " << fUsedBuffers.size() << endl;
545d509f 1195 AliHLTRawBufferPList::iterator iter=fUsedBuffers.begin();
1196 for (; iter!=fUsedBuffers.end(); iter++) {
775975be 1197 cout << " "; (*iter)->Print("min");
545d509f 1198 }
775975be 1199 cout << " free buffers: " << fFreeBuffers.size() << endl;
545d509f 1200 iter=fFreeBuffers.begin();
1201 for (; iter!=fFreeBuffers.end(); iter++) {
775975be 1202 cout << " "; (*iter)->Print("min");
545d509f 1203 }
1204}
48dedf26 1205
1206
1207vector<AliHLTDataBuffer::AliHLTRawPage*> AliHLTDataBuffer::AliHLTRawPage::fgGlobalPages;
1208
1209AliHLTUInt32_t AliHLTDataBuffer::AliHLTRawPage::fgGlobalPageSize=1024*1024*10;
1210
1211AliHLTDataBuffer::AliHLTRawBuffer* AliHLTDataBuffer::AliHLTRawPage::GlobalAlloc(AliHLTUInt32_t size, int verbosity)
1212{
1213 // alloc a buffer of specified size from the global pages
1214 AliHLTDataBuffer::AliHLTRawBuffer* rawbuffer=NULL;
1215 vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=fgGlobalPages.begin();
1216 AliHLTLogging log;
1217 for (page=fgGlobalPages.begin();page!=fgGlobalPages.end(); page++) {
1218 if ((rawbuffer=(*page)->Alloc(size))!=NULL) {
1219 if (verbosity>1) {
1220 log.Logging(kHLTLogInfo, "AliHLTDataBuffer::AliHLTRawPage::GlobalAlloc", "data buffer handling", "allocated raw buffer %p from page %p\n", rawbuffer, *page);
1221 rawbuffer->Print("min");
1222 }
1223 break;
1224 }
1225 }
1226 if (!rawbuffer) {
1227 AliHLTDataBuffer::AliHLTRawPage* rawpage=new AliHLTDataBuffer::AliHLTRawPage(fgGlobalPageSize);
1228 if (!rawpage) {
1229 log.Logging(kHLTLogError, "AliHLTDataBuffer::AliHLTRawPage::GlobalAlloc", "data buffer handling", "can not create raw page");
1230 return NULL;
1231 }
1232 fgGlobalPages.push_back(rawpage);
1233 if ((rawbuffer=rawpage->Alloc(size))!=NULL) {
1234 if (verbosity>1) {
1235 log.Logging(kHLTLogInfo, "AliHLTDataBuffer::AliHLTRawPage::GlobalAlloc", "data buffer handling", "allocated raw buffer %p from page %p\n", rawbuffer, rawpage);
1236 rawbuffer->Print("min");
1237 }
1238 }
1239 }
1240
1241 return rawbuffer;
1242}
1243
1244AliHLTDataBuffer::AliHLTRawPage* AliHLTDataBuffer::AliHLTRawPage::FindPage(AliHLTDataBuffer::AliHLTRawBuffer* buffer)
1245{
1246 // find buffer in the global pages
1247 vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=fgGlobalPages.begin();
1248 for (; page!=fgGlobalPages.end(); page++) {
1249 if ((*page)->HasBuffer(buffer)) {
1250 return *page;
1251 }
1252 }
1253
1254 return NULL;
1255}
1256
1257int AliHLTDataBuffer::AliHLTRawPage::GlobalClean()
1258{
1259 // cleanup the global pages */
1260 vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=fgGlobalPages.begin();
1261 while (page!=fgGlobalPages.end()) {
1262 if (!(*page)->IsUsed()) {
1263 delete *page;
1264 page=fgGlobalPages.erase(page);
1265 continue;
1266 }
1267 AliHLTLogging log;
1268 log.Logging(kHLTLogError, "AliHLTDataBuffer::AliHLTRawPage::GlobalClean", "data buffer handling", "HLT memory page still in use, skipping cleanup, potential memory leak");
1269
1270 page++;
1271 }
1272
1273 return 0;
1274}
1275
1276AliHLTDataBuffer::AliHLTRawPage* AliHLTDataBuffer::AliHLTRawPage::NextPage(AliHLTDataBuffer::AliHLTRawPage* prev)
1277{
1278 // get next global page
1279 vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=fgGlobalPages.begin();
1280 for (; page!=fgGlobalPages.end(); page++) {
1281 if (prev==NULL) return *page;
1282 if (*page!=prev) continue;
1283 if (++page!=fgGlobalPages.end()) return *page;
1284 break;
1285 }
1286 return NULL;
1287}