use of io.pravega.segmentstore.contracts.ReadResultEntryType.EndOfStreamSegment in project pravega by pravega.
the class PravegaRequestProcessor method handleReadResult.
/**
* Handles a readResult.
* If there are cached entries that can be returned without blocking only these are returned.
* Otherwise the call will request the data and setup a callback to return the data when it is available.
* If no data is available but it was detected that the Segment had been truncated beyond the current offset,
* an appropriate message is sent back over the connection.
*/
private void handleReadResult(ReadSegment request, ReadResult result) {
String segment = request.getSegment();
ArrayList<BufferView> cachedEntries = new ArrayList<>();
ReadResultEntry nonCachedEntry = collectCachedEntries(request.getOffset(), result, cachedEntries);
final String operation = "readSegment";
boolean truncated = nonCachedEntry != null && nonCachedEntry.getType() == Truncated;
boolean endOfSegment = nonCachedEntry != null && nonCachedEntry.getType() == EndOfStreamSegment;
boolean atTail = nonCachedEntry != null && nonCachedEntry.getType() == Future;
if (!cachedEntries.isEmpty() || endOfSegment) {
// We managed to collect some data. Send it.
ByteBuf data = toByteBuf(cachedEntries);
SegmentRead reply = new SegmentRead(segment, request.getOffset(), atTail, endOfSegment, data, request.getRequestId());
connection.send(reply);
this.statsRecorder.read(segment, reply.getData().readableBytes());
} else if (truncated) {
// We didn't collect any data, instead we determined that the current read offset was truncated.
// Determine the current Start Offset and send that back.
segmentStore.getStreamSegmentInfo(segment, TIMEOUT).thenAccept(info -> connection.send(new SegmentIsTruncated(request.getRequestId(), segment, info.getStartOffset(), EMPTY_STACK_TRACE, nonCachedEntry.getStreamSegmentOffset()))).exceptionally(e -> handleException(request.getRequestId(), segment, nonCachedEntry.getStreamSegmentOffset(), operation, wrapCancellationException(e)));
} else {
Preconditions.checkState(nonCachedEntry != null, "No ReadResultEntries returned from read!?");
nonCachedEntry.requestContent(TIMEOUT);
nonCachedEntry.getContent().thenAccept(contents -> {
ByteBuf data = toByteBuf(Collections.singletonList(contents));
SegmentRead reply = new SegmentRead(segment, nonCachedEntry.getStreamSegmentOffset(), atTail, endOfSegment, data, request.getRequestId());
connection.send(reply);
this.statsRecorder.read(segment, reply.getData().readableBytes());
}).exceptionally(exception -> {
Throwable e = Exceptions.unwrap(exception);
if (e instanceof StreamSegmentTruncatedException) {
// The Segment may have been truncated in Storage after we got this entry but before we managed
// to make a read. In that case, send the appropriate error back.
final String clientReplyStackTrace = replyWithStackTraceOnError ? e.getMessage() : EMPTY_STACK_TRACE;
connection.send(new SegmentIsTruncated(request.getRequestId(), segment, ((StreamSegmentTruncatedException) e).getStartOffset(), clientReplyStackTrace, nonCachedEntry.getStreamSegmentOffset()));
} else {
handleException(request.getRequestId(), segment, nonCachedEntry.getStreamSegmentOffset(), operation, wrapCancellationException(e));
}
return null;
}).exceptionally(e -> handleException(request.getRequestId(), segment, nonCachedEntry.getStreamSegmentOffset(), operation, wrapCancellationException(e)));
}
}
Aggregations