6878369: (ch) AsynchronousSocketChannel read/write methods that specify timeouts should not throw IAE

Reviewed-by: forax
This commit is contained in:
Alan Bateman 2010-11-24 09:51:31 +00:00
parent fac39410b5
commit b6b4b5086c
3 changed files with 65 additions and 61 deletions

View File

@ -110,7 +110,8 @@ import java.nio.ByteBuffer;
* state of the {@link ByteBuffer}, or the sequence of buffers, for the I/O
* operation is not defined. Buffers should be discarded or at least care must
* be taken to ensure that the buffers are not accessed while the channel remains
* open.
* open. All methods that accept timeout parameters treat values less than or
* equal to zero to mean that the I/O operation does not timeout.
*
* @since 1.7
*/
@ -367,7 +368,7 @@ public abstract class AsynchronousSocketChannel
* @param dst
* The buffer into which bytes are to be transferred
* @param timeout
* The timeout, or {@code 0L} for no timeout
* The maximum time for the I/O operation to complete
* @param unit
* The time unit of the {@code timeout} argument
* @param attachment
@ -376,8 +377,7 @@ public abstract class AsynchronousSocketChannel
* The handler for consuming the result
*
* @throws IllegalArgumentException
* If the {@code timeout} parameter is negative or the buffer is
* read-only
* If the buffer is read-only
* @throws ReadPendingException
* If a read operation is already in progress on this channel
* @throws NotYetConnectedException
@ -471,7 +471,7 @@ public abstract class AsynchronousSocketChannel
* The maximum number of buffers to be accessed; must be non-negative
* and no larger than {@code dsts.length - offset}
* @param timeout
* The timeout, or {@code 0L} for no timeout
* The maximum time for the I/O operation to complete
* @param unit
* The time unit of the {@code timeout} argument
* @param attachment
@ -483,8 +483,7 @@ public abstract class AsynchronousSocketChannel
* If the pre-conditions for the {@code offset} and {@code length}
* parameter aren't met
* @throws IllegalArgumentException
* If the {@code timeout} parameter is negative, or a buffer is
* read-only
* If the buffer is read-only
* @throws ReadPendingException
* If a read operation is already in progress on this channel
* @throws NotYetConnectedException
@ -524,7 +523,7 @@ public abstract class AsynchronousSocketChannel
* @param src
* The buffer from which bytes are to be retrieved
* @param timeout
* The timeout, or {@code 0L} for no timeout
* The maximum time for the I/O operation to complete
* @param unit
* The time unit of the {@code timeout} argument
* @param attachment
@ -532,8 +531,6 @@ public abstract class AsynchronousSocketChannel
* @param handler
* The handler for consuming the result
*
* @throws IllegalArgumentException
* If the {@code timeout} parameter is negative
* @throws WritePendingException
* If a write operation is already in progress on this channel
* @throws NotYetConnectedException
@ -623,7 +620,7 @@ public abstract class AsynchronousSocketChannel
* The maximum number of buffers to be accessed; must be non-negative
* and no larger than {@code srcs.length - offset}
* @param timeout
* The timeout, or {@code 0L} for no timeout
* The maximum time for the I/O operation to complete
* @param unit
* The time unit of the {@code timeout} argument
* @param attachment
@ -634,8 +631,6 @@ public abstract class AsynchronousSocketChannel
* @throws IndexOutOfBoundsException
* If the pre-conditions for the {@code offset} and {@code length}
* parameter aren't met
* @throws IllegalArgumentException
* If the {@code timeout} parameter is negative
* @throws WritePendingException
* If a write operation is already in progress on this channel
* @throws NotYetConnectedException

View File

@ -235,8 +235,6 @@ abstract class AsynchronousSocketChannelImpl
if (remoteAddress == null)
throw new NotYetConnectedException();
if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout");
boolean hasSpaceToRead = isScatteringRead || dst.hasRemaining();
boolean shutdown = false;
@ -342,8 +340,6 @@ abstract class AsynchronousSocketChannelImpl
if (isOpen()) {
if (remoteAddress == null)
throw new NotYetConnectedException();
if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout");
// check and update state
synchronized (writeLock) {
if (writeKilled)

View File

@ -22,7 +22,7 @@
*/
/* @test
* @bug 4607272 6842687
* @bug 4607272 6842687 6878369
* @summary Unit test for AsynchronousSocketChannel
* @run main/timeout=600 Basic
*/
@ -712,52 +712,57 @@ public class Basic {
}
static void testTimeout() throws Exception {
System.out.println("-- timeouts --");
testTimeout(Integer.MIN_VALUE, TimeUnit.SECONDS);
testTimeout(-1L, TimeUnit.SECONDS);
testTimeout(0L, TimeUnit.SECONDS);
testTimeout(2L, TimeUnit.SECONDS);
}
static void testTimeout(final long timeout, final TimeUnit unit) throws Exception {
Server server = new Server();
AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
ch.connect(server.address()).get();
System.out.println("-- timeout when reading --");
ByteBuffer dst = ByteBuffer.allocate(512);
final AtomicReference<Throwable> readException = new AtomicReference<Throwable>();
// this read should timeout
ch.read(dst, 3, TimeUnit.SECONDS, (Void)null,
new CompletionHandler<Integer,Void>()
{
// this read should timeout if value is > 0
ch.read(dst, timeout, unit, null, new CompletionHandler<Integer,Void>() {
public void completed(Integer result, Void att) {
throw new RuntimeException("Should not complete");
readException.set(new RuntimeException("Should not complete"));
}
public void failed(Throwable exc, Void att) {
readException.set(exc);
}
});
// wait for exception
while (readException.get() == null) {
Thread.sleep(100);
if (timeout > 0L) {
// wait for exception
while (readException.get() == null) {
Thread.sleep(100);
}
if (!(readException.get() instanceof InterruptedByTimeoutException))
throw new RuntimeException("InterruptedByTimeoutException expected");
// after a timeout then further reading should throw unspecified runtime exception
boolean exceptionThrown = false;
try {
ch.read(dst);
} catch (RuntimeException x) {
exceptionThrown = true;
}
if (!exceptionThrown)
throw new RuntimeException("RuntimeException expected after timeout.");
} else {
Thread.sleep(1000);
Throwable exc = readException.get();
if (exc != null)
throw new RuntimeException(exc);
}
if (!(readException.get() instanceof InterruptedByTimeoutException))
throw new RuntimeException("InterruptedByTimeoutException expected");
// after a timeout then further reading should throw unspecified runtime exception
boolean exceptionThrown = false;
try {
ch.read(dst);
} catch (RuntimeException x) {
exceptionThrown = true;
}
if (!exceptionThrown)
throw new RuntimeException("RuntimeException expected after timeout.");
System.out.println("-- timeout when writing --");
final AtomicReference<Throwable> writeException = new AtomicReference<Throwable>();
final long timeout = 5;
final TimeUnit unit = TimeUnit.SECONDS;
// write bytes to fill socket buffer
ch.write(genBuffer(), timeout, unit, ch,
new CompletionHandler<Integer,AsynchronousSocketChannel>()
@ -769,24 +774,32 @@ public class Basic {
writeException.set(exc);
}
});
if (timeout > 0) {
// wait for exception
while (writeException.get() == null) {
Thread.sleep(100);
}
if (!(writeException.get() instanceof InterruptedByTimeoutException))
throw new RuntimeException("InterruptedByTimeoutException expected");
// wait for exception
while (writeException.get() == null) {
Thread.sleep(100);
// after a timeout then further writing should throw unspecified runtime exception
boolean exceptionThrown = false;
try {
ch.write(genBuffer());
} catch (RuntimeException x) {
exceptionThrown = true;
}
if (!exceptionThrown)
throw new RuntimeException("RuntimeException expected after timeout.");
} else {
Thread.sleep(1000);
Throwable exc = writeException.get();
if (exc != null)
throw new RuntimeException(exc);
}
if (!(writeException.get() instanceof InterruptedByTimeoutException))
throw new RuntimeException("InterruptedByTimeoutException expected");
// after a timeout then further writing should throw unspecified runtime exception
exceptionThrown = false;
try {
ch.write(genBuffer());
} catch (RuntimeException x) {
exceptionThrown = true;
}
if (!exceptionThrown)
throw new RuntimeException("RuntimeException expected after timeout.");
// clean-up
server.accept().close();
ch.close();
server.close();
}