Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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 @@ -247,28 +247,53 @@ public enum ChecksumCombineMode {
tags = ConfigTag.CLIENT)
private String fsDefaultBucketLayout = "FILE_SYSTEM_OPTIMIZED";

// ozone.client.hbase.enhancements.enabled
@Config(key = "hbase.enhancements.enabled",
defaultValue = "false",
description = "DO NOT manually set this config. Set ozone.hbase.enhancements.enabled instead." +
"This config will be overridden by ozone.hbase.enhancements.enabled. " +
"When set to false, HBase enhancement-related Ozone (experimental) features " +
"are disabled regardless of whether those configs are set.",
tags = ConfigTag.CLIENT)
private boolean hbaseEnhancementsEnabled = false;

// ozone.client.fs.hsync.enabled
@Config(key = "fs.hsync.enabled",
defaultValue = "false",
description = "DO NOT manually set this config. " +
"This config will be overridden by ozone.fs.hsync.enabled. " +
"Enable hsync/hflush on the Ozone client. " +
"Can be enabled only when ozone.hbase.enhancements.enabled = true",
tags = ConfigTag.CLIENT)
private boolean fsHsyncEnabled = false;

// ozone.client.incremental.chunk.list
@Config(key = "incremental.chunk.list",
defaultValue = "true",
defaultValue = "false",
type = ConfigType.BOOLEAN,
description = "Client PutBlock request can choose incremental chunk " +
"list rather than full chunk list to optimize performance. " +
"Critical to HBase. EC does not support this feature.",
"Critical to HBase. EC does not support this feature. " +
"Can be enabled only when ozone.hbase.enhancements.enabled = true",
tags = ConfigTag.CLIENT)
private boolean incrementalChunkList = true;
private boolean incrementalChunkList = false;

// ozone.client.stream.putblock.piggybacking
@Config(key = "stream.putblock.piggybacking",
defaultValue = "true",
defaultValue = "false",
type = ConfigType.BOOLEAN,
description = "Allow PutBlock to be piggybacked in WriteChunk " +
"requests if the chunk is small.",
description = "Allow PutBlock to be piggybacked in WriteChunk requests if the chunk is small. " +
"Can be enabled only when ozone.hbase.enhancements.enabled = true",
tags = ConfigTag.CLIENT)
private boolean enablePutblockPiggybacking = true;
private boolean enablePutblockPiggybacking = false;

// ozone.client.key.write.concurrency
@Config(key = "key.write.concurrency",
defaultValue = "1",
description = "Maximum concurrent writes allowed on each key. " +
"Defaults to 1 which matches the behavior before HDDS-9844. " +
"For unlimited write concurrency, set this to -1 or any negative integer value.",
"For unlimited write concurrency, set this to -1 or any negative integer value. " +
"Any value other than 1 is effective only when ozone.hbase.enhancements.enabled = true",
tags = ConfigTag.CLIENT)
private int maxConcurrentWritePerKey = 1;

Expand Down Expand Up @@ -298,6 +323,35 @@ public void validate() {
OzoneConfigKeys.OZONE_CLIENT_BYTES_PER_CHECKSUM_MIN_SIZE;
}

// Verify client configs related to HBase enhancements
// Enforce ozone.hbase.enhancements.enabled master switch
if (!hbaseEnhancementsEnabled) {
// ozone.hbase.enhancements.enabled = false
if (fsHsyncEnabled) {
LOG.warn("Ignoring ozone.client.fs.hsync.enabled = {} because HBase enhancements are disabled. " +
"To enable it, set ozone.hbase.enhancements.enabled = true as well.", fsHsyncEnabled);
fsHsyncEnabled = false;
LOG.debug("ozone.client.fs.hsync.enabled = {}", fsHsyncEnabled);
}
if (incrementalChunkList) {
LOG.warn("Ignoring ozone.client.incremental.chunk.list = {} because HBase enhancements are disabled. " +
"To enable it, set ozone.hbase.enhancements.enabled = true as well.", incrementalChunkList);
incrementalChunkList = false;
LOG.debug("ozone.client.incremental.chunk.list = {}", incrementalChunkList);
}
if (enablePutblockPiggybacking) {
LOG.warn("Ignoring ozone.client.stream.putblock.piggybacking = {} because HBase enhancements are disabled. " +
"To enable it, set ozone.hbase.enhancements.enabled = true as well.", enablePutblockPiggybacking);
enablePutblockPiggybacking = false;
LOG.debug("ozone.client.stream.putblock.piggybacking = {}", enablePutblockPiggybacking);
}
if (maxConcurrentWritePerKey != 1) {
LOG.warn("Ignoring ozone.client.key.write.concurrency = {} because HBase enhancements are disabled. " +
"To enable it, set ozone.hbase.enhancements.enabled = true as well.", maxConcurrentWritePerKey);
maxConcurrentWritePerKey = 1;
LOG.debug("ozone.client.key.write.concurrency = {}", maxConcurrentWritePerKey);
}
}
}

