Rejecting BufferPool.release() of buffers below factor

This commit is contained in:
Joakim Erdfelt 2012-12-11 12:47:18 -07:00
parent 9a71d75003
commit 3fd59fa189
3 changed files with 40 additions and 8 deletions

View File

@ -25,9 +25,12 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class MappedByteBufferPool implements ByteBufferPool
{
private static final Logger LOG = Log.getLogger(MappedByteBufferPool.class);
private final ConcurrentMap<Integer, Queue<ByteBuffer>> directBuffers = new ConcurrentHashMap<>();
private final ConcurrentMap<Integer, Queue<ByteBuffer>> heapBuffers = new ConcurrentHashMap<>();
private final int factor;
@ -60,14 +63,24 @@ public class MappedByteBufferPool implements ByteBufferPool
}
BufferUtil.clear(result);
if(LOG.isDebugEnabled()) {
LOG.debug("acquire({}, {}) -> {}", size, direct, BufferUtil.toDetailString(result));
}
return result;
}
@Override
public void release(ByteBuffer buffer)
{
if(LOG.isDebugEnabled()) {
LOG.debug("release({})", BufferUtil.toDetailString(buffer));
}
if (buffer == null)
return;
return; // nothing to do
if (buffer.capacity() < factor)
return; // don't bother keeping track of this buffer (it obviously didn't come from this bytebuffer pool
int bucket = bucketFor(buffer.capacity());
ConcurrentMap<Integer, Queue<ByteBuffer>> buffers = buffersFor(buffer.isDirect());

View File

@ -18,18 +18,17 @@
package org.eclipse.jetty.io;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.nio.ByteBuffer;
import java.util.Queue;
import java.util.concurrent.ConcurrentMap;
import org.eclipse.jetty.util.StringUtil;
import org.junit.Ignore;
import org.junit.Test;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
public class MappedByteBufferPoolTest
{
@Test
@ -82,4 +81,25 @@ public class MappedByteBufferPoolTest
assertTrue(buffers.isEmpty());
}
/**
* In a scenario where BufferPool is being used, but some edges cases that use ByteBuffer.allocate()
* and then later that buffer is released via the BufferPool, that non acquired buffer can contaminate
* the buffer pool.
*/
@Test
public void testReleaseTiny() throws Exception
{
MappedByteBufferPool bufferPool = new MappedByteBufferPool();
// Release a few small non-pool buffers
bufferPool.release(ByteBuffer.wrap(StringUtil.getUtf8Bytes("Hello")));
bufferPool.release(ByteBuffer.wrap(StringUtil.getUtf8Bytes("There")));
// acquire small pool
ByteBuffer small = bufferPool.acquire(35, false);
assertThat(small.capacity(), greaterThanOrEqualTo(35));
small.limit(35);
bufferPool.release(small);
}
}

View File

@ -1,3 +1,2 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
org.eclipse.jetty.LEVEL=INFO