Made Generator.Result immutable. Now instead of holding a list and

being mutable, it is a single-linked list that is traversed
recursively.
This commit is contained in:
Simone Bordet 2013-10-28 16:36:55 +01:00
parent 4706ed5d87
commit 98de7500f9
8 changed files with 53 additions and 56 deletions

View File

@ -77,11 +77,10 @@ public class ClientGenerator extends Generator
int maxCapacity = 4 + 4 + 2 * MAX_PARAM_LENGTH; int maxCapacity = 4 + 4 + 2 * MAX_PARAM_LENGTH;
// One FCGI_BEGIN_REQUEST + N FCGI_PARAMS + one last FCGI_PARAMS // One FCGI_BEGIN_REQUEST + N FCGI_PARAMS + one last FCGI_PARAMS
Result result = new Result(byteBufferPool, callback);
ByteBuffer beginRequestBuffer = byteBufferPool.acquire(16, false); ByteBuffer beginRequestBuffer = byteBufferPool.acquire(16, false);
BufferUtil.clearToFill(beginRequestBuffer); BufferUtil.clearToFill(beginRequestBuffer);
result.add(beginRequestBuffer, true); Result result = new Result(byteBufferPool, callback, beginRequestBuffer, true);
// Generate the FCGI_BEGIN_REQUEST frame // Generate the FCGI_BEGIN_REQUEST frame
beginRequestBuffer.putInt(0x01_01_00_00 + request); beginRequestBuffer.putInt(0x01_01_00_00 + request);
@ -95,7 +94,7 @@ public class ClientGenerator extends Generator
int capacity = 8 + Math.min(maxCapacity, fieldsLength); int capacity = 8 + Math.min(maxCapacity, fieldsLength);
ByteBuffer buffer = byteBufferPool.acquire(capacity, true); ByteBuffer buffer = byteBufferPool.acquire(capacity, true);
BufferUtil.clearToFill(buffer); BufferUtil.clearToFill(buffer);
result.add(buffer, true); result = result.append(buffer, true);
// Generate the FCGI_PARAMS frame // Generate the FCGI_PARAMS frame
buffer.putInt(0x01_04_00_00 + request); buffer.putInt(0x01_04_00_00 + request);
@ -133,7 +132,7 @@ public class ClientGenerator extends Generator
ByteBuffer lastParamsBuffer = byteBufferPool.acquire(8, false); ByteBuffer lastParamsBuffer = byteBufferPool.acquire(8, false);
BufferUtil.clearToFill(lastParamsBuffer); BufferUtil.clearToFill(lastParamsBuffer);
result.add(lastParamsBuffer, true); result = result.append(lastParamsBuffer, true);
// Generate the last FCGI_PARAMS frame // Generate the last FCGI_PARAMS frame
lastParamsBuffer.putInt(0x01_04_00_00 + request); lastParamsBuffer.putInt(0x01_04_00_00 + request);
@ -160,6 +159,6 @@ public class ClientGenerator extends Generator
public Result generateRequestContent(int request, ByteBuffer content, boolean lastContent, Callback callback) public Result generateRequestContent(int request, ByteBuffer content, boolean lastContent, Callback callback)
{ {
return generateContent(request, content, lastContent, callback, FCGI.FrameType.STDIN); return generateContent(request, content, false, lastContent, callback, FCGI.FrameType.STDIN);
} }
} }

View File

