Skip to content

SearchableSnapshotIndexInput should read all bytes #52199

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

Merged
merged 5 commits into from
Feb 12, 2020

Conversation

tlrx
Copy link
Member

@tlrx tlrx commented Feb 11, 2020

This pull request fixes a bug in SearchableSnapshotIndexInput which does not use the InputStream.read(byte[], int, int) method correctly.

The javadoc indicates that:

An attempt is made to read as many as len bytes, but a smaller number may be read.

Consequently, SearchableSnapshotIndexInput should try to read more bytes when a first reading operation has not brought back all the requested bytes.

@tlrx tlrx added >bug :Distributed Coordination/Snapshot/Restore Anything directly related to the `_snapshot/*` APIs labels Feb 11, 2020
@tlrx tlrx requested a review from DaveCTurner February 11, 2020 13:18
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-distributed (:Distributed/Snapshot/Restore)

@DaveCTurner
Copy link
Contributor

D'oh, of course. Change looks good, but can we engineer a test that fails because of this bug too?

@tlrx
Copy link
Member Author

tlrx commented Feb 11, 2020

@DaveCTurner the bug was here since the beginning and passed all reviews. I'm just happy that adding S3 integration tests caught this.

but can we engineer a test that fails because of this bug too?

Sure, I should have added one, just doing ten things at a time 😓

I pushed 4de4f81 which randomized how read bytes operations are served. I did not add a specific test but we already have assertions, intensive randomized read tests and we'll soon have integration tests so I think we're good. Unless you think otherwise?

Copy link
Contributor

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a couple more comments.

offset + optimizedReadSize + directReadSize,
length - optimizedReadSize - directReadSize);
if (read == -1) {
break;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means we hit the end of the file, which I think is unexpected. In tests the assertion below will fail; in production we will proceed even though some of the buffer contains its old contents, which would be bad. I think instead we should throw an EOFException here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think instead we should throw an EOFException here.

I pushed e06a94b

assert read <= length : read + " vs " + length;
pos += read;
return read;
int totalRead = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we extract a method to do this? The two changes to this file look very similar.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, done in e06a94b

@tlrx tlrx requested a review from DaveCTurner February 11, 2020 14:27
@tlrx
Copy link
Member Author

tlrx commented Feb 11, 2020

@DaveCTurner Thanks for your review. I've applied your feedback, would you mind to have another look?

@@ -276,7 +296,7 @@ boolean canContinueSequentialRead(int part, long pos) {

int read(byte[] b, int offset, int length) throws IOException {
assert this.pos < maxPos : "should not try and read from a fully-read stream";
int read = inputStream.read(b, offset, length);
final int read = readFully(inputStream, b, offset, length, () -> {});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering whether we should throw an EOFException if this hits EOF too. Do we need to behave differently here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh no I get it now, we might use this to read past the end of a stream that we previously opened. Never mind.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@DaveCTurner DaveCTurner dismissed their stale review February 11, 2020 15:45

Changes addressed

Copy link
Contributor

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@tlrx
Copy link
Member Author

tlrx commented Feb 12, 2020

Waiting for #52258 to be merged first.

@tlrx tlrx merged commit 957a7ae into elastic:feature/searchable-snapshots Feb 12, 2020
@tlrx
Copy link
Member Author

tlrx commented Feb 12, 2020

Thanks David

@tlrx tlrx deleted the S3RetryingInputStream branch February 12, 2020 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>bug :Distributed Coordination/Snapshot/Restore Anything directly related to the `_snapshot/*` APIs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants