com.bigdata.io
Class DirectBufferPool

java.lang.Object
  extended by com.bigdata.io.DirectBufferPool

public class DirectBufferPool
extends Object

An instance of this class manages a JVM-wide pool of direct (aka native) ByteBuffers. Methods are provided to acquire a ByteBuffer from the pool and to release a ByteBuffer back to the pool.

Note: There is a bug in the release of large temporary direct ByteBuffers which motivates this class. For regular journals that overflow, the write cache is allocated once and handed off from journal to journal. However, there is no such opportunity for temporary stores. Unfortunately it is NOT an option to simply disable the write cache for temporary stores since NIO will allocate (and fail to release) an "temporary" direct buffer for the operation which transfers the data from the TransientBufferStrategy to disk. Therefore the data is copied into a temporary buffer allocated from this pool and then the buffer is either handed off to the IBufferStrategy for use as its write cache (in which case the TemporaryRawStore holds a reference to the buffer and releases it back to those pool when it is finalized) or the buffer is immediately released back to this pool.

Note: Precisely because of the bug which motivates this class, we DO NOT release buffers back to the JVM. This means that the size of a DirectBufferPool can only increase, but at least you get to (re-)use the memory that you have allocated rather than leaking it to the native heap.

Version:
$Id: DirectBufferPool.java 4783 2011-06-23 18:27:27Z thompsonbry $
Author:
Bryan Thompson
See Also:
ab76d1d4479fffffffffa5abfb09c719a30?bug_id=6210541
TODO:
It should be possible to define a method which attempts to release direct buffers back to the JVM. The JVM can eventually GC them after a full GC, but often not in time to avoid an OOM error on the Java heap.

Nested Class Summary
static interface DirectBufferPool.Options
          Options for provisioning the static instance of the DirectBufferPool.
 
Field Summary
static DirectBufferPool INSTANCE
          A JVM-wide pool of direct ByteBuffers used for a variety of purposes with a default DirectBufferPool.Options.BUFFER_CAPACITY of 1 MB.
 
Constructor Summary
protected DirectBufferPool(String name, int poolCapacity, int bufferCapacity)
          Create a direct ByteBuffer pool.
 
Method Summary
 IBufferAccess acquire()
          Return an IBufferAccess wrapping a direct ByteBuffer.
 IBufferAccess acquire(long timeout, TimeUnit unit)
          Return an IBufferAccess wrapping a direct ByteBuffer.
 int getAcquiredBufferCount()
          The #of ByteBuffers which are currently acquired.
 int getBufferCapacity()
          The capacity of the ByteBuffers managed by this pool as specified to the ctor.
static CounterSet getCounters()
          Return the CounterSet for the DirectBufferPool.
 String getName()
          The name of this buffer pool instance.
 int getPoolCapacity()
          The capacity of the buffer as specified to the ctor.
 int getPoolSize()
          The approximate #of ByteBuffers currently managed by this pool.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

INSTANCE

public static final DirectBufferPool INSTANCE
A JVM-wide pool of direct ByteBuffers used for a variety of purposes with a default DirectBufferPool.Options.BUFFER_CAPACITY of 1 MB.

Note: acquire() requests will block once the pool capacity has been reached until a buffer is release(ByteBuffer)ed.

Constructor Detail

DirectBufferPool

protected DirectBufferPool(String name,
                           int poolCapacity,
                           int bufferCapacity)
Create a direct ByteBuffer pool.

Note: When the poolSize is bounded then acquire() MAY block. This can introduce deadlocks into the application. You can use a timeout to limit the sensitivity to deadlocks or you can use an unbounded pool and accept that OutOfMemoryErrors will arise if there is too much concurrent demand for the buffers supplied by this pool.

Parameters:
poolCapacity - The maximum capacity of the pool. Use Integer.MAX_VALUE to have a pool with an unbounded number of buffers.
bufferCapacity - The capacity of the ByteBuffers managed by this pool.
See Also:
INSTANCE
Method Detail

getName

public String getName()
The name of this buffer pool instance.


getAcquiredBufferCount

public int getAcquiredBufferCount()
The #of ByteBuffers which are currently acquired. This counter is incremented when a buffer is acquired and decremented when a buffer is released.


getPoolCapacity

public int getPoolCapacity()
The capacity of the buffer as specified to the ctor.


getPoolSize

public int getPoolSize()
The approximate #of ByteBuffers currently managed by this pool.


getBufferCapacity

public int getBufferCapacity()
The capacity of the ByteBuffers managed by this pool as specified to the ctor.


acquire

public IBufferAccess acquire()
                      throws InterruptedException
Return an IBufferAccess wrapping a direct ByteBuffer. The capacity of the buffer is determined by the configuration of this pool. The position will be equal to zero, the limit will be equal to the capacity, and the mark will not be set.

Note: This method will block if there are no free buffers in the pool and the pool was configured with a maximum capacity. It WILL log an error if it blocks. While blocking is not very safe, using a heap (vs direct) ByteBuffer is not very safe either since Java NIO will allocate a temporary direct ByteBuffer for IOs and that can both run out of memory and leak memory.

Returns:
A direct ByteBuffer.
Throws:
InterruptedException - if the caller's Thread is interrupted awaiting a buffer.
OutOfMemoryError - if there is not enough free memory to fulfill the request.

acquire

public IBufferAccess acquire(long timeout,
                             TimeUnit unit)
                      throws InterruptedException,
                             TimeoutException
Return an IBufferAccess wrapping a direct ByteBuffer. The capacity of the buffer is determined by the configuration of this pool. The position will be equal to zero, the limit will be equal to the capacity, and the mark will not be set.

Note: This method will block if there are no free buffers in the pool and the pool was configured with a maximum capacity. In addition it MAY block if there is not enough free memory to fulfill the request. It WILL log an error if it blocks. While blocking is not very safe, using a heap (vs direct) ByteBuffer is not very safe either since Java NIO will allocate a temporary direct ByteBuffer for IOs and that can both run out of memory and leak memory.

Parameters:
timeout - The timeout.
unit - The units for that timeout.
Returns:
A direct ByteBuffer.
Throws:
InterruptedException - if the caller's Thread is interrupted awaiting a buffer.
TimeoutException

getCounters

public static CounterSet getCounters()
Return the CounterSet for the DirectBufferPool.

Returns:
The counters.


Copyright © 2006-2012 SYSTAP, LLC. All Rights Reserved.