public long getStreamBufferFlushSize() {
Expand Down Expand Up @@ -486,6 +540,22 @@ public void setDatastreamPipelineMode(boolean datastreamPipelineMode) {
this.datastreamPipelineMode = datastreamPipelineMode;
}

public void setHBaseEnhancementsEnabled(boolean isHBaseEnhancementsEnabled) {
this.hbaseEnhancementsEnabled = isHBaseEnhancementsEnabled;
}

public boolean getHBaseEnhancementsEnabled() {
return this.hbaseEnhancementsEnabled;
}

public void setFsHsyncEnabled(boolean fsHsyncEnabled) {
this.fsHsyncEnabled = fsHsyncEnabled;
}

public boolean getFsHsyncEnabled() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

not used anywhere in the production code.
It seems to me ozone.client.fs.hsync.enabled is not needed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It is supposed to be used by the client instead of ozone.fs.hsync.enabled to enforce the check in one place. Need adjustment.

return this.fsHsyncEnabled;
}

public void setIncrementalChunkList(boolean enable) {
this.incrementalChunkList = enable;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,7 @@ public BlockOutputStream(
blkIDBuilder.build()).addMetadata(keyValue);
this.pipeline = pipeline;
// tell DataNode I will send incremental chunk list
// EC does not support incremental chunk list.
this.supportIncrementalChunkList = config.getIncrementalChunkList() &&
this instanceof RatisBlockOutputStream && allDataNodesSupportPiggybacking();
this.supportIncrementalChunkList = canEnableIncrementalChunkList();
LOG.debug("incrementalChunkList is {}", supportIncrementalChunkList);
if (supportIncrementalChunkList) {
this.containerBlockData.addMetadata(INCREMENTAL_CHUNK_LIST_KV);
Expand Down Expand Up @@ -237,11 +235,51 @@ public BlockOutputStream(
config.getBytesPerChecksum());
this.clientMetrics = clientMetrics;
this.streamBufferArgs = streamBufferArgs;
this.allowPutBlockPiggybacking = config.getEnablePutblockPiggybacking() &&
allDataNodesSupportPiggybacking();
this.allowPutBlockPiggybacking = canEnablePutblockPiggybacking();
LOG.debug("PutBlock piggybacking is {}", allowPutBlockPiggybacking);
}

/**
* Helper method to check if incremental chunk list can be enabled.
* Prints debug messages if it cannot be enabled.
*/
private boolean canEnableIncrementalChunkList() {
boolean confEnableIncrementalChunkList = config.getIncrementalChunkList();
if (!confEnableIncrementalChunkList) {
return false;
}

if (!(this instanceof RatisBlockOutputStream)) {
// Note: EC does not support incremental chunk list
LOG.debug("Unable to enable incrementalChunkList because BlockOutputStream is not a RatisBlockOutputStream");
return false;
}
if (!allDataNodesSupportPiggybacking()) {
// Not all datanodes support piggybacking and incremental chunk list.
LOG.debug("Unable to enable incrementalChunkList because not all datanodes support piggybacking");
return false;
}
return confEnableIncrementalChunkList;
}

/**
* Helper method to check if PutBlock piggybacking can be enabled.
* Prints debug message if it cannot be enabled.
*/
private boolean canEnablePutblockPiggybacking() {
boolean confEnablePutblockPiggybacking = config.getEnablePutblockPiggybacking();
if (!confEnablePutblockPiggybacking) {
return false;
}

if (!allDataNodesSupportPiggybacking()) {
// Not all datanodes support piggybacking and incremental chunk list.
LOG.debug("Unable to enable PutBlock piggybacking because not all datanodes support piggybacking");
return false;
}
return confEnablePutblockPiggybacking;
}

private boolean allDataNodesSupportPiggybacking() {
// return true only if all DataNodes in the pipeline are on a version
// that supports PutBlock piggybacking.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_CLIENT_BYTES_PER_CHECKSUM_MIN_SIZE;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

class TestOzoneClientConfig {

Expand All @@ -36,4 +38,50 @@ void missingSizeSuffix() {

assertEquals(OZONE_CLIENT_BYTES_PER_CHECKSUM_MIN_SIZE, subject.getBytesPerChecksum());
}

@Test
void testClientHBaseEnhancementsEnabledTrue() {
// When ozone.client.hbase.enhancements.enabled = true,
// related client configs should be effective as-is.
OzoneConfiguration conf = new OzoneConfiguration();

// Note: Use ozone.hbase.enhancements.enabled instead in prod
conf.setBoolean("ozone.client.hbase.enhancements.enabled", true);

// Note: Use ozone.fs.hsync.enabled instead in prod
conf.setBoolean("ozone.client.fs.hsync.enabled", true);
conf.setBoolean("ozone.client.incremental.chunk.list", true);
conf.setBoolean("ozone.client.stream.putblock.piggybacking", true);
conf.setInt("ozone.client.key.write.concurrency", -1);

OzoneClientConfig subject = conf.getObject(OzoneClientConfig.class);

assertTrue(subject.getFsHsyncEnabled());
assertTrue(subject.getIncrementalChunkList());
assertTrue(subject.getEnablePutblockPiggybacking());
assertEquals(-1, subject.getMaxConcurrentWritePerKey());
}

@Test
void testClientHBaseEnhancementsEnabledFalse() {
// When ozone.client.hbase.enhancements.enabled = false,
// related client configs should be reverted back to default.
OzoneConfiguration conf = new OzoneConfiguration();

// Note: Use ozone.hbase.enhancements.enabled instead in prod
conf.setBoolean("ozone.client.hbase.enhancements.enabled", false);

// Note: Use ozone.fs.hsync.enabled instead in prod
conf.setBoolean("ozone.client.fs.hsync.enabled", true);
conf.setBoolean("ozone.client.incremental.chunk.list", true);
conf.setBoolean("ozone.client.stream.putblock.piggybacking", true);
conf.setInt("ozone.client.key.write.concurrency", -1);

OzoneClientConfig subject = conf.getObject(OzoneClientConfig.class);

assertFalse(subject.getFsHsyncEnabled());
assertFalse(subject.getIncrementalChunkList());
assertFalse(subject.getEnablePutblockPiggybacking());
assertEquals(1, subject.getMaxConcurrentWritePerKey());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,19 @@ public final class OzoneConfigKeys {
public static final String OZONE_FS_DATASTREAM_AUTO_THRESHOLD_DEFAULT
= "4MB";

/**
* Flag to allow hbase-related features and enhancements to be enabled in the first place.
*/
public static final String OZONE_HBASE_ENHANCEMENTS_ENABLED
= "ozone.hbase.enhancements.enabled";
public static final boolean OZONE_HBASE_ENHANCEMENTS_ENABLED_DEFAULT
= false;

/**
* Flag to enable hsync/hflush.
*/
public static final String OZONE_FS_HSYNC_ENABLED
= "ozone.fs.hsync.enabled";
= "ozone.fs.hsync.enabled"; // OzoneConfigKeys is not passed to BOS ?
Comment thread
smengcl marked this conversation as resolved.
Outdated
public static final boolean OZONE_FS_HSYNC_ENABLED_DEFAULT
= false;

Expand Down
22 changes: 20 additions & 2 deletions hadoop-hdds/common/src/main/resources/ozone-default.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4216,12 +4216,30 @@
</description>
</property>

<property>
<name>ozone.hbase.enhancements.enabled</name>
<value>false</value>
<tag>OZONE, CLIENT, OM</tag>
<description>
When set to false, HBase enhancement-related Ozone (experimental) features
are disabled regardless of whether those configs are set.

More precisely, here is the list of configs and values overridden when this config is set to false:
1. ozone.fs.hsync.enabled = false
2. ozone.client.incremental.chunk.list = false
3. ozone.client.stream.putblock.piggybacking = false
4. ozone.client.key.write.concurrency = 1

A warning message will be printed if any of the above configs are overridden by this.
</description>
</property>
<property>
<name>ozone.fs.hsync.enabled</name>
<value>false</value>
<tag>OZONE, CLIENT</tag>
<tag>OZONE, CLIENT, OM</tag>
<description>
Enable hsync/hflush. By default they are disabled.
Enable hsync/hflush on the Ozone Manager and/or client side. Disabled by default.
Can be enabled only when ozone.hbase.enhancements.enabled = true
</description>
</property>
<property>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.apache.hadoop.crypto.key.KeyProvider;
import org.apache.hadoop.fs.FileEncryptionInfo;
import org.apache.hadoop.fs.Syncable;
import org.apache.hadoop.ozone.om.helpers.OzoneFSUtils;
import org.apache.hadoop.util.Time;
import org.apache.hadoop.hdds.client.DefaultReplicationConfig;
import org.apache.hadoop.hdds.client.ECReplicationConfig;
Expand Down Expand Up @@ -250,7 +251,7 @@ public RpcClient(ConfigurationSource conf, String omServiceId)
this.userRights = aclConfig.getUserDefaultRights();
this.groupRights = aclConfig.getGroupDefaultRights();

this.clientConfig = conf.getObject(OzoneClientConfig.class);
this.clientConfig = OzoneFSUtils.getClientConfig(conf);
this.ecReconstructExecutor = MemoizedSupplier.valueOf(() -> createThreadPoolExecutor(
EC_RECONSTRUCT_STRIPE_READ_POOL_MIN_SIZE, clientConfig.getEcReconstructStripeReadPoolLimit(),
"ec-reconstruct-reader-TID-%d"));
Expand Down Expand Up @@ -2489,9 +2490,7 @@ private OzoneOutputStream createOutputStream(OpenKeySession openKey)
private OzoneOutputStream createOutputStream(OpenKeySession openKey,
KeyOutputStream keyOutputStream)
throws IOException {
boolean enableHsync = conf.getBoolean(
OzoneConfigKeys.OZONE_FS_HSYNC_ENABLED,
OzoneConfigKeys.OZONE_FS_HSYNC_ENABLED_DEFAULT);
boolean enableHsync = OzoneFSUtils.canEnableHsync(conf);
keyOutputStream
.addPreallocateBlocks(openKey.getKeyInfo().getLatestVersionLocations(),
openKey.getOpenVersion());
Expand All @@ -2503,9 +2502,7 @@ private OzoneOutputStream createOutputStream(OpenKeySession openKey,

private OzoneOutputStream createSecureOutputStream(OpenKeySession openKey,
OutputStream keyOutputStream, Syncable syncable) throws IOException {
boolean enableHsync = conf.getBoolean(
OzoneConfigKeys.OZONE_FS_HSYNC_ENABLED,
OzoneConfigKeys.OZONE_FS_HSYNC_ENABLED_DEFAULT);
boolean enableHsync = OzoneFSUtils.canEnableHsync(conf);
final FileEncryptionInfo feInfo =
openKey.getKeyInfo().getFileEncryptionInfo();
if (feInfo != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ private void init(boolean incrementalChunkList) throws IOException {

((InMemoryConfiguration)config).setFromObject(clientConfig);

((InMemoryConfiguration) config).setBoolean(
OzoneConfigKeys.OZONE_HBASE_ENHANCEMENTS_ENABLED, true);
((InMemoryConfiguration) config).setBoolean(
OzoneConfigKeys.OZONE_FS_HSYNC_ENABLED, true);

Expand Down
Loading