280843 buffer pool mixing types

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@492 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2009-07-08 07:39:23 +00:00
parent e8862a3fb1
commit f13ac17713
9 changed files with 246 additions and 34 deletions

View File

@ -3,6 +3,7 @@ jetty-7.0.0.RC0-SNAPSHOT
+ JETTY-967 create standalone build for PKCS12Import at codehaus
+ JETTY-1056 update jetty-ant module for Jetty 7 at codehaus trunk
+ JETTY-1058 Handle trailing / with aliases
+ 280843 Buffer pool uses isHeader
jetty-7.0.0.M4 1 June 2009
+ 281059 NPE in QTP with debug on

View File

@ -379,7 +379,6 @@ public class HttpClient extends HttpBuffers implements Attributes
/**
* @see org.eclipse.jetty.http.HttpBuffers#newResponseHeader(int)
*/
@Override
protected Buffer newResponseHeader(int size)
{
if (_connectorType == CONNECTOR_SOCKET)
@ -387,6 +386,23 @@ public class HttpClient extends HttpBuffers implements Attributes
return new IndirectNIOBuffer(size);
}
/* ------------------------------------------------------------------------------- */
protected boolean isRequestHeader(Buffer buffer)
{
if (_connectorType == CONNECTOR_SOCKET)
return buffer instanceof ByteArrayBuffer;
return buffer instanceof IndirectNIOBuffer;
}
/* ------------------------------------------------------------------------------- */
protected boolean isResponseHeader(Buffer buffer)
{
if (_connectorType == CONNECTOR_SOCKET)
return buffer instanceof ByteArrayBuffer;
return buffer instanceof IndirectNIOBuffer;
}
/* ------------------------------------------------------------ */
public int getMaxConnectionsPerAddress()
{

View File

@ -95,6 +95,11 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector,
// TODO indirect?
return new DirectNIOBuffer(size);
}
@Override
protected boolean isHeader(Buffer buffer)
{
return true;
}
};
buffers.setBufferSize(ssl_session.getApplicationBufferSize());
buffers.setHeaderSize(ssl_session.getPacketBufferSize());

View File

