]> git.uio.no Git - u/mrichter/AliRoot.git/commitdiff
several improvments for AliHLTSystem memory page handling
authorrichterm <richterm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 2 Feb 2010 07:46:21 +0000 (07:46 +0000)
committerrichterm <richterm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 2 Feb 2010 07:46:21 +0000 (07:46 +0000)
- implementing global methods
- bugfixes for splitting and merging of buffers
- extended unit test checking both AliHLTDataBuffer and the handling of raw pages
- added checking of buffer content with random data
still to be activated for normal operation

HLT/BASE/AliHLTDataBuffer.cxx
HLT/BASE/AliHLTDataBuffer.h
HLT/BASE/test/testAliHLTDataBuffer.C

index 148d372e5d23ffabfd401b541b23123b1f78c125..ea4b9aab6ec404ce498fe4270af35927f4e99031 100644 (file)
@@ -360,6 +360,7 @@ int AliHLTDataBuffer::SetSegments(AliHLTUInt8_t* pTgt, AliHLTComponentBlockData*
     if (fpBuffer) {
       if (*fpBuffer==pTgt) {
        AliHLTDataBuffer::AliHLTDataSegment segment;
+       AliHLTUInt32_t maxSize=0;
        for (int i=0; i<iSize; i++) {
          // This function has to model the behavior of PubSub
          // For output blocks only the fOffset value is used, this must be the offset
@@ -378,6 +379,12 @@ int AliHLTDataBuffer::SetSegments(AliHLTUInt8_t* pTgt, AliHLTComponentBlockData*
              segment.fSpecification=arrayBlockData[i].fSpecification;
              fSegments.push_back(segment);
              HLTDebug("set segment %s with size %d at offset %d", AliHLTComponent::DataType2Text(segment.fDataType).data(), segment.fSegmentSize, segment.fSegmentOffset);
+
+             // find the actual size of the data
+             if ((arrayBlockData[i].fOffset!=~(AliHLTUInt32_t)0) &&
+                 arrayBlockData[i].fOffset+arrayBlockData[i].fSize>maxSize) {
+               maxSize=arrayBlockData[i].fOffset+arrayBlockData[i].fSize;
+             }
            } else {
              HLTError("block data specification %#d (%s) exceeds size of data buffer", i, AliHLTComponent::DataType2Text(arrayBlockData[i].fDataType).data());
              HLTError("block offset=%d, block size=%d, buffer size=%d", arrayBlockData[i].fOffset, arrayBlockData[i].fSize, fpBuffer->GetUsedSize());
@@ -390,6 +397,8 @@ int AliHLTDataBuffer::SetSegments(AliHLTUInt8_t* pTgt, AliHLTComponentBlockData*
            iResult=-ERANGE;
          }
        }
+       // to be enabled if unit test is ready
+       //iResult=SetRawBufferDataSize(fpBuffer, maxSize);      
       } else {
        HLTError("this data buffer (%p) does not match the internal data buffer %p of raw buffer %p", pTgt, fpBuffer->GetPointer(), fpBuffer);
        iResult=-EINVAL;
@@ -482,6 +491,28 @@ AliHLTDataBuffer::AliHLTRawBuffer* AliHLTDataBuffer::CreateRawBuffer(AliHLTUInt3
   return pRawBuffer;
 }
 
+int AliHLTDataBuffer::SetRawBufferDataSize(AliHLTRawBuffer* pBuffer, AliHLTUInt32_t size) const
+{
+  // see header file for function documentation
+  int iResult=0;
+  if (!pBuffer) return -EINVAL;
+  if (size>pBuffer->GetUsedSize()) {
+    HLTError("indicated data size %d exceeds data buffer %p (%d)", size, pBuffer->GetPointer(), pBuffer->GetUsedSize());
+    return -ENOSPC;
+  }
+  if (fgkSafetyPatternSize>0) {
+    if (pBuffer->CheckPattern(fgkSafetyPattern, fgkSafetyPatternSize)) {
+      HLTError("potential memory corruption: component has written beyond end of data buffer %p size %d", pBuffer->GetPointer(), pBuffer->GetUsedSize());
+    }
+  }
+  // shrink the buffer and write new pattern at the end
+  pBuffer->UseBuffer(size);
+  if (fgkSafetyPatternSize>0) {
+    pBuffer->WritePattern(fgkSafetyPattern, fgkSafetyPatternSize);
+  }
+  return iResult;
+}
+
 int AliHLTDataBuffer::ReleaseRawBuffer(AliHLTRawBuffer* pBuffer)
 {
   // see header file for function documentation
@@ -829,7 +860,7 @@ AliHLTDataBuffer::AliHLTRawBuffer* AliHLTDataBuffer::AliHLTRawBuffer::Split(AliH
 {
   // split a buffer at specified size
   // only possible for buffers with external memory
-  if (size>0 && fTotalSize>size && 
+  if (fTotalSize>size && 
       (fSize==0 || fSize<size) &&
       fExternalPtr!=NULL) {
     AliHLTRawBuffer* part2=new AliHLTRawBuffer(fTotalSize-size, fPtr+size);
@@ -895,6 +926,23 @@ int AliHLTDataBuffer::AliHLTRawBuffer::Merge(const AliHLTDataBuffer::AliHLTRawBu
 
   if (!fExternalPtr || !neighbor.fExternalPtr) return -EPERM;
 
+  if (neighbor.fTotalSize==0 &&
+      fPtr < neighbor.fPtr &&
+      fPtr+fTotalSize > neighbor.fPtr) {
+    // special case for a buffer of zero size embedded into this buffer
+    // nothing to do
+    return 0;
+  }
+  if (fTotalSize==0 &&
+      neighbor.fPtr < fPtr &&
+      neighbor.fPtr+neighbor.fTotalSize > fPtr) {
+    // special case for this buffer of size zero embedded into another buffer
+    fPtr=neighbor.fPtr;
+    fExternalPtr=fPtr;
+    fTotalSize+=neighbor.fTotalSize;
+    fSize=0;
+    return 0;
+  }
   if (fPtr+fTotalSize == neighbor.fPtr) {
     fTotalSize+=neighbor.fTotalSize;
     fSize=0;
@@ -936,11 +984,11 @@ AliHLTDataBuffer::AliHLTRawPage::AliHLTRawPage(AliHLTUInt32_t pagesize)
 AliHLTDataBuffer::AliHLTRawPage::~AliHLTRawPage()
 {
   // destructor
-  if (fUsedBuffers.size()>0) {
+  if (IsUsed()) {
     // do not free if the resources have not been completely freed
     HLTError("memory mismatch: not all allocated intances have been released");
   } else {
-    if (fFreeBuffers.size()>0) {
+    if (IsFragmented()) {
       HLTWarning("page still fragmented");
     }
     AliHLTRawBufferPList::iterator element=fFreeBuffers.begin();
@@ -964,7 +1012,12 @@ AliHLTDataBuffer::AliHLTRawBuffer* AliHLTDataBuffer::AliHLTRawPage::Alloc(AliHLT
   for (AliHLTRawBufferPList::iterator iter=fFreeBuffers.begin();
        iter!=fFreeBuffers.end();
        iter++) {
-    if ((*iter)->GetTotalSize()>=size) {
+    if ((*iter)->GetTotalSize()==size) {
+      AliHLTRawBuffer* thisbuffer=*iter;
+      fFreeBuffers.erase(iter);
+      fUsedBuffers.push_back(thisbuffer);
+      return thisbuffer;
+    } else if ((*iter)->GetTotalSize()>size) {
       AliHLTRawBuffer* thisbuffer=*iter;
       AliHLTRawBuffer* newbuffer=thisbuffer->Split(size);
       if (newbuffer) {
@@ -972,7 +1025,7 @@ AliHLTDataBuffer::AliHLTRawBuffer* AliHLTDataBuffer::AliHLTRawPage::Alloc(AliHLT
        fUsedBuffers.push_back(thisbuffer);
        return thisbuffer;
       } else {
-       HLTWarning("failed to split raw buffer %p", *iter);
+       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);
       }
     }
   }
@@ -987,25 +1040,45 @@ int AliHLTDataBuffer::AliHLTRawPage::Free(AliHLTRawBuffer* pBuffer)
        iter!=fUsedBuffers.end() && iResult>=0;
        iter++) {
     if ((*iter)==pBuffer) {
+      if (false/*pBuffer->GetTotalSize()==0*/) {
+       HLTInfo("release zero lenght buffer %p %d (used %d)", pBuffer, pBuffer->GetTotalSize(), pBuffer->GetUsedSize());
+       pBuffer->Print("");
+       Print("");
+      }
       fUsedBuffers.erase(iter);
       AliHLTRawBufferPList::iterator prev=fFreeBuffers.begin();
       for (; prev!=fFreeBuffers.end() && iResult>=0; prev++) {
-       if ((*pBuffer)<(*(*prev))) {
+       if (false/*pBuffer->GetTotalSize()==0*/) {
+         HLTInfo("iterator buffer %p %d (used %d)", (*prev), (*prev)->GetTotalSize(), (*prev)->GetUsedSize());
+         (*prev)->Print("");
+       }
+       if ((*pBuffer)<(*(*prev)) ||
+           ((*prev)->GetTotalSize()==0 && pBuffer->GetPointer()<=(*prev)->GetPointer() && (*prev)->GetPointer()<=pBuffer->GetPointer()+pBuffer->GetTotalSize())) {
          // check consecutive buffers
-         if ((*(*prev)) == (pBuffer->GetPointer()+pBuffer->GetTotalSize())) {
+         if ((*(*prev)) == (pBuffer->GetPointer()+pBuffer->GetTotalSize()) ||
+             ((*prev)->GetTotalSize()==0 && pBuffer->GetPointer()<=(*prev)->GetPointer() && (*prev)->GetPointer()<=pBuffer->GetPointer()+pBuffer->GetTotalSize())) {
            // the buffer to be released has a consecutive free buffer -> merge them
            if ((iResult=pBuffer->Merge(*(*prev)))>=0) {
              delete *prev;
              *prev=pBuffer;
+           } else {
+             HLTError("failed to merge consecutive/overlapping buffers %p and %p", pBuffer, (*prev));
+             pBuffer->Print("");
+             (*prev)->Print("");
            }
            break;
          }
          fFreeBuffers.insert(prev, pBuffer);
          break;
        }
-       if ((*pBuffer)>(*(*prev))) {
+       if ((*pBuffer)>(*(*prev)) ||
+           (pBuffer->GetTotalSize()==0 && (*prev)->GetPointer()<=pBuffer->GetPointer() && pBuffer->GetPointer()<=(*prev)->GetPointer()+(*prev)->GetTotalSize())) {
          // check consecutive buffers
-         if ((*pBuffer) == ((*prev)->GetPointer()+(*prev)->GetTotalSize())) {
+         if ((*pBuffer) == ((*prev)->GetPointer()+(*prev)->GetTotalSize())||
+             (pBuffer->GetTotalSize()==0 && (*prev)->GetPointer()<=pBuffer->GetPointer() && pBuffer->GetPointer()<=(*prev)->GetPointer()+(*prev)->GetTotalSize())) {
+           if (false/*pBuffer->GetTotalSize()==0*/) {
+             HLTInfo("merge with buffer %p %d (used %d)", (*prev), (*prev)->GetTotalSize(), (*prev)->GetUsedSize());
+           }
            // the buffer to be released is consecutive to a free buffer -> merge them
            if ((iResult=pBuffer->Merge(*(*prev)))>=0) {
              AliHLTRawBufferPList::iterator succ=prev+1;
@@ -1025,8 +1098,39 @@ int AliHLTDataBuffer::AliHLTRawPage::Free(AliHLTRawBuffer* pBuffer)
        }
       }
       if (prev==fFreeBuffers.end()) {
+       if (false/*pBuffer->GetTotalSize()==0*/) {
+         HLTInfo("insert as free buffer");
+         Print("");
+       }
        fFreeBuffers.push_back(pBuffer);
       }
+
+      // merge consecutive free buffers
+      prev=fFreeBuffers.begin();
+      for (AliHLTRawBufferPList::iterator current=prev+1; current!=fFreeBuffers.end() && iResult>=0; ) {
+       // check if the buffer is embedded into the previous one
+       if ((*current)->GetTotalSize()==0 && (*prev)->GetPointer()<=(*current)->GetPointer() && (*current)->GetPointer()<(*prev)->GetPointer()+(*prev)->GetTotalSize())  {
+         if ((iResult=(*prev)->Merge(*(*current)))>=0) {
+           current=fFreeBuffers.erase(current);
+           continue;
+         } else {
+           HLTError("failed to merge embedded zero length buffer into preceeding buffer");
+           Print("");
+         }
+       }
+       // check if the buffer is consecutive to the previous one
+       if ((*(*current)) == ((*prev)->GetPointer()+(*prev)->GetTotalSize())) {
+         if ((iResult=(*prev)->Merge(*(*current)))>=0) {
+           current=fFreeBuffers.erase(current);
+           continue;
+         } else {
+           HLTError("failed to merge consecutive free buffers");
+           Print("");
+         }
+       }
+       prev=current++;
+      }
+
       // buffer was part of this page
       return 0;
     }
@@ -1043,12 +1147,20 @@ int AliHLTDataBuffer::AliHLTRawPage::SetSize(AliHLTDataBuffer::AliHLTRawBuffer*
        iter!=fUsedBuffers.end() && iResult>=0;
        iter++) {
     if ((*iter)==pBuffer) {      // buffer was part of this page
+      if ((*iter)->GetTotalSize()==size) return 0;
+      if ((*iter)->GetTotalSize()<size) {
+       HLTError("%d exceeds total size of buffer %p (%d used %d)\n", size, *iter, (*iter)->GetTotalSize(), (*iter)->GetUsedSize());
+       return -ENOSPC;
+      }
+      //HLTInfo("setting size %d of buffer %p (%d used %d)", size, *iter, (*iter)->GetTotalSize(), (*iter)->GetUsedSize());
       AliHLTDataBuffer::AliHLTRawBuffer* freespace=(*iter)->Split(size);
+      //(*iter)->Print("");
       if (freespace) {
+       //freespace->Print("");
        fUsedBuffers.push_back(freespace);
        Free(freespace);
       } else {
-       HLTWarning("failed to split raw buffer %p in order to relase unused memory", *iter);    
+       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);
       }
       return 0;
     }
@@ -1057,6 +1169,20 @@ int AliHLTDataBuffer::AliHLTRawPage::SetSize(AliHLTDataBuffer::AliHLTRawBuffer*
   return 1;
 }
 
+bool AliHLTDataBuffer::AliHLTRawPage::HasBuffer(AliHLTDataBuffer::AliHLTRawBuffer* pBuffer)
+{
+  /// check if the buffer is in this page
+  for (AliHLTRawBufferPList::iterator iter=fUsedBuffers.begin();
+       iter!=fUsedBuffers.end();
+       iter++) {
+    if ((*iter)==pBuffer) {      // buffer was part of this page
+      return true;
+    }
+  }
+  // buffer not found in this page
+  return false;
+}
+
 AliHLTUInt32_t AliHLTDataBuffer::AliHLTRawPage::Capacity() const 
 {
   /// get max available contiguous buffer
@@ -1068,10 +1194,20 @@ AliHLTUInt32_t AliHLTDataBuffer::AliHLTRawPage::Capacity() const
   return capacity;
 }
 
-void AliHLTDataBuffer::AliHLTRawPage::Print(const char* /*option*/)
+void AliHLTDataBuffer::AliHLTRawPage::Print(const char* option)
 {
   /// print page information
+  if (strcmp(option, "global")==0) {
+    cout << "number of global pages: " << fgGlobalPages.size() << endl;
+    for (AliHLTRawPage* rawpage=NextPage(NULL);
+        rawpage!=NULL; 
+        rawpage=NextPage(rawpage)) {
+      rawpage->Print("");
+    }
+    return;
+  }
   cout << "************* AliHLTRawPage status ***********" << endl;
+  cout << "  instance " << this << endl;
   printf("  buffer %p  size %d", fPtr, fSize);
   cout << "  used buffers: " << fUsedBuffers.size() << endl;
   AliHLTRawBufferPList::iterator iter=fUsedBuffers.begin();
@@ -1084,3 +1220,86 @@ void AliHLTDataBuffer::AliHLTRawPage::Print(const char* /*option*/)
     cout << "  "; (*iter)->Print("min");
   }
 }
+
+
+vector<AliHLTDataBuffer::AliHLTRawPage*> AliHLTDataBuffer::AliHLTRawPage::fgGlobalPages;
+
+AliHLTUInt32_t AliHLTDataBuffer::AliHLTRawPage::fgGlobalPageSize=1024*1024*10;
+
+AliHLTDataBuffer::AliHLTRawBuffer* AliHLTDataBuffer::AliHLTRawPage::GlobalAlloc(AliHLTUInt32_t size, int verbosity)
+{
+  // alloc a buffer of specified size from the global pages
+  AliHLTDataBuffer::AliHLTRawBuffer* rawbuffer=NULL;
+  vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=fgGlobalPages.begin();
+  AliHLTLogging log;
+  for (page=fgGlobalPages.begin();page!=fgGlobalPages.end(); page++) {
+    if ((rawbuffer=(*page)->Alloc(size))!=NULL) {
+      if (verbosity>1) {
+       log.Logging(kHLTLogInfo, "AliHLTDataBuffer::AliHLTRawPage::GlobalAlloc", "data buffer handling", "allocated raw buffer %p from page %p\n", rawbuffer, *page);
+       rawbuffer->Print("min");
+      }
+      break;
+    }
+  }
+  if (!rawbuffer) {
+    AliHLTDataBuffer::AliHLTRawPage* rawpage=new AliHLTDataBuffer::AliHLTRawPage(fgGlobalPageSize);
+    if (!rawpage) {
+      log.Logging(kHLTLogError, "AliHLTDataBuffer::AliHLTRawPage::GlobalAlloc", "data buffer handling", "can not create raw page");
+      return NULL;
+    }
+    fgGlobalPages.push_back(rawpage);
+    if ((rawbuffer=rawpage->Alloc(size))!=NULL) {
+      if (verbosity>1) {
+       log.Logging(kHLTLogInfo, "AliHLTDataBuffer::AliHLTRawPage::GlobalAlloc", "data buffer handling", "allocated raw buffer %p from page %p\n", rawbuffer, rawpage);
+       rawbuffer->Print("min");
+      }
+    }
+  }
+
+  return rawbuffer;
+}
+
+AliHLTDataBuffer::AliHLTRawPage* AliHLTDataBuffer::AliHLTRawPage::FindPage(AliHLTDataBuffer::AliHLTRawBuffer* buffer)
+{
+  // find buffer in the global pages
+  vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=fgGlobalPages.begin();
+  for (; page!=fgGlobalPages.end(); page++) {
+    if ((*page)->HasBuffer(buffer)) {
+      return *page;
+    }
+  }
+
+  return NULL;
+}
+
+int AliHLTDataBuffer::AliHLTRawPage::GlobalClean()
+{
+  // cleanup the global pages */
+  vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=fgGlobalPages.begin();
+  while (page!=fgGlobalPages.end()) {
+    if (!(*page)->IsUsed()) {
+      delete *page;
+      page=fgGlobalPages.erase(page);
+      continue;
+    }
+    AliHLTLogging log;
+    log.Logging(kHLTLogError, "AliHLTDataBuffer::AliHLTRawPage::GlobalClean", "data buffer handling", "HLT memory page still in use, skipping cleanup, potential memory leak");
+    
+    page++;
+  }
+  
+  return 0;
+}
+
+AliHLTDataBuffer::AliHLTRawPage* AliHLTDataBuffer::AliHLTRawPage::NextPage(AliHLTDataBuffer::AliHLTRawPage* prev)
+{
+  // get next global page
+  vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=fgGlobalPages.begin();
+  for (; page!=fgGlobalPages.end(); page++) {
+    if (prev==NULL) return *page;
+    if (*page!=prev) continue;
+    if (++page!=fgGlobalPages.end()) return *page;
+    break;
+  }
+  return NULL;
+}
index 34c3666d4d5adbe3af2507f240cc32c4e71f8d23..4c7af5aa022781b511b2799f129965013da5f768 100644 (file)
@@ -326,17 +326,30 @@ class AliHLTDataBuffer : public TObject, public AliHLTLogging
     /** destructor */
     virtual ~AliHLTRawPage();
 
+    /** alloc a buffer of specified size from the global pages*/
+    static AliHLTRawBuffer* GlobalAlloc(AliHLTUInt32_t size, int verbosity=0);
+    /** find buffer in the global pages */
+    static AliHLTRawPage* FindPage(AliHLTRawBuffer* buffer);
+    /** cleanup the global pages */
+    static int GlobalClean();
+    /** adjust global page size */
+    static void SetGlobalPageSize(AliHLTUInt32_t size) {fgGlobalPageSize=size;}
+    /** find next page after prev, or first page */
+    static AliHLTRawPage* NextPage(AliHLTRawPage* prev=NULL);
+
     /** alloc a buffer of specified size */
     AliHLTRawBuffer* Alloc(AliHLTUInt32_t size);
     /** free a buffer and merge consecutive free buffers */
     int Free(AliHLTRawBuffer* pBuffer);
     /** set the size of a raw buffer and release the remaining part */
     int SetSize(AliHLTRawBuffer* pBuffer, AliHLTUInt32_t size);
+    /// check if the buffer is in this page
+    bool HasBuffer(AliHLTRawBuffer* pBuffer);
 
     AliHLTUInt32_t Size() const {return fSize;}
     AliHLTUInt32_t Capacity() const;
     bool IsUsed() const {return fUsedBuffers.size()>0;}
-    bool IsFragmented() const {return (fFreeBuffers.size()+fUsedBuffers.size()>0)>1;}
+    bool IsFragmented() const {return (fFreeBuffers.size()+fUsedBuffers.size())>1;}
 
     /**
      * Print page information
@@ -349,6 +362,11 @@ class AliHLTDataBuffer : public TObject, public AliHLTLogging
     /** assignment operator prohibited */
     AliHLTRawPage& operator=(const AliHLTRawPage&);
 
+    /// list of global pages
+    static vector<AliHLTDataBuffer::AliHLTRawPage*> fgGlobalPages; //! transient
+    /// pages size of global pages
+    static AliHLTUInt32_t fgGlobalPageSize;                        //! transient
+
     /** page size */
     AliHLTUInt32_t fSize;                                          // see above
     /** the memory segment */
@@ -492,12 +510,15 @@ class AliHLTDataBuffer : public TObject, public AliHLTLogging
   int FindMatchingDataSegments(const AliHLTComponent* pConsumer, 
                               vector<AliHLTDataBuffer::AliHLTDataSegment>& tgtList);
 
+ protected:
+  // 2010-02-01 make function protected in order to be used from unit test
   /**
    * Reset the data buffer.
    * Removes all consumers back to the @ref fConsumers list, deletes
    * segments and releases the Raw Buffer.
    */
   int ResetDataBuffer();
+ private:
 
   //////////////////////////////////////////////////////////////////////////////
 
@@ -538,6 +559,12 @@ class AliHLTDataBuffer : public TObject, public AliHLTLogging
    */
   static AliHLTRawBuffer* CreateRawBuffer(AliHLTUInt32_t size);
 
+  /**
+   * Set the data size of a raw buffer after it has been filled by
+   * the component.
+   */
+  int SetRawBufferDataSize(AliHLTRawBuffer* pBuffer, AliHLTUInt32_t size) const;
+
   /**
    * Mark a buffer as free.
    * After the Data Buffer has finnished using the raw buffer, it is released
index 4e7ecd5fc473e885e5050a71f99eb27497b797b1..66faab3bde637747f84302633e350a2f48323cb2 100644 (file)
@@ -43,33 +43,329 @@ using namespace std;
 int gVerbosity=0;
 const int gPagesize=1024*1024*10;
 
-int testAliHLTRawPage();
+template<class T>
+int testLoop(vector<T>& descriptions, int nofLevels, int nofCycles);
 int GetRandom(int min, int max);
 
-struct testProcessDescription {
+class AliHLTRandomBuffer {
+public:
+  AliHLTRandomBuffer(): fpBuffer(NULL), fBufferSize(0), fInstances() {}
+  AliHLTRandomBuffer(AliHLTUInt32_t size): fpBuffer(NULL), fBufferSize(0), fInstances() {Init(size);}
+  AliHLTRandomBuffer(const AliHLTRandomBuffer&): fpBuffer(NULL), fBufferSize(0), fInstances() {}
+  AliHLTRandomBuffer& operator=(const AliHLTRandomBuffer& src) {if (&src!=this) {fpBuffer=NULL; fBufferSize=0;} return *this;}
+  ~AliHLTRandomBuffer() {}
+
+  int Init(AliHLTUInt32_t size) {
+    if (fpBuffer) return -EINPROGRESS;
+    
+    fpBuffer=new AliHLTUInt8_t[size];
+    if (!fpBuffer) return -ENOMEM;
+    fBufferSize=size;
+
+    int words=size/sizeof(AliHLTUInt32_t);
+    AliHLTUInt32_t* pTgt=reinterpret_cast<AliHLTUInt32_t*>(fpBuffer);
+    for (int i=0; i<words; i++, pTgt++) *pTgt=GetRandom(0, 0x7fffffff);
+    return 0;
+  }
+
+  struct AliHLTRandomBufferInstance {
+    int fId;
+    AliHLTUInt32_t fOffset;
+    AliHLTUInt32_t fSize;
+  };
+
+  int CreateInstance(AliHLTUInt32_t size) {
+    if (size>fBufferSize) return -ENOSPC;
+
+    AliHLTRandomBufferInstance instance;
+    instance.fId=fInstances.size()>0?fInstances.back().fId+1:0;
+    instance.fOffset=GetRandom(0, fBufferSize-size);
+    instance.fSize=size;
+    fInstances.push_back(instance);
+    return instance.fId;
+  }
+
+  int ReleaseInstance(int id) {
+    for (vector<AliHLTRandomBufferInstance>::iterator instance=fInstances.begin();
+        instance!=fInstances.end(); instance++) {
+      if (instance->fId==id) {
+       fInstances.erase(instance);
+       return 0;
+      }
+    }
+    return -ENOENT;
+  }
+
+  const AliHLTUInt8_t* GetBuffer(int id) {
+    for (vector<AliHLTRandomBufferInstance>::iterator instance=fInstances.begin();
+        instance!=fInstances.end(); instance++) {
+      if (instance->fId==id) {
+
+       return fpBuffer+instance->fOffset;
+      }
+    }
+    return NULL;
+  }
+
+  bool CompareBuffer(const AliHLTUInt8_t* buffer, AliHLTUInt32_t size, int id) {
+    if (!buffer) return false;
+    for (vector<AliHLTRandomBufferInstance>::iterator instance=fInstances.begin();
+        instance!=fInstances.end(); instance++) {
+      if (instance->fId==id) {
+       if (instance->fSize!=size) {
+         cout << "CompareBuffer ("<< instance->fId << "): size missmatch: " << size << ", expected " << instance->fSize << endl; 
+         return false;
+       }
+       return memcmp(buffer, fpBuffer+instance->fOffset, size)==0;
+      }
+    }
+    return false;
+  }
+
+  void Print(const char* /*option*/) {
+    cout << "AliHLTRandomBufferInstance " << this << ": buffer " << (void*)fpBuffer << " size " << fBufferSize << endl;
+    if (!fpBuffer) return;
+
+    int words=fBufferSize/sizeof(AliHLTUInt32_t);
+    int lines=words/4;
+    AliHLTUInt32_t* pTgt=reinterpret_cast<AliHLTUInt32_t*>(fpBuffer);
+    for (int line=0; line<lines; line++) {
+      for (int i=0; i<4; i++, pTgt++) cout << hex << " 0x" << (*pTgt);
+      cout << endl;
+    }
+    if (words*sizeof(AliHLTUInt32_t)!=fBufferSize) cout << "some remaining bytes left due to alignment" << endl;
+  }
+
+private:
+  AliHLTUInt8_t* fpBuffer;
+  AliHLTUInt32_t fBufferSize;
+
+  vector<AliHLTRandomBufferInstance> fInstances;
+};
+
+AliHLTRandomBuffer gData(2*gPagesize);
+
+/**
+ * @class AliHLTTestRawPage
+ * Helper class for testing cycles of memory allocation, buffer modification, and
+ * cleanup with the AliHLTRawPage within the function testLoop.
+ */
+class AliHLTTestRawPage {
+public:
+  AliHLTTestRawPage() : fBuffer(NULL) {}
+  AliHLTTestRawPage(const AliHLTTestRawPage& src) : fBuffer(src.fBuffer) {}
+  AliHLTTestRawPage& operator=(const AliHLTTestRawPage& src) {
+    fBuffer=src.fBuffer;
+    return *this;
+  }
+
+  ~AliHLTTestRawPage() {}
+
+  bool IsAllocated() {return fBuffer!=NULL;}
+  bool Alloc(AliHLTUInt32_t size, int verbosity) {
+    fBuffer=AliHLTDataBuffer::AliHLTRawPage::GlobalAlloc(size);
+    if (!fBuffer) return false;
+    if (verbosity>1) {
+      printf("allocated raw buffer %p from page %p\n", fBuffer, AliHLTDataBuffer::AliHLTRawPage::FindPage(fBuffer));
+      fBuffer->Print("min");
+    }
+    return true;
+  }
+
+  AliHLTUInt8_t* GetPointer() {return fBuffer?fBuffer->GetPointer():NULL;}
+
+  bool SetSize(AliHLTUInt32_t size, int verbosity) {
+    AliHLTDataBuffer::AliHLTRawPage* rawpage=AliHLTDataBuffer::AliHLTRawPage::FindPage(fBuffer);
+    if (rawpage) {
+      if (rawpage->SetSize(fBuffer, size)==0) {
+       if (verbosity>1) {
+         cout << "setting size for raw buffer " << fBuffer << " of page " << rawpage << endl;
+         fBuffer->Print("min");
+       }
+       return true;
+      } else {
+       cerr << "failed to set size for raw buffer " << fBuffer << endl; 
+      }
+    } else {
+      cerr << "can not find raw page for buffer " << fBuffer << endl;
+    }
+    
+    return false;
+  }
+
+  bool Free(int verbosity) {
+    AliHLTDataBuffer::AliHLTRawPage* rawpage=AliHLTDataBuffer::AliHLTRawPage::FindPage(fBuffer);
+    if (rawpage) {
+      if (rawpage->Free(fBuffer)==0) {
+       if (verbosity>1) cout << "released raw buffer " << fBuffer << " from page " << rawpage << endl;
+       fBuffer=NULL;
+       return true;
+      } else {
+       cerr << "failed to release raw buffer " << fBuffer  << endl;
+      }
+    } else {
+      cerr << "can not find raw page for buffer " << fBuffer  << endl;
+    }
+    return false;
+  }
+
+  AliHLTUInt32_t GetTotalSize() {return fBuffer?fBuffer->GetTotalSize():0;}
+
+  bool GlobalClean(int verbosity) {
+    int nofPages=0;
+    for (AliHLTDataBuffer::AliHLTRawPage* rawpage=AliHLTDataBuffer::AliHLTRawPage::NextPage(NULL);
+        rawpage!=NULL; 
+        rawpage=AliHLTDataBuffer::AliHLTRawPage::NextPage(rawpage)) {
+      nofPages++;
+    }
+    if (verbosity>=1) {
+      cout << "total number of pages: " << nofPages << endl;
+    }
+
+    AliHLTDataBuffer::AliHLTRawPage::GlobalClean();
+    return true;
+  }
+
+  void Print(const char* options) {
+    if (strcmp(options, "pages")==0 ||
+       strcmp(options, "global")==0) {
+      AliHLTDataBuffer::AliHLTRawPage::NextPage(NULL)->Print("global");
+      return;
+    }
+  }
+private:
+  AliHLTDataBuffer::AliHLTRawBuffer* fBuffer;
+};
+
+struct testRawPageDescription {
+  testRawPageDescription() : fLevel(0), fBufferSize(0), fDataId(-1), fTest() {};
   int fLevel;
   AliHLTUInt32_t fBufferSize;
-  AliHLTDataBuffer::AliHLTRawBuffer* fRawBuffer;
+  int fDataId;
+  AliHLTTestRawPage fTest;
 };
 
-int testAliHLTDataBuffer()
-{
-  int iResult=0;
-  if ((iResult=testAliHLTRawPage())<0) return iResult;
+class AliHLTDataBufferWrapper : public AliHLTDataBuffer {
+public:
+  int ResetDataBuffer() {
+    return AliHLTDataBuffer::ResetDataBuffer();
+  }
+};
+
+/**
+ * @class AliHLTTestDataBuffer
+ * Helper class for testing cycles of memory allocation, buffer modification, and
+ * cleanup with the AliHLTDataBuffer within the function testLoop.
+ */
+class AliHLTTestDataBuffer {
+public:
+  AliHLTTestDataBuffer() : fInstance(NULL), fBuffer(NULL), fSize(0) {}
+  AliHLTTestDataBuffer(const AliHLTTestDataBuffer&)  : fInstance(NULL), fBuffer(NULL), fSize(0) {} ;
+  AliHLTTestDataBuffer& operator=(const AliHLTTestDataBuffer&) {
+    fInstance=NULL;
+    fBuffer=NULL;
+    fSize=0;
+    return *this;
+  }
+
+  bool IsAllocated() {return fBuffer!=NULL;}
+  bool Alloc(AliHLTUInt32_t size, int verbosity) {
+    if (!fInstance) {
+      fInstance=new AliHLTDataBufferWrapper;
+      if (!fInstance) return false;
+      fInstance->SetGlobalLoggingLevel(verbosity>1?kHLTLogAll:(AliHLTComponentLogSeverity)0x7c);
+    }
+    
+    fBuffer=fInstance->GetTargetBuffer(size);
+    if (!fBuffer) return false;
+    fSize=size;
+    if (verbosity>1) {
+      cout << "allocated data buffer" << this << endl;
+    }
+    return true;
+  }
+
+  AliHLTUInt8_t* GetPointer() {return fBuffer;}
+
+  bool SetSize(AliHLTUInt32_t size, int verbosity) {
+    if (!fInstance) return false;
+    if (verbosity>1) {
+      cout << "setting size for data buffer " << this << ": allocated size " << fSize << " -> " << size << endl;
+    }
+    fSize=size;
+    return true;
+  }
 
+  bool Free(int verbosity) {
+    if (!fInstance) return false;
+    fSize=0;
+    if (fInstance->ResetDataBuffer()==0) {
+      if (verbosity>1) cout << "released data buffer " << this << endl;
+      fBuffer=NULL;
+      return true;
+    } else {
+      cerr << "failed to release raw buffer " << fBuffer  << endl;
+    }
+
+    return false;
+  }
+
+  AliHLTUInt32_t GetTotalSize() {return fSize;}
+
+  bool GlobalClean(int verbosity) {
+    if (!fInstance) return false;
+    if (verbosity>=1) {
+      fInstance->PrintStatistics();
+    }
+    delete fInstance;
+    return true;
+  }
+
+  void Print(const char* options) {
+    if (strcmp(options, "pages")==0 ||
+       strcmp(options, "global")==0) {
+      fInstance->PrintStatistics();
+    }
+  }
+private:
+  AliHLTDataBufferWrapper* fInstance;
+  AliHLTUInt8_t* fBuffer;
+  AliHLTUInt32_t fSize;
+};
+
+struct testDataBufferDescription {
+  testDataBufferDescription() : fLevel(0), fBufferSize(0), fDataId(-1), fTest() {};
+  int fLevel;
+  AliHLTUInt32_t fBufferSize;
+  int fDataId;
+  AliHLTTestDataBuffer fTest;
+};
+
+template<class T,class S>
+int CopyDescription(vector<T>& target, vector<S>& source)
+{
+  target.clear();
+  for (unsigned i=0; i<source.size(); i++) {
+    T clone;
+    clone.fLevel=source[i].fLevel;
+    clone.fBufferSize=source[i].fBufferSize;
+    clone.fDataId=source[i].fDataId;
+    target.push_back(clone);
+  }
   return 0;
 }
 
-int fillTestSample(int levels, int processes, vector<testProcessDescription>& descriptions)
+template<class T>
+int fillTestSample(int levels, int processes, vector<T>& descriptions)
 {
   int availableProcesses=processes;
   for (int level=0; level<levels; level++) {
     int levelprocesses=GetRandom(availableProcesses/2, availableProcesses-(levels-level));
     for (int process=0; process<levelprocesses; process++) {
-      testProcessDescription desc;
+      T desc;
       desc.fLevel=level;
-      desc.fBufferSize=GetRandom(1024, 3*gPagesize/processes);
-      desc.fRawBuffer=NULL;
+      desc.fBufferSize=GetRandom(1024, gPagesize/levelprocesses);
+      //desc.fTest.Clear();
       descriptions.push_back(desc);
     }
     availableProcesses-=levelprocesses;
@@ -77,43 +373,22 @@ int fillTestSample(int levels, int processes, vector<testProcessDescription>& de
   return 0;
 }
 
-int allocateBuffers(vector<testProcessDescription>& descriptions,
-                   vector<AliHLTDataBuffer::AliHLTRawPage*>& pages,
+template<class T>
+int allocateBuffers(vector<T>& descriptions,
                    int level=-1)
 {
   for (unsigned i=0; i<descriptions.size(); i++) {
     if (level>=0 && descriptions[i].fLevel<level) continue;
     if (level>=0 && descriptions[i].fLevel>level) break;
-    if (descriptions[i].fRawBuffer) {
+    if (descriptions[i].fTest.IsAllocated()) {
       cerr << "warning: buffer already allocated" << endl;
       continue;
     }
 
-    vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=pages.begin();
-    for (page=pages.begin();page!=pages.end(); page++) {
-      if ((descriptions[i].fRawBuffer=(*page)->Alloc(GetRandom(descriptions[i].fBufferSize/2, descriptions[i].fBufferSize)))!=NULL) {
-       if (gVerbosity>1) {
-         printf("allocated raw buffer %p from page %p\n", descriptions[i].fRawBuffer, *page);
-         descriptions[i].fRawBuffer->Print("min");
-       }
-       break;
-      }
-    }
-    if (!descriptions[i].fRawBuffer) {
-      AliHLTDataBuffer::AliHLTRawPage* rawpage=new AliHLTDataBuffer::AliHLTRawPage(gPagesize);
-      if (!rawpage) {
-       cerr << "can not create raw page" << endl;
-       return -ENOMEM;
-      }
-      pages.push_back(rawpage);
-      if ((descriptions[i].fRawBuffer=rawpage->Alloc(GetRandom(descriptions[i].fBufferSize/2, descriptions[i].fBufferSize)))!=NULL) {
-       if (gVerbosity>1) {
-         printf("allocated raw buffer %p from page %p\n", descriptions[i].fRawBuffer, rawpage);
-         descriptions[i].fRawBuffer->Print("min");
-       }
-      }
+    if (descriptions[i].fTest.Alloc(GetRandom(descriptions[i].fBufferSize/2, descriptions[i].fBufferSize), gVerbosity)) {
     }
-    if (!descriptions[i].fRawBuffer) {
+
+    if (!descriptions[i].fTest.IsAllocated()) {
       cerr << "failed to allocate buffer for process " << i << endl;
       return -EFAULT;
     }
@@ -121,15 +396,15 @@ int allocateBuffers(vector<testProcessDescription>& descriptions,
   return 0;
 }
                   
-int setBufferSizes(vector<testProcessDescription>& descriptions,
-                  vector<AliHLTDataBuffer::AliHLTRawPage*>& pages,
+template<class T>
+int setBufferSizes(vector<T>& descriptions,
                   int level=-1)
 {
   // set buffer size for all processes of the specified level
   // buffer size is chosen randomly between 0 and the allocated size
   vector<unsigned> positions;
   for (unsigned i=0; i<descriptions.size(); i++) {
-    if (!descriptions[i].fRawBuffer) continue;
+    if (!descriptions[i].fTest.IsAllocated()) continue;
     if (level>=0 && descriptions[i].fLevel<level) continue;
     if (level>=0 && descriptions[i].fLevel>level) break;
     positions.push_back(i);
@@ -138,33 +413,38 @@ int setBufferSizes(vector<testProcessDescription>& descriptions,
   random_shuffle(positions.begin(), positions.end());
   for (vector<unsigned>::iterator position=positions.begin();
        position!=positions.end(); position++) {
-    vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=pages.begin();
-    for (; page!=pages.end(); page++) {
-      if ((*page)->SetSize(descriptions[*position].fRawBuffer, GetRandom(0, descriptions[*position].fBufferSize))==0) {
-       if (gVerbosity>1) {
-         cout << "setting size for raw buffer " << descriptions[*position].fRawBuffer << " of page " << *page << ", process level " << descriptions[*position].fLevel << endl;
-         descriptions[*position].fRawBuffer->Print("min");
-       }
-       break;
-      }
+    AliHLTUInt32_t datasize=GetRandom(0, descriptions[*position].fTest.GetTotalSize());
+    descriptions[*position].fDataId=gData.CreateInstance(datasize);
+    const AliHLTUInt8_t* pSrc=gData.GetBuffer(descriptions[*position].fDataId);
+    if (!pSrc) {
+      cout << "error creating data instance" << endl;
+      return -1;
     }
-    if (page==pages.end()) {
-      cerr << "failed to set size for raw buffer " << descriptions[*position].fRawBuffer << "of process " << *position << endl;
-      return -EFAULT;
+    AliHLTUInt8_t* pTgt=descriptions[*position].fTest.GetPointer();
+    if (!pTgt) {
+      cout << "error target buffer" << endl;
+      return -1;
+    }
+    memcpy(pTgt, pSrc, datasize);
+    if (descriptions[*position].fTest.SetSize(datasize, gVerbosity)) {
+      if (gVerbosity>1) cout << "  process " << *position << " level " << descriptions[*position].fLevel << endl;
+    } else {
+      cout << "failed allocation for process " << *position << " level " << descriptions[*position].fLevel << endl;
+      return -1;
     }
   }
   return 0;
 }
-                  
-int releaseBuffers(vector<testProcessDescription>& descriptions,
-                  vector<AliHLTDataBuffer::AliHLTRawPage*>& pages,
+
+template<class T>                 
+int releaseBuffers(vector<T>& descriptions,
                   int level=-1)
 {
   // find the processes to be releases according to the specified level
   // shuffle the processes and then release in this random order
   vector<unsigned> positions;
   for (unsigned i=0; i<descriptions.size(); i++) {
-    if (!descriptions[i].fRawBuffer) continue;
+    if (!descriptions[i].fTest.IsAllocated()) continue;
     if (level>=0 && descriptions[i].fLevel<level) continue;
     if (level>=0 && descriptions[i].fLevel>level) break;
     positions.push_back(i);
@@ -173,99 +453,108 @@ int releaseBuffers(vector<testProcessDescription>& descriptions,
   random_shuffle(positions.begin(), positions.end());
   for (vector<unsigned>::iterator position=positions.begin();
        position!=positions.end(); position++) {
-    vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=pages.begin();
-    for (; page!=pages.end(); page++) {
-      if ((*page)->Free(descriptions[*position].fRawBuffer)==0) {
-       if (gVerbosity>1) cout << "released raw buffer " << descriptions[*position].fRawBuffer << " from page " << *page << ", process level " << descriptions[*position].fLevel << endl;
-       descriptions[*position].fRawBuffer=NULL;
-       break;
-      }
+    if (!gData.CompareBuffer(descriptions[*position].fTest.GetPointer(), descriptions[*position].fTest.GetTotalSize(), descriptions[*position].fDataId)) {
+      cout << "data comparison failed for process " << *position << " level " << descriptions[*position].fLevel << endl;
+      return -1;
     }
-    if (page==pages.end()) {
-      cerr << "failed to release raw buffer " << descriptions[*position].fRawBuffer << "of process " << *position << endl;
-      return -EFAULT;
+    gData.ReleaseInstance(descriptions[*position].fDataId);
+    if (descriptions[*position].fTest.Free(gVerbosity)) {
+      if (gVerbosity>1) cout << "  process " << *position << " level " << descriptions[*position].fLevel << endl;
+    } else {
+      cout << "failed deallocation for process " << *position << " level " << descriptions[*position].fLevel << endl;
+      return -1;
     }
   }
   return 0;
 }
-                  
-int testAliHLTRawPage()
+
+template<class T>
+int testLoop(vector<T>& descriptions, int nofLevels, int nofCycles)
 {
+  // test the buffer allocation and deallocation from the AliHLTRawPage
+  //
+  // build a hierarchy of processes like in a real chain, in the first
+  // implementation it is only a linear tree
+  // the number of levels and processes are randomly chosen from a certain range
+  // processes are distributed among the levels such that there is a decreasing
+  // number of processes but at least one process
+  //
+  // The test cycle consists of the following steps
+  // - loop over all levels
+  //   - allocation of a maximum buffer for every process of the current level
+  //   - set the buffer size to be used for every process of the current level
+  //   - release buffers of the previous level
+  // - check all created raw pages and throw error, if
+  //   - not all buffers released
+  //   - not all memory released
+  //   - still fragmented
+  // 
   int iResult=0;
-  int nofLevels=GetRandom(3,5);
-  int nofProcesses=GetRandom(nofLevels,10);
-  int nofCycles=GetRandom(5,10);
-
-  vector<testProcessDescription> descriptions;
-  if ((iResult=fillTestSample(nofLevels, nofProcesses, descriptions))<0) {
-    cerr << "failed to fill test sample" << endl;
-    return iResult;
-  }
-
-  if (gVerbosity>1) {
-    for (unsigned i=0; i<descriptions.size(); i++) {
-      cout << "process " << i << ": level " << descriptions[i].fLevel << "   max size " << descriptions[i].fBufferSize << endl;
-    }
-  }
 
-  vector<AliHLTDataBuffer::AliHLTRawPage*> pages;
-  vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=pages.end();
-  for (int cycle=0; cycle<nofCycles; cycle++) {
-    unsigned process=0;
+  AliHLTDataBuffer::AliHLTRawPage* rawpage=NULL;
+  for (int cycle=0; cycle<nofCycles && iResult>=0; cycle++) {
     for (int level=0; level<=nofLevels; level++) {
       // allocate buffers
       if (level<nofLevels) {
-       if ((iResult=allocateBuffers(descriptions, pages, level))<0) {
+       if ((iResult=allocateBuffers(descriptions, level))<0) {
          cerr << "failed to allocate buffers" << endl;
          return iResult;
        }
       }
 
-      if (gVerbosity>0) cout << "level " << level << " - status of pages: " << pages.size() << endl;
-      for (page=pages.begin();page!=pages.end(); page++) {
-       if (gVerbosity>0) (*page)->Print("");
+      if (gVerbosity>1) {
+       cout << "finished allocation - level " << level << " ";
+       descriptions[0].fTest.Print("pages");
       }
 
       if (level<nofLevels) {
-       if ((iResult=setBufferSizes(descriptions, pages, level))<0) {
+       if ((iResult=setBufferSizes(descriptions, level))<0) {
          cerr << "failed setting  buffers" << endl;
          return iResult;
        }
       }
 
-      if (gVerbosity>0) cout << "level " << level << " - status of pages: " << pages.size() << endl;
-      for (page=pages.begin();page!=pages.end(); page++) {
-       if (gVerbosity>0) (*page)->Print("");
+      if (gVerbosity>1) {
+       cout << "finished size modification - level " << level << " ";
+       descriptions[0].fTest.Print("pages");
       }
 
       if (level>0) {
-       if ((iResult=releaseBuffers(descriptions, pages, level-1))<0) {
+       if ((iResult=releaseBuffers(descriptions, level-1))<0) {
          cerr << "failed to release buffers" << endl;
          return iResult;
        }
       }
     }
 
-    if (gVerbosity>0) 
-      cout << "status of released pages:" << endl;
-    for (page=pages.begin();page!=pages.end(); page++) {
-      if (gVerbosity>0) (*page)->Print("");
-      if ((*page)->IsUsed()) {
-       cerr << "page " << *page << " has used buffers" << endl;
-       return -EFAULT;
-      }
-      if ((*page)->Size()!=(*page)->Capacity()) {
-       cerr << "page " << *page << " not completely released" << endl;
-       return -EFAULT;
-      }
-      if ((*page)->IsFragmented()) {
-       cerr << "page " << *page << " is still fragmented" << endl;
-       return -EFAULT;
+    if (gVerbosity>1) {
+      cout << "status of released pages: " << endl << "  ";
+      descriptions[0].fTest.Print("pages");
+    }
+    for (rawpage=AliHLTDataBuffer::AliHLTRawPage::NextPage(NULL);
+        rawpage!=NULL; 
+        rawpage=AliHLTDataBuffer::AliHLTRawPage::NextPage(rawpage)) {
+      if (rawpage->IsUsed()) {
+       cerr << "page " << rawpage << " has used buffers" << endl;
+       iResult=-EFAULT;
+      } else if (rawpage->Size()!=rawpage->Capacity()) {
+       cerr << "page " << rawpage << " not completely released" << endl;
+       iResult=-EFAULT;
+      } else if (rawpage->IsFragmented()) {
+       cerr << "page " << rawpage << " is still fragmented" << endl;
+       iResult=-EFAULT;
       }
     }
+    AliHLTDataBuffer::SetGlobalEventCount(cycle);
   }
 
-  return 0;
+  if (iResult<0) {
+    descriptions[0].fTest.Print("pages");
+  }
+
+  descriptions[0].fTest.GlobalClean(gVerbosity);
+
+  return iResult;
 }
 
 /**
@@ -284,6 +573,44 @@ int GetRandom(int min, int max)
   return min+rand.Integer(max-min);
 }
 
+int testAliHLTDataBuffer()
+{
+  int iResult=0;
+  const int iMaxLevels=10;
+  int nofLevels=GetRandom(3,iMaxLevels);
+  int nofProcesses=GetRandom(nofLevels,2*iMaxLevels);
+  int nofCycles=100;//GetRandom(1000,10000);
+
+  vector<testDataBufferDescription> descriptions;
+
+  if ((iResult=fillTestSample(nofLevels, nofProcesses, descriptions))<0) {
+    cerr << "failed to fill test sample" << endl;
+    return iResult;
+  }
+
+  // adjust to the level of the last entry
+  nofLevels=descriptions[descriptions.size()-1].fLevel;
+
+  if (gVerbosity>0) {
+    cout << "    Test setup: " << nofLevels << " levels/ " << nofProcesses << " processes/ " << nofCycles << " cycle(s)" << endl;
+    cout << "    Pagesize: " << gPagesize << endl;
+    for (unsigned i=0; i<descriptions.size(); i++) {
+      cout << "      process " << i << ": level " << descriptions[i].fLevel << "   max size " << descriptions[i].fBufferSize << endl;
+    }
+  }
+
+  if ((iResult=testLoop(descriptions, nofLevels, nofCycles))<0) return iResult;
+
+  if (gVerbosity>0) {
+    cout << "checking memory allocation using AliHLTRawPage directly ..." << endl;
+  }
+  vector<testRawPageDescription> rawpagedesc;
+  CopyDescription(rawpagedesc, descriptions);
+  if ((iResult=testLoop(rawpagedesc, nofLevels, nofCycles))<0) return iResult;
+
+  return 0;
+}
+
 /////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////
 //
@@ -292,6 +619,13 @@ int GetRandom(int min, int max)
 int main(int /*argc*/, const char** /*argv*/)
 {
   int iResult=0;
-  iResult=testAliHLTDataBuffer();
+  const int nofCycles=10;
+  for (int cycle=0; cycle<nofCycles && iResult>=0; cycle++) {
+    iResult=testAliHLTDataBuffer();
+    if (((cycle+1)*100/nofCycles)%10==0) {
+      cout << (cycle+1)*100/nofCycles << "% complete" << endl;
+    }
+  }
+
   return iResult;
 }