@ -83,8 +83,8 @@ public class Flusher
result = queue.poll(); result = queue.poll();
} }
active = result; active = result;
List<ByteBuffer> buffers = result.getByteBuffers(); ByteBuffer[] buffers = result.getByteBuffers();
endPoint.write(this, buffers.toArray(new ByteBuffer[buffers.size()])); endPoint.write(this, buffers);
return false; return false;
} }
@ -133,7 +133,7 @@ public class Flusher
{ {
private ShutdownResult() private ShutdownResult()
{ {
super(null, new Adapter()); super(null, null, null, false);
} }
@Override @Override

View File

@ -19,8 +19,6 @@
package org.eclipse.jetty.fcgi.generator; package org.eclipse.jetty.fcgi.generator;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.fcgi.FCGI; import org.eclipse.jetty.fcgi.FCGI;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
@ -38,18 +36,18 @@ public class Generator
this.byteBufferPool = byteBufferPool; this.byteBufferPool = byteBufferPool;
} }
protected Result generateContent(int id, ByteBuffer content, boolean lastContent, Callback callback, FCGI.FrameType frameType) protected Result generateContent(int id, ByteBuffer content, boolean recycle, boolean lastContent, Callback callback, FCGI.FrameType frameType)
{ {
id &= 0xFF_FF; id &= 0xFF_FF;
int remaining = content == null ? 0 : content.remaining(); int remaining = content == null ? 0 : content.remaining();
Result result = new Result(byteBufferPool, callback); Result result = new Result(byteBufferPool, callback, null, false);
while (remaining > 0 || lastContent) while (remaining > 0 || lastContent)
{ {
ByteBuffer buffer = byteBufferPool.acquire(8, false); ByteBuffer buffer = byteBufferPool.acquire(8, false);
BufferUtil.clearToFill(buffer); BufferUtil.clearToFill(buffer);
result.add(buffer, true); result = result.append(buffer, true);
// Generate the frame header // Generate the frame header
buffer.put((byte)0x01); buffer.put((byte)0x01);
@ -67,7 +65,7 @@ public class Generator
int limit = content.limit(); int limit = content.limit();
content.limit(content.position() + length); content.limit(content.position() + length);
ByteBuffer slice = content.slice(); ByteBuffer slice = content.slice();
result.add(slice, false); result = result.append(slice, recycle);
content.position(content.limit()); content.position(content.limit());
content.limit(limit); content.limit(limit);
remaining -= length; remaining -= length;
@ -80,42 +78,51 @@ public class Generator
{ {
private final ByteBufferPool byteBufferPool; private final ByteBufferPool byteBufferPool;
private final Callback callback; private final Callback callback;
private final List<ByteBuffer> buffers; private final ByteBuffer buffer;
private final List<Boolean> recycles; private final boolean recycle;
private final Result previous;
public Result(ByteBufferPool byteBufferPool, Callback callback) public Result(ByteBufferPool byteBufferPool, Callback callback, ByteBuffer buffer, boolean recycle)
{ {
this(byteBufferPool, callback, new ArrayList<ByteBuffer>(4), new ArrayList<Boolean>(4)); this(byteBufferPool, callback, buffer, recycle, null);
} }
public Result(Result that) private Result(ByteBufferPool byteBufferPool, Callback callback, ByteBuffer buffer, boolean recycle, Result previous)
{
this(that.byteBufferPool, that.callback, that.buffers, that.recycles);
}
private Result(ByteBufferPool byteBufferPool, Callback callback, List<ByteBuffer> buffers, List<Boolean> recycles)
{ {
this.byteBufferPool = byteBufferPool; this.byteBufferPool = byteBufferPool;
this.callback = callback; this.callback = callback;
this.buffers = buffers; this.buffer = buffer;
this.recycles = recycles; this.recycle = recycle;
this.previous = previous;
} }
public void add(ByteBuffer buffer, boolean recycle) public Result append(ByteBuffer buffer, boolean recycle)
{ {
buffers.add(buffer); return new Result(byteBufferPool, null, buffer, recycle, this);
recycles.add(recycle);
} }
public List<ByteBuffer> getByteBuffers() public ByteBuffer[] getByteBuffers()
{ {
return buffers; return getByteBuffers(0);
}
private ByteBuffer[] getByteBuffers(int length)
{
int newLength = length + (buffer == null ? 0 : 1);
ByteBuffer[] result;
result = previous != null ? previous.getByteBuffers(newLength) : new ByteBuffer[newLength];
if (buffer != null)
result[result.length - newLength] = buffer;
return result;
} }
@Override @Override
public void succeeded() public void succeeded()
{ {
recycle(); recycle();
if (previous != null)
previous.succeeded();
if (callback != null)
callback.succeeded(); callback.succeeded();
} }
@ -123,17 +130,16 @@ public class Generator
public void failed(Throwable x) public void failed(Throwable x)
{ {
recycle(); recycle();
if (previous != null)
previous.failed(x);
if (callback != null)
callback.failed(x); callback.failed(x);
} }
protected void recycle() protected void recycle()
{ {
for (int i = 0; i < buffers.size(); ++i) if (recycle)
{
ByteBuffer buffer = buffers.get(i);
if (recycles.get(i))
byteBufferPool.release(buffer); byteBufferPool.release(buffer);
} }
} }
}
} }

View File

@ -85,20 +85,12 @@ public class ServerGenerator extends Generator
buffer.flip(); buffer.flip();
return new Result(generateContent(request, buffer, false, callback, FCGI.FrameType.STDOUT)) return generateContent(request, buffer, true, false, callback, FCGI.FrameType.STDOUT);
{
@Override
protected void recycle()
{
super.recycle();
byteBufferPool.release(buffer);
}
};
} }
public Result generateResponseContent(int request, ByteBuffer content, boolean lastContent, Callback callback) public Result generateResponseContent(int request, ByteBuffer content, boolean lastContent, Callback callback)
{ {
Result result = generateContent(request, content, lastContent, callback, FCGI.FrameType.STDOUT); Result result = generateContent(request, content, false, lastContent, callback, FCGI.FrameType.STDOUT);
if (lastContent) if (lastContent)
{ {
// Generate the FCGI_END_REQUEST // Generate the FCGI_END_REQUEST
@ -109,7 +101,7 @@ public class ServerGenerator extends Generator
endRequestBuffer.putInt(0x00_08_00_00); endRequestBuffer.putInt(0x00_08_00_00);
endRequestBuffer.putLong(0x00L); endRequestBuffer.putLong(0x00L);
endRequestBuffer.flip(); endRequestBuffer.flip();
result.add(endRequestBuffer, true); result = result.append(endRequestBuffer, true);
} }
return result; return result;
} }