@ -39,6 +39,11 @@ public abstract class HttpBuffers extends AbstractLifeCycle
{
return newRequestHeader(size);
}
@Override
protected boolean isHeader(Buffer buffer)
{
return isRequestHeader(buffer);
}
};
private final ThreadLocalBuffers _responseBuffers = new ThreadLocalBuffers()
@ -54,6 +59,11 @@ public abstract class HttpBuffers extends AbstractLifeCycle
{
return newResponseHeader(size);
}
@Override
protected boolean isHeader(Buffer buffer)
{
return isResponseHeader(buffer);
}
};
public HttpBuffers()
@ -129,6 +139,22 @@ public abstract class HttpBuffers extends AbstractLifeCycle
protected abstract Buffer newResponseBuffer(int size);
protected abstract Buffer newResponseHeader(int size);
/* ------------------------------------------------------------ */
/**
* @param buffer
* @return True if the buffer is the correct type for a request header buffer
*/
protected abstract boolean isRequestHeader(Buffer buffer);
/* ------------------------------------------------------------ */
/**
* @param buffer
* @return True if the buffer is the correct type for a response header buffer
*/
protected abstract boolean isResponseHeader(Buffer buffer);
/**
* @param headerBufferSize The headerBufferSize to set.

View File

@ -24,7 +24,8 @@ public abstract class ThreadLocalBuffers implements Buffers
{
private int _bufferSize=12*1024;
private int _headerSize=6*1024;
/* ------------------------------------------------------------ */
private final ThreadLocal<ThreadBuffers> _buffers=new ThreadLocal<ThreadBuffers>()
{
protected ThreadBuffers initialValue()
@ -33,6 +34,12 @@ public abstract class ThreadLocalBuffers implements Buffers
}
};
/* ------------------------------------------------------------ */
public ThreadLocalBuffers()
{
}
/* ------------------------------------------------------------ */
public Buffer getBuffer()
{
ThreadBuffers buffers = _buffers.get();
@ -53,6 +60,7 @@ public abstract class ThreadLocalBuffers implements Buffers
return newBuffer(_bufferSize);
}
/* ------------------------------------------------------------ */
public Buffer getHeader()
{
ThreadBuffers buffers = _buffers.get();
@ -63,7 +71,7 @@ public abstract class ThreadLocalBuffers implements Buffers
return b;
}
if (buffers._other!=null && buffers._other.capacity()==_headerSize)
if (buffers._other!=null && buffers._other.capacity()==_headerSize && isHeader(buffers._other))
{
Buffer b=buffers._other;
buffers._other=null;
@ -73,6 +81,7 @@ public abstract class ThreadLocalBuffers implements Buffers
return newHeader(_headerSize);
}
/* ------------------------------------------------------------ */
public Buffer getBuffer(int size)
{
ThreadBuffers buffers = _buffers.get();
@ -86,6 +95,7 @@ public abstract class ThreadLocalBuffers implements Buffers
return newBuffer(size);
}
/* ------------------------------------------------------------ */
public void returnBuffer(Buffer buffer)
{
buffer.clear();
@ -96,22 +106,17 @@ public abstract class ThreadLocalBuffers implements Buffers
ThreadBuffers buffers = _buffers.get();
if (size==_bufferSize && buffers._buffer==null)
{
buffers._buffer=buffer;
}
else if (size==_headerSize && buffers._header==null)
{
if (buffers._header==null && size==_headerSize && isHeader(buffer))
buffers._header=buffer;
}
else if (size==_bufferSize && buffers._buffer==null)
buffers._buffer=buffer;
else
{
buffers._other=buffer;
}
}
/* ------------------------------------------------------------ */
/**
* @return Returns the buffer size in bytes.
*/
@ -119,7 +124,8 @@ public abstract class ThreadLocalBuffers implements Buffers
{
return _bufferSize;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the header size in bytes.
*/
@ -128,10 +134,30 @@ public abstract class ThreadLocalBuffers implements Buffers
return _headerSize;
}
/* ------------------------------------------------------------ */
/**
* Create a new content Buffer
* @param size
* @return new Buffer
*/
protected abstract Buffer newBuffer(int size);
/* ------------------------------------------------------------ */
/**
* Create a new header Buffer
* @param size
* @return new Buffer
*/
protected abstract Buffer newHeader(int size);
/* ------------------------------------------------------------ */
/**
* @param buffer
* @return True if the buffer is the correct type to be a Header buffer
*/
protected abstract boolean isHeader(Buffer buffer);
/* ------------------------------------------------------------ */
/**
* @param size The buffer size in bytes
*/
@ -140,6 +166,7 @@ public abstract class ThreadLocalBuffers implements Buffers
_bufferSize = size;
}
/* ------------------------------------------------------------ */
/**
* @param size The header size in bytes
*/
@ -147,7 +174,9 @@ public abstract class ThreadLocalBuffers implements Buffers
{
_headerSize = size;
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
protected static class ThreadBuffers
{
Buffer _buffer;

View File

@ -14,8 +14,10 @@
package org.eclipse.jetty.io;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import junit.framework.TestCase;
@ -103,10 +105,126 @@ public class ThreadLocalBuffersTest
throws Exception
{
execAbstractBuffer( );
}
public void testDifferentSizes()
throws Exception
{
InnerBuffers buffers = new InnerBuffers();
buffers.setHeaderSize(128);
buffers.setBufferSize(256);
Buffer h1 = buffers.getHeader();
Buffer h2 = buffers.getHeader();
Buffer b1 = buffers.getBuffer();
Buffer b2 = buffers.getBuffer();
Buffer b3 = buffers.getBuffer(512);
buffers.returnBuffer(h1);
buffers.returnBuffer(h2);
buffers.returnBuffer(b1);
buffers.returnBuffer(b2);
buffers.returnBuffer(b3);
assertTrue(h1==buffers.getHeader()); // pooled header
assertTrue(h2!=buffers.getHeader()); // b2 replaced h2 in other slot
assertTrue(b1==buffers.getBuffer()); // pooled buffer
assertTrue(b2!=buffers.getBuffer()); // b3 replaced b2 in other slot
assertTrue(b3==buffers.getBuffer(512)); // b2 from other slot
buffers.returnBuffer(h1);
buffers.returnBuffer(h2);
buffers.returnBuffer(b1);
assertTrue(h1==buffers.getHeader()); // pooled header
assertTrue(h2==buffers.getHeader()); // h2 in other slot
assertTrue(b1==buffers.getBuffer()); // pooled buffer
assertTrue(b2!=buffers.getBuffer()); // new buffer
assertTrue(b3!=buffers.getBuffer(512)); // new buffer
// check that sizes are respected
buffers.returnBuffer(b3);
buffers.returnBuffer(b1);
buffers.returnBuffer(b2);
buffers.returnBuffer(h1);
buffers.returnBuffer(h2);
assertTrue(h1==buffers.getHeader()); // pooled header
assertTrue(h2==buffers.getHeader()); // h2 in other slot
assertTrue(b1==buffers.getBuffer()); // pooled buffer
assertTrue(b2!=buffers.getBuffer()); // new buffer
assertTrue(b3!=buffers.getBuffer(512)); // new buffer
}
public void testSameSizes()
throws Exception
{
Buffer buffer=null;
InnerBuffers buffers = new InnerBuffers();
buffers.setHeaderSize(128);
buffers.setBufferSize(128);
Buffer h1 = buffers.getHeader();
Buffer h2 = buffers.getHeader();
Buffer b1 = buffers.getBuffer();
Buffer b2 = buffers.getBuffer();
Buffer b3 = buffers.getBuffer(128);
List<Buffer> known = new ArrayList<Buffer>();
known.add(h1);
known.add(h2);
known.add(b1);
known.add(b2);
known.add(h1);
buffers.returnBuffer(h1);
buffers.returnBuffer(h2);
buffers.returnBuffer(b1);
buffers.returnBuffer(b2);
buffers.returnBuffer(b3);
assertTrue(h1==buffers.getHeader()); // pooled header
buffer=buffers.getHeader();
for (Buffer b:known) assertTrue(b!=buffer); // new buffer
assertTrue(h2==buffers.getBuffer()); // h2 used from buffer slot
assertTrue(b3==buffers.getBuffer()); // b1 from other slot
buffer=buffers.getBuffer(128);
for (Buffer b:known) assertTrue(b!=buffer); // new buffer
buffers.returnBuffer(h1);
buffers.returnBuffer(h2);
buffers.returnBuffer(b1);
assertTrue(h1==buffers.getHeader()); // pooled header
buffer=buffers.getHeader();
for (Buffer b:known) assertTrue(b!=buffer); // new buffer
assertTrue(h2==buffers.getBuffer()); // h2 used from buffer slot
assertTrue(b1==buffers.getBuffer()); // h2 used from other slot
buffers.returnBuffer(h1);
buffers.returnBuffer(b1);
buffers.returnBuffer(h2);
assertTrue(h1==buffers.getHeader()); // pooled header
assertTrue(h2==buffers.getHeader()); // h2 from other slot
buffer=buffers.getHeader();
for (Buffer b:known) assertTrue(b!=buffer); // new buffer
assertTrue(b1==buffers.getBuffer()); // b1 used from buffer slot
buffer=buffers.getBuffer();
for (Buffer b:known) assertTrue(b!=buffer); // new buffer
}
static class HeaderBuffer extends ByteArrayBuffer
{
public HeaderBuffer(int size)
{
super(size);
}
}
static class InnerBuffers extends ThreadLocalBuffers
{
@Override
@ -114,13 +232,16 @@ public class ThreadLocalBuffersTest
{
return new ByteArrayBuffer( size );
}
@Override
protected Buffer newHeader(int size)
{
return new ByteArrayBuffer( size );
return new HeaderBuffer( size );
}
@Override
protected boolean isHeader(Buffer buffer)
{
return buffer instanceof HeaderBuffer;
}
}

View File

@ -130,6 +130,18 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
{
return new ByteArrayBuffer(size);
}
/* ------------------------------------------------------------------------------- */
protected boolean isRequestHeader(Buffer buffer)
{
return true;
}
/* ------------------------------------------------------------------------------- */
protected boolean isResponseHeader(Buffer buffer)
{
return true;
}
/* ------------------------------------------------------------------------------- */
/*

View File

@ -17,6 +17,7 @@
package org.eclipse.jetty.server.nio;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
import org.eclipse.jetty.io.nio.NIOBuffer;
@ -46,20 +47,6 @@ public abstract class AbstractNIOConnector extends AbstractConnector implements
{
_useDirectBuffers=direct;
}
// TODO
// Header buffers always byte array buffers (efficiency of random access)
// There are lots of things to consider here... DIRECT buffers are faster to
// send but more expensive to build and access! so we have choices to make...
// + headers are constructed bit by bit and parsed bit by bit, so INDiRECT looks
// good for them.
// + but will a gather write of an INDIRECT header with a DIRECT body be any good?
// this needs to be benchmarked.
// + Will it be possible to get a DIRECT header buffer just for the gather writes of
// content from file mapped buffers?
// + Are gather writes worth the effort? Maybe they will work well with two INDIRECT
// buffers being copied into a single kernel buffer?
/* ------------------------------------------------------------------------------- */
public Buffer newRequestBuffer(int size)
@ -82,8 +69,18 @@ public abstract class AbstractNIOConnector extends AbstractConnector implements
/* ------------------------------------------------------------------------------- */
public Buffer newResponseHeader(int size)
{
// TODO maybe can be direct?
return new IndirectNIOBuffer(size);
}
/* ------------------------------------------------------------------------------- */
protected boolean isRequestHeader(Buffer buffer)
{
return buffer instanceof IndirectNIOBuffer;
}
/* ------------------------------------------------------------------------------- */
protected boolean isResponseHeader(Buffer buffer)
{
return buffer instanceof IndirectNIOBuffer;
}
}

View File

@ -554,6 +554,11 @@ public class SslSelectChannelConnector extends SelectChannelConnector
// TODO indirect?
return new DirectNIOBuffer(size);
}
@Override
protected boolean isHeader(Buffer buffer)
{
return true;
}
};
buffers.setBufferSize(ssl_session.getApplicationBufferSize());
buffers.setHeaderSize(ssl_session.getPacketBufferSize());