Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Wilkins2015-07-23 01:32:28 +0000
committerGreg Wilkins2015-07-23 01:32:28 +0000
commitac8316756c53e7c2be8b81fa1ecb4f35dabd576e (patch)
treea8d66a214e53b3d12f211e467f9b47ddbad4264b
parent30a99ddcf403e0dc20e2d723b6cc71359691c517 (diff)
downloadorg.eclipse.jetty.project-ac8316756c53e7c2be8b81fa1ecb4f35dabd576e.tar.gz
org.eclipse.jetty.project-ac8316756c53e7c2be8b81fa1ecb4f35dabd576e.tar.xz
org.eclipse.jetty.project-ac8316756c53e7c2be8b81fa1ecb4f35dabd576e.zip
473322 - GatherWrite limit handling
-rw-r--r--jetty-io/src/test/java/org/eclipse/jetty/io/IOTest.java36
-rw-r--r--jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AfterContentTransformer.java9
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/IO.java53
3 files changed, 95 insertions, 3 deletions
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/IOTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/IOTest.java
index 81bf8be1cb..573d1b077c 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/IOTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/IOTest.java
@@ -25,6 +25,7 @@ import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
@@ -33,13 +34,17 @@ import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
+import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
+import java.nio.file.StandardOpenOption;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import org.eclipse.jetty.io.ClientConnectionFactory.Helper;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.OS;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.IO;
@@ -452,4 +457,35 @@ public class IOTest
Assert.assertEquals(ByteBuffer.wrap(data), read);
}
+
+ @Test
+ public void testGatherWrite() throws Exception
+ {
+ File dir = MavenTestingUtils.getTargetTestingDir();
+ if (!dir.exists())
+ dir.mkdir();
+
+ File file = File.createTempFile("test",".txt",dir);
+ file.deleteOnExit();
+ FileChannel out = FileChannel.open(file.toPath(),
+ StandardOpenOption.CREATE,
+ StandardOpenOption.READ,
+ StandardOpenOption.WRITE,
+ StandardOpenOption.DELETE_ON_CLOSE);
+
+ ByteBuffer[] buffers = new ByteBuffer[4096];
+ long expected=0;
+ for (int i=0;i<buffers.length;i++)
+ {
+ buffers[i]=BufferUtil.toBuffer(i);
+ expected+=buffers[i].remaining();
+ }
+
+ long wrote = IO.write(out,buffers,0,buffers.length);
+
+ assertEquals(expected,wrote);
+
+ for (int i=0;i<buffers.length;i++)
+ assertEquals(0,buffers[i].remaining());
+ }
}
diff --git a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AfterContentTransformer.java b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AfterContentTransformer.java
index e34aed18f0..b0b919c4e5 100644
--- a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AfterContentTransformer.java
+++ b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AfterContentTransformer.java
@@ -33,6 +33,7 @@ import java.nio.file.attribute.FileAttribute;
import java.util.ArrayList;
import java.util.List;
+import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.component.Destroyable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -249,8 +250,9 @@ public abstract class AfterContentTransformer implements AsyncMiddleManServlet.C
int size = sourceBuffers.size();
if (size > 0)
{
- inputFile.write(sourceBuffers.toArray(new ByteBuffer[size]));
+ ByteBuffer[] buffers = sourceBuffers.toArray(new ByteBuffer[size]);
sourceBuffers.clear();
+ IO.write(inputFile,buffers,0,buffers.length);
}
}
inputFile.write(input);
@@ -421,6 +423,7 @@ public abstract class AfterContentTransformer implements AsyncMiddleManServlet.C
return stream;
}
+
private void overflow(ByteBuffer output) throws IOException
{
if (outputFile == null)
@@ -434,8 +437,10 @@ public abstract class AfterContentTransformer implements AsyncMiddleManServlet.C
int size = sinkBuffers.size();
if (size > 0)
{
- outputFile.write(sinkBuffers.toArray(new ByteBuffer[size]));
+ ByteBuffer[] buffers = sinkBuffers.toArray(new ByteBuffer[size]);
sinkBuffers.clear();
+
+ IO.write(outputFile,buffers,0,buffers.length);
}
}
outputFile.write(output);
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/IO.java b/jetty-util/src/main/java/org/eclipse/jetty/util/IO.java
index 6a0032a874..ead3793330 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/IO.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/IO.java
@@ -29,6 +29,9 @@ import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.GatheringByteChannel;
import java.nio.charset.Charset;
import org.eclipse.jetty.util.log.Log;
@@ -366,7 +369,8 @@ public class IO
{
if (writer != null)
writer.close();
- } catch (IOException e)
+ }
+ catch (IOException e)
{
LOG.ignore(e);
}
@@ -380,6 +384,52 @@ public class IO
copy(in,bout);
return bout.toByteArray();
}
+
+ /* ------------------------------------------------------------ */
+ /**
+ * A gathering write utility wrapper.
+ * <p>This method wraps a gather write with a loop that handles the limitations of some operating systems that
+ * have a limit on the number of buffers written. The method loops on the write until either all the content
+ * is written or no progress is made.
+ * @param out The GatheringgByteChannel to write to
+ * @param buffers The buffers to write
+ * @param offset The offset into the buffers array
+ * @param length The length in buffers to write
+ * @return The total bytes written
+ * @throws IOException
+ */
+ public static long write(GatheringByteChannel out, ByteBuffer[] buffers, int offset, int length) throws IOException
+ {
+ long total=0;
+ write: while (length>0)
+ {
+ // Write as much as we can
+ long wrote=out.write(buffers,offset,length);
+
+ // If we can't write any more, give up
+ if (wrote==0)
+ break;
+
+ // count the total
+ total+=wrote;
+
+ // Look for unwritten content
+ for (int i=offset;i<buffers.length;i++)
+ {
+ if (buffers[i].hasRemaining())
+ {
+ // loop with new offset and length;
+ length=length-(i-offset);
+ offset=i;
+ continue write;
+ }
+ }
+ length=0;
+ }
+
+ return total;
+ }
+
/* ------------------------------------------------------------ */
/**
@@ -487,6 +537,7 @@ public class IO
}
private static NullWrite __nullWriter = new NullWrite();
private static PrintWriter __nullPrintWriter = new PrintWriter(__nullWriter);
+
}

Back to the top