text: // ==========================================================================
  //                 SeqAn - The Library for Sequence Analysis
  // ==========================================================================
  // Copyright (c) 2006-2013, Knut Reinert, FU Berlin
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are met:
  //
  //     * Redistributions of source code must retain the above copyright
  //       notice, this list of conditions and the following disclaimer.
  //     * Redistributions in binary form must reproduce the above copyright
  //       notice, this list of conditions and the following disclaimer in the
  //       documentation and/or other materials provided with the distribution.
  //     * Neither the name of Knut Reinert or the FU Berlin nor the names of
  //       its contributors may be used to endorse or promote products derived
  //       from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
  // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  // DAMAGE.
  //
  // ==========================================================================
  // Author: David Weese <david.weese@fu-berlin.de>
  // ==========================================================================
  // Implements lots of internal data structures for low-level file access used
  // by the External String, external sorters and mappers (Pool), FileStream.
  // ==========================================================================
  
  #ifndef SEQAN_HEADER_FILE_PAGE_H
  #define SEQAN_HEADER_FILE_PAGE_H
  
  
  /* IOREV
   * _nottested_
   * _nodoc_
   *
   * not tested by any test or app
   * no documentation for the functions
   *
   * contains lots of seemingly important code, however doc is sparse
   * to non-existent. Code needs thorough investigation, to understand
   * how/if this works
   *
   * probably Weese's code according to holtgrew
   *
   *
   */
  
  
  //////////////////////////////////////////////////////////////////////////////
  
  namespace seqan {
  
  // ============================================================================
  // Forwards
  // ============================================================================
  
  template <typename TConfig>
  struct MMap;
  
  
  	//////////////////////////////////////////////////////////////////////////////
  	// base class for memory buffers
  
      struct Dynamic;
  
      template <size_t PAGESIZE>
      struct Fixed;
  
  	template <typename TFile, typename TSpec = Dynamic>
      struct PageFrame;
  
  
  	template <typename TValue, typename TSpec = Simple>
  	struct Buffer
  	{
  //IOREV _nodoc_
  		typedef	typename Size<Buffer>::Type                 TSize;
  		typedef	typename Iterator<Buffer, Standard>::Type   TIterator;
  
  		TIterator	begin;      // the beginning of the buffer
          TIterator	end;        // end of valid data
          TSize		pageSize;   // size of allocated memory
  
          Buffer():
              begin(NULL),
              end(NULL),
              pageSize(0) {}
  
          Buffer(TIterator _begin, TIterator _end):
              begin(_begin),
              end(_end),
              pageSize(0) {}
  
          Buffer(TIterator _begin, TSize _size):
              begin(_begin),
              end(_begin + _size),
              pageSize(0) {}
  
  //        template <typename T>
  //        Buffer(T &x):
  //        {
  //            const_cast<int&>(x);
  //        }
  //
  //        Buffer(TSize _pageSize):
  //            begin(NULL),
  //            end(NULL),
  //            pageSize(_pageSize) {}
  
          inline TValue       & operator[](TSize i)       { return begin[i]; }
          inline TValue const & operator[](TSize i) const { return begin[i]; }
  	};
  
  
  	//////////////////////////////////////////////////////////////////////////////
  	// meta-function interface
  
  	template <typename TValue, typename TSpec>
      struct Value<Buffer<TValue, TSpec> >
      {
          typedef TValue Type;
      };
  
  	template <typename TValue, typename TSpec>
  	struct Size<Buffer<TValue, TSpec> >
      {
          typedef size_t Type;
      };
  
  	template <typename TValue, typename TSpec>
      struct Iterator<Buffer<TValue, TSpec>, Standard>
      {
          typedef TValue *Type;
      };
  
  	template <typename TValue, typename TSpec>
      struct Iterator<Buffer<TValue, TSpec> const, Standard>
      {
          typedef TValue const *Type;
      };
  
  
  	//////////////////////////////////////////////////////////////////////////////
  	// global interface
  
  	template <typename TValue, typename TSpec>
      inline typename Size<Buffer<TValue, TSpec> >::Type
      capacity(Buffer<TValue, TSpec> const &me)
      {
          return me.pageSize;
      }
  
  	template <typename TValue, typename TFile, size_t PAGESIZE>
      inline typename Size<Buffer<TValue, PageFrame<TFile, Fixed<PAGESIZE> > > >::Type
      capacity(Buffer<TValue, PageFrame<TFile, Fixed<PAGESIZE> > > const &)
      {
          return PAGESIZE;
      }
  
  	template <typename TValue, typename TSpec, typename TSize>
      inline void
      _setCapacity(Buffer<TValue, TSpec> &me, TSize size)
      {
          me.pageSize = size;
      }
  
  	template <typename TValue, typename TSpec>
      inline typename Size<Buffer<TValue, TSpec> >::Type
      length(Buffer<TValue, TSpec> const &me)
      {
          return me.end - me.begin;
      }
  
  	template <typename TValue, typename TFile, size_t PAGESIZE>
      inline typename Size<Buffer<TValue, PageFrame<TFile, Fixed<PAGESIZE> > > >::Type
      length(Buffer<TValue, PageFrame<TFile, Fixed<PAGESIZE> > > const &)
      {
          return PAGESIZE;
      }
  
  	template <typename TValue, typename TSpec, typename TSize>
      inline void
      resize(Buffer<TValue, TSpec> &me, TSize size)
      {
          me.end = me.begin + size;
      }
  
      template <typename TValue, typename TSpec, typename TSize, typename T>
  	inline bool
      allocPage(Buffer<TValue, TSpec> &buffer, TSize size, T const & me)
      {
  //IOREV _nodoc_
          allocate(me, buffer.begin, size);
          _setCapacity(buffer, size);
          resize(buffer, size);
  		#ifdef SEQAN_VVERBOSE
  			::std::cerr << "allocPage: " << ::std::hex << (void*)buffer.begin << ::std::dec << ::std::endl;
  		#endif
          return buffer.begin != NULL;
  	}
  
  	template <typename TValue, typename TSpec, typename T>
  	inline void
      freePage(Buffer<TValue, TSpec> &buffer, T const & me)
      {
  //IOREV _nodoc_
  		#ifdef SEQAN_VVERBOSE
  			if ((void*)buffer.begin)
  				::std::cerr << "freePage:  " << ::std::hex << (void*)buffer.begin << ::std::dec << ::std::endl;
  		#endif
  		deallocate(me, buffer.begin, capacity(buffer));
  		buffer.begin = NULL;
          resize(buffer, 0);
          _setCapacity(buffer, 0);
  	}
  
  	template <typename TValue, typename TSpec>
  	inline typename Iterator<Buffer<TValue, TSpec>, Standard>::Type
      begin(Buffer<TValue, TSpec> &pf, Standard)
      {
  		return pf.begin;
  	}
  
  	template <typename TValue, typename TSpec>
  	inline typename Iterator<Buffer<TValue, TSpec> const, Standard>::Type
      begin(Buffer<TValue, TSpec> const &pf, Standard)
      {
  		return pf.begin;
  	}
  
  	template <typename TValue, typename TSpec>
  	inline typename Iterator<Buffer<TValue, TSpec>, Standard>::Type
      end(Buffer<TValue, TSpec> &pf, Standard)
      {
  		return pf.end;
  	}
  
  	template <typename TValue, typename TSpec>
  	inline typename Iterator<Buffer<TValue, TSpec> const, Standard>::Type
      end(Buffer<TValue, TSpec> const &pf, Standard)
      {
  		return pf.end;
  	}
  
  
  
      //////////////////////////////////////////////////////////////////////////////
  	// a bucket is a structure to represent a small window of a page
      // used by algorithms which need a global view of all pages (merge sort, mapper)
  
  	template <typename TValue>
      struct PageBucket
  	{
  //IOREV _nodoc_ has some unformatted comments in code, but not enough doc
  		typedef	typename Iterator<PageBucket, Standard>::Type TIterator;
  
          unsigned    pageOfs;                // begin of bucket window with relation to page begin
          TIterator	begin, cur, end;        // begin/end of buckets memory buffer and a pointer
      };
  
      template <typename TValue>
      struct PageBucketExtended : public PageBucket< TValue > {
  //IOREV _nodoc_
  		int     	pageNo;		            // related page (needed by merger sort)
      };
      
  	template <typename TValue>
      ::std::ostream& operator<<(::std::ostream &out, const PageBucketExtended<TValue> &pb) {
  //IOREV _ _nodoc_
          for(TValue *cur = pb.begin; cur != pb.end; cur++)
              out << *cur << " ";
          return out;
      }
  
  
  	//////////////////////////////////////////////////////////////////////////////
  	// meta-function interface
  
  	template <typename TValue>
      struct Value< PageBucket<TValue> >		{ typedef TValue Type; };
  //IOREV
  
      template <typename TValue>
      struct Size< PageBucket<TValue> >		{ typedef size_t Type; };
  //IOREV
  
      template <typename TValue>
      struct Iterator< PageBucket<TValue>, Standard >			{ typedef TValue *Type; };
  //IOREV
  
      template <typename TValue>
      struct Iterator< PageBucket<TValue> const, Standard >	{ typedef TValue const *Type; };
  //IOREV
  
  	//////////////////////////////////////////////////////////////////////////////
  
      template <typename TFilePos, typename TSize>
      struct FilePageRequest
      {
          enum FilePageRequestMode {
              MODE_RDONLY = 1,
              MODE_WRONLY = 2,
              MODE_RDWR   = 3
          };
  
          TFilePos            filePos;
          TSize               size;
          FilePageRequestMode mode;
      };
  
  	//////////////////////////////////////////////////////////////////////////////
  
      enum PageFrameStatus
      {
          UNUSED,
          READING,
          PREPROCESSING,
          READY,
          POSTPROCESSING,
          POSTPROCESSED,
          WRITING
      };
  
  	//////////////////////////////////////////////////////////////////////////////
  	// page frame of dynamic size
  
      template <typename TValue, typename TFile>
  	struct Buffer<TValue, PageFrame<TFile, Dynamic> > :
          public Buffer<TValue>
  	{
  //IOREV _nodoc_
  		typedef Buffer<TValue>                      TBase;
  		typedef TFile                               File;
  		typedef typename Size<TFile>::Type          TFileSize;
          typedef typename AsyncRequest<TFile>::Type  AsyncRequest;
          typedef FilePageRequest<TFileSize, size_t>  TFilePageRequest;
  
          TFilePageRequest pageRequest;
  
  		bool			dirty;		// data needs to be written to disk before freeing
  		unsigned		pageNo;		// maps frames to pages (reverse vector mapper)
          AsyncRequest    request;    // request structure of the async io process
  		PageFrameStatus status;
          Buffer          *next;      // next buffer in a chained list
  
          Buffer():
  			TBase(),
              dirty(false),
              pageNo(MaxValue<unsigned>::VALUE),
  			status(READY),
  			next(NULL) {}
      };
  
  
  	//////////////////////////////////////////////////////////////////////////////
  	// page frame of static size
  
  //IOREV
  
      typedef ::std::list<Position<String<void*> >::Type> PageLRUList;    // least recently usage list
  	typedef PageLRUList::iterator PageLRUEntry;
  
      template < typename TValue,
                 typename TFile,
                 size_t PAGESIZE_ >
  	struct Buffer<TValue, PageFrame<TFile, Fixed<PAGESIZE_> > >
      {
  		typedef TFile                                       File;
          typedef typename AsyncRequest<TFile>::Type          AsyncRequest;
  		typedef	typename Iterator<Buffer, Standard>::Type   TIterator;
  
  		enum            { PAGESIZE = PAGESIZE_ };
  		enum DataStatus	{ ON_DISK = -1, UNINITIALIZED = -2 };
  		enum Priority	{ NORMAL_LEVEL = 0, PREFETCH_LEVEL = 1, ITERATOR_LEVEL = 2, PERMANENT_LEVEL = 3 };
  
          TIterator       begin;
          TIterator       end;
          AsyncRequest    request;    // request structure of the async io process
  		PageFrameStatus status;
  		DataStatus		dataStatus;
  		PageLRUEntry	lruEntry;   // priority based lru
          Priority        priority;
  		int     		pageNo;		// maps frames to pages (reverse vector mapper)
  		bool			dirty;		// data needs to be written to disk before freeing
  
  		Buffer():
              begin(NULL),
              end(NULL)
          {
              clear(*this);
          }
  
          template <typename TPos>
          inline TValue &
          operator[] (TPos i)
          {
              return begin[i];
          }
  
          template <typename TPos>
          inline TValue const &
          operator[] (TPos i) const
          {
              return begin[i];
          }
  	};
  
      template < typename TValue,
                 typename TFile,
                 size_t PAGESIZE_ >
      inline void
      clear(Buffer<TValue, PageFrame<TFile, Fixed<PAGESIZE_> > > &me)
      {
          typedef Buffer<TValue, PageFrame<TFile, Fixed<PAGESIZE_> > > TPageFrame;
          me.status = READY;
          me.dataStatus = TPageFrame::UNINITIALIZED;
          me.priority = TPageFrame::NORMAL_LEVEL;
          me.pageNo = -1;
          me.dirty = false;
      }
  
  
  	//////////////////////////////////////////////////////////////////////////////
  	// a memory-mapped page frame
  /*
      template <typename TValue, typename TFile, typename TConfig>
  	struct PageFrame< TValue, TFile, MMap<TConfig> >: public Buffer<TValue>
      {
  		typedef Buffer<TValue> TBase;
  
          enum Status		{ READY, READING, WRITING };
  
  		unsigned   		pageNo;		// maps frames to pages (reverse vector mapper)
  		Status			status;
          PageFrame       *next;      // next buffer in a chained list
  
          PageFrame():
  			TBase(),
              pageNo(MaxValue<unsigned>::VALUE),
  			next(NULL) {}
      };
  */
  
  	//////////////////////////////////////////////////////////////////////////////
  	// meta-function interface
  
  	template <typename TValue, typename TFile, size_t PAGESIZE>
      struct Iterator<Buffer<TValue, PageFrame<TFile, Fixed<PAGESIZE> > >, Standard >
      {
          typedef VolatilePtr<TValue> Type;
      };
  
  	template <typename TValue, typename TFile, size_t PAGESIZE>
      struct Iterator<Buffer<TValue, PageFrame<TFile, Fixed<PAGESIZE> > > const, Standard >
      {
          typedef VolatilePtr<TValue> const Type;
      };
  
  
  
  
  	//////////////////////////////////////////////////////////////////////////////
  	// various page frame methods
  
  	template <typename TValue, typename TFile, typename TSpec>
      inline const char *
      _pageFrameStatusString(Buffer<TValue, PageFrame<TFile, TSpec> > const &pf)
      {
          switch (pf.status)
          {
  			case READY:
                  return "READY";
  			case READING:
                  return "READING";
  			case WRITING:
                  return "WRITING";
              case UNUSED:
                  return "UNUSED";
              case PREPROCESSING:
                  return "PREPROCESSING";
              case POSTPROCESSING:
                  return "POSTPROCESSING";
              case POSTPROCESSED:
                  return "POSTPROCESSED";
              default:
                  return "UNKNOWN";
          }
      }
  
  	template <typename TValue, typename TFile, typename TSpec>
      ::std::ostream& operator<<(::std::ostream &out, const Buffer<TValue, PageFrame<TFile, TSpec> > &pf)
  	{
  //IOREV _nodoc_
          out << "PageFrame @ " << pf.pageNo;
          if (pf.dirty)
              out << " DIRTY ";
          else
              out << " CLEAN ";
  
          out << _pageFrameStatusString(pf);
  
  //        if (pf.dataStatus == pf.ON_DISK)
  //            out << " ON_DISK";
  //        else
  //            out << " UNITIALIZED";
  //
  //        out << " Prio:" << pf.priority;
          out << " Buffer:" << (void*)pf.begin;
  
          return out;
  	}
  
  	template <typename TValue, typename TFile, typename TSpec, typename T> inline
  	void allocPage(Buffer<TValue, PageFrame<TFile, TSpec> > &pf, T const & me) 
  	{
  //IOREV _nodoc_
  		TValue* tmp = NULL;
  		allocate(me, tmp, capacity(pf));
  		//bzero(tmp, sizeof(TValue) * capacity(pf));
  		pf.begin = tmp;
  		#ifdef SEQAN_VVERBOSE
  			::std::cerr << "allocPage: " << ::std::hex << &pf << '\t' << tmp << ::std::dec << ::std::endl;
  		#endif
  	}
  
  	template <typename TValue, typename TFile, typename TSpec, typename T> inline
  	void freePage(Buffer<TValue, PageFrame<TFile, TSpec> > &pf, T const & me) 
  	{
  //IOREV _nodoc_
  		#ifdef SEQAN_VVERBOSE
  			if ((void*)pf.begin)
  				::std::cerr << "freePage:  " << ::std::hex << &pf << '\t' << (void*)pf.begin << ::std::dec << ::std::endl;
  		#endif
          nukeCopies(pf.begin);
  		deallocate(me, (TValue*)pf.begin, capacity(pf));
  		pf.begin = NULL;
          resize(pf, 0);
  	}
  
  	template <typename TValue, typename TFile, typename TSpec> inline
  	bool readPage(int pageNo, Buffer<TValue, PageFrame<TFile, TSpec> > &pf, TFile &file)
  	{
  //IOREV _nodoc_
  		typedef typename Position<TFile>::Type TPos;
  		#ifdef SEQAN_VVERBOSE
  			::std::cerr << "readPage:  " << ::std::hex << &pf << '\t' << (void*)pf.begin;
  			::std::cerr << " from page " << ::std::dec << pageNo << ::std::endl;
  		#endif
  		pf.dirty = false;
  		pf.status = READING;
  //        resize(pf, capacity(pf));
  
  		bool readResult = asyncReadAt(file, (TValue*)pf.begin, length(pf), (TPos)pageNo * (TPos)capacity(pf), pf.request);
  
          // TODO(weese): Throw an I/O exception
          if (!readResult)
              SEQAN_FAIL("%s operation could not be initiated: \"%s\"", _pageFrameStatusString(pf), strerror(errno));
  
          return readResult;
  	}
  
  	template <typename TValue, typename TFile, typename TSpec> inline
  	bool unmapPage(Buffer<TValue, PageFrame<TFile, TSpec> > &pf, TFile &)
  	{
          if (pf.begin)
          {
  #ifdef PLATFORM_WINDOWS
  #else
              munmap(pf.begin, length(pf) * sizeof(TValue));
  #endif
  			pf.begin = NULL;
          }
          return true;
      }
  
  	template <typename TValue, typename TFile, typename TSpec, typename TSize> inline
  	bool mapReadPage(Buffer<TValue, PageFrame<TFile, TSpec> > &pf, TFile &file, TSize size)
  	{
  		typedef typename Position<TFile>::Type TPos;
          unmapPage(pf, file);
  		pf.status = READY;
          SEQAN_ASSERT_GT(size, 0);
  
  #ifdef PLATFORM_WINDOWS
  #if 0
  		DWORD prot = 0;
  		DWORD access = 0;
  		if ((me._openMode & OPEN_MASK) == OPEN_RDONLY) 
  		{
  			prot = PAGE_READONLY;
  			access = FILE_MAP_READ;
  		} else {
  			prot = PAGE_READWRITE;
  			access = FILE_MAP_ALL_ACCESS;
  		}
          LARGE_INTEGER largeSize;
  		largeSize.QuadPart = new_capacity;
  		largeSize.QuadPart *= sizeof(TValue);
  
  		me.handle = CreateFileMapping(file.handle, &MMapStringDefaultAttributes, prot, largeSize.HighPart, largeSize.LowPart, NULL);
  		if (me.handle == NULL)
  		{
              SEQAN_FAIL(
                  "CreateFileMapping(%d, %d, 0, 0, 0) failed in mapReadPage: \"%s\"",
                  file.handle, access, strerror(errno));
  		#if SEQAN_ENABLE_DEBUG
  			::std::cerr << "CreateFileMapping failed. (ErrNo=" << GetLastError() << ")" << ::std::endl;
  		#endif
  			return false;
  		}
  
  		pf.begin = (TValue *) MapViewOfFile(pf.handle, access, 0, 0, 0);	
  		if (pf.begin == NULL)
  		{
              SEQAN_FAIL(
                  "MapViewOfFile(%d, %d, 0, 0, 0) failed in mapReadPage: \"%s\"",
                  pf.handle, access, strerror(errno));
  			return false;
  		}
  				
  		me.data_begin = (TValue *) addr;
  #endif
  #else
          pf.begin = (TValue*)mmap(NULL, size * sizeof(TValue), PROT_READ | PROT_WRITE, MAP_PRIVATE, file.handle, (TPos)pf.pageNo * (TPos)capacity(pf) * (TPos)sizeof(TValue));
  
          if (pf.begin == MAP_FAILED)
          {
              pf.begin = pf.end = NULL;
              SEQAN_FAIL(
                  "mmap(NULL, %llu, PROT_READ | PROT_WRITE, MAP_PRIVATE, %d, %llu) failed in mapReadPage: \"%s\"",
                  size * sizeof(TValue), file.handle, (TPos)pf.pageNo * (TPos)capacity(pf) * (TPos)sizeof(TValue), strerror(errno));
              return false;
          }
  #endif
          pf.end = pf.begin + size;
          return true;
      }
  
  	template <typename TValue, typename TFile, typename TSpec, typename TSize> inline
  	bool mapWritePage(Buffer<TValue, PageFrame<TFile, TSpec> > &pf, TFile &file, TSize size) 
  	{
  		typedef typename Position<TFile>::Type TPos;
          unmapPage(pf, file);
          pf.status = READY;
          SEQAN_ASSERT_GT(size, 0u);
          
  #ifdef PLATFORM_WINDOWS
  #else
          pf.begin = (TValue*)mmap(NULL, size * sizeof(TValue), PROT_READ | PROT_WRITE, MAP_SHARED, file.handle, (TPos)pf.pageNo * (TPos)capacity(pf) * (TPos)sizeof(TValue));
  
          if (pf.begin == MAP_FAILED)
          {
              pf.begin = pf.end = NULL;
              SEQAN_FAIL(
                  "mmap(NULL, %llu, PROT_READ | PROT_WRITE, MAP_SHARED, %d, %llu) failed in mapWritePage: \"%s\"",
                  size * sizeof(TValue), file.handle, (TPos)pf.pageNo * (TPos)capacity(pf) * (TPos)sizeof(TValue), strerror(errno));
              return false;
          }
  #endif
          pf.end = pf.begin + size;
          return true;
      }
  
  	template <typename TValue, typename TFile, typename TSpec> inline
  	bool writePage(Buffer<TValue, PageFrame<TFile, TSpec> > &pf, int pageNo, TFile &file) 
  	{
  //IOREV _nodoc_
  		typedef typename Position<TFile>::Type TPos;
  		#ifdef SEQAN_VVERBOSE
  			::std::cerr << "writePage: " << ::std::hex << &pf << '\t' << (void*)pf.begin;
  			::std::cerr << " from page " << ::std::dec << pageNo << ::std::endl;
  		#endif
  		pf.status = WRITING;
  //        resize(pf, capacity(pf));
  
  		bool writeResult = asyncWriteAt(file, (TValue*)pf.begin, length(pf), (TPos)pageNo * (TPos)capacity(pf), pf.request);
  
          // TODO(weese): Throw an I/O exception
          if (!writeResult)
              SEQAN_FAIL("%s operation could not be initiated: \"%s\"", _pageFrameStatusString(pf), strerror(errno));
  
          return writeResult;
  	}
  
  	template < typename TValue, typename TFile, typename TSpec, typename TSize> inline
      bool readLastPage(int pageNo, Buffer<TValue, PageFrame<TFile, TSpec> > &pf, TFile &file, TSize size) 
  	{
  //IOREV _nodoc_
  		typedef typename Position<TFile>::Type TPos;
  		#ifdef SEQAN_VVERBOSE
  			::std::cerr << "readPage:  " << ::std::hex << &pf << '\t' << (void*)pf.begin;
  			::std::cerr << " from page " << ::std::dec << pageNo << " size " << size << ::std::endl;
  		#endif
  		pf.dirty = false;
  		pf.status = READY;
  //        resize(pf, size);
  
  		bool readResult = readAt(file, (TValue*)pf.begin, size, (TPos)pageNo * (TPos)capacity(pf));
  
          // TODO(weese): Throw an I/O exception
          if (!readResult)
              SEQAN_FAIL("%s operation could not be initiated: \"%s\"", _pageFrameStatusString(pf), strerror(errno));
  
          return readResult;
  	}
  
  	template <typename TValue, typename TFile, typename TSpec, typename TSize> inline
  	bool writeLastPage(Buffer<TValue, PageFrame<TFile, TSpec> > &pf, int pageNo, TFile &file, TSize size) 
  	{
  //IOREV _nodoc_
  		typedef typename Position<TFile>::Type TPos;
  		#ifdef SEQAN_VVERBOSE
  			::std::cerr << "writePage: " << ::std::hex << &pf << '\t' << (void*)pf.begin;
  			::std::cerr << " from page " << ::std::dec << pageNo << " size " << size << ::std::endl;
  		#endif
  		pf.dirty = false;
  		pf.status = READY;
  //        resize(pf, size);
  
  		bool writeResult = writeAt(file, (TValue*)pf.begin, size, (TPos)pageNo * (TPos)capacity(pf));
  
          // TODO(weese): Throw an I/O exception
          if (!writeResult)
              SEQAN_FAIL("%s operation could not be initiated: \"%s\"", _pageFrameStatusString(pf), strerror(errno));
  
          return writeResult;
  	}
  
  	template <typename TValue, typename TFile, typename TSpec> inline
  	bool waitFor(Buffer<TValue, PageFrame<TFile, TSpec> > &pf) 
  	{
  //IOREV _nodoc_ equally named functions with different purposes in system_thread.h, system_event.h and file_async.h
  		if (pf.status == READY)
              return true;
  
          bool waitResult = waitFor(pf.request);
  
          // TODO(weese): Throw an I/O exception
          if (!waitResult)
          {
              //printRequest(pf.request);
              SEQAN_FAIL("%s operation could not be completed: \"%s\"", _pageFrameStatusString(pf), strerror(errno));
          }
  
          pf.status = READY;
          pf.dirty = false;
          return waitResult;
  	}
  
  	template <typename TValue, typename TFile, typename TSpec, typename TTime> inline
  	bool waitFor(Buffer<TValue, PageFrame<TFile, TSpec> > &pf, TTime timeOut, bool &inProgress)
  	{
  //IOREV _nodoc_ equally named functions with different purposes in system_thread.h, system_event.h and file_async.h (none documented)
  		if (pf.status == READY)
          {
              inProgress = false;
              return true;
          }
  
          bool waitResult = waitFor(pf.request, timeOut, inProgress);
  
          // TODO(weese): Throw an I/O exception
          if (!waitResult)
          {
              //printRequest(pf.request);
              SEQAN_FAIL("%s operation could not be completed: \"%s\"", _pageFrameStatusString(pf), strerror(errno));
          }
  
          if (!inProgress)
          {
              pf.status = READY;
              pf.dirty = false;
          }
          return waitResult;
  	}
  
  	template <typename TValue, typename TFile, typename TSpec> inline
  	bool cancel(Buffer<TValue, PageFrame<TFile, TSpec> > &pf, TFile &file) 
  	{
  //IOREV _nodoc_ equally named functions with different purposes in pipe/pool_*.h, system_thread.h, and file_async.h (only the latter documented)
          bool dummy;
          waitFor(pf, 0, dummy);
  		if (pf.status != READY) 
  		{
              if (!cancel(file, pf.request)) return false;
              pf.status = READY;
          }
          return true;
  	}
  
  	//////////////////////////////////////////////////////////////////////////////
  	// page based read/write methods used by Pool classes
  
      template <typename TValue, typename TFile> inline
  	bool readPage(Buffer<TValue, PageFrame<TFile, Dynamic> > &pf, TFile &file) 
  	{
  //IOREV _nodoc_
          if (length(pf) == capacity(pf))
              return readPage(pf.pageNo, pf, file);
          else
              return readLastPage(pf.pageNo, pf, file, length(pf));
  	}
  
  	template <typename TValue, typename TFile> inline
  	bool writePage(Buffer<TValue, PageFrame<TFile, Dynamic> > &pf, TFile &file) 
  	{
  //IOREV _nodoc_
          if (length(pf) == capacity(pf))
              return writePage(pf, pf.pageNo, file);
          else
              return writeLastPage(pf, pf.pageNo, file, length(pf));
  	}
  
  	template <typename TValue, typename TFile> inline
  	unsigned readBucket(PageBucket<TValue> &b, int pageNo, size_t pageSize, size_t dataSize, TFile &file) 
  	{
  //IOREV _nodoc_
  		typedef typename Position<TFile>::Type TPos;
          size_t readSize = _min(dataSize - b.pageOfs, (size_t)(b.end - b.begin));
  		#ifdef SEQAN_VVERBOSE
  			::std::cerr << "readBucket:  " << ::std::hex << b.begin;
  			::std::cerr << " from page " << ::std::dec << pageNo << " at " << (TPos)pageNo * (TPos)pageSize + b.pageOfs;
  			::std::cerr << " size " << readSize << ::std::endl;
  		#endif
          if (readSize && readAt(file, b.begin, readSize, (TPos)pageNo * (TPos)pageSize + b.pageOfs)) {
              b.pageOfs += readSize;
              b.cur = b.begin;
              b.end = b.begin + readSize;
              return readSize;
          } else
              return 0;
  	}
  
  	template <typename TValue, typename TFile> inline
  	bool writeBucket(PageBucket<TValue> &b, int pageNo, size_t pageSize, TFile &file) 
  	{
  //IOREV _nodoc_
  		typedef typename Position<TFile>::Type TPos;
  		#ifdef SEQAN_VVERBOSE
  			::std::cerr << "writeBucket: " << ::std::hex << b.begin;
  			::std::cerr << " from page " << ::std::dec << pageNo << " at " << (TPos)pageNo * (TPos)pageSize + b.pageOfs;
  			::std::cerr << " size " << b.cur - b.begin << ::std::endl;
  		#endif
          if ((b.cur == b.begin) || writeAt(file, b.begin, b.cur - b.begin, (TPos)pageNo * (TPos)pageSize + b.pageOfs)) {
              b.pageOfs += b.cur - b.begin;
              b.cur = b.begin;
              return true;
          } else
              return false;
  	}
  
  	template <typename TValue, typename TPageOfs, typename TFile> inline
  	bool writeBucket(Buffer<TValue, PageFrame<TFile, Dynamic> > &pf, TPageOfs &pageOfs, TFile &file)
  	{
  //IOREV _nodoc_
  		typedef typename Position<TFile>::Type TPos;
  		#ifdef SEQAN_VVERBOSE
  			::std::cerr << "writeBucket: " << ::std::hex << pf.begin;
  			::std::cerr << " from page " << ::std::dec << pf.pageNo << " at " << (TPos)pf.pageNo * (TPos)capacity(pf) + pageOfs;
  			::std::cerr << " size " << length(pf) << ::std::endl;
  		#endif
          if (pf.end == pf.begin) return true;
          if (asyncWriteAt(file, pf.begin, length(pf), (TPos)pf.pageNo * (TPos)capacity(pf) + pageOfs, pf.request)) {
              pf.status = WRITING;
              pageOfs += length(pf);
              return true;
          } else
              return false;
  	}
  
  
  	//////////////////////////////////////////////////////////////////////////////
  
      template <typename TPageFrame>
      struct PageChain 
  	{
  //IOREV _nodoc_
          TPageFrame          *first, *last;
          unsigned            frames, maxFrames;
          
          PageChain(unsigned _maxFrames = 0):
              first(NULL),
              last(NULL),
              frames(0),
              maxFrames(_maxFrames)
          {
              for(unsigned i = 0; i < _maxFrames; ++i)
                  pushBack();
          }
          
          ~PageChain()
          {
              while (!empty())
                  delete &popFront();
          }
          
          inline TPageFrame & operator[](int k) 
  		{
              TPageFrame *p = first;
              for (; k > 0; --k)
                  p = p->next;
              return *p;
          }
          
          inline TPageFrame const & operator[](int k) const 
  		{
              TPageFrame *p = first;
              for (; k > 0; --k)
                  p = p->next;
              return *p;
          }
  
          inline TPageFrame * getReadyPage() 
  		{
              if (empty())
                  return &pushBack();
  
              if (frames < maxFrames)
              {
                  bool inProgress;
                  bool waitResult = waitFor(*first, 0, inProgress);
                  
                  // TODO(weese): Throw an I/O exception
                  if (!waitResult)
                      SEQAN_FAIL("%s operation could not be completed: \"%s\"", _pageFrameStatusString(*first), strerror(errno));
  
                  if (!inProgress)
                      return &pushBack();
              }
  
              bool waitResult = waitFor(*first);
  
              // TODO(weese): Throw an I/O exception
              if (!waitResult)
                  SEQAN_FAIL("%s operation could not be completed: \"%s\"", _pageFrameStatusString(*first), strerror(errno));
  
              return &firstToEnd();
          }
  
          template <typename TFile>
          inline void cancelAll(TFile &file) 
  		{
              TPageFrame *p = first;
              for (; p != NULL; p = p->next)
                  cancel(*p, file);
          }
  
          inline void waitForAll() 
  		{
              for (TPageFrame *p = first; p != NULL; p = p->next)
              {
                  bool waitResult = waitFor(*p);
  
                  // TODO(weese): Throw an I/O exception
                  if (!waitResult)
                      SEQAN_FAIL("%s operation could not be completed: \"%s\"", _pageFrameStatusString(*p), strerror(errno));
              }
          }
  
      public:
  
          inline bool
          empty()
          {
              return first == NULL;
          }
  
          inline unsigned
          size()
          {
              return frames;
          }
  
          inline TPageFrame &
          front()
          {
              return *first;
          }
  
          inline TPageFrame &
          back()
          {
              return *last;
          }
  
          //
          // append a PageFrame at the end of this chain
          //
          inline TPageFrame &
          pushBack(TPageFrame &pageFrame)
  		{
              if (last != NULL)
                  last->next = &pageFrame;
              else
                  first = &pageFrame;
              
              last = &pageFrame;
              pageFrame.next = NULL;
              ++frames;
  
              return pageFrame;
          }
  
          //
          // append a *new* PageFrame at the end of this chain
          //
          inline TPageFrame &
          pushBack()
  		{
              TPageFrame *pageFrame = new TPageFrame();
              return pushBack(*pageFrame);
          }
  
          //
          // remove a PageFrame from this chain
          //
          inline TPageFrame &
          erase(TPageFrame & pageFrame)
          {
              TPageFrame *prev = NULL;
              TPageFrame *p;
  
              for (p = first; p != NULL; p = p->next)
              {
                  if (p == &pageFrame)
                  {
                      // found it, now detach from neighbors
                      if (prev == NULL)
                          first = p->next;
                      else
                          prev->next = p->next;
  
                      p->next = NULL;
  
                      // were we the last?
                      if (last == p)
                          last = prev;
  
                      --frames;
                      break;
                  }
                  prev = p;
              }
              // we assert that the page has been found
              SEQAN_ASSERT(p != NULL);
              return pageFrame;
          }
  
          inline TPageFrame &
          popFront()
          {
              // equivalent to erase(front())
              TPageFrame *p = first;
              if (p != NULL)
              {
                  first = p->next;
                  p->next = NULL;
                  if (first == NULL)
                      last = NULL;
                  --frames;
              }
              else
                  SEQAN_FAIL("pop() was called on an empty PageChain.");
              return *p;
          }
  
          //
          // move first page to the end of this chain
          // return the moved page
          //
          inline TPageFrame &
          firstToEnd()
  		{
              // equivalent to pushBack(popFront())
              last->next = first;
              last = first;
              first = first->next;
              last->next = NULL;
              return *last;
          }
  
  
  // call pop(chain.front())
  
  //        inline TPageFrame &
  //        popFront()
  //		{
  //            TPageFrame *p = first;
  //            if (p) {
  //                first = first->next;
  //                if (!first) last = NULL;
  //                --frames;
  //                delete p;
  //            }
  //            return p;
  //        }
      };
  
  	//////////////////////////////////////////////////////////////////////////////
  	// meta-function interface
  
      template <typename TPageFrame>    
  	struct Value< PageChain<TPageFrame> > 
  	{
  //IOREV
  		typedef TPageFrame Type;
  	};
  
      template <typename TPageFrame>    
  	struct Size< PageChain<TPageFrame> > 
  	{
  //IOREV
  		typedef unsigned Type;
  	};
  
      template <typename TPageFrame>    
  	struct Iterator< PageChain<TPageFrame> > 
  	{
  //IOREV
  		typedef TPageFrame *Type;
  	};
  
      template <typename TPageFrame>    
  	struct Iterator< PageChain<TPageFrame> const > 
  	{
  //IOREV
  		typedef TPageFrame const *Type;
  	};
  
  
  	//////////////////////////////////////////////////////////////////////////////
  	// page container with lru mechanism
  	// the lru strategy uses different priorities
  	// the page with the least priority is used first
  	// 0..random access pages
  	// 1..forward iterator pages
  	// 2..quasi permanent pages
  
      template < typename TPageFrame,
                 unsigned FRAMES,
                 unsigned PRIORITY_LEVELS = TPageFrame::PERMANENT_LEVEL + 1 >
  	struct PageContainer
  	{
  //IOREV _nodoc_ has some in-code comments
  		typedef String<TPageFrame>					TPages;
  		typedef typename Position<TPages>::Type		TPos;
  
  		enum { PriorityLevels = PRIORITY_LEVELS };
  
  		TPages			pages;
          PageLRUList		*lruList;
  
  		PageContainer()
  		{
  			lruList = new PageLRUList[PRIORITY_LEVELS];
  			resize(pages, FRAMES, Exact());
              for(TPos i = 0; i < FRAMES; ++i)
  			    pages[i].lruEntry = lruList[0].insert(lruList[0].end(), i);
          }
  
  		~PageContainer()
  		{
  			delete[] lruList;
  		}
  
          inline TPageFrame       & operator[](TPos i)       { return pages[i]; }
          inline TPageFrame const & operator[](TPos i) const { return pages[i]; }
  
  		inline void push_back() 
  		{
  			TPos last = length(pages);
  			resize(pages, last + 1);
  			pages[last].lruEntry = lruList[0].insert(lruList[0].end(), last);
  		}
  
  		inline void erase(int frameNo) 
  		{
  			lruList[pages[frameNo].priority].erase(pages[frameNo].lruEntry);
              seqan::erase(pages, frameNo);
  		}
  
          inline void rename(int frameNo) 
  		{
              *(pages[frameNo].lruEntry) = frameNo;
          }
  
  		inline void pop_back() 
  		{
  			lruList[back(pages).priority].erase(back(pages).lruEntry);
  			seqan::erase(pages, endPosition(pages) - 1);
  		}
  
          inline void _print()
          {
              std::cout << std::endl;
              for(TPos i = 0; i < FRAMES; ++i)
  			    std::cout << pages[i] << std::endl;
          }
  
  		//////////////////////////////////////////////////////////////////////////////
  		// lru strategy interface
  
  		inline void upgrade(const TPageFrame &pf) 
  		{
  			lruList[pf.priority].splice(lruList[pf.priority].begin(), lruList[pf.priority], pf.lruEntry);
  			pf.lruEntry = lruList[pf.priority].begin();
  		}
  
  		inline void downgrade(const TPageFrame &pf) 
  		{
  			lruList[pf.priority].splice(lruList[pf.priority].end(), lruList[pf.priority], pf.lruEntry);
  			pf.lruEntry = lruList[pf.priority].end();
  			--pf.lruEntry;
  		}
  
  		inline void upgrade(TPageFrame &pf, int newPriority) 
  		{
  			lruList[newPriority].splice(lruList[newPriority].begin(), lruList[pf.priority], pf.lruEntry);
  			pf.lruEntry = lruList[newPriority].begin();
  			pf.priority = static_cast<typename TPageFrame::Priority> (newPriority);
  		}
  
  		inline void downgrade(TPageFrame &pf, int newPriority) 
  		{
  			lruList[newPriority].splice(lruList[newPriority].end(), lruList[pf.priority], pf.lruEntry);
  			pf.lruEntry = lruList[newPriority].end();
  			--pf.lruEntry;
  			pf.priority = static_cast<typename TPageFrame::Priority> (newPriority);
  		}
  
  		inline void _dump() 
  		{
  			for(unsigned i = 0; i < PRIORITY_LEVELS; ++i) {
                  ::std::cerr << "|";
                  PageLRUList::const_iterator I = lruList[i].end();
                  PageLRUList::const_iterator first = lruList[i].begin();
  				while (I != first) {
  					--I;
                      TPageFrame &pf = pages[*I];
                      ::std::cerr << pf.pageNo;
                      if (pf.dirty) ::std::cerr << "*";
                      else          ::std::cerr << " ";
                      if (pf.status == READY) ::std::cerr << "  ";
                      else                    ::std::cerr << ". ";
  				};
              }
              ::std::cerr << ::std::endl;
  		}
  
          // Function is a functor which is called with a PageFrame object,
          // that is dirty or not READY (in an IO transfer)
  		template <class Function>
  		inline int mru(Function Func_, unsigned maxLevel = PRIORITY_LEVELS - 1) 
  		{
  			for(unsigned i = 0; i <= maxLevel; ++i) {
                  PageLRUList::const_iterator I = lruList[i].end();
                  PageLRUList::const_iterator first = lruList[i].begin();
  				while (I != first) {
  					--I;
  					TPageFrame& pf = pages[*I];
  					if (pf.status == READY && !pf.dirty)
  						return *I;
  					else
  						if (Func_(pf)) return *I;
  				};
              }
  			#ifdef SEQAN_VVERBOSE
  				::std::cerr << "ALL PAGES DIRTY OR IN USE (try to use const iterators) :-(" << ::std::endl;
  			#endif
  			return -1;
  		}
  
  		inline int mruDirty() 
  		{
              for(unsigned i = 0; i < PRIORITY_LEVELS; ++i)
                  if (!lruList[i].empty())
                      return lruList[i].back();
  			return -1;
  		}
  	};
  
  
  	//////////////////////////////////////////////////////////////////////////////
  	// meta-function interface
  
  	template <typename TPageFrame, unsigned FRAMES, unsigned PRIORITY_LEVELS>
  	struct Host< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> > 
  	{
  //IOREV
  		typedef String<TPageFrame> Type;
  	};
  
  	template <typename TPageFrame, unsigned FRAMES, unsigned PRIORITY_LEVELS>
  	struct Host< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> const > 
  	{
  //IOREV
  		typedef String<TPageFrame> const Type;
  	};
  
  	template <typename TPageFrame, unsigned FRAMES, unsigned PRIORITY_LEVELS>
  	struct Value< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> > 
  	{
  //IOREV
  		typedef TPageFrame Type;
  	};
  
  	template <typename TPageFrame, unsigned FRAMES, unsigned PRIORITY_LEVELS>
  	struct Size< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> >:
  		public Size< typename Host< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> >::Type> {};
  //IOREV
  
  	template <typename TPageFrame, unsigned FRAMES, unsigned PRIORITY_LEVELS>
  	struct Position< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> >:
  		public Position< typename Host< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> >::Type> {};
  //IOREV
  
  	template <typename TPageFrame, unsigned FRAMES, unsigned PRIORITY_LEVELS>
  	struct Iterator< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> >:
  		public Iterator< typename Host< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> >::Type> {};
  //IOREV
  
  	template <typename TPageFrame, unsigned FRAMES, unsigned PRIORITY_LEVELS>
  	struct Iterator< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> const >:
  		public Iterator< typename Host< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> const>::Type> {};
  //IOREV
  
  
  	//////////////////////////////////////////////////////////////////////////////
  	// global interface
  
  	template <typename TPageFrame, unsigned FRAMES, unsigned PRIORITY_LEVELS, typename TExpand>
  	inline void reserve(
  		PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> &pageCont,
  		unsigned Count_,
  		Tag<TExpand> expand)
  	{
  //IOREV
  		reserve(pageCont.pages, Count_, expand);
  	}
  
      template <typename TPageFrame, unsigned FRAMES, unsigned PRIORITY_LEVELS>
  	inline void resize(
  		PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> &pageCont, 
  		unsigned Count_) 
  	{
  //IOREV
  		unsigned Size_ = length(pageCont.pages);
  		if (Size_ < Count_) {
  			reserve(pageCont.pages, Count_);
              for(unsigned i = Size_; i < Count_; ++i)
                  pageCont.push_back();
  		} else 
  			if (Size_ > Count_)
  				for(unsigned i = Count_; i < Size_; ++i)
  					pageCont.pop_back();
  	}
  
      template <typename TPageFrame, unsigned FRAMES, unsigned PRIORITY_LEVELS>
  	inline typename Size< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> >::Type
  	length(PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> const &pageCont) 
  	{
  //IOREV
  		return length(pageCont.pages);
  	}
  
  	template <typename TPageFrame, unsigned FRAMES, unsigned PRIORITY_LEVELS>
  	inline typename Iterator< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS>, Standard >::Type
  	begin(
  		PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> &pageCont,
  		Standard const) 
  	{
  //IOREV
  		return begin(pageCont.pages, Standard());
  	}
  
  	template <typename TPageFrame, unsigned FRAMES, unsigned PRIORITY_LEVELS>
  	inline typename Iterator< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> const, Standard >::Type
  	begin(
  		PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> const &pageCont,
  		Standard const) 
  	{
  //IOREV
  		return begin(pageCont.pages, Standard());
  	}
  
  	template <typename TPageFrame, unsigned FRAMES, unsigned PRIORITY_LEVELS>
  	inline typename Iterator< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS>, Standard >::Type
  	end(
  		PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> &pageCont,
  		Standard const) 
  	{
  //IOREV
  		return end(pageCont.pages, Standard());
  	}
  
  	template <typename TPageFrame, unsigned FRAMES, unsigned PRIORITY_LEVELS>
  	inline typename Iterator< PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> const, Standard >::Type
  	end(
  		PageContainer<TPageFrame, FRAMES, PRIORITY_LEVELS> const &pageCont,
  		Standard const) 
  	{
  //IOREV
  		return end(pageCont.pages, Standard());
  	}
  
  
  
  
  	//////////////////////////////////////////////////////////////////////////////
  
      template <typename TValue, typename TSize, typename T, class Function>
      inline bool equiDistantDistribution(
          Buffer<TValue> &_clusterBuffer, size_t _bufferSize, T const &me,
          TSize _size, size_t _pageSize,
          Function const &Func_)
      {
  //IOREV _nodoc_
  //        ::std::cerr << "equiDistantDistribution: size=" << _size << "\tpageSize=" << _pageSize << ::std::endl;
          unsigned _pages         = enclosingBlocks(_size, _pageSize);
          if (!_pages) {
  			::std::cerr << "equiDistantDistribution: _pages is null!" << ::std::endl;
              return false;
          }
  
          if (_bufferSize < _pages) {
  			::std::cerr << "equiDistantDistribution: clusterBufferSize is too small -> raised to " << _pages << ::std::endl;
              _bufferSize = _pages;
          }
  
          size_t lastPageSize = _size % _pageSize;
          unsigned pages      = _pages;
  
          if ((TSize)_bufferSize > _size)
              _bufferSize = _size;
  
          allocPage(_clusterBuffer, _bufferSize, me);
          PageBucketExtended<TValue> pb;
          pb.begin = _clusterBuffer.begin;
  
          size_t clusterSize = _bufferSize / pages;
  //        ::std::cerr << "equiDistantDistribution: pages=" << _pages << "\tclusterSize=" << clusterSize << ::std::endl;
          if (lastPageSize > 0 && clusterSize >= lastPageSize) {
              // last page bucket would get more memory than page would need
              // --> exclude from equi-size distribution
              if (--pages) {
                  _bufferSize -= lastPageSize;
                  clusterSize = _bufferSize / pages;
              }
          }
  
          if (pages) {
              size_t remainder = _bufferSize % pages;
              for(unsigned i = 0, numerator = 0; i < pages; ++i) {
                  pb.end = pb.begin + clusterSize;
                  if ((numerator += remainder) >= pages) {    // simple bresenham for distribution
                      numerator -= pages;
                      ++pb.end;
                  }
                  pb.cur = pb.begin;
                  pb.pageOfs = 0;
  			    Func_(pb);
                  pb.begin = pb.end;
              }
          }
  
          if (pages < _pages) {
              pb.end = pb.begin + lastPageSize;
              pb.cur = pb.begin;
              pb.pageOfs = 0;
  			Func_(pb);
          }
  
          return true;
      }
  
      template <typename TValue, typename TSize, typename T, class Function>
      inline unsigned equiDistantAlignedDistribution(
          Buffer<TValue> &_clusterBuffer, size_t aligning, size_t _bufferSize, T const &me,
          TSize _size, size_t _pageSize,
          Function const &Func_)
      {
  //IOREV _nodoc_
          unsigned _pages         = enclosingBlocks(_size, _pageSize);
  //        ::std::cerr << "equiDistantAlignedDistribution: size=" << _size << "\tpageSize=" << _pageSize << ::std::endl;
          if (!_pages) {
  			::std::cerr << "equiDistantAlignedDistribution: _pages is null!" << ::std::endl;
              return 0;
          }
  
          if (_bufferSize < _pages) {
  			::std::cerr << "equiDistantAlignedDistribution: clusterBufferSize is too small -> raised to " << _pages << ::std::endl;
              _bufferSize = _pages;
          }
  
          size_t lastPageSize = _size % _pageSize;
          unsigned pages      = _pages;
  
          if ((TSize)_bufferSize > _size)
              _bufferSize = _size;
  
          size_t clusterSize = _bufferSize / pages;
          size_t aclusterSize = (clusterSize / aligning) * aligning;
          if (clusterSize - aclusterSize > aligning / 2)
              aclusterSize += aligning;
  
  //        ::std::cerr << "equiDistantAlignedDistribution: pages=" << _pages << "\tclusterSize=" << aclusterSize << ::std::endl;
  
  		if (aclusterSize != 0) {
  
  			if (lastPageSize > 0 && aclusterSize > lastPageSize) {
  				// last page bucket would get more memory than page would need
  				// --> exclude from equi-size distribution
  				--pages;
  				allocPage(_clusterBuffer, aclusterSize * pages + lastPageSize, me);
  			} else
  				allocPage(_clusterBuffer, aclusterSize * pages, me);
  
  			PageBucketExtended<TValue> pb;
  			pb.begin = _clusterBuffer.begin;
  
  			if (pages) {
  				for(unsigned i = 0; i < pages; ++i) {
  					pb.end = pb.begin + aclusterSize;
  					pb.cur = pb.begin;
  					pb.pageOfs = 0;
  					Func_(pb);
  					pb.begin = pb.end;
  				}
  			}
  
  			if (pages < _pages) {
  				pb.end = pb.begin + lastPageSize;
  				pb.cur = pb.begin;
  				pb.pageOfs = 0;
  				Func_(pb);
  			}
  		}
  
          return aclusterSize;
      }
  
  }
  
  #endif
  