You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2015/05/22 11:25:41 UTC
svn commit: r1681050 -
/tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java
Author: remm
Date: Fri May 22 09:25:41 2015
New Revision: 1681050
URL: http://svn.apache.org/r1681050
Log:
Cleanup and move around the NIO2 sendfile code, addressing a fixme. There should be no functional change.
Modified:
tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java?rev=1681050&r1=1681049&r2=1681050&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java Fri May 22 09:25:41 2015
@@ -592,6 +592,80 @@ public class Nio2Endpoint extends Abstra
}
};
+ private CompletionHandler<Integer, SendfileData> sendfileHandler
+ = new CompletionHandler<Integer, SendfileData>() {
+
+ @Override
+ public void completed(Integer nWrite, SendfileData attachment) {
+ if (nWrite.intValue() < 0) {
+ failed(new EOFException(), attachment);
+ return;
+ }
+ attachment.pos += nWrite.intValue();
+ ByteBuffer buffer = getSocket().getBufHandler().getWriteBuffer();
+ if (!buffer.hasRemaining()) {
+ if (attachment.length <= 0) {
+ // All data has now been written
+ setSendfileData(null);
+ try {
+ attachment.fchannel.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ if (attachment.keepAlive) {
+ if (!isInline()) {
+ awaitBytes();
+ } else {
+ attachment.doneInline = true;
+ }
+ } else {
+ if (!isInline()) {
+ getEndpoint().processSocket(Nio2SocketWrapper.this, SocketStatus.DISCONNECT, false);
+ } else {
+ attachment.doneInline = true;
+ }
+ }
+ return;
+ } else {
+ getSocket().getBufHandler().configureWriteBufferForWrite();
+ int nRead = -1;
+ try {
+ nRead = attachment.fchannel.read(buffer);
+ } catch (IOException e) {
+ failed(e, attachment);
+ return;
+ }
+ if (nRead > 0) {
+ getSocket().getBufHandler().configureWriteBufferForRead();
+ if (attachment.length < buffer.remaining()) {
+ buffer.limit(buffer.limit() - buffer.remaining() + (int) attachment.length);
+ }
+ attachment.length -= nRead;
+ } else {
+ failed(new EOFException(), attachment);
+ return;
+ }
+ }
+ }
+ getSocket().write(buffer, getNio2WriteTimeout(), TimeUnit.MILLISECONDS, attachment, this);
+ }
+
+ @Override
+ public void failed(Throwable exc, SendfileData attachment) {
+ try {
+ attachment.fchannel.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ if (!isInline()) {
+ getEndpoint().processSocket(Nio2SocketWrapper.this, SocketStatus.ERROR, false);
+ } else {
+ attachment.doneInline = true;
+ attachment.error = true;
+ }
+ }
+ };
+
public Nio2SocketWrapper(Nio2Channel channel, Nio2Endpoint endpoint) {
super(channel, endpoint);
socketBufferHandler = channel.getBufHandler();
@@ -1284,8 +1358,46 @@ public class Nio2Endpoint extends Abstra
@Override
public SendfileState processSendfile(SendfileDataBase sendfileData) {
- setSendfileData((SendfileData) sendfileData);
- return ((Nio2Endpoint) getEndpoint()).processSendfile(this);
+ SendfileData data = (SendfileData) sendfileData;
+ setSendfileData(data);
+ // Configure the send file data
+ if (data.fchannel == null || !data.fchannel.isOpen()) {
+ java.nio.file.Path path = new File(sendfileData.fileName).toPath();
+ try {
+ data.fchannel = java.nio.channels.FileChannel
+ .open(path, StandardOpenOption.READ).position(sendfileData.pos);
+ } catch (IOException e) {
+ return SendfileState.ERROR;
+ }
+ }
+ getSocket().getBufHandler().configureWriteBufferForWrite();
+ ByteBuffer buffer = getSocket().getBufHandler().getWriteBuffer();
+ int nRead = -1;
+ try {
+ nRead = data.fchannel.read(buffer);
+ } catch (IOException e1) {
+ return SendfileState.ERROR;
+ }
+
+ if (nRead >= 0) {
+ data.length -= nRead;
+ getSocket().getBufHandler().configureWriteBufferForRead();
+ Nio2Endpoint.startInline();
+ getSocket().write(buffer, getNio2WriteTimeout(), TimeUnit.MILLISECONDS,
+ data, sendfileHandler);
+ Nio2Endpoint.endInline();
+ if (data.doneInline) {
+ if (data.error) {
+ return SendfileState.ERROR;
+ } else {
+ return SendfileState.DONE;
+ }
+ } else {
+ return SendfileState.PENDING;
+ }
+ } else {
+ return SendfileState.ERROR;
+ }
}
@@ -1467,126 +1579,6 @@ public class Nio2Endpoint extends Abstra
}
}
- private CompletionHandler<Integer, SendfileData> sendfile = new CompletionHandler<Integer, SendfileData>() {
-
- @Override
- public void completed(Integer nWrite, SendfileData attachment) {
- if (nWrite.intValue() < 0) { // Reach the end of stream
- failed(new EOFException(), attachment);
- return;
- }
- // TODO: Lots of direct access to the socketWriteBuffer.
- // Refactor to use socketBufferHandler
- attachment.pos += nWrite.intValue();
- if (!attachment.buffer.hasRemaining()) {
- if (attachment.length <= 0) {
- // All data has now been written
- attachment.socket.setSendfileData(null);
- try {
- attachment.fchannel.close();
- } catch (IOException e) {
- // Ignore
- }
- if (attachment.keepAlive) {
- if (!isInline()) {
- attachment.socket.awaitBytes();
- } else {
- attachment.doneInline = true;
- }
- } else {
- if (!isInline()) {
- processSocket(attachment.socket, SocketStatus.DISCONNECT, false);
- } else {
- attachment.doneInline = true;
- }
- }
- return;
- } else {
- attachment.buffer.clear();
- int nRead = -1;
- try {
- nRead = attachment.fchannel.read(attachment.buffer);
- } catch (IOException e) {
- failed(e, attachment);
- return;
- }
- if (nRead > 0) {
- attachment.buffer.flip();
- if (attachment.length < attachment.buffer.remaining()) {
- attachment.buffer.limit(attachment.buffer.limit() - attachment.buffer.remaining() + (int) attachment.length);
- }
- attachment.length -= nRead;
- } else {
- failed(new EOFException(), attachment);
- return;
- }
- }
- }
- attachment.socket.getSocket().write(attachment.buffer,
- attachment.socket.getNio2WriteTimeout(), TimeUnit.MILLISECONDS,
- attachment, this);
- }
-
- @Override
- public void failed(Throwable exc, SendfileData attachment) {
- try {
- attachment.fchannel.close();
- } catch (IOException e) {
- // Ignore
- }
- if (!isInline()) {
- processSocket(attachment.socket, SocketStatus.ERROR, false);
- } else {
- attachment.doneInline = true;
- attachment.error = true;
- }
- }
- };
-
- public SendfileState processSendfile(Nio2SocketWrapper socket) {
-
- // Configure the send file data
- SendfileData data = socket.getSendfileData();
- if (data.fchannel == null || !data.fchannel.isOpen()) {
- java.nio.file.Path path = new File(data.fileName).toPath();
- try {
- data.fchannel = java.nio.channels.FileChannel
- .open(path, StandardOpenOption.READ).position(data.pos);
- } catch (IOException e) {
- return SendfileState.ERROR;
- }
- }
- socket.getSocket().getBufHandler().configureWriteBufferForWrite();
- ByteBuffer buffer = socket.getSocket().getBufHandler().getWriteBuffer();
- int nRead = -1;
- try {
- nRead = data.fchannel.read(buffer);
- } catch (IOException e1) {
- return SendfileState.ERROR;
- }
-
- if (nRead >= 0) {
- data.socket = socket;
- data.buffer = buffer;
- data.length -= nRead;
- socket.getSocket().getBufHandler().configureWriteBufferForRead();
- Nio2Endpoint.startInline();
- socket.getSocket().write(buffer, socket.getNio2WriteTimeout(), TimeUnit.MILLISECONDS,
- data, sendfile);
- Nio2Endpoint.endInline();
- if (data.doneInline) {
- if (data.error) {
- return SendfileState.ERROR;
- } else {
- return SendfileState.DONE;
- }
- } else {
- return SendfileState.PENDING;
- }
- } else {
- return SendfileState.ERROR;
- }
- }
// ---------------------------------------------- SocketProcessor Inner Class
/**
@@ -1697,10 +1689,8 @@ public class Nio2Endpoint extends Abstra
* SendfileData class.
*/
public static class SendfileData extends SendfileDataBase {
- protected FileChannel fchannel;
+ private FileChannel fchannel;
// Internal use only
- private Nio2SocketWrapper socket;
- private ByteBuffer buffer;
private boolean doneInline = false;
private boolean error = false;
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org