View File

@ -38,7 +38,7 @@ public class HttpClientTransportOverFCGI extends AbstractHttpClientTransport
public HttpClientTransportOverFCGI(String scriptRoot) public HttpClientTransportOverFCGI(String scriptRoot)
{ {
this(Runtime.getRuntime().availableProcessors() / 2 + 1, false, scriptRoot); this(Math.max(1, Runtime.getRuntime().availableProcessors() / 2), false, scriptRoot);
} }
public HttpClientTransportOverFCGI(int selectors, boolean multiplexed, String scriptRoot) public HttpClientTransportOverFCGI(int selectors, boolean multiplexed, String scriptRoot)

View File

@ -1,3 +1,3 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
org.eclipse.jetty.client.LEVEL=DEBUG #org.eclipse.jetty.client.LEVEL=DEBUG
org.eclipse.jetty.fcgi.LEVEL=DEBUG #org.eclipse.jetty.fcgi.LEVEL=DEBUG

View File

@ -1,3 +1,3 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
org.eclipse.jetty.client.LEVEL=DEBUG #org.eclipse.jetty.client.LEVEL=DEBUG
org.eclipse.jetty.fcgi.LEVEL=DEBUG #org.eclipse.jetty.fcgi.LEVEL=DEBUG

View File

@ -60,7 +60,7 @@ public class HttpChannelOverFCGI extends HttpChannel<ByteBuffer>
{ {
if (FCGI.Headers.REQUEST_METHOD.equalsIgnoreCase(field.getName())) if (FCGI.Headers.REQUEST_METHOD.equalsIgnoreCase(field.getName()))
method = field.getValue(); method = field.getValue();
else if (FCGI.Headers.REQUEST_URI.equalsIgnoreCase(field.getName())) else if (FCGI.Headers.DOCUMENT_URI.equalsIgnoreCase(field.getName()))
path = field.getValue(); path = field.getValue();
else if (FCGI.Headers.QUERY_STRING.equalsIgnoreCase(field.getName())) else if (FCGI.Headers.QUERY_STRING.equalsIgnoreCase(field.getName()))
query = field.getValue(); query = field.getValue();