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