com.sap.hana.datalake.files.HdlfsRetryPolicies Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sap-hdlfs Show documentation
Show all versions of sap-hdlfs Show documentation
An implementation of org.apache.hadoop.fs.FileSystem targeting SAP HANA Data Lake Files.
// © 2022-2023 SAP SE or an SAP affiliate company. All rights reserved.
package com.sap.hana.datalake.files;
import com.sap.hana.datalake.files.exception.HdlfsOperationException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdfs.client.HdfsClientConfigKeys;
import com.sap.hana.datalake.files.shaded.org.apache.hadoop.io.retry.RetryPolicies;
import org.apache.hadoop.io.retry.RetryPolicy;
import org.apache.hadoop.io.retry.RetryUtils;
import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.thirdparty.com.google.common.base.Preconditions;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
public class HdlfsRetryPolicies {
public final static int MERGE_RETRY_FILE_NOT_FOUND_LIMIT_DEFAULT = 50;
public final static int MERGE_RETRY_FILE_NOT_FOUND_INTERVAL_MS_DEFAULT = 500;
public final static int MIN_MERGE_RETRY_FILE_NOT_FOUND_LIMIT = 1;
public final static int MIN_MERGE_RETRY_FILE_NOT_FOUND_INTERVAL_MS = 0;
public final static int OPEN_RETRY_FILE_NOT_FOUND_LIMIT_DEFAULT = 50;
public final static int OPEN_RETRY_FILE_NOT_FOUND_INTERVAL_MS_DEFAULT = 500;
public final static int MIN_OPEN_RETRY_FILE_NOT_FOUND_LIMIT = 1;
public final static int MIN_OPEN_RETRY_FILE_NOT_FOUND_INTERVAL_MS = 0;
public final static int DELETE_TEMP_DIR_RETRY_DIR_NOT_EMPTY_LIMIT_DEFAULT = 50;
public final static int DELETE_TEMP_DIR_RETRY_DIR_NOT_EMPTY_INTERVAL_MS_DEFAULT = 500;
public final static int MIN_DELETE_TEMP_DIR_RETRY_DIR_NOT_EMPTY_LIMIT = 1;
public final static int MIN_DELETE_TEMP_DIR_RETRY_DIR_NOT_EMPTY_INTERVAL_MS = 0;
public static RetryPolicy createDefaultRetryPolicy(final Configuration conf) {
final boolean retryPolicyEnabled = conf.getBoolean(HdlfsConstants.FS_HDLFS_HTTP_CLIENT_RETRY_POLICY_ENABLED_KEY, HdlfsConstants.FS_HDLFS_HTTP_CLIENT_RETRY_POLICY_ENABLED_DEFAULT);
final String retryPolicySpec = conf.get(HdlfsConstants.FS_HDLFS_HTTP_CLIENT_RETRY_POLICY_SPEC_KEY, HdlfsConstants.FS_HDLFS_HTTP_CLIENT_RETRY_POLICY_SPEC_DEFAULT);
final RetryPolicy retryByExceptionDefaultPolicy = RetryUtils.getDefaultRetryPolicy(conf, HdfsClientConfigKeys.HttpClient.RETRY_POLICY_ENABLED_KEY, retryPolicyEnabled,
HdfsClientConfigKeys.HttpClient.RETRY_POLICY_SPEC_KEY, retryPolicySpec,
/* remoteExceptionToRetry */ "org.apache.hadoop.hdfs.server.namenode.SafeModeException");
return new HdlfsRetryPolicies.RetryByExceptionBuilder()
.withDefaultPolicy(retryByExceptionDefaultPolicy)
.withExceptionToPolicyMapping(AccessControlException.class, RetryPolicies.TRY_ONCE_THEN_FAIL)
.build();
}
public static RetryPolicy createMergeFileNotFoundRetryPolicy(final Configuration conf) {
final boolean fsCacheEnabled = conf.getBoolean(HdlfsConstants.FSCACHE_ENABLED, HdlfsConstants.FSCACHE_ENABLED_DEFAULT);
final boolean mergeFileNotFoundRetryEnabled = conf.getBoolean(HdlfsConstants.CONFIG_MERGE_RETRY_FILE_NOT_FOUND_ENABLED_KEY, fsCacheEnabled);
// Should be enabled by default in eventual consistency scenarios, so we set the default to be the same as FsCache
if (mergeFileNotFoundRetryEnabled) {
final RetryPolicy fileNotFoundPolicy = new FixedSleepPolicyBuilder(conf)
.maxRetries(HdlfsConstants.CONFIG_MERGE_RETRY_FILE_NOT_FOUND_LIMIT_KEY, HdlfsRetryPolicies.MERGE_RETRY_FILE_NOT_FOUND_LIMIT_DEFAULT, HdlfsRetryPolicies.MIN_MERGE_RETRY_FILE_NOT_FOUND_LIMIT)
.sleepTimeMs(HdlfsConstants.CONFIG_MERGE_RETRY_FILE_NOT_FOUND_INTERVAL_KEY, HdlfsRetryPolicies.MERGE_RETRY_FILE_NOT_FOUND_INTERVAL_MS_DEFAULT, HdlfsRetryPolicies.MIN_MERGE_RETRY_FILE_NOT_FOUND_INTERVAL_MS)
.build();
return new HdlfsRetryPolicies.RetryByExceptionBuilder()
.withDefaultPolicy(RetryPolicies.TRY_ONCE_THEN_FAIL)
.withExceptionToPolicyMapping(FileNotFoundException.class, fileNotFoundPolicy)
.withExceptionProcessor(ex -> ex instanceof HdlfsOperationException ? (Exception) ex.getCause() : ex)
.build();
}
return RetryPolicies.TRY_ONCE_THEN_FAIL;
}
public static RetryPolicy createOpenFileNotFoundRetryPolicy(final Configuration conf) {
final boolean fsCacheEnabled = conf.getBoolean(HdlfsConstants.FSCACHE_ENABLED, HdlfsConstants.FSCACHE_ENABLED_DEFAULT);
final boolean openFileNotFoundRetryEnabled = conf.getBoolean(HdlfsConstants.CONFIG_OPEN_RETRY_FILE_NOT_FOUND_ENABLED_KEY, fsCacheEnabled);
// Should be enabled by default in eventual consistency scenarios, so we set the default to be the same as FsCache
if (openFileNotFoundRetryEnabled) {
final RetryPolicy fileNotFoundPolicy = new FixedSleepPolicyBuilder(conf)
.maxRetries(HdlfsConstants.CONFIG_OPEN_RETRY_FILE_NOT_FOUND_LIMIT_KEY, HdlfsRetryPolicies.OPEN_RETRY_FILE_NOT_FOUND_LIMIT_DEFAULT, HdlfsRetryPolicies.MIN_OPEN_RETRY_FILE_NOT_FOUND_LIMIT)
.sleepTimeMs(HdlfsConstants.CONFIG_OPEN_RETRY_FILE_NOT_FOUND_INTERVAL_KEY, HdlfsRetryPolicies.OPEN_RETRY_FILE_NOT_FOUND_INTERVAL_MS_DEFAULT, HdlfsRetryPolicies.MIN_OPEN_RETRY_FILE_NOT_FOUND_INTERVAL_MS)
.build();
return new HdlfsRetryPolicies.RetryByExceptionBuilder()
.withDefaultPolicy(RetryPolicies.TRY_ONCE_THEN_FAIL)
.withExceptionToPolicyMapping(FileNotFoundException.class, fileNotFoundPolicy)
.build();
}
return RetryPolicies.TRY_ONCE_THEN_FAIL;
}
public static RetryPolicy createMPUDeleteTempDirRetryPolicy(final Configuration conf) {
final boolean createDeleteTempDirRetryEnabled = conf.getBoolean(HdlfsConstants.CONFIG_DELETE_MPU_TEMP_DIR_RETRY_DIR_NOT_EMPTY_ENABLED_KEY, true);
if (createDeleteTempDirRetryEnabled) {
return new FixedSleepPolicyBuilder(conf)
.maxRetries(HdlfsConstants.CONFIG_DELETE_MPU_TEMP_DIR_RETRY_DIR_NOT_EMPTY_LIMIT_KEY, HdlfsRetryPolicies.DELETE_TEMP_DIR_RETRY_DIR_NOT_EMPTY_LIMIT_DEFAULT, HdlfsRetryPolicies.MIN_DELETE_TEMP_DIR_RETRY_DIR_NOT_EMPTY_LIMIT)
.sleepTimeMs(HdlfsConstants.CONFIG_DELETE_MPU_TEMP_DIR_RETRY_DIR_NOT_EMPTY_INTERVAL_KEY, HdlfsRetryPolicies.DELETE_TEMP_DIR_RETRY_DIR_NOT_EMPTY_INTERVAL_MS_DEFAULT, HdlfsRetryPolicies.MIN_DELETE_TEMP_DIR_RETRY_DIR_NOT_EMPTY_INTERVAL_MS)
.build();
}
return RetryPolicies.TRY_ONCE_THEN_FAIL;
}
private HdlfsRetryPolicies() {
// no-op
}
public static class RetryByExceptionBuilder {
private final Map, RetryPolicy> exceptionToPolicyMap = new HashMap<>();
private Function exceptionProcessor;
private RetryPolicy defaultRetryPolicy;
public RetryByExceptionBuilder() {
// no-op
}
public RetryByExceptionBuilder withDefaultPolicy(final RetryPolicy defaultRetryPolicy) {
this.defaultRetryPolicy = defaultRetryPolicy;
return this;
}
public RetryByExceptionBuilder withExceptionToPolicyMapping(final Class extends Exception> exception, final RetryPolicy retryPolicy) {
this.exceptionToPolicyMap.put(exception, retryPolicy);
return this;
}
public RetryByExceptionBuilder withExceptionToPolicyMap(Map, RetryPolicy> exceptionToPolicyMap) {
exceptionToPolicyMap.keySet().forEach(key -> this.exceptionToPolicyMap.put(key, exceptionToPolicyMap.get(key)));
return this;
}
public RetryByExceptionBuilder withExceptionProcessor(final Function exceptionProcessor) {
this.exceptionProcessor = exceptionProcessor;
return this;
}
public RetryPolicy build() {
this.defaultRetryPolicy = this.defaultRetryPolicy == null ? RetryPolicies.TRY_ONCE_THEN_FAIL : this.defaultRetryPolicy;
this.exceptionProcessor = this.exceptionProcessor == null ? ex -> ex : this.exceptionProcessor;
return RetryPolicies.retryByException(this.defaultRetryPolicy, this.exceptionToPolicyMap, this.exceptionProcessor);
}
}
public static class FixedSleepPolicyBuilder {
private final Configuration conf;
private Integer maxRetries;
private Integer sleepTimeMs;
public FixedSleepPolicyBuilder(final Configuration conf) {
this.conf = conf;
}
public FixedSleepPolicyBuilder maxRetries(final String maxRetriesKey, final int maxRetriesDefault, final int minRetries) {
this.maxRetries = this.conf.getInt(maxRetriesKey, maxRetriesDefault);
Preconditions.checkArgument(this.maxRetries >= minRetries,
String.format("Config [%s] too small: [%d]; must be at least [%d]", maxRetriesKey, this.maxRetries, minRetries));
return this;
}
public FixedSleepPolicyBuilder sleepTimeMs(final String sleepTimeKey, final int sleepTimeMsDefault, final int minSleepTimeMs) {
this.sleepTimeMs = this.conf.getInt(sleepTimeKey, sleepTimeMsDefault);
Preconditions.checkArgument(this.sleepTimeMs >= minSleepTimeMs,
String.format("Config [%s] too small: [%d]; must be at least [%d]", sleepTimeKey, this.sleepTimeMs, minSleepTimeMs));
return this;
}
public RetryPolicy build() {
Preconditions.checkArgument(this.maxRetries != null, "maxRetries must not be null");
Preconditions.checkArgument(this.sleepTimeMs != null, "sleepTimeMs must not be null");
return RetryPolicies.retryUpToMaximumCountWithFixedSleep(this.maxRetries, this.sleepTimeMs, TimeUnit.MILLISECONDS);
}
}
}
// © 2022-2023 SAP SE or an SAP affiliate company. All rights reserved.
© 2015 - 2025 Weber Informatics LLC | Privacy Policy