Skip to content
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

Better support for partial buffer reads/writes in translog infrastructure #6576

Closed
wants to merge 14 commits into from

Conversation

bleskes
Copy link
Contributor

@bleskes bleskes commented Jun 20, 2014

Some IO api can return after writing & reading only a part of the requested data. On these rare occasions, we should call the methods again to read/write the rest of the data. This has cause rare translog corruption while writing huge documents on Windows.

Closes #6441

PS. I'll add java docs to the new Channels util class, but wanted to start the review process.

…ture

Some IO api can return after writing & reading only a part of the requested data. On these rare occasions, we should call the methods again to read/write the rest of the data. This has cause rare translog corruption while writing  huge documents on Windows.

Closes elastic#6441
this.versionType = VersionType.fromValue(in.readByte());
}
} catch (ElasticsearchException e) {
throw new ElasticsearchException("failed to read [" + type + "][" + id + "]", e);
Copy link
Member

Choose a reason for hiding this comment

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

can we catch Throwable here since we add relevant info to wrap the exception? Also, can it be an IndexShard based exception, so we also capture the index and shard id?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed it to throwable, but I don't see where to get the index and shard id from here..

Copy link
Contributor

Choose a reason for hiding this comment

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

I disagee, see my other comment. Catching throwable is a big no-go, as it can hide Errors like OOM (even if you rethrow).

For this case, catching ElasticSearchException is better.

if (version >= 6) {
this.versionType = VersionType.fromValue(in.readByte());
}
} catch (Throwable t) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Cathcing Throwable is always a bad idea, because it also catches InterruptedException and Errors and this causes the interrupt status to be ignored later. It also hides stuff like OOM!!!
You should be more selective in catching those Exceptions, the only one that can happen here should be IllegalStateEx and IOExeption? So please, use a multi-catch!

@areek areek assigned rmuir and unassigned rmuir Jun 23, 2014
@bleskes
Copy link
Contributor Author

bleskes commented Jun 23, 2014

@rmuir @uschindler pushed another commit based on your feedback. Thx.

I still need to do the forbidden API.

this.versionType = VersionType.fromValue(in.readByte());
}
} catch (Exception e) {
if (e instanceof InterruptedException) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think InterruptedException is maybe not needed, because its checked and not in the signatures anywhere. But Exception is much better than Throwable. Thanks!

The main issue was: It hides OutOfMemoryError and this confuses users and makes reporting tools for JVM problems useless.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK. Thought we wanted to have it... removing the InterruptedException

@uschindler
Copy link
Contributor

Looks fine now. Should I retest?

@bleskes
Copy link
Contributor Author

bleskes commented Jun 23, 2014

Sure. Thx!!

On Mon, Jun 23, 2014 at 5:58 PM, Uwe Schindler notifications@github.com
wrote:

Looks fine now. Should I retest?

Reply to this email directly or view it on GitHub:
#6576 (comment)

@uschindler
Copy link
Contributor

OK, tested and works. I am still investigating about the while-loop: What happens if disk is full? Would Channel#write() then always return 0, so it will get endless loop?

As far as I remeber, the Javadocs say, that at least 1 byte is written. Have to validate! Otherwise a disk-full would produce an endless loop. At least with this patch we should also prevent translog corrumption with disk full, because it should throw exception!

@uschindler
Copy link
Contributor

I have no idea how to handle writes of 0 bytes... MAYBE you should do a test with a disk full (e.g. tmpfs with limited size).

Otherwise patch looks fine.

@bleskes
Copy link
Contributor Author

bleskes commented Jun 24, 2014

@uschindler the java docs say "A socket channel in non-blocking mode, for example, cannot write any more bytes than are free in the socket's output buffer." & "The number of bytes written, possibly zero"

I think this implies that an error is indicated by an exception and we should just retry upon 0 return value?

@uschindler
Copy link
Contributor

I think the main problem here is, that it is undefined. The Javadocs of FileChannel#read (more the interface docs @ http://docs.oracle.com/javase/7/docs/api/java/nio/channels/ReadableByteChannel.html) clearly state how it works: "It is guaranteed, however, that if a channel is in blocking mode and there is at least one byte remaining in the buffer then this method will block until at least one byte is read" - but nothing like that for write.

In Lucene's NIOFSDirectory we assert on exactly this behaviour when reading from the FileChannel (which is blocking).

Is the channel of the tranlog blocking or not?

I am just afraid that in some cases (especially for sockets), where nothing can be written, we wait in a spinning loop until the number of bytes is > 0.

import java.nio.channels.GatheringByteChannel;
import java.nio.channels.WritableByteChannel;

public abstract class Channels {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we have a real unittest for this class? I mean it's tested well but I'd love to have a dedicated test for that really hammers it.

Copy link
Contributor

Choose a reason for hiding this comment

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

can we make this class final with a default private ctor?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

final I get. Wondering why the default private ctor?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah - I get it :) final to prevent extending, private ctor to replace the abstract. Coming up.

@s1monw
Copy link
Contributor

s1monw commented Jun 24, 2014

I really think the channel API needs to go into forbidden APIs ...I also left some comments on the commit.

@s1monw s1monw removed the review label Jun 24, 2014
@bleskes
Copy link
Contributor Author

bleskes commented Jun 24, 2014

@s1monw thx. I still have a todo for this one to add the channel write/read methods to the forbidden API.

@s1monw s1monw removed the review label Jun 30, 2014
@uschindler
Copy link
Contributor

I agree with @s1monw: java.io.Closeable requires that close() must be idempotent. Otherwise patch looks fine.

…unting during failures in snapshot creation. Added double close protection in SimpleFsTranslogFile. Using scaledRandomIntBetween in tests
@bleskes
Copy link
Contributor Author

bleskes commented Jul 1, 2014

@s1monw I pushed another update.

@bleskes bleskes added the review label Jul 1, 2014
@s1monw
Copy link
Contributor

s1monw commented Jul 1, 2014

LGTM

@s1monw s1monw removed the review label Jul 1, 2014
bleskes added a commit that referenced this pull request Jul 1, 2014
…ture

Some IO api can return after writing & reading only a part of the requested data. On these rare occasions, we should call the methods again to read/write the rest of the data. This has cause rare translog corruption while writing huge documents on Windows.

Noteful parts of the commit:
- A new Channels class with utility methods for reading and writing to channels
- Writing or reading to channels is added to the forbidden API list
- Added locking to SimpleFsTranslogFile
- Removed FileChannelInputStream which was not used

Closes #6441 , #6576
@bleskes bleskes added the bug label Jul 1, 2014
bleskes added a commit that referenced this pull request Jul 1, 2014
…ture

Some IO api can return after writing & reading only a part of the requested data. On these rare occasions, we should call the methods again to read/write the rest of the data. This has cause rare translog corruption while writing huge documents on Windows.

Noteful parts of the commit:
- A new Channels class with utility methods for reading and writing to channels
- Writing or reading to channels is added to the forbidden API list
- Added locking to SimpleFsTranslogFile
- Removed FileChannelInputStream which was not used

Closes #6441 , #6576
@bleskes
Copy link
Contributor Author

bleskes commented Jul 1, 2014

Pushed this. Thx all for reviewing (back porting to 1.2 run into conflicts, I'll go through them later carefully and push it as well)

@bleskes bleskes closed this Jul 1, 2014
@uschindler
Copy link
Contributor

Thanks @bleskes! It was a pleasure to work with you, nice work, really!

bleskes added a commit that referenced this pull request Jul 2, 2014
…ture

Some IO api can return after writing & reading only a part of the requested data. On these rare occasions, we should call the methods again to read/write the rest of the data. This has cause rare translog corruption while writing huge documents on Windows.

Noteful parts of the commit:
- A new Channels class with utility methods for reading and writing to channels
- Writing or reading to channels is added to the forbidden API list
- Added locking to SimpleFsTranslogFile
- Removed FileChannelInputStream which was not used

Closes #6441 , #6576
@bleskes bleskes deleted the partial_reads_writes branch July 2, 2014 08:35
@bleskes bleskes changed the title Better support for partial buffer reads/writes in translog infrastructure [Translog] Better support for partial buffer reads/writes in translog infrastructure Jul 7, 2014
@clintongormley clintongormley changed the title [Translog] Better support for partial buffer reads/writes in translog infrastructure Internal: [Translog] Better support for partial buffer reads/writes in translog infrastructure Jul 9, 2014
@clintongormley clintongormley changed the title Internal: [Translog] Better support for partial buffer reads/writes in translog infrastructure Indexing: [Translog] Better support for partial buffer reads/writes in translog infrastructure Jul 16, 2014
@clintongormley clintongormley changed the title Indexing: [Translog] Better support for partial buffer reads/writes in translog infrastructure Better support for partial buffer reads/writes in translog infrastructure Jun 7, 2015
@SimplyWhiteMan
Copy link

does this update included in the version 1.2.1?

@bleskes
Copy link
Contributor Author

bleskes commented Jun 8, 2015

@SimplyWhiteMan it only made into 1.2.2 (see PR labels). Also, since 1.2.2 we have so many similar issues that I urge to upgrade to the 1.5.2 (or 1.6.0 coming soonish). Going 1.2.2 will be a bad idea...

mute pushed a commit to mute/elasticsearch that referenced this pull request Jul 29, 2015
…ture

Some IO api can return after writing & reading only a part of the requested data. On these rare occasions, we should call the methods again to read/write the rest of the data. This has cause rare translog corruption while writing huge documents on Windows.

Noteful parts of the commit:
- A new Channels class with utility methods for reading and writing to channels
- Writing or reading to channels is added to the forbidden API list
- Added locking to SimpleFsTranslogFile
- Removed FileChannelInputStream which was not used

Closes elastic#6441 , elastic#6576
@clintongormley clintongormley added :Distributed/Distributed A catch all label for anything in the Distributed Area. If you aren't sure, use this one. :Distributed/Engine Anything around managing Lucene and the Translog in an open shard. and removed :Translog :Distributed/Distributed A catch all label for anything in the Distributed Area. If you aren't sure, use this one. labels Feb 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>bug :Distributed/Engine Anything around managing Lucene and the Translog in an open shard. v1.2.2 v1.3.0 v2.0.0-beta1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ElasticsearchIllegalArgumentException No version type match
7 participants