diff --git a/hadoop-common-project/hadoop-common/src/site/markdown/filesystem/fsdatainputstream.md b/hadoop-common-project/hadoop-common/src/site/markdown/filesystem/fsdatainputstream.md
index b8f9e87e66..090696483b 100644
--- a/hadoop-common-project/hadoop-common/src/site/markdown/filesystem/fsdatainputstream.md
+++ b/hadoop-common-project/hadoop-common/src/site/markdown/filesystem/fsdatainputstream.md
@@ -119,59 +119,6 @@ Return the data at the current position.
else
result = -1
-### `InputStream.available()`
-
-Returns the number of bytes "estimated" to be readable on a stream before `read()`
-blocks on any IO (i.e. the thread is potentially suspended for some time).
-
-That is: for all values `v` returned by `available()`, `read(buffer, 0, v)`
-is should not block.
-
-#### Postconditions
-
-```python
-if len(data) == 0:
- result = 0
-
-elif pos >= len(data):
- result = 0
-
-else:
- d = "the amount of data known to be already buffered/cached locally"
- result = min(1, d) # optional but recommended: see below.
-```
-
-As `0` is a number which is always meets this condition, it is nominally
-possible for an implementation to simply return `0`. However, this is not
-considered useful, and some applications/libraries expect a positive number.
-
-#### The GZip problem.
-
-[JDK-7036144](http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7036144),
-"GZIPInputStream readTrailer uses faulty available() test for end-of-stream"
-discusses how the JDK's GZip code it uses `available()` to detect an EOF,
-in a loop similar to the the following
-
-```java
-while(instream.available()) {
- process(instream.read());
-}
-```
-
-The correct loop would have been:
-
-```java
-int r;
-while((r=instream.read()) >= 0) {
- process(r);
-}
-```
-
-If `available()` ever returns 0, then the gzip loop halts prematurely.
-
-For this reason, implementations *should* return a value >=1, even
-if it breaks that requirement of `available()` returning the amount guaranteed
-not to block on reads.
### `InputStream.read(buffer[], offset, length)`
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/AbstractContractSeekTest.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/AbstractContractSeekTest.java
index db3691611b..ca8e4a053b 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/AbstractContractSeekTest.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/AbstractContractSeekTest.java
@@ -32,7 +32,6 @@
import java.io.IOException;
import java.util.Random;
-import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.IO_FILE_BUFFER_SIZE_KEY;
import static org.apache.hadoop.fs.contract.ContractTestUtils.createFile;
import static org.apache.hadoop.fs.contract.ContractTestUtils.dataset;
import static org.apache.hadoop.fs.contract.ContractTestUtils.skip;
@@ -100,18 +99,14 @@ public void testSeekZeroByteFile() throws Throwable {
describe("seek and read a 0 byte file");
instream = getFileSystem().open(zeroByteFile);
assertEquals(0, instream.getPos());
- assertAvailableIsZero(instream);
//expect initial read to fai;
int result = instream.read();
assertMinusOne("initial byte read", result);
- assertAvailableIsZero(instream);
byte[] buffer = new byte[1];
//expect that seek to 0 works
instream.seek(0);
- assertAvailableIsZero(instream);
//reread, expect same exception
result = instream.read();
- assertAvailableIsZero(instream);
assertMinusOne("post-seek byte read", result);
result = instream.read(buffer, 0, 1);
assertMinusOne("post-seek buffer read", result);
@@ -137,8 +132,8 @@ public void testBlockReadZeroByteFile() throws Throwable {
@Test
public void testSeekReadClosedFile() throws Throwable {
instream = getFileSystem().open(smallSeekFile);
- getLogger().debug("Stream is of type {}",
- instream.getClass().getCanonicalName());
+ getLogger().debug(
+ "Stream is of type " + instream.getClass().getCanonicalName());
instream.close();
try {
instream.seek(0);
@@ -173,26 +168,10 @@ public void testSeekReadClosedFile() throws Throwable {
try {
long offset = instream.getPos();
} catch (IOException e) {
- // it is valid to raise error here; but the test is applied to make
+ // its valid to raise error here; but the test is applied to make
// sure there's no other exception like an NPE.
}
- // a closed stream should either fail or return 0 bytes.
- try {
- int a = instream.available();
- LOG.info("available() returns a value on a closed file: {}", a);
- assertAvailableIsZero(instream);
- } catch (IOException | IllegalStateException expected) {
- // expected
- }
- // a closed stream should either fail or return 0 bytes.
- try {
- int a = instream.available();
- LOG.info("available() returns a value on a closed file: {}", a);
- assertAvailableIsZero(instream);
- } catch (IOException | IllegalStateException expected) {
- // expected
- }
//and close again
instream.close();
}
@@ -226,7 +205,6 @@ public void testSeekFile() throws Throwable {
//expect that seek to 0 works
instream.seek(0);
int result = instream.read();
- assertAvailableIsPositive(instream);
assertEquals(0, result);
assertEquals(1, instream.read());
assertEquals(2, instream.getPos());
@@ -248,24 +226,13 @@ public void testSeekAndReadPastEndOfFile() throws Throwable {
//go just before the end
instream.seek(TEST_FILE_LEN - 2);
assertTrue("Premature EOF", instream.read() != -1);
- assertAvailableIsPositive(instream);
assertTrue("Premature EOF", instream.read() != -1);
- checkAvailabilityAtEOF();
assertMinusOne("read past end of file", instream.read());
}
- /**
- * This can be overridden if a filesystem always returns 01
- * @throws IOException
- */
- protected void checkAvailabilityAtEOF() throws IOException {
- assertAvailableIsZero(instream);
- }
-
@Test
public void testSeekPastEndOfFileThenReseekAndRead() throws Throwable {
- describe("do a seek past the EOF, " +
- "then verify the stream recovers");
+ describe("do a seek past the EOF, then verify the stream recovers");
instream = getFileSystem().open(smallSeekFile);
//go just before the end. This may or may not fail; it may be delayed until the
//read
@@ -294,7 +261,6 @@ public void testSeekPastEndOfFileThenReseekAndRead() throws Throwable {
//now go back and try to read from a valid point in the file
instream.seek(1);
assertTrue("Premature EOF", instream.read() != -1);
- assertAvailableIsPositive(instream);
}
/**
@@ -312,7 +278,6 @@ public void testSeekBigFile() throws Throwable {
//expect that seek to 0 works
instream.seek(0);
int result = instream.read();
- assertAvailableIsPositive(instream);
assertEquals(0, result);
assertEquals(1, instream.read());
assertEquals(2, instream.read());
@@ -331,7 +296,6 @@ public void testSeekBigFile() throws Throwable {
instream.seek(0);
assertEquals(0, instream.getPos());
instream.read();
- assertAvailableIsPositive(instream);
assertEquals(1, instream.getPos());
byte[] buf = new byte[80 * 1024];
instream.readFully(1, buf, 0, buf.length);
@@ -350,7 +314,7 @@ public void testPositionedBulkReadDoesntChangePosition() throws Throwable {
instream.seek(39999);
assertTrue(-1 != instream.read());
assertEquals(40000, instream.getPos());
- assertAvailableIsPositive(instream);
+
int v = 256;
byte[] readBuffer = new byte[v];
assertEquals(v, instream.read(128, readBuffer, 0, v));
@@ -358,7 +322,6 @@ public void testPositionedBulkReadDoesntChangePosition() throws Throwable {
assertEquals(40000, instream.getPos());
//content is the same too
assertEquals("@40000", block[40000], (byte) instream.read());
- assertAvailableIsPositive(instream);
//now verify the picked up data
for (int i = 0; i < 256; i++) {
assertEquals("@" + i, block[i + 128], readBuffer[i]);
@@ -413,7 +376,6 @@ public void testReadFullyZeroByteFile() throws Throwable {
assertEquals(0, instream.getPos());
byte[] buffer = new byte[1];
instream.readFully(0, buffer, 0, 0);
- assertAvailableIsZero(instream);
assertEquals(0, instream.getPos());
// seek to 0 read 0 bytes from it
instream.seek(0);
@@ -589,9 +551,7 @@ public void testReadSmallFile() throws Throwable {
fail("Expected an exception, got " + r);
} catch (EOFException e) {
handleExpectedException(e);
- } catch (IOException
- | IllegalArgumentException
- | IndexOutOfBoundsException e) {
+ } catch (IOException | IllegalArgumentException | IndexOutOfBoundsException e) {
handleRelaxedException("read() with a negative position ",
"EOFException",
e);
@@ -627,29 +587,6 @@ public void testReadAtExactEOF() throws Throwable {
instream = getFileSystem().open(smallSeekFile);
instream.seek(TEST_FILE_LEN -1);
assertTrue("read at last byte", instream.read() > 0);
- assertAvailableIsZero(instream);
assertEquals("read just past EOF", -1, instream.read());
}
-
- /**
- * Assert that the number of bytes available is zero.
- * @param in input stream
- */
- protected static void assertAvailableIsZero(FSDataInputStream in)
- throws IOException {
- assertEquals("stream.available() should be zero",
- 0, in.available());
- }
-
- /**
- * Assert that the number of bytes available is greater than zero.
- * @param in input stream
- */
- protected static void assertAvailableIsPositive(FSDataInputStream in)
- throws IOException {
- int available = in.available();
- assertTrue("stream.available() should be positive but is "
- + available,
- available > 0);
- }
}
diff --git a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AInputStream.java b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AInputStream.java
index 8aac868853..c92a85ea57 100644
--- a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AInputStream.java
+++ b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AInputStream.java
@@ -218,7 +218,7 @@ private synchronized void reopen(String reason, long targetPos, long length,
}
@Override
- public synchronized long getPos() {
+ public synchronized long getPos() throws IOException {
return (nextReadPos < 0) ? 0 : nextReadPos;
}
@@ -620,26 +620,15 @@ public synchronized boolean resetConnection() throws IOException {
return isObjectStreamOpen();
}
- /**
- * Return the number of bytes available.
- * If the inner stream is closed, the value is 1 for consistency
- * with S3ObjectStream -and so address the GZip bug
- * http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7036144 .
- * If the stream is open, then it is the amount returned by the
- * wrapped stream.
- * @return a value greater than or equal to zero.
- * @throws IOException IO failure.
- */
@Override
public synchronized int available() throws IOException {
checkNotClosed();
- if (contentLength == 0 || (nextReadPos >= contentLength)) {
- return 0;
- }
- return wrappedStream == null
- ? 1
- : wrappedStream.available();
+ long remaining = remainingInFile();
+ if (remaining > Integer.MAX_VALUE) {
+ return Integer.MAX_VALUE;
+ }
+ return (int)remaining;
}
/**
@@ -648,8 +637,8 @@ public synchronized int available() throws IOException {
*/
@InterfaceAudience.Private
@InterfaceStability.Unstable
- public synchronized long remainingInFile() throws IOException {
- return contentLength - getPos();
+ public synchronized long remainingInFile() {
+ return this.contentLength - this.pos;
}
/**
@@ -660,7 +649,7 @@ public synchronized long remainingInFile() throws IOException {
@InterfaceAudience.Private
@InterfaceStability.Unstable
public synchronized long remainingInCurrentRequest() {
- return contentRangeFinish - getPos();
+ return this.contentRangeFinish - this.pos;
}
@InterfaceAudience.Private
diff --git a/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/contract/s3a/ITestS3AContractSeek.java b/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/contract/s3a/ITestS3AContractSeek.java
index 3513d0179c..9332621d11 100644
--- a/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/contract/s3a/ITestS3AContractSeek.java
+++ b/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/contract/s3a/ITestS3AContractSeek.java
@@ -80,7 +80,7 @@ public class ITestS3AContractSeek extends AbstractContractSeekTest {
* which S3A Supports.
* @return a list of seek policies to test.
*/
- @Parameterized.Parameters(name = "{0}-{1}")
+ @Parameterized.Parameters
public static Collection