-
Notifications
You must be signed in to change notification settings - Fork 9.1k
HADOOP-16852: Report read-ahead error back #1898
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
ace7311
5e29d12
5870238
1cb20db
dbf0254
4ba43ef
772c275
035fa7a
0a83ffe
52fba32
58ac701
5d1e427
08c0723
669f3c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,12 +21,15 @@ | |
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
| import java.io.IOException; | ||
| import java.util.Collection; | ||
| import java.util.LinkedList; | ||
| import java.util.Queue; | ||
| import java.util.Stack; | ||
| import java.util.concurrent.CountDownLatch; | ||
|
|
||
| import com.google.common.annotations.VisibleForTesting; | ||
|
|
||
| /** | ||
| * The Read Buffer Manager for Rest AbfsClient. | ||
| */ | ||
|
|
@@ -141,7 +144,8 @@ void queueReadAhead(final AbfsInputStream stream, final long requestedOffset, fi | |
| * @param buffer the buffer to read data into. Note that the buffer will be written into from offset 0. | ||
| * @return the number of bytes read | ||
snvijaya marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| */ | ||
| int getBlock(final AbfsInputStream stream, final long position, final int length, final byte[] buffer) { | ||
| int getBlock(final AbfsInputStream stream, final long position, final int length, final byte[] buffer) | ||
| throws IOException { | ||
| // not synchronized, so have to be careful with locking | ||
| if (LOGGER.isTraceEnabled()) { | ||
| LOGGER.trace("getBlock for file {} position {} thread {}", | ||
|
|
@@ -253,7 +257,12 @@ private synchronized boolean tryEvict() { | |
| } | ||
|
|
||
| private boolean evict(final ReadBuffer buf) { | ||
| freeList.push(buf.getBufferindex()); | ||
| // As failed ReadBuffers (bufferIndx = -1) are saved in completedReadList, | ||
| // avoid adding it to freeList. | ||
| if (buf.getBufferindex() != -1) { | ||
| freeList.push(buf.getBufferindex()); | ||
| } | ||
|
Comment on lines
+261
to
+265
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @snvijaya There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its set to -1 when read fails. You will find the diff for this in ReadBuffer.java line 110. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @snvijaya |
||
|
|
||
| completedReadList.remove(buf); | ||
| if (LOGGER.isTraceEnabled()) { | ||
| LOGGER.trace("Evicting buffer idx {}; was used for file {} offset {} length {}", | ||
|
|
@@ -289,6 +298,27 @@ private ReadBuffer getFromList(final Collection<ReadBuffer> list, final AbfsInpu | |
| return null; | ||
| } | ||
|
|
||
| /** | ||
| * Returns buffers that failed or passed from completed queue | ||
steveloughran marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| * @param stream | ||
| * @param requestedOffset | ||
| * @return | ||
| */ | ||
| private ReadBuffer getBufferFromCompletedQueue(final AbfsInputStream stream, final long requestedOffset) { | ||
| for (ReadBuffer buffer : completedReadList) { | ||
| // Buffer is returned if the requestedOffset is at or above buffer's | ||
| // offset but less than buffer's length or the actual requestedLength | ||
| if ((buffer.getStream() == stream) | ||
| && (requestedOffset >= buffer.getOffset()) | ||
| && ((requestedOffset < buffer.getOffset() + buffer.getLength()) | ||
steveloughran marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| || (requestedOffset < buffer.getOffset() + buffer.getRequestedLength()))) { | ||
| return buffer; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| private void clearFromReadAheadQueue(final AbfsInputStream stream, final long requestedOffset) { | ||
| ReadBuffer buffer = getFromList(readAheadQueue, stream, requestedOffset); | ||
| if (buffer != null) { | ||
|
|
@@ -299,11 +329,28 @@ private void clearFromReadAheadQueue(final AbfsInputStream stream, final long re | |
| } | ||
|
|
||
| private int getBlockFromCompletedQueue(final AbfsInputStream stream, final long position, final int length, | ||
| final byte[] buffer) { | ||
| ReadBuffer buf = getFromList(completedReadList, stream, position); | ||
| if (buf == null || position >= buf.getOffset() + buf.getLength()) { | ||
| final byte[] buffer) throws IOException { | ||
| ReadBuffer buf = getBufferFromCompletedQueue(stream, position); | ||
|
|
||
| if (buf == null) { | ||
| return 0; | ||
| } | ||
|
|
||
| if (buf.getStatus() == ReadBufferStatus.READ_FAILED) { | ||
| // To prevent new read requests to fail due to old read-ahead attempts, | ||
| // return exception only from buffers that failed within last THRESHOLD_AGE_MILLISECONDS | ||
| if ((currentTimeMillis() - (buf.getTimeStamp()) < THRESHOLD_AGE_MILLISECONDS)) { | ||
DadanielZ marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| throw buf.getErrException(); | ||
| } else { | ||
| return 0; | ||
| } | ||
| } | ||
|
|
||
| if ((buf.getStatus() != ReadBufferStatus.AVAILABLE) | ||
| || (position >= buf.getOffset() + buf.getLength())) { | ||
| return 0; | ||
| } | ||
|
|
||
| int cursor = (int) (position - buf.getOffset()); | ||
| int availableLengthInBuffer = buf.getLength() - cursor; | ||
| int lengthToCopy = Math.min(length, availableLengthInBuffer); | ||
|
|
@@ -368,14 +415,18 @@ void doneReading(final ReadBuffer buffer, final ReadBufferStatus result, final i | |
| inProgressList.remove(buffer); | ||
| if (result == ReadBufferStatus.AVAILABLE && bytesActuallyRead > 0) { | ||
| buffer.setStatus(ReadBufferStatus.AVAILABLE); | ||
| buffer.setTimeStamp(currentTimeMillis()); | ||
| buffer.setLength(bytesActuallyRead); | ||
| completedReadList.add(buffer); | ||
| } else { | ||
| freeList.push(buffer.getBufferindex()); | ||
| // buffer should go out of scope after the end of the calling method in ReadBufferWorker, and eligible for GC | ||
| // buffer will be deleted as per the eviction policy. | ||
| } | ||
|
|
||
| buffer.setStatus(result); | ||
| buffer.setTimeStamp(currentTimeMillis()); | ||
| completedReadList.add(buffer); | ||
| } | ||
|
|
||
| //outside the synchronized, since anyone receiving a wake-up from the latch must see safe-published results | ||
| buffer.getLatch().countDown(); // wake up waiting threads (if any) | ||
| } | ||
|
|
@@ -392,4 +443,19 @@ void doneReading(final ReadBuffer buffer, final ReadBufferStatus result, final i | |
| private long currentTimeMillis() { | ||
| return System.nanoTime() / 1000 / 1000; | ||
| } | ||
|
|
||
| @VisibleForTesting | ||
| int getThreshold_age_milliseconds() { | ||
| return THRESHOLD_AGE_MILLISECONDS; | ||
| } | ||
|
|
||
| @VisibleForTesting | ||
| int getCompletedReadListSize() { | ||
| return completedReadList.size(); | ||
| } | ||
|
|
||
| @VisibleForTesting | ||
| void callTryEvict() { | ||
| tryEvict(); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.