Skip to content

Commit 79f8583

Browse files
committed
HDFS-15042 Add more tests for ByteBufferPositionedReadable.
Changes * Javadocs in ByteBufferPositionedReadable are a bit stricter. * switch to parameterized JUnit test runs for on/off heap buffers * factor put main assertions into higher level asserts New tests * negative offset for reads of actual/empty buffers * read position > EOF. * empty files * verify that interleaving simple reads/seeks work. Change-Id: I27294b15f7cad8e1b87150d9e9fac0623fc44c45
1 parent 4d22d1c commit 79f8583

File tree

5 files changed

+334
-94
lines changed

5 files changed

+334
-94
lines changed

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ByteBufferPositionedReadable.java

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,24 @@
2525
import org.apache.hadoop.classification.InterfaceStability;
2626

2727
/**
28+
* The javadocs for this interface follows RFC 2119 rules regarding the use of
29+
* MUST, MUST NOT, MAY, and SHALL.
30+
* <p>
2831
* Implementers of this interface provide a positioned read API that writes to a
2932
* {@link ByteBuffer} rather than a {@code byte[]}.
30-
*
33+
* <p>
34+
* <b>Thread safety</b>
35+
* <p>
36+
* These operations doe not change the current offset of a stream as returned
37+
* by {@link Seekable#getPos()} and MUST BE thread-safe.
38+
* Implementations MAY block other readers while one read operation
39+
* is in progress; this MAY include blocking <i>all</i> read() calls.
40+
* <p>
41+
* <b>Concurrent file access</b>
42+
* <p>
43+
* No guarantees are made as to when or whether changes made to a file
44+
* are visible to readers of this API reading the data through an already
45+
* open stream instance.
3146
* @see PositionedReadable
3247
* @see ByteBufferReadable
3348
*/
@@ -54,12 +69,11 @@ public interface ByteBufferPositionedReadable {
5469
* stream supports this interface, otherwise they might get a
5570
* {@link UnsupportedOperationException}.
5671
* <p>
57-
* Implementations should treat 0-length requests as legitimate, and must not
72+
* Implementations MUST treat 0-length requests as legitimate, and MUST NOT
5873
* signal an error upon their receipt.
59-
* <p>
60-
* This does not change the current offset of a file, and is thread-safe.
61-
*
62-
* @param position position within file
74+
* The {@code position} offset MUST BE zero or positive; if negative
75+
* an EOFException SHALL BE raised.
76+
* @param position position within stream. This MUST be &gt;=0.
6377
* @param buf the ByteBuffer to receive the results of the read operation.
6478
* @return the number of bytes read, possibly zero, or -1 if reached
6579
* end-of-stream
@@ -78,12 +92,23 @@ public interface ByteBufferPositionedReadable {
7892
* {@link #read(long, ByteBuffer)}, the difference is that this method is
7993
* guaranteed to read data until the {@link ByteBuffer} is full, or until
8094
* the end of the data stream is reached.
81-
*
82-
* @param position position within file
95+
* <p>
96+
* The {@code position} offset MUST BE zero or positive; if negative
97+
* an EOFException SHALL BE raised.
98+
* <p>
99+
* Implementations MUST treat 0-length requests as legitimate -and, and so
100+
* MUST NOT signal an error if the read position was valid.
101+
* For zero-byte reads, read position greater {@code getPos()} MAY be
102+
* considered valid; a negative position MUST always fail.
103+
* <p>
104+
* If the EOF was reached before the buffer was completely read -the
105+
* state of the buffer is undefined. It may be unchanged or it may be
106+
* partially or completely overwritten.
107+
* @param position position within stream. This must be &gt;=0.
83108
* @param buf the ByteBuffer to receive the results of the read operation.
84109
* @throws IOException if there is some error performing the read
85110
* @throws EOFException the end of the data was reached before
86-
* the read operation completed
111+
* the read operation completed, or the position value is negative.
87112
* @see #read(long, ByteBuffer)
88113
*/
89114
void readFully(long position, ByteBuffer buf) throws IOException;

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FSExceptionMessages.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ public class FSExceptionMessages {
3535
public static final String NEGATIVE_SEEK =
3636
"Cannot seek to a negative offset";
3737

38+
/**
39+
* Negative offset read forbidden : {@value}
40+
*/
41+
public static final String NEGATIVE_POSITION_READ =
42+
"Cannot read from a negative position";
43+
3844
/**
3945
* Seeks : {@value}
4046
*/

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/TestCryptoStreams.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545
import org.junit.BeforeClass;
4646
import org.junit.Test;
4747

48+
import static org.apache.hadoop.fs.FSExceptionMessages.CANNOT_SEEK_PAST_EOF;
49+
import static org.apache.hadoop.fs.FSExceptionMessages.EOF_IN_READ_FULLY;
50+
import static org.apache.hadoop.fs.FSExceptionMessages.NEGATIVE_POSITION_READ;
4851
import static org.apache.hadoop.fs.contract.ContractTestUtils.assertCapabilities;
4952

5053
public class TestCryptoStreams extends CryptoStreamsTestBase {
@@ -339,16 +342,16 @@ public void readFully(long position, ByteBuffer buf) throws IOException {
339342
}
340343

341344
if (position > length) {
342-
throw new IOException("Cannot read after EOF.");
345+
throw new EOFException(CANNOT_SEEK_PAST_EOF);
343346
}
344347
if (position < 0) {
345-
throw new IOException("Cannot read to negative offset.");
348+
throw new EOFException(NEGATIVE_POSITION_READ);
346349
}
347350

348351
checkStream();
349352

350353
if (position + buf.remaining() > length) {
351-
throw new EOFException("Reach the end of stream.");
354+
throw new EOFException(EOF_IN_READ_FULLY);
352355
}
353356

354357
buf.put(data, (int) position, buf.remaining());

hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/DFSInputStream.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292

9393
import javax.annotation.Nonnull;
9494

95+
import static org.apache.hadoop.fs.FSExceptionMessages.NEGATIVE_POSITION_READ;
9596
import static org.apache.hadoop.hdfs.util.IOUtilsClient.updateReadStatistics;
9697

9798
/****************************************************************
@@ -1718,6 +1719,9 @@ public int read(long position, final ByteBuffer buf) throws IOException {
17181719
@Override
17191720
public void readFully(long position, final ByteBuffer buf)
17201721
throws IOException {
1722+
if (position < 0) {
1723+
throw new EOFException(NEGATIVE_POSITION_READ);
1724+
}
17211725
int nread = 0;
17221726
while (buf.hasRemaining()) {
17231727
int nbytes = read(position + nread, buf);

0 commit comments

Comments
 (0)