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

HADOOP-17928. Syncable: S3A to warn and downgrade #3585

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2205,7 +2205,16 @@
</description>
</property>

<!-- Azure file system properties -->
<property>
<name>fs.s3a.downgrade.syncable.exceptions</name>
<value>true</value>
<description>
Warn but continue when applications use Syncable.hsync when writing
to S3A.
</description>
</property>

<!-- Azure file system properties -->
<property>
<name>fs.AbstractFileSystem.wasb.impl</name>
<value>org.apache.hadoop.fs.azure.Wasb</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ private Constants() {
* Value: {@value}.
*/
public static final boolean DOWNGRADE_SYNCABLE_EXCEPTIONS_DEFAULT =
false;
true;

/**
* The capacity of executor queues for operations other than block
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -924,30 +924,48 @@ connector isn't saving any data at all. The `Syncable` API, especially the
`hsync()` call, are critical for applications such as HBase to safely
persist data.

The S3A connector throws an `UnsupportedOperationException` when these API calls
are made, because the guarantees absolutely cannot be met: nothing is being flushed
or saved.
When configured to do so, the S3A connector throws an `UnsupportedOperationException`
when these API calls are made, because the API guarantees absolutely cannot be met:
_nothing is being flushed or saved_.

* Applications which intend to invoke the Syncable APIs call `hasCapability("hsync")` on
* Applications which intend to invoke the Syncable APIs should call `hasCapability("hsync")` on
the stream to see if they are supported.
* Or catch and downgrade `UnsupportedOperationException`.

These recommendations _apply to all filesystems_.
These recommendations _apply to all filesystems_.

To downgrade the S3A connector to simply warning of the use of
For consistency with other filesystems, S3A output streams
do not by default reject the `Syncable` calls -instead
they print a warning of its use.


The count of invocations of the two APIs are collected in the S3A filesystem
Statistics/IOStatistics and so their use can be monitored.

To switch the S3A connector to rejecting all use of
`hsync()` or `hflush()` calls, set the option
`fs.s3a.downgrade.syncable.exceptions` to true.
`fs.s3a.downgrade.syncable.exceptions` to `false`.

```xml
<property>
<name>fs.s3a.downgrade.syncable.exceptions</name>
<value>true</value>
<value>false</value>
</property>
```

The count of invocations of the two APIs are collected
in the S3A filesystem Statistics/IOStatistics and so
their use can be monitored.
Regardless of the setting, the `Syncable` API calls do not work.
Telling the store to *not* downgrade the calls is a way to
1. Prevent applications which require Syncable to work from being deployed
against S3.
2. Identify applications which are making the calls even though they don't
need to. These applications can then be fixed -something which may take
time.

Put differently: it is safest to disable downgrading syncable exceptions.
However, enabling the downgrade stops applications unintentionally using the API
from breaking.

*Tip*: try turning it on in staging environments to see what breaks.

### `RemoteFileChangedException` and read-during-overwrite

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ public void testCallingCloseAfterCallingAbort() throws Exception {
*/
@Test
public void testSyncableUnsupported() throws Exception {
final S3ABlockOutputStream.BlockOutputStreamBuilder
builder = mockS3ABuilder();
builder.withDowngradeSyncableExceptions(false);
stream = spy(new S3ABlockOutputStream(builder));
intercept(UnsupportedOperationException.class, () -> stream.hflush());
intercept(UnsupportedOperationException.class, () -> stream.hsync());
}
Expand Down