From e70429c4a0c6bc0ad71186cf526b5f8d6f48841e Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Thu, 12 Jan 2023 02:35:19 -0800 Subject: [PATCH 01/38] retryReason foundations. --- .../azurebfs/services/AbfsRestOperation.java | 9 ++++ .../fs/azurebfs/services/RetryReason.java | 54 +++++++++++++++++++ .../services/RetryReasonCaptureMechanism.java | 5 ++ 3 files changed, 68 insertions(+) create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonCaptureMechanism.java diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java index 00da9b6601338..274183644c289 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java @@ -23,6 +23,7 @@ import java.net.HttpURLConnection; import java.net.URL; import java.net.UnknownHostException; +import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; @@ -73,6 +74,8 @@ public class AbfsRestOperation { private AbfsHttpOperation result; private AbfsCounters abfsCounters; + private final List failureReasons = new ArrayList<>(); + /** * Checks if there is non-null HTTP response. * @return true if there is a non-null HTTP response from the ABFS call. @@ -303,6 +306,7 @@ private boolean executeHttpOperation(final int retryCount, } catch (UnknownHostException ex) { String hostname = null; hostname = httpOperation.getHost(); + failureReasons.add(RetryReason.UNKNOWN_HOST.name()); LOG.warn("Unknown host name: {}. Retrying to resolve the host name...", hostname); if (!client.getRetryPolicy().shouldRetry(retryCount, -1)) { @@ -314,6 +318,8 @@ private boolean executeHttpOperation(final int retryCount, LOG.debug("HttpRequestFailure: {}, {}", httpOperation, ex); } + failureReasons.add(RetryReason.getEnum(ex, -1).name()); + if (!client.getRetryPolicy().shouldRetry(retryCount, -1)) { throw new InvalidAbfsRestOperationException(ex); } @@ -326,6 +332,9 @@ private boolean executeHttpOperation(final int retryCount, LOG.debug("HttpRequest: {}: {}", operationType, httpOperation); if (client.getRetryPolicy().shouldRetry(retryCount, httpOperation.getStatusCode())) { + int status = httpOperation.getStatusCode(); + failureReasons.add(String.format("%s_%d", + RetryReason.getEnum(null, status).name(), status)); return false; } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java new file mode 100644 index 0000000000000..cb6395bb00810 --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -0,0 +1,54 @@ +package org.apache.hadoop.fs.azurebfs.services; + +import java.io.IOException; +import java.net.SocketException; +import java.util.Arrays; +import java.util.stream.Collectors; + +public enum RetryReason { + CONNECTION_TIMEOUT, + READ_TIMEOUT(((exceptionCaptured, statusCode) -> { + return "Read timed out".equalsIgnoreCase(exceptionCaptured.getMessage()); + }), 2), + UNKNOWN_HOST, + CONNECTION_RESET(((exceptionCaptured, statusCode) -> { + return "connect timed out".equalsIgnoreCase(exceptionCaptured.getMessage()); + }), 2), + STATUS_5XX(((exceptionCaptured, statusCode) -> { + return statusCode/100 == 5; + }), 0), + STATUS_4XX(((exceptionCaptured, statusCode) -> { + return statusCode/100 == 4; + }), 0), + UNKNOWN_SOCKET_EXCEPTION(((exceptionCaptured, statusCode) -> { + return exceptionCaptured instanceof SocketException; + }), 1), + UNKNOWN_IO_EXCEPTION(((exceptionCaptured, statusCode) -> { + return exceptionCaptured instanceof IOException; + }), 0); + + private RetryReasonCaptureMechanism mechanism = null; + private int rank = 0; + + RetryReason() { + + } + + RetryReason(RetryReasonCaptureMechanism mechanism, int rank) { + this.mechanism = mechanism; + this.rank = rank; + } + + static RetryReason getEnum(Exception ex, Integer statusCode) { + RetryReason retryReasonResult = null; + for(RetryReason retryReason : Arrays.stream(values()).sorted().collect( + Collectors.toList())) { + if(retryReason.mechanism != null) { + if(retryReason.mechanism.canCapture(ex, statusCode)) { + retryReasonResult = retryReason; + } + } + } + return retryReasonResult; + } +} diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonCaptureMechanism.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonCaptureMechanism.java new file mode 100644 index 0000000000000..93c0d446f6540 --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonCaptureMechanism.java @@ -0,0 +1,5 @@ +package org.apache.hadoop.fs.azurebfs.services; + +interface RetryReasonCaptureMechanism { + boolean canCapture(Exception exceptionCaptured, Integer statusCode); +} From 2ddd8c93dc66e147add7930bff4d4248353e5dad Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Thu, 12 Jan 2023 02:56:00 -0800 Subject: [PATCH 02/38] send failureReasons for adding in x-ms-client-request-id --- .../azurebfs/services/AbfsRestOperation.java | 2 +- .../fs/azurebfs/utils/TracingContext.java | 22 ++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java index 274183644c289..0eba4ae5bc9e9 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java @@ -253,7 +253,7 @@ private boolean executeHttpOperation(final int retryCount, // initialize the HTTP request and open the connection httpOperation = new AbfsHttpOperation(url, method, requestHeaders); incrementCounter(AbfsStatistic.CONNECTIONS_MADE, 1); - tracingContext.constructHeader(httpOperation); + tracingContext.constructHeader(httpOperation, failureReasons); switch(client.getAuthType()) { case Custom: diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java index 5a115451df159..e41db5a619e1d 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java @@ -18,6 +18,7 @@ package org.apache.hadoop.fs.azurebfs.utils; +import java.util.List; import java.util.UUID; import org.slf4j.Logger; @@ -67,6 +68,9 @@ public class TracingContext { public static final int MAX_CLIENT_CORRELATION_ID_LENGTH = 72; public static final String CLIENT_CORRELATION_ID_PATTERN = "[a-zA-Z0-9-]*"; + //x-ms-client-request-id can have maximum 1KB string + private static final Integer MAX_CLIENT_REQUEST_ID = 1024; + /** * Initialize TracingContext * @param clientCorrelationID Provided over config by client @@ -152,8 +156,10 @@ public void setListener(Listener listener) { * X_MS_CLIENT_REQUEST_ID header of the http operation * @param httpOperation AbfsHttpOperation instance to set header into * connection + * @param previousFailures List of failures seen before this API trigger on + * same operation from AbfsClient. */ - public void constructHeader(AbfsHttpOperation httpOperation) { + public void constructHeader(AbfsHttpOperation httpOperation, List previousFailures) { clientRequestId = UUID.randomUUID().toString(); switch (format) { case ALL_ID_FORMAT: // Optional IDs (e.g. streamId) may be empty @@ -161,6 +167,7 @@ public void constructHeader(AbfsHttpOperation httpOperation) { clientCorrelationID + ":" + clientRequestId + ":" + fileSystemID + ":" + primaryRequestId + ":" + streamID + ":" + opType + ":" + retryCount; + header = addFailureReasons(header, previousFailures); break; case TWO_ID_FORMAT: header = clientCorrelationID + ":" + clientRequestId; @@ -174,6 +181,19 @@ public void constructHeader(AbfsHttpOperation httpOperation) { httpOperation.setRequestProperty(HttpHeaderConfigurations.X_MS_CLIENT_REQUEST_ID, header); } + private String addFailureReasons(final String header, + final List previousFailures) { + String headerResult = header; + for(int iter = previousFailures.size() -1; iter >=0; iter--) { + headerResult += previousFailures.get(iter); + if(headerResult.length() > MAX_CLIENT_REQUEST_ID) { + headerResult = headerResult.substring(0, MAX_CLIENT_REQUEST_ID); + break; + } + } + return headerResult; + } + /** * Return header representing the request associated with the tracingContext * @return Header string set into X_MS_CLIENT_REQUEST_ID From cc2deb2717c4ab4a05fd93112701cf1601d8d942 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Fri, 13 Jan 2023 00:19:09 -0800 Subject: [PATCH 03/38] added heuristics in RetryReason --- .../azurebfs/services/AbfsRestOperation.java | 6 +- .../fs/azurebfs/services/RetryReason.java | 67 ++++++++++++++++--- .../RetryReasonAbbreviationCreator.java | 5 ++ .../fs/azurebfs/utils/TracingContext.java | 5 +- .../services/TestAbfsRestOperation.java | 26 +++++++ 5 files changed, 96 insertions(+), 13 deletions(-) create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java create mode 100644 hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java index 0eba4ae5bc9e9..253e654c306fd 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java @@ -251,7 +251,7 @@ private boolean executeHttpOperation(final int retryCount, try { // initialize the HTTP request and open the connection - httpOperation = new AbfsHttpOperation(url, method, requestHeaders); + httpOperation = getHttpOperation(); incrementCounter(AbfsStatistic.CONNECTIONS_MADE, 1); tracingContext.constructHeader(httpOperation, failureReasons); @@ -343,6 +343,10 @@ private boolean executeHttpOperation(final int retryCount, return true; } + private AbfsHttpOperation getHttpOperation() throws IOException { + return new AbfsHttpOperation(url, method, requestHeaders); + } + /** * Incrementing Abfs counters with a long value. * diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index cb6395bb00810..cb5035ec5d5c4 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -6,37 +6,82 @@ import java.util.stream.Collectors; public enum RetryReason { - CONNECTION_TIMEOUT, + //3character string + //4xx exact status + //in case of 503: give reason of throttling , ref anmol@ PR. + //result.getStorageErrorMessage() + // + CONNECTION_TIMEOUT(((exceptionCaptured, statusCode) -> { + return "connect timed out".equalsIgnoreCase(exceptionCaptured.getMessage()); + }), 2, "CT"), READ_TIMEOUT(((exceptionCaptured, statusCode) -> { return "Read timed out".equalsIgnoreCase(exceptionCaptured.getMessage()); - }), 2), - UNKNOWN_HOST, + }), 2, "RT"), + UNKNOWN_HOST("UH"), CONNECTION_RESET(((exceptionCaptured, statusCode) -> { - return "connect timed out".equalsIgnoreCase(exceptionCaptured.getMessage()); - }), 2), + return exceptionCaptured.getMessage().contains("Connection reset"); + }), 2, "CR"), STATUS_5XX(((exceptionCaptured, statusCode) -> { return statusCode/100 == 5; - }), 0), + }), 0, ((ex, statusCode, serverErrorMessage) -> { + if(statusCode == 503) { + //ref: https://github.com/apache/hadoop/pull/4564/files#diff-75a2f54df6618d4015c63812e6a9916ddfb475d246850edfd2a6f57e36805e79 + serverErrorMessage = serverErrorMessage.split(System.lineSeparator(), 2)[0]; + if("Ingress is over the account limit.".equalsIgnoreCase(serverErrorMessage)) { + return "ING"; + } + if("Egress is over the account limit.".equalsIgnoreCase(serverErrorMessage)) { + return "EGR"; + } + if("Operations per second is over the account limit.".equalsIgnoreCase(serverErrorMessage)) { + return "OPR"; + } + return "503"; + } + return statusCode + ""; + })), STATUS_4XX(((exceptionCaptured, statusCode) -> { return statusCode/100 == 4; - }), 0), + }), 0, ((ex, statusCode, serverErrorMessage) -> { + return statusCode + ""; + })), UNKNOWN_SOCKET_EXCEPTION(((exceptionCaptured, statusCode) -> { return exceptionCaptured instanceof SocketException; - }), 1), + }), 1, "SE"), UNKNOWN_IO_EXCEPTION(((exceptionCaptured, statusCode) -> { return exceptionCaptured instanceof IOException; - }), 0); + }), 0, "IOE"); private RetryReasonCaptureMechanism mechanism = null; + private RetryReasonAbbreviationCreator retryReasonAbbreviationCreator = null; private int rank = 0; - RetryReason() { + private String abbreviation; + + RetryReason(String abbreviation) { + this.abbreviation = abbreviation; + } + RetryReason(RetryReasonCaptureMechanism mechanism, int rank, String abbreviation) { + this.mechanism = mechanism; + this.rank = rank; + this.abbreviation = abbreviation; } - RetryReason(RetryReasonCaptureMechanism mechanism, int rank) { + RetryReason(RetryReasonCaptureMechanism mechanism, int rank, RetryReasonAbbreviationCreator abbreviationCreator) { this.mechanism = mechanism; this.rank = rank; + this.retryReasonAbbreviationCreator = abbreviationCreator; + } + + public String getAbbreviation(Exception ex, Integer statusCode, String serverErrorMessage) { + if(abbreviation != null) { + return abbreviation; + } + if(retryReasonAbbreviationCreator != null) { + return retryReasonAbbreviationCreator.getAbbreviation(ex, statusCode, serverErrorMessage); + } + return null; } static RetryReason getEnum(Exception ex, Integer statusCode) { diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java new file mode 100644 index 0000000000000..4f8c894e36187 --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java @@ -0,0 +1,5 @@ +package org.apache.hadoop.fs.azurebfs.services; + +public interface RetryReasonAbbreviationCreator { + String getAbbreviation(Exception ex, Integer statusCode, String serverErrorMessage); +} diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java index e41db5a619e1d..3a80612db3897 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java @@ -184,8 +184,11 @@ public void constructHeader(AbfsHttpOperation httpOperation, List previo private String addFailureReasons(final String header, final List previousFailures) { String headerResult = header; + if(previousFailures.size() > 0) { + headerResult += ":"; + } for(int iter = previousFailures.size() -1; iter >=0; iter--) { - headerResult += previousFailures.get(iter); + headerResult += String.format("%d_%s", iter, previousFailures.get(iter)); if(headerResult.length() > MAX_CLIENT_REQUEST_ID) { headerResult = headerResult.substring(0, MAX_CLIENT_REQUEST_ID); break; diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java new file mode 100644 index 0000000000000..4261b65d83462 --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java @@ -0,0 +1,26 @@ +package org.apache.hadoop.fs.azurebfs.services; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; +import org.mockito.Mockito; + +public class TestAbfsRestOperation { + + @Test + public void testClientRequestIdForTimeoutRetry() throws Exception { + List headers = new ArrayList<>(); + + AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( + AbfsRestOperationType.ReadFile, + Mockito.mock(AbfsClient.class), + "PUT", + null, + new ArrayList<>() + )); + + AbfsHttpOperation httpOperation = Mockito.spy(new AbfsHttpOperation(null, "PUT", new ArrayList<>())); + + } +} From eece65f98ed34305d34f193fd971e0fdbaa969b5 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Fri, 13 Jan 2023 02:55:16 -0800 Subject: [PATCH 04/38] fixed test for connect timed out --- .../azurebfs/services/AbfsHttpOperation.java | 2 +- .../azurebfs/services/AbfsRestOperation.java | 20 ++++-- .../fs/azurebfs/services/RetryReason.java | 30 ++++++-- .../fs/azurebfs/utils/TracingContext.java | 22 ++---- .../services/TestAbfsRestOperation.java | 72 ++++++++++++++++++- 5 files changed, 115 insertions(+), 31 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsHttpOperation.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsHttpOperation.java index 413bf3686898b..2b5a8232d1d7b 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsHttpOperation.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsHttpOperation.java @@ -277,7 +277,7 @@ public AbfsHttpOperation(final URL url, final String method, final List failureReasons = new ArrayList<>(); + private String failureReasons = null; /** * Checks if there is non-null HTTP response. @@ -211,7 +212,7 @@ public void execute(TracingContext tracingContext) private void completeExecute(TracingContext tracingContext) throws AzureBlobFileSystemException { // see if we have latency reports from the previous requests - String latencyHeader = this.client.getAbfsPerfTracker().getClientLatency(); + String latencyHeader = getClientLatency(); if (latencyHeader != null && !latencyHeader.isEmpty()) { AbfsHttpHeader httpHeader = new AbfsHttpHeader(HttpHeaderConfigurations.X_MS_ABFS_CLIENT_LATENCY, latencyHeader); @@ -240,6 +241,11 @@ private void completeExecute(TracingContext tracingContext) LOG.trace("{} REST operation complete", operationType); } + @VisibleForTesting + String getClientLatency() { + return this.client.getAbfsPerfTracker().getClientLatency(); + } + /** * Executes a single HTTP operation to complete the REST operation. If it * fails, there may be a retry. The retryCount is incremented with each @@ -306,7 +312,7 @@ private boolean executeHttpOperation(final int retryCount, } catch (UnknownHostException ex) { String hostname = null; hostname = httpOperation.getHost(); - failureReasons.add(RetryReason.UNKNOWN_HOST.name()); + failureReasons = RetryReason.UNKNOWN_HOST.getAbbreviation(ex, null, null); LOG.warn("Unknown host name: {}. Retrying to resolve the host name...", hostname); if (!client.getRetryPolicy().shouldRetry(retryCount, -1)) { @@ -318,7 +324,7 @@ private boolean executeHttpOperation(final int retryCount, LOG.debug("HttpRequestFailure: {}, {}", httpOperation, ex); } - failureReasons.add(RetryReason.getEnum(ex, -1).name()); + failureReasons = RetryReason.getEnum(ex, -1).getAbbreviation(ex, -1, ""); if (!client.getRetryPolicy().shouldRetry(retryCount, -1)) { throw new InvalidAbfsRestOperationException(ex); @@ -333,8 +339,7 @@ private boolean executeHttpOperation(final int retryCount, if (client.getRetryPolicy().shouldRetry(retryCount, httpOperation.getStatusCode())) { int status = httpOperation.getStatusCode(); - failureReasons.add(String.format("%s_%d", - RetryReason.getEnum(null, status).name(), status)); + failureReasons = RetryReason.getEnum(null, status).getAbbreviation(null, status, httpOperation.getStorageErrorMessage()); return false; } @@ -343,7 +348,8 @@ private boolean executeHttpOperation(final int retryCount, return true; } - private AbfsHttpOperation getHttpOperation() throws IOException { + @VisibleForTesting + AbfsHttpOperation getHttpOperation() throws IOException { return new AbfsHttpOperation(url, method, requestHeaders); } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index cb5035ec5d5c4..88c35978bc61e 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -2,7 +2,9 @@ import java.io.IOException; import java.net.SocketException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.stream.Collectors; public enum RetryReason { @@ -12,14 +14,14 @@ public enum RetryReason { //result.getStorageErrorMessage() // CONNECTION_TIMEOUT(((exceptionCaptured, statusCode) -> { - return "connect timed out".equalsIgnoreCase(exceptionCaptured.getMessage()); + return exceptionCaptured != null && "connect timed out".equalsIgnoreCase(exceptionCaptured.getMessage()); }), 2, "CT"), READ_TIMEOUT(((exceptionCaptured, statusCode) -> { - return "Read timed out".equalsIgnoreCase(exceptionCaptured.getMessage()); + return exceptionCaptured != null && "Read timed out".equalsIgnoreCase(exceptionCaptured.getMessage()); }), 2, "RT"), UNKNOWN_HOST("UH"), CONNECTION_RESET(((exceptionCaptured, statusCode) -> { - return exceptionCaptured.getMessage().contains("Connection reset"); + return exceptionCaptured != null && exceptionCaptured.getMessage().contains("Connection reset"); }), 2, "CR"), STATUS_5XX(((exceptionCaptured, statusCode) -> { return statusCode/100 == 5; @@ -84,10 +86,28 @@ public String getAbbreviation(Exception ex, Integer statusCode, String serverErr return null; } + private static List retryReasonLSortedist; + + private synchronized static void sortRetryReason() { + if(retryReasonLSortedist != null) { + return; + } + List list = new ArrayList<>(); + for(RetryReason reason : values()) { + list.add(reason); + } + list.sort((c1, c2) -> { + return c1.rank - c2.rank; + }); + retryReasonLSortedist = list; + } + static RetryReason getEnum(Exception ex, Integer statusCode) { RetryReason retryReasonResult = null; - for(RetryReason retryReason : Arrays.stream(values()).sorted().collect( - Collectors.toList())) { + if(retryReasonLSortedist == null) { + sortRetryReason(); + } + for(RetryReason retryReason : retryReasonLSortedist) { if(retryReason.mechanism != null) { if(retryReason.mechanism.canCapture(ex, statusCode)) { retryReasonResult = retryReason; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java index 3a80612db3897..b7a0ea319894b 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java @@ -156,10 +156,10 @@ public void setListener(Listener listener) { * X_MS_CLIENT_REQUEST_ID header of the http operation * @param httpOperation AbfsHttpOperation instance to set header into * connection - * @param previousFailures List of failures seen before this API trigger on + * @param previousFailure List of failures seen before this API trigger on * same operation from AbfsClient. */ - public void constructHeader(AbfsHttpOperation httpOperation, List previousFailures) { + public void constructHeader(AbfsHttpOperation httpOperation, String previousFailure) { clientRequestId = UUID.randomUUID().toString(); switch (format) { case ALL_ID_FORMAT: // Optional IDs (e.g. streamId) may be empty @@ -167,7 +167,7 @@ public void constructHeader(AbfsHttpOperation httpOperation, List previo clientCorrelationID + ":" + clientRequestId + ":" + fileSystemID + ":" + primaryRequestId + ":" + streamID + ":" + opType + ":" + retryCount; - header = addFailureReasons(header, previousFailures); + header = addFailureReasons(header, previousFailure); break; case TWO_ID_FORMAT: header = clientCorrelationID + ":" + clientRequestId; @@ -182,19 +182,11 @@ public void constructHeader(AbfsHttpOperation httpOperation, List previo } private String addFailureReasons(final String header, - final List previousFailures) { - String headerResult = header; - if(previousFailures.size() > 0) { - headerResult += ":"; + final String previousFailure) { + if(previousFailure == null) { + return header; } - for(int iter = previousFailures.size() -1; iter >=0; iter--) { - headerResult += String.format("%d_%s", iter, previousFailures.get(iter)); - if(headerResult.length() > MAX_CLIENT_REQUEST_ID) { - headerResult = headerResult.substring(0, MAX_CLIENT_REQUEST_ID); - break; - } - } - return headerResult; + return String.format("%s_%s", header, previousFailure); } /** diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java index 4261b65d83462..80183df6bd456 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java @@ -1,26 +1,92 @@ package org.apache.hadoop.fs.azurebfs.services; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.SocketException; +import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.List; +import org.assertj.core.api.Assertions; import org.junit.Test; +import org.mockito.Mock; import org.mockito.Mockito; +import org.apache.hadoop.fs.azurebfs.utils.TracingContext; + +import static org.apache.hadoop.fs.azurebfs.services.AuthType.OAuth; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.nullable; + public class TestAbfsRestOperation { @Test public void testClientRequestIdForTimeoutRetry() throws Exception { - List headers = new ArrayList<>(); + + AbfsClient abfsClient = Mockito.mock(AbfsClient.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); + addMockBehaviourToAbfsClient(abfsClient, retryPolicy); + AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( AbfsRestOperationType.ReadFile, - Mockito.mock(AbfsClient.class), + abfsClient, "PUT", null, new ArrayList<>() )); - AbfsHttpOperation httpOperation = Mockito.spy(new AbfsHttpOperation(null, "PUT", new ArrayList<>())); + AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); + addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); + + Mockito.doThrow(new SocketTimeoutException("connect timed out")).doNothing() + .when(httpOperation).processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); + + Mockito.doReturn(200).when(httpOperation).getStatusCode(); + + TracingContext tracingContext = Mockito.mock(TracingContext.class); + Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); + + int[] count = new int[1]; + count[0] = 0; + Mockito.doAnswer(invocationOnMock -> { + if(count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("CT"); + } + if(count[0] == 2) { + throw new Exception(); + } + count[0]++; + return null; + }).when(tracingContext).constructHeader(any(), any()); + abfsRestOperation.execute(tracingContext); + + } + + private void addMockBehaviourToRestOpAndHttpOp(final AbfsRestOperation abfsRestOperation, + final AbfsHttpOperation httpOperation) throws IOException { + HttpURLConnection httpURLConnection = Mockito.mock(HttpURLConnection.class); + Mockito.doNothing().when(httpURLConnection).setRequestProperty(nullable(String.class), nullable(String.class)); + Mockito.doReturn(httpURLConnection).when(httpOperation).getConnection(); + Mockito.doReturn("").when(abfsRestOperation).getClientLatency(); + + //new AbfsHttpOperation(null, "PUT", new ArrayList<>())); + Mockito.doReturn(httpOperation).when(abfsRestOperation).getHttpOperation(); } + + private void addMockBehaviourToAbfsClient(final AbfsClient abfsClient, + final ExponentialRetryPolicy retryPolicy) throws IOException { + Mockito.doReturn(OAuth).when(abfsClient).getAuthType(); + Mockito.doReturn("").when(abfsClient).getAccessToken(); + AbfsThrottlingIntercept intercept = Mockito.mock(AbfsThrottlingIntercept.class); + Mockito.doReturn(intercept).when(abfsClient).getIntercept(); + Mockito.doNothing().when(intercept).sendingRequest(any(), nullable(AbfsCounters.class)); + Mockito.doNothing().when(intercept).updateMetrics(any(), any()); + + Mockito.doReturn(retryPolicy).when(abfsClient).getRetryPolicy(); + Mockito.doReturn(true).when(retryPolicy).shouldRetry(nullable(Integer.class), nullable(Integer.class)); + Mockito.doReturn(false).when(retryPolicy).shouldRetry(1, 200); + } + } From 40adc3e8b9444fa0ded00afee183f343a563a55c Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Fri, 13 Jan 2023 03:30:57 -0800 Subject: [PATCH 05/38] testabfsrestOperation: to add 5xx tests --- .../fs/azurebfs/services/RetryReason.java | 2 +- .../services/TestAbfsRestOperation.java | 261 +++++++++++++++++- 2 files changed, 259 insertions(+), 4 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index 88c35978bc61e..5700863df263f 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -21,7 +21,7 @@ public enum RetryReason { }), 2, "RT"), UNKNOWN_HOST("UH"), CONNECTION_RESET(((exceptionCaptured, statusCode) -> { - return exceptionCaptured != null && exceptionCaptured.getMessage().contains("Connection reset"); + return exceptionCaptured != null && exceptionCaptured.getMessage() != null && exceptionCaptured.getMessage().contains("Connection reset"); }), 2, "CR"), STATUS_5XX(((exceptionCaptured, statusCode) -> { return statusCode/100 == 5; diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java index 80183df6bd456..7b75214906673 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java @@ -1,9 +1,11 @@ package org.apache.hadoop.fs.azurebfs.services; import java.io.IOException; +import java.io.InterruptedIOException; import java.net.HttpURLConnection; import java.net.SocketException; import java.net.SocketTimeoutException; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; @@ -21,7 +23,7 @@ public class TestAbfsRestOperation { @Test - public void testClientRequestIdForTimeoutRetry() throws Exception { + public void testClientRequestIdForConnectTimeoutRetry() throws Exception { AbfsClient abfsClient = Mockito.mock(AbfsClient.class); ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); @@ -53,14 +55,267 @@ public void testClientRequestIdForTimeoutRetry() throws Exception { if(count[0] == 1) { Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("CT"); } - if(count[0] == 2) { - throw new Exception(); + count[0]++; + return null; + }).when(tracingContext).constructHeader(any(), any()); + + abfsRestOperation.execute(tracingContext); + Assertions.assertThat(count[0]).isEqualTo(2); + } + + @Test + public void testClientRequestIdForReadTimeoutRetry() throws Exception { + + AbfsClient abfsClient = Mockito.mock(AbfsClient.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); + addMockBehaviourToAbfsClient(abfsClient, retryPolicy); + + + AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( + AbfsRestOperationType.ReadFile, + abfsClient, + "PUT", + null, + new ArrayList<>() + )); + + AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); + addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); + + Mockito.doThrow(new SocketTimeoutException("Read timed out")).doNothing() + .when(httpOperation).processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); + + Mockito.doReturn(200).when(httpOperation).getStatusCode(); + + TracingContext tracingContext = Mockito.mock(TracingContext.class); + Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); + + int[] count = new int[1]; + count[0] = 0; + Mockito.doAnswer(invocationOnMock -> { + if(count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("RT"); + } + count[0]++; + return null; + }).when(tracingContext).constructHeader(any(), any()); + + abfsRestOperation.execute(tracingContext); + Assertions.assertThat(count[0]).isEqualTo(2); + } + + @Test + public void testClientRequestIdForUnknownHostRetry() throws Exception { + + AbfsClient abfsClient = Mockito.mock(AbfsClient.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); + addMockBehaviourToAbfsClient(abfsClient, retryPolicy); + + + AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( + AbfsRestOperationType.ReadFile, + abfsClient, + "PUT", + null, + new ArrayList<>() + )); + + AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); + addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); + + Mockito.doThrow(new UnknownHostException()).doNothing() + .when(httpOperation).processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); + + Mockito.doReturn(200).when(httpOperation).getStatusCode(); + + TracingContext tracingContext = Mockito.mock(TracingContext.class); + Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); + + int[] count = new int[1]; + count[0] = 0; + Mockito.doAnswer(invocationOnMock -> { + if(count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("UH"); + } + count[0]++; + return null; + }).when(tracingContext).constructHeader(any(), any()); + + abfsRestOperation.execute(tracingContext); + Assertions.assertThat(count[0]).isEqualTo(2); + + } + + @Test + public void testClientRequestIdForConnectionResetRetry() throws Exception { + + AbfsClient abfsClient = Mockito.mock(AbfsClient.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); + addMockBehaviourToAbfsClient(abfsClient, retryPolicy); + + + AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( + AbfsRestOperationType.ReadFile, + abfsClient, + "PUT", + null, + new ArrayList<>() + )); + + AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); + addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); + + Mockito.doThrow(new SocketException("Connection reset by peer")).doNothing() + .when(httpOperation).processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); + + Mockito.doReturn(200).when(httpOperation).getStatusCode(); + + TracingContext tracingContext = Mockito.mock(TracingContext.class); + Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); + + int[] count = new int[1]; + count[0] = 0; + Mockito.doAnswer(invocationOnMock -> { + if(count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("CR"); + } + count[0]++; + return null; + }).when(tracingContext).constructHeader(any(), any()); + + abfsRestOperation.execute(tracingContext); + Assertions.assertThat(count[0]).isEqualTo(2); + } + + @Test + public void testClientRequestIdForUnknownSocketExRetry() throws Exception { + + AbfsClient abfsClient = Mockito.mock(AbfsClient.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); + addMockBehaviourToAbfsClient(abfsClient, retryPolicy); + + + AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( + AbfsRestOperationType.ReadFile, + abfsClient, + "PUT", + null, + new ArrayList<>() + )); + + AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); + addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); + + Mockito.doThrow(new SocketException("unknown")).doNothing() + .when(httpOperation).processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); + + Mockito.doReturn(200).when(httpOperation).getStatusCode(); + + TracingContext tracingContext = Mockito.mock(TracingContext.class); + Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); + + int[] count = new int[1]; + count[0] = 0; + Mockito.doAnswer(invocationOnMock -> { + if(count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("SE"); + } + count[0]++; + return null; + }).when(tracingContext).constructHeader(any(), any()); + + abfsRestOperation.execute(tracingContext); + Assertions.assertThat(count[0]).isEqualTo(2); + } + + @Test + public void testClientRequestIdForIOERetry() throws Exception { + + AbfsClient abfsClient = Mockito.mock(AbfsClient.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); + addMockBehaviourToAbfsClient(abfsClient, retryPolicy); + + + AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( + AbfsRestOperationType.ReadFile, + abfsClient, + "PUT", + null, + new ArrayList<>() + )); + + AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); + addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); + + Mockito.doThrow(new InterruptedIOException()).doNothing() + .when(httpOperation).processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); + + Mockito.doReturn(200).when(httpOperation).getStatusCode(); + + TracingContext tracingContext = Mockito.mock(TracingContext.class); + Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); + + int[] count = new int[1]; + count[0] = 0; + Mockito.doAnswer(invocationOnMock -> { + if(count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("IOE"); + } + count[0]++; + return null; + }).when(tracingContext).constructHeader(any(), any()); + + abfsRestOperation.execute(tracingContext); + Assertions.assertThat(count[0]).isEqualTo(2); + } + + @Test + public void testClientRequestIdFor4XXRetry() throws Exception { + + AbfsClient abfsClient = Mockito.mock(AbfsClient.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); + addMockBehaviourToAbfsClient(abfsClient, retryPolicy); + + + AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( + AbfsRestOperationType.ReadFile, + abfsClient, + "PUT", + null, + new ArrayList<>() + )); + + AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); + addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); + + Mockito.doNothing().doNothing() + .when(httpOperation).processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); + + int[] statusCount = new int[1]; + statusCount[0] = 0; + Mockito.doAnswer(answer -> { + if(statusCount[0] <= 5) { + statusCount[0]++; + return 400; + } + return 200; + }).when(httpOperation).getStatusCode(); + + TracingContext tracingContext = Mockito.mock(TracingContext.class); + Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); + + int[] count = new int[1]; + count[0] = 0; + Mockito.doAnswer(invocationOnMock -> { + if(count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("400"); } count[0]++; return null; }).when(tracingContext).constructHeader(any(), any()); abfsRestOperation.execute(tracingContext); + Assertions.assertThat(count[0]).isEqualTo(2); } From 77c9d2112f96336fcbafc20a6be454371e7cd083 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Fri, 13 Jan 2023 03:44:32 -0800 Subject: [PATCH 06/38] test added --- .../azurebfs/services/AbfsHttpOperation.java | 2 +- .../fs/azurebfs/services/RetryReason.java | 60 +++-- .../services/TestAbfsRestOperation.java | 213 ++++++++++++++---- 3 files changed, 211 insertions(+), 64 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsHttpOperation.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsHttpOperation.java index 2b5a8232d1d7b..413bf3686898b 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsHttpOperation.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsHttpOperation.java @@ -277,7 +277,7 @@ public AbfsHttpOperation(final URL url, final String method, final List { - return exceptionCaptured != null && "connect timed out".equalsIgnoreCase(exceptionCaptured.getMessage()); + return exceptionCaptured != null && "connect timed out".equalsIgnoreCase( + exceptionCaptured.getMessage()); }), 2, "CT"), READ_TIMEOUT(((exceptionCaptured, statusCode) -> { - return exceptionCaptured != null && "Read timed out".equalsIgnoreCase(exceptionCaptured.getMessage()); + return exceptionCaptured != null && "Read timed out".equalsIgnoreCase( + exceptionCaptured.getMessage()); }), 2, "RT"), UNKNOWN_HOST("UH"), CONNECTION_RESET(((exceptionCaptured, statusCode) -> { - return exceptionCaptured != null && exceptionCaptured.getMessage() != null && exceptionCaptured.getMessage().contains("Connection reset"); + return exceptionCaptured != null && exceptionCaptured.getMessage() != null + && exceptionCaptured.getMessage().contains("Connection reset"); }), 2, "CR"), STATUS_5XX(((exceptionCaptured, statusCode) -> { - return statusCode/100 == 5; + return statusCode / 100 == 5; }), 0, ((ex, statusCode, serverErrorMessage) -> { - if(statusCode == 503) { + if (statusCode == 503) { //ref: https://github.com/apache/hadoop/pull/4564/files#diff-75a2f54df6618d4015c63812e6a9916ddfb475d246850edfd2a6f57e36805e79 - serverErrorMessage = serverErrorMessage.split(System.lineSeparator(), 2)[0]; - if("Ingress is over the account limit.".equalsIgnoreCase(serverErrorMessage)) { + serverErrorMessage = serverErrorMessage.split(System.lineSeparator(), + 2)[0]; + if ("Ingress is over the account limit.".equalsIgnoreCase( + serverErrorMessage)) { return "ING"; } - if("Egress is over the account limit.".equalsIgnoreCase(serverErrorMessage)) { + if ("Egress is over the account limit.".equalsIgnoreCase( + serverErrorMessage)) { return "EGR"; } - if("Operations per second is over the account limit.".equalsIgnoreCase(serverErrorMessage)) { + if ("Operations per second is over the account limit.".equalsIgnoreCase( + serverErrorMessage)) { return "OPR"; } return "503"; @@ -43,7 +50,7 @@ public enum RetryReason { return statusCode + ""; })), STATUS_4XX(((exceptionCaptured, statusCode) -> { - return statusCode/100 == 4; + return statusCode / 100 == 4; }), 0, ((ex, statusCode, serverErrorMessage) -> { return statusCode + ""; })), @@ -55,7 +62,9 @@ public enum RetryReason { }), 0, "IOE"); private RetryReasonCaptureMechanism mechanism = null; + private RetryReasonAbbreviationCreator retryReasonAbbreviationCreator = null; + private int rank = 0; private String abbreviation; @@ -64,24 +73,31 @@ public enum RetryReason { this.abbreviation = abbreviation; } - RetryReason(RetryReasonCaptureMechanism mechanism, int rank, String abbreviation) { + RetryReason(RetryReasonCaptureMechanism mechanism, + int rank, + String abbreviation) { this.mechanism = mechanism; this.rank = rank; this.abbreviation = abbreviation; } - RetryReason(RetryReasonCaptureMechanism mechanism, int rank, RetryReasonAbbreviationCreator abbreviationCreator) { + RetryReason(RetryReasonCaptureMechanism mechanism, + int rank, + RetryReasonAbbreviationCreator abbreviationCreator) { this.mechanism = mechanism; this.rank = rank; this.retryReasonAbbreviationCreator = abbreviationCreator; } - public String getAbbreviation(Exception ex, Integer statusCode, String serverErrorMessage) { - if(abbreviation != null) { + public String getAbbreviation(Exception ex, + Integer statusCode, + String serverErrorMessage) { + if (abbreviation != null) { return abbreviation; } - if(retryReasonAbbreviationCreator != null) { - return retryReasonAbbreviationCreator.getAbbreviation(ex, statusCode, serverErrorMessage); + if (retryReasonAbbreviationCreator != null) { + return retryReasonAbbreviationCreator.getAbbreviation(ex, statusCode, + serverErrorMessage); } return null; } @@ -89,11 +105,11 @@ public String getAbbreviation(Exception ex, Integer statusCode, String serverErr private static List retryReasonLSortedist; private synchronized static void sortRetryReason() { - if(retryReasonLSortedist != null) { + if (retryReasonLSortedist != null) { return; } List list = new ArrayList<>(); - for(RetryReason reason : values()) { + for (RetryReason reason : values()) { list.add(reason); } list.sort((c1, c2) -> { @@ -104,12 +120,12 @@ private synchronized static void sortRetryReason() { static RetryReason getEnum(Exception ex, Integer statusCode) { RetryReason retryReasonResult = null; - if(retryReasonLSortedist == null) { + if (retryReasonLSortedist == null) { sortRetryReason(); } - for(RetryReason retryReason : retryReasonLSortedist) { - if(retryReason.mechanism != null) { - if(retryReason.mechanism.canCapture(ex, statusCode)) { + for (RetryReason retryReason : retryReasonLSortedist) { + if (retryReason.mechanism != null) { + if (retryReason.mechanism.canCapture(ex, statusCode)) { retryReasonResult = retryReason; } } diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java index 7b75214906673..aa6578ceb6757 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java @@ -26,12 +26,13 @@ public class TestAbfsRestOperation { public void testClientRequestIdForConnectTimeoutRetry() throws Exception { AbfsClient abfsClient = Mockito.mock(AbfsClient.class); - ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock( + ExponentialRetryPolicy.class); addMockBehaviourToAbfsClient(abfsClient, retryPolicy); AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( - AbfsRestOperationType.ReadFile, + AbfsRestOperationType.ReadFile, abfsClient, "PUT", null, @@ -41,8 +42,11 @@ public void testClientRequestIdForConnectTimeoutRetry() throws Exception { AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - Mockito.doThrow(new SocketTimeoutException("connect timed out")).doNothing() - .when(httpOperation).processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); + Mockito.doThrow(new SocketTimeoutException("connect timed out")) + .doNothing() + .when(httpOperation) + .processResponse(nullable(byte[].class), nullable(int.class), + nullable(int.class)); Mockito.doReturn(200).when(httpOperation).getStatusCode(); @@ -52,8 +56,9 @@ public void testClientRequestIdForConnectTimeoutRetry() throws Exception { int[] count = new int[1]; count[0] = 0; Mockito.doAnswer(invocationOnMock -> { - if(count[0] == 1) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("CT"); + if (count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)) + .isEqualTo("CT"); } count[0]++; return null; @@ -67,7 +72,8 @@ public void testClientRequestIdForConnectTimeoutRetry() throws Exception { public void testClientRequestIdForReadTimeoutRetry() throws Exception { AbfsClient abfsClient = Mockito.mock(AbfsClient.class); - ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock( + ExponentialRetryPolicy.class); addMockBehaviourToAbfsClient(abfsClient, retryPolicy); @@ -82,8 +88,11 @@ public void testClientRequestIdForReadTimeoutRetry() throws Exception { AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - Mockito.doThrow(new SocketTimeoutException("Read timed out")).doNothing() - .when(httpOperation).processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); + Mockito.doThrow(new SocketTimeoutException("Read timed out")) + .doNothing() + .when(httpOperation) + .processResponse(nullable(byte[].class), nullable(int.class), + nullable(int.class)); Mockito.doReturn(200).when(httpOperation).getStatusCode(); @@ -93,8 +102,9 @@ public void testClientRequestIdForReadTimeoutRetry() throws Exception { int[] count = new int[1]; count[0] = 0; Mockito.doAnswer(invocationOnMock -> { - if(count[0] == 1) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("RT"); + if (count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)) + .isEqualTo("RT"); } count[0]++; return null; @@ -108,7 +118,8 @@ public void testClientRequestIdForReadTimeoutRetry() throws Exception { public void testClientRequestIdForUnknownHostRetry() throws Exception { AbfsClient abfsClient = Mockito.mock(AbfsClient.class); - ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock( + ExponentialRetryPolicy.class); addMockBehaviourToAbfsClient(abfsClient, retryPolicy); @@ -123,8 +134,11 @@ public void testClientRequestIdForUnknownHostRetry() throws Exception { AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - Mockito.doThrow(new UnknownHostException()).doNothing() - .when(httpOperation).processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); + Mockito.doThrow(new UnknownHostException()) + .doNothing() + .when(httpOperation) + .processResponse(nullable(byte[].class), nullable(int.class), + nullable(int.class)); Mockito.doReturn(200).when(httpOperation).getStatusCode(); @@ -134,8 +148,9 @@ public void testClientRequestIdForUnknownHostRetry() throws Exception { int[] count = new int[1]; count[0] = 0; Mockito.doAnswer(invocationOnMock -> { - if(count[0] == 1) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("UH"); + if (count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)) + .isEqualTo("UH"); } count[0]++; return null; @@ -150,7 +165,8 @@ public void testClientRequestIdForUnknownHostRetry() throws Exception { public void testClientRequestIdForConnectionResetRetry() throws Exception { AbfsClient abfsClient = Mockito.mock(AbfsClient.class); - ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock( + ExponentialRetryPolicy.class); addMockBehaviourToAbfsClient(abfsClient, retryPolicy); @@ -165,8 +181,11 @@ public void testClientRequestIdForConnectionResetRetry() throws Exception { AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - Mockito.doThrow(new SocketException("Connection reset by peer")).doNothing() - .when(httpOperation).processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); + Mockito.doThrow(new SocketException("Connection reset by peer")) + .doNothing() + .when(httpOperation) + .processResponse(nullable(byte[].class), nullable(int.class), + nullable(int.class)); Mockito.doReturn(200).when(httpOperation).getStatusCode(); @@ -176,8 +195,9 @@ public void testClientRequestIdForConnectionResetRetry() throws Exception { int[] count = new int[1]; count[0] = 0; Mockito.doAnswer(invocationOnMock -> { - if(count[0] == 1) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("CR"); + if (count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)) + .isEqualTo("CR"); } count[0]++; return null; @@ -191,7 +211,8 @@ public void testClientRequestIdForConnectionResetRetry() throws Exception { public void testClientRequestIdForUnknownSocketExRetry() throws Exception { AbfsClient abfsClient = Mockito.mock(AbfsClient.class); - ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock( + ExponentialRetryPolicy.class); addMockBehaviourToAbfsClient(abfsClient, retryPolicy); @@ -206,8 +227,11 @@ public void testClientRequestIdForUnknownSocketExRetry() throws Exception { AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - Mockito.doThrow(new SocketException("unknown")).doNothing() - .when(httpOperation).processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); + Mockito.doThrow(new SocketException("unknown")) + .doNothing() + .when(httpOperation) + .processResponse(nullable(byte[].class), nullable(int.class), + nullable(int.class)); Mockito.doReturn(200).when(httpOperation).getStatusCode(); @@ -217,8 +241,9 @@ public void testClientRequestIdForUnknownSocketExRetry() throws Exception { int[] count = new int[1]; count[0] = 0; Mockito.doAnswer(invocationOnMock -> { - if(count[0] == 1) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("SE"); + if (count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)) + .isEqualTo("SE"); } count[0]++; return null; @@ -232,7 +257,8 @@ public void testClientRequestIdForUnknownSocketExRetry() throws Exception { public void testClientRequestIdForIOERetry() throws Exception { AbfsClient abfsClient = Mockito.mock(AbfsClient.class); - ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock( + ExponentialRetryPolicy.class); addMockBehaviourToAbfsClient(abfsClient, retryPolicy); @@ -247,8 +273,11 @@ public void testClientRequestIdForIOERetry() throws Exception { AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - Mockito.doThrow(new InterruptedIOException()).doNothing() - .when(httpOperation).processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); + Mockito.doThrow(new InterruptedIOException()) + .doNothing() + .when(httpOperation) + .processResponse(nullable(byte[].class), nullable(int.class), + nullable(int.class)); Mockito.doReturn(200).when(httpOperation).getStatusCode(); @@ -258,8 +287,9 @@ public void testClientRequestIdForIOERetry() throws Exception { int[] count = new int[1]; count[0] = 0; Mockito.doAnswer(invocationOnMock -> { - if(count[0] == 1) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("IOE"); + if (count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)) + .isEqualTo("IOE"); } count[0]++; return null; @@ -273,7 +303,8 @@ public void testClientRequestIdForIOERetry() throws Exception { public void testClientRequestIdFor4XXRetry() throws Exception { AbfsClient abfsClient = Mockito.mock(AbfsClient.class); - ExponentialRetryPolicy retryPolicy = Mockito.mock(ExponentialRetryPolicy.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock( + ExponentialRetryPolicy.class); addMockBehaviourToAbfsClient(abfsClient, retryPolicy); @@ -288,13 +319,16 @@ public void testClientRequestIdFor4XXRetry() throws Exception { AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - Mockito.doNothing().doNothing() - .when(httpOperation).processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); + Mockito.doNothing() + .doNothing() + .when(httpOperation) + .processResponse(nullable(byte[].class), nullable(int.class), + nullable(int.class)); int[] statusCount = new int[1]; statusCount[0] = 0; Mockito.doAnswer(answer -> { - if(statusCount[0] <= 5) { + if (statusCount[0] <= 5) { statusCount[0]++; return 400; } @@ -307,8 +341,98 @@ public void testClientRequestIdFor4XXRetry() throws Exception { int[] count = new int[1]; count[0] = 0; Mockito.doAnswer(invocationOnMock -> { - if(count[0] == 1) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)).isEqualTo("400"); + if (count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)) + .isEqualTo("400"); + } + count[0]++; + return null; + }).when(tracingContext).constructHeader(any(), any()); + + abfsRestOperation.execute(tracingContext); + Assertions.assertThat(count[0]).isEqualTo(2); + + } + + @Test + public void testClientRequestIdFor500Retry() throws Exception { + testClientRequestIdFor5XXRetry(500, "", "500"); + } + + @Test + public void testClientRequestIdFor503INGRetry() throws Exception { + testClientRequestIdFor5XXRetry(503, "Ingress is over the account limit.", + "ING"); + } + + @Test + public void testClientRequestIdFor503egrRetry() throws Exception { + testClientRequestIdFor5XXRetry(503, "Egress is over the account limit.", + "EGR"); + } + + @Test + public void testClientRequestIdFor503OPRRetry() throws Exception { + testClientRequestIdFor5XXRetry(503, + "Operations per second is over the account limit.", "OPR"); + } + + @Test + public void testClientRequestIdFor503OtherRetry() throws Exception { + testClientRequestIdFor5XXRetry(503, "Other.", "503"); + } + + + private void testClientRequestIdFor5XXRetry(int status, + String serverErrorMessage, + String keyExpected) throws Exception { + + AbfsClient abfsClient = Mockito.mock(AbfsClient.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock( + ExponentialRetryPolicy.class); + addMockBehaviourToAbfsClient(abfsClient, retryPolicy); + + + AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( + AbfsRestOperationType.ReadFile, + abfsClient, + "PUT", + null, + new ArrayList<>() + )); + + AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); + addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); + + Mockito.doNothing() + .doNothing() + .when(httpOperation) + .processResponse(nullable(byte[].class), nullable(int.class), + nullable(int.class)); + + int[] statusCount = new int[1]; + statusCount[0] = 0; + Mockito.doAnswer(answer -> { + if (statusCount[0] <= 5) { + statusCount[0]++; + return status; + } + return 200; + }).when(httpOperation).getStatusCode(); + + Mockito.doReturn(serverErrorMessage) + .when(httpOperation) + .getStorageErrorMessage(); + + TracingContext tracingContext = Mockito.mock(TracingContext.class); + Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); + + int[] count = new int[1]; + count[0] = 0; + Mockito.doAnswer(invocationOnMock -> { + if (count[0] == 1) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)) + .isEqualTo(keyExpected); } count[0]++; return null; @@ -322,7 +446,9 @@ public void testClientRequestIdFor4XXRetry() throws Exception { private void addMockBehaviourToRestOpAndHttpOp(final AbfsRestOperation abfsRestOperation, final AbfsHttpOperation httpOperation) throws IOException { HttpURLConnection httpURLConnection = Mockito.mock(HttpURLConnection.class); - Mockito.doNothing().when(httpURLConnection).setRequestProperty(nullable(String.class), nullable(String.class)); + Mockito.doNothing() + .when(httpURLConnection) + .setRequestProperty(nullable(String.class), nullable(String.class)); Mockito.doReturn(httpURLConnection).when(httpOperation).getConnection(); Mockito.doReturn("").when(abfsRestOperation).getClientLatency(); @@ -334,13 +460,18 @@ private void addMockBehaviourToAbfsClient(final AbfsClient abfsClient, final ExponentialRetryPolicy retryPolicy) throws IOException { Mockito.doReturn(OAuth).when(abfsClient).getAuthType(); Mockito.doReturn("").when(abfsClient).getAccessToken(); - AbfsThrottlingIntercept intercept = Mockito.mock(AbfsThrottlingIntercept.class); + AbfsThrottlingIntercept intercept = Mockito.mock( + AbfsThrottlingIntercept.class); Mockito.doReturn(intercept).when(abfsClient).getIntercept(); - Mockito.doNothing().when(intercept).sendingRequest(any(), nullable(AbfsCounters.class)); + Mockito.doNothing() + .when(intercept) + .sendingRequest(any(), nullable(AbfsCounters.class)); Mockito.doNothing().when(intercept).updateMetrics(any(), any()); Mockito.doReturn(retryPolicy).when(abfsClient).getRetryPolicy(); - Mockito.doReturn(true).when(retryPolicy).shouldRetry(nullable(Integer.class), nullable(Integer.class)); + Mockito.doReturn(true) + .when(retryPolicy) + .shouldRetry(nullable(Integer.class), nullable(Integer.class)); Mockito.doReturn(false).when(retryPolicy).shouldRetry(1, 200); } From b5d176bcf3f6cdd36a3b6894965828e82aef12ed Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Fri, 13 Jan 2023 03:51:32 -0800 Subject: [PATCH 07/38] test: testClientRequestIdForConnectAndReadTimeoutRetry --- .../services/TestAbfsRestOperation.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java index aa6578ceb6757..747c26de6c4cf 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java @@ -68,6 +68,57 @@ public void testClientRequestIdForConnectTimeoutRetry() throws Exception { Assertions.assertThat(count[0]).isEqualTo(2); } + @Test + public void testClientRequestIdForConnectAndReadTimeoutRetry() throws Exception { + + AbfsClient abfsClient = Mockito.mock(AbfsClient.class); + ExponentialRetryPolicy retryPolicy = Mockito.mock( + ExponentialRetryPolicy.class); + addMockBehaviourToAbfsClient(abfsClient, retryPolicy); + + + AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( + AbfsRestOperationType.ReadFile, + abfsClient, + "PUT", + null, + new ArrayList<>() + )); + + AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); + addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); + + Mockito.doThrow(new SocketTimeoutException("connect timed out")) + .doThrow(new SocketTimeoutException("read timed out")) + .doNothing() + .when(httpOperation) + .processResponse(nullable(byte[].class), nullable(int.class), + nullable(int.class)); + + Mockito.doReturn(200).when(httpOperation).getStatusCode(); + + TracingContext tracingContext = Mockito.mock(TracingContext.class); + Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); + + int[] count = new int[1]; + count[0] = 0; + Mockito.doAnswer(invocationOnMock -> { + if (count[0] == 1 ) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)) + .isEqualTo("CT"); + } + if(count[0] == 2) { + Assertions.assertThat((String) invocationOnMock.getArgument(1)) + .isEqualTo("RT"); + } + count[0]++; + return null; + }).when(tracingContext).constructHeader(any(), any()); + + abfsRestOperation.execute(tracingContext); + Assertions.assertThat(count[0]).isEqualTo(3); + } + @Test public void testClientRequestIdForReadTimeoutRetry() throws Exception { @@ -473,6 +524,7 @@ private void addMockBehaviourToAbfsClient(final AbfsClient abfsClient, .when(retryPolicy) .shouldRetry(nullable(Integer.class), nullable(Integer.class)); Mockito.doReturn(false).when(retryPolicy).shouldRetry(1, 200); + Mockito.doReturn(false).when(retryPolicy).shouldRetry(2, 200); } } From c980762c6293bf57ece9a781c1ad27170236e003 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Fri, 13 Jan 2023 03:55:19 -0800 Subject: [PATCH 08/38] small refactors --- .../fs/azurebfs/services/AbfsRestOperation.java | 11 +++++------ .../hadoop/fs/azurebfs/services/RetryReason.java | 7 ------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java index 6d722adbed848..858c6ab6e47d7 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java @@ -23,7 +23,6 @@ import java.net.HttpURLConnection; import java.net.URL; import java.net.UnknownHostException; -import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; @@ -75,7 +74,7 @@ public class AbfsRestOperation { private AbfsHttpOperation result; private AbfsCounters abfsCounters; - private String failureReasons = null; + private String failureReason = null; /** * Checks if there is non-null HTTP response. @@ -259,7 +258,7 @@ private boolean executeHttpOperation(final int retryCount, // initialize the HTTP request and open the connection httpOperation = getHttpOperation(); incrementCounter(AbfsStatistic.CONNECTIONS_MADE, 1); - tracingContext.constructHeader(httpOperation, failureReasons); + tracingContext.constructHeader(httpOperation, failureReason); switch(client.getAuthType()) { case Custom: @@ -312,7 +311,7 @@ private boolean executeHttpOperation(final int retryCount, } catch (UnknownHostException ex) { String hostname = null; hostname = httpOperation.getHost(); - failureReasons = RetryReason.UNKNOWN_HOST.getAbbreviation(ex, null, null); + failureReason = RetryReason.UNKNOWN_HOST.getAbbreviation(ex, null, null); LOG.warn("Unknown host name: {}. Retrying to resolve the host name...", hostname); if (!client.getRetryPolicy().shouldRetry(retryCount, -1)) { @@ -324,7 +323,7 @@ private boolean executeHttpOperation(final int retryCount, LOG.debug("HttpRequestFailure: {}, {}", httpOperation, ex); } - failureReasons = RetryReason.getEnum(ex, -1).getAbbreviation(ex, -1, ""); + failureReason = RetryReason.getEnum(ex, -1).getAbbreviation(ex, -1, ""); if (!client.getRetryPolicy().shouldRetry(retryCount, -1)) { throw new InvalidAbfsRestOperationException(ex); @@ -339,7 +338,7 @@ private boolean executeHttpOperation(final int retryCount, if (client.getRetryPolicy().shouldRetry(retryCount, httpOperation.getStatusCode())) { int status = httpOperation.getStatusCode(); - failureReasons = RetryReason.getEnum(null, status).getAbbreviation(null, status, httpOperation.getStorageErrorMessage()); + failureReason = RetryReason.getEnum(null, status).getAbbreviation(null, status, httpOperation.getStorageErrorMessage()); return false; } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index d300ce6a4f3cc..1eb6781ffd046 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -3,16 +3,9 @@ import java.io.IOException; import java.net.SocketException; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; public enum RetryReason { - //3character string - //4xx exact status - //in case of 503: give reason of throttling , ref anmol@ PR. - //result.getStorageErrorMessage() - // CONNECTION_TIMEOUT(((exceptionCaptured, statusCode) -> { return exceptionCaptured != null && "connect timed out".equalsIgnoreCase( exceptionCaptured.getMessage()); From 34fe0290b6a148a5c3448c066915bda74f55945e Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Sat, 14 Jan 2023 00:10:15 -0800 Subject: [PATCH 09/38] removed non-required capture interface --- .../azurebfs/services/AbfsRestOperation.java | 6 +- .../fs/azurebfs/services/RetryReason.java | 119 ++++++++---------- .../RetryReasonAbbreviationCreator.java | 2 +- .../services/RetryReasonCaptureMechanism.java | 5 - 4 files changed, 59 insertions(+), 73 deletions(-) delete mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonCaptureMechanism.java diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java index 858c6ab6e47d7..702060c93aeab 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java @@ -311,7 +311,7 @@ private boolean executeHttpOperation(final int retryCount, } catch (UnknownHostException ex) { String hostname = null; hostname = httpOperation.getHost(); - failureReason = RetryReason.UNKNOWN_HOST.getAbbreviation(ex, null, null); + failureReason = RetryReason.getAbbreviation(ex, null, null); LOG.warn("Unknown host name: {}. Retrying to resolve the host name...", hostname); if (!client.getRetryPolicy().shouldRetry(retryCount, -1)) { @@ -323,7 +323,7 @@ private boolean executeHttpOperation(final int retryCount, LOG.debug("HttpRequestFailure: {}, {}", httpOperation, ex); } - failureReason = RetryReason.getEnum(ex, -1).getAbbreviation(ex, -1, ""); + failureReason = RetryReason.getAbbreviation(ex, -1, ""); if (!client.getRetryPolicy().shouldRetry(retryCount, -1)) { throw new InvalidAbfsRestOperationException(ex); @@ -338,7 +338,7 @@ private boolean executeHttpOperation(final int retryCount, if (client.getRetryPolicy().shouldRetry(retryCount, httpOperation.getStatusCode())) { int status = httpOperation.getStatusCode(); - failureReason = RetryReason.getEnum(null, status).getAbbreviation(null, status, httpOperation.getStorageErrorMessage()); + failureReason = RetryReason.getAbbreviation(null, status, httpOperation.getStorageErrorMessage()); return false; } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index 1eb6781ffd046..b519748959b41 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -2,26 +2,42 @@ import java.io.IOException; import java.net.SocketException; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; public enum RetryReason { - CONNECTION_TIMEOUT(((exceptionCaptured, statusCode) -> { - return exceptionCaptured != null && "connect timed out".equalsIgnoreCase( - exceptionCaptured.getMessage()); - }), 2, "CT"), - READ_TIMEOUT(((exceptionCaptured, statusCode) -> { - return exceptionCaptured != null && "Read timed out".equalsIgnoreCase( - exceptionCaptured.getMessage()); - }), 2, "RT"), - UNKNOWN_HOST("UH"), - CONNECTION_RESET(((exceptionCaptured, statusCode) -> { - return exceptionCaptured != null && exceptionCaptured.getMessage() != null - && exceptionCaptured.getMessage().contains("Connection reset"); - }), 2, "CR"), - STATUS_5XX(((exceptionCaptured, statusCode) -> { - return statusCode / 100 == 5; - }), 0, ((ex, statusCode, serverErrorMessage) -> { + CONNECTION_TIMEOUT(2, ((ex, statusCode, serverErrorMessage) -> { + if(ex != null && "connect timed out".equalsIgnoreCase( + ex.getMessage())) { + return "CT"; + } + return null; + })), + READ_TIMEOUT(2, ((exceptionCaptured, statusCode, serverErrorMessage) -> { + if(exceptionCaptured != null && "Read timed out".equalsIgnoreCase( + exceptionCaptured.getMessage())) { + return "RT"; + } + return null; + })), + UNKNOWN_HOST(2, ((ex, statusCode, serverErrorMessage) -> { + if(ex instanceof UnknownHostException) { + return "UH"; + } + return null; + })), + CONNECTION_RESET(2, ((exceptionCaptured, statusCode, serverErrorMessage) -> { + if(exceptionCaptured != null && exceptionCaptured.getMessage() != null + && exceptionCaptured.getMessage().contains("Connection reset")) { + return "CR"; + } + return null; + })), + STATUS_5XX(0, ((ex, statusCode, serverErrorMessage) -> { + if(statusCode == null || statusCode / 100 != 5) { + return null; + } if (statusCode == 503) { //ref: https://github.com/apache/hadoop/pull/4564/files#diff-75a2f54df6618d4015c63812e6a9916ddfb475d246850edfd2a6f57e36805e79 serverErrorMessage = serverErrorMessage.split(System.lineSeparator(), @@ -42,59 +58,35 @@ public enum RetryReason { } return statusCode + ""; })), - STATUS_4XX(((exceptionCaptured, statusCode) -> { - return statusCode / 100 == 4; - }), 0, ((ex, statusCode, serverErrorMessage) -> { + STATUS_4XX(0, ((ex, statusCode, serverErrorMessage) -> { + if(statusCode == null || statusCode / 100 != 4) { + return null; + } return statusCode + ""; })), - UNKNOWN_SOCKET_EXCEPTION(((exceptionCaptured, statusCode) -> { - return exceptionCaptured instanceof SocketException; - }), 1, "SE"), - UNKNOWN_IO_EXCEPTION(((exceptionCaptured, statusCode) -> { - return exceptionCaptured instanceof IOException; - }), 0, "IOE"); - - private RetryReasonCaptureMechanism mechanism = null; + UNKNOWN_SOCKET_EXCEPTION(1, ((ex, statusCode, serverErrorMessage) -> { + if(ex instanceof SocketException) { + return "SE"; + } + return null; + })), + UNKNOWN_IO_EXCEPTION(0, ((ex, statusCode, serverErrorMessage) -> { + if(ex instanceof IOException) { + return "IOE"; + } + return null; + })); private RetryReasonAbbreviationCreator retryReasonAbbreviationCreator = null; private int rank = 0; - private String abbreviation; - - RetryReason(String abbreviation) { - this.abbreviation = abbreviation; - } - - RetryReason(RetryReasonCaptureMechanism mechanism, - int rank, - String abbreviation) { - this.mechanism = mechanism; - this.rank = rank; - this.abbreviation = abbreviation; - } - - RetryReason(RetryReasonCaptureMechanism mechanism, - int rank, + RetryReason(int rank, RetryReasonAbbreviationCreator abbreviationCreator) { - this.mechanism = mechanism; this.rank = rank; this.retryReasonAbbreviationCreator = abbreviationCreator; } - public String getAbbreviation(Exception ex, - Integer statusCode, - String serverErrorMessage) { - if (abbreviation != null) { - return abbreviation; - } - if (retryReasonAbbreviationCreator != null) { - return retryReasonAbbreviationCreator.getAbbreviation(ex, statusCode, - serverErrorMessage); - } - return null; - } - private static List retryReasonLSortedist; private synchronized static void sortRetryReason() { @@ -111,18 +103,17 @@ private synchronized static void sortRetryReason() { retryReasonLSortedist = list; } - static RetryReason getEnum(Exception ex, Integer statusCode) { - RetryReason retryReasonResult = null; + static String getAbbreviation(Exception ex, Integer statusCode, String storageStatusCode) { + String result = null; if (retryReasonLSortedist == null) { sortRetryReason(); } for (RetryReason retryReason : retryReasonLSortedist) { - if (retryReason.mechanism != null) { - if (retryReason.mechanism.canCapture(ex, statusCode)) { - retryReasonResult = retryReason; - } + String enumCaputredAndAbbreviate = retryReason.retryReasonAbbreviationCreator.capturableAndGetAbbreviation(ex, statusCode, storageStatusCode); + if (enumCaputredAndAbbreviate != null) { + result = enumCaputredAndAbbreviate; } } - return retryReasonResult; + return result; } } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java index 4f8c894e36187..af6d0dece2b6c 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java @@ -1,5 +1,5 @@ package org.apache.hadoop.fs.azurebfs.services; public interface RetryReasonAbbreviationCreator { - String getAbbreviation(Exception ex, Integer statusCode, String serverErrorMessage); + String capturableAndGetAbbreviation(Exception ex, Integer statusCode, String serverErrorMessage); } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonCaptureMechanism.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonCaptureMechanism.java deleted file mode 100644 index 93c0d446f6540..0000000000000 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonCaptureMechanism.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.apache.hadoop.fs.azurebfs.services; - -interface RetryReasonCaptureMechanism { - boolean canCapture(Exception exceptionCaptured, Integer statusCode); -} From 7acee90c5ce2a78126a14d9c8ced42445818c4b9 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Sat, 14 Jan 2023 00:20:52 -0800 Subject: [PATCH 10/38] ASF license; javadocs on the interface. --- .../fs/azurebfs/services/RetryReason.java | 18 +++++++++++ .../RetryReasonAbbreviationCreator.java | 32 +++++++++++++++++++ .../fs/azurebfs/utils/TracingContext.java | 2 +- .../services/TestAbfsRestOperation.java | 18 +++++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index b519748959b41..6ab02bf4cfb7e 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -1,3 +1,21 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.hadoop.fs.azurebfs.services; import java.io.IOException; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java index af6d0dece2b6c..283f569e812fe 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java @@ -1,5 +1,37 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.hadoop.fs.azurebfs.services; +/** + * Interface to be implemented by each enum in {@link RetryReason}. The methods + * of the interface define if the given enum can be applied on the given server + * response. + * */ public interface RetryReasonAbbreviationCreator { + /** + * Returns an abbreviation if the {@link RetryReason} enum can be applied on + * the server response. + * @param ex exception captured in the server API call. + * @param statusCode statusCode on the server response + * @param serverErrorMessage serverErrorMessage on the server response. + * @return

  1. null if the enum can not be used on the server response
  2. + *
  3. abbreviation corresponding to the server response.
+ * */ String capturableAndGetAbbreviation(Exception ex, Integer statusCode, String serverErrorMessage); } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java index b7a0ea319894b..2fd5e45f6ff32 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java @@ -183,7 +183,7 @@ public void constructHeader(AbfsHttpOperation httpOperation, String previousFail private String addFailureReasons(final String header, final String previousFailure) { - if(previousFailure == null) { + if (previousFailure == null) { return header; } return String.format("%s_%s", header, previousFailure); diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java index 747c26de6c4cf..cae649a8d686e 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java @@ -1,3 +1,21 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.hadoop.fs.azurebfs.services; import java.io.IOException; From b7d712166fc72a915d2fee593787e4acc3af2b38 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Sat, 14 Jan 2023 01:22:18 -0800 Subject: [PATCH 11/38] minimize TestAbfsRestOperation class with added methods for common testing --- .../services/TestAbfsRestOperation.java | 436 ++++-------------- 1 file changed, 85 insertions(+), 351 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java index cae649a8d686e..66b2893a8f209 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java @@ -25,12 +25,11 @@ import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.util.ArrayList; -import java.util.List; import org.assertj.core.api.Assertions; import org.junit.Test; -import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.stubbing.Stubber; import org.apache.hadoop.fs.azurebfs.utils.TracingContext; @@ -43,333 +42,105 @@ public class TestAbfsRestOperation { @Test public void testClientRequestIdForConnectTimeoutRetry() throws Exception { - AbfsClient abfsClient = Mockito.mock(AbfsClient.class); - ExponentialRetryPolicy retryPolicy = Mockito.mock( - ExponentialRetryPolicy.class); - addMockBehaviourToAbfsClient(abfsClient, retryPolicy); - - - AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( - AbfsRestOperationType.ReadFile, - abfsClient, - "PUT", - null, - new ArrayList<>() - )); - - AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); - addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - - Mockito.doThrow(new SocketTimeoutException("connect timed out")) - .doNothing() - .when(httpOperation) - .processResponse(nullable(byte[].class), nullable(int.class), - nullable(int.class)); - - Mockito.doReturn(200).when(httpOperation).getStatusCode(); - - TracingContext tracingContext = Mockito.mock(TracingContext.class); - Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); - - int[] count = new int[1]; - count[0] = 0; - Mockito.doAnswer(invocationOnMock -> { - if (count[0] == 1) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)) - .isEqualTo("CT"); - } - count[0]++; - return null; - }).when(tracingContext).constructHeader(any(), any()); - - abfsRestOperation.execute(tracingContext); - Assertions.assertThat(count[0]).isEqualTo(2); + Exception[] exceptions = new Exception[1]; + String[] abbreviations = new String[1]; + exceptions[0] = new SocketTimeoutException("connect timed out"); + abbreviations[0] = "CT"; + testClientRequestIdForTimeoutRetry(exceptions, abbreviations, 1); } @Test public void testClientRequestIdForConnectAndReadTimeoutRetry() throws Exception { - - AbfsClient abfsClient = Mockito.mock(AbfsClient.class); - ExponentialRetryPolicy retryPolicy = Mockito.mock( - ExponentialRetryPolicy.class); - addMockBehaviourToAbfsClient(abfsClient, retryPolicy); - - - AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( - AbfsRestOperationType.ReadFile, - abfsClient, - "PUT", - null, - new ArrayList<>() - )); - - AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); - addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - - Mockito.doThrow(new SocketTimeoutException("connect timed out")) - .doThrow(new SocketTimeoutException("read timed out")) - .doNothing() - .when(httpOperation) - .processResponse(nullable(byte[].class), nullable(int.class), - nullable(int.class)); - - Mockito.doReturn(200).when(httpOperation).getStatusCode(); - - TracingContext tracingContext = Mockito.mock(TracingContext.class); - Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); - - int[] count = new int[1]; - count[0] = 0; - Mockito.doAnswer(invocationOnMock -> { - if (count[0] == 1 ) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)) - .isEqualTo("CT"); - } - if(count[0] == 2) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)) - .isEqualTo("RT"); - } - count[0]++; - return null; - }).when(tracingContext).constructHeader(any(), any()); - - abfsRestOperation.execute(tracingContext); - Assertions.assertThat(count[0]).isEqualTo(3); + Exception[] exceptions = new Exception[2]; + String[] abbreviations = new String[2]; + exceptions[0] = new SocketTimeoutException("connect timed out"); + abbreviations[0] = "CT"; + exceptions[1] = new SocketTimeoutException("Read timed out"); + abbreviations[1] = "RT"; + testClientRequestIdForTimeoutRetry(exceptions, abbreviations, 1); } @Test public void testClientRequestIdForReadTimeoutRetry() throws Exception { - - AbfsClient abfsClient = Mockito.mock(AbfsClient.class); - ExponentialRetryPolicy retryPolicy = Mockito.mock( - ExponentialRetryPolicy.class); - addMockBehaviourToAbfsClient(abfsClient, retryPolicy); - - - AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( - AbfsRestOperationType.ReadFile, - abfsClient, - "PUT", - null, - new ArrayList<>() - )); - - AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); - addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - - Mockito.doThrow(new SocketTimeoutException("Read timed out")) - .doNothing() - .when(httpOperation) - .processResponse(nullable(byte[].class), nullable(int.class), - nullable(int.class)); - - Mockito.doReturn(200).when(httpOperation).getStatusCode(); - - TracingContext tracingContext = Mockito.mock(TracingContext.class); - Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); - - int[] count = new int[1]; - count[0] = 0; - Mockito.doAnswer(invocationOnMock -> { - if (count[0] == 1) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)) - .isEqualTo("RT"); - } - count[0]++; - return null; - }).when(tracingContext).constructHeader(any(), any()); - - abfsRestOperation.execute(tracingContext); - Assertions.assertThat(count[0]).isEqualTo(2); + Exception[] exceptions = new Exception[1]; + String[] abbreviations = new String[1]; + exceptions[0] = new SocketTimeoutException("Read timed out"); + abbreviations[0] = "RT"; + testClientRequestIdForTimeoutRetry(exceptions, abbreviations, 1); } @Test public void testClientRequestIdForUnknownHostRetry() throws Exception { - - AbfsClient abfsClient = Mockito.mock(AbfsClient.class); - ExponentialRetryPolicy retryPolicy = Mockito.mock( - ExponentialRetryPolicy.class); - addMockBehaviourToAbfsClient(abfsClient, retryPolicy); - - - AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( - AbfsRestOperationType.ReadFile, - abfsClient, - "PUT", - null, - new ArrayList<>() - )); - - AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); - addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - - Mockito.doThrow(new UnknownHostException()) - .doNothing() - .when(httpOperation) - .processResponse(nullable(byte[].class), nullable(int.class), - nullable(int.class)); - - Mockito.doReturn(200).when(httpOperation).getStatusCode(); - - TracingContext tracingContext = Mockito.mock(TracingContext.class); - Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); - - int[] count = new int[1]; - count[0] = 0; - Mockito.doAnswer(invocationOnMock -> { - if (count[0] == 1) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)) - .isEqualTo("UH"); - } - count[0]++; - return null; - }).when(tracingContext).constructHeader(any(), any()); - - abfsRestOperation.execute(tracingContext); - Assertions.assertThat(count[0]).isEqualTo(2); - + Exception[] exceptions = new Exception[1]; + String[] abbreviations = new String[1]; + exceptions[0] = new UnknownHostException(); + abbreviations[0] = "UH"; + testClientRequestIdForTimeoutRetry(exceptions, abbreviations, 1); } @Test public void testClientRequestIdForConnectionResetRetry() throws Exception { - - AbfsClient abfsClient = Mockito.mock(AbfsClient.class); - ExponentialRetryPolicy retryPolicy = Mockito.mock( - ExponentialRetryPolicy.class); - addMockBehaviourToAbfsClient(abfsClient, retryPolicy); - - - AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( - AbfsRestOperationType.ReadFile, - abfsClient, - "PUT", - null, - new ArrayList<>() - )); - - AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); - addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - - Mockito.doThrow(new SocketException("Connection reset by peer")) - .doNothing() - .when(httpOperation) - .processResponse(nullable(byte[].class), nullable(int.class), - nullable(int.class)); - - Mockito.doReturn(200).when(httpOperation).getStatusCode(); - - TracingContext tracingContext = Mockito.mock(TracingContext.class); - Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); - - int[] count = new int[1]; - count[0] = 0; - Mockito.doAnswer(invocationOnMock -> { - if (count[0] == 1) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)) - .isEqualTo("CR"); - } - count[0]++; - return null; - }).when(tracingContext).constructHeader(any(), any()); - - abfsRestOperation.execute(tracingContext); - Assertions.assertThat(count[0]).isEqualTo(2); + Exception[] exceptions = new Exception[1]; + String[] abbreviations = new String[1]; + exceptions[0] = new SocketTimeoutException("Connection reset by peer"); + abbreviations[0] = "CR"; + testClientRequestIdForTimeoutRetry(exceptions, abbreviations, 1); } @Test public void testClientRequestIdForUnknownSocketExRetry() throws Exception { - - AbfsClient abfsClient = Mockito.mock(AbfsClient.class); - ExponentialRetryPolicy retryPolicy = Mockito.mock( - ExponentialRetryPolicy.class); - addMockBehaviourToAbfsClient(abfsClient, retryPolicy); - - - AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( - AbfsRestOperationType.ReadFile, - abfsClient, - "PUT", - null, - new ArrayList<>() - )); - - AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); - addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - - Mockito.doThrow(new SocketException("unknown")) - .doNothing() - .when(httpOperation) - .processResponse(nullable(byte[].class), nullable(int.class), - nullable(int.class)); - - Mockito.doReturn(200).when(httpOperation).getStatusCode(); - - TracingContext tracingContext = Mockito.mock(TracingContext.class); - Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); - - int[] count = new int[1]; - count[0] = 0; - Mockito.doAnswer(invocationOnMock -> { - if (count[0] == 1) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)) - .isEqualTo("SE"); - } - count[0]++; - return null; - }).when(tracingContext).constructHeader(any(), any()); - - abfsRestOperation.execute(tracingContext); - Assertions.assertThat(count[0]).isEqualTo(2); + Exception[] exceptions = new Exception[1]; + String[] abbreviations = new String[1]; + exceptions[0] = new SocketException("unknown"); + abbreviations[0] = "SE"; + testClientRequestIdForTimeoutRetry(exceptions, abbreviations, 1); } @Test public void testClientRequestIdForIOERetry() throws Exception { + Exception[] exceptions = new Exception[1]; + String[] abbreviations = new String[1]; + exceptions[0] = new InterruptedIOException(); + abbreviations[0] = "IOE"; + testClientRequestIdForTimeoutRetry(exceptions, abbreviations, 1); + } - AbfsClient abfsClient = Mockito.mock(AbfsClient.class); - ExponentialRetryPolicy retryPolicy = Mockito.mock( - ExponentialRetryPolicy.class); - addMockBehaviourToAbfsClient(abfsClient, retryPolicy); - - - AbfsRestOperation abfsRestOperation = Mockito.spy(new AbfsRestOperation( - AbfsRestOperationType.ReadFile, - abfsClient, - "PUT", - null, - new ArrayList<>() - )); - - AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); - addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - - Mockito.doThrow(new InterruptedIOException()) - .doNothing() - .when(httpOperation) - .processResponse(nullable(byte[].class), nullable(int.class), - nullable(int.class)); - - Mockito.doReturn(200).when(httpOperation).getStatusCode(); + @Test + public void testClientRequestIdFor400Retry() throws Exception { + testClientRequestIdForStatusRetry(400, "", "400"); + } + @Test + public void testClientRequestIdFor500Retry() throws Exception { + testClientRequestIdForStatusRetry(500, "", "500"); + } - TracingContext tracingContext = Mockito.mock(TracingContext.class); - Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); + @Test + public void testClientRequestIdFor503INGRetry() throws Exception { + testClientRequestIdForStatusRetry(503, "Ingress is over the account limit.", + "ING"); + } - int[] count = new int[1]; - count[0] = 0; - Mockito.doAnswer(invocationOnMock -> { - if (count[0] == 1) { - Assertions.assertThat((String) invocationOnMock.getArgument(1)) - .isEqualTo("IOE"); - } - count[0]++; - return null; - }).when(tracingContext).constructHeader(any(), any()); + @Test + public void testClientRequestIdFor503egrRetry() throws Exception { + testClientRequestIdForStatusRetry(503, "Egress is over the account limit.", + "EGR"); + } - abfsRestOperation.execute(tracingContext); - Assertions.assertThat(count[0]).isEqualTo(2); + @Test + public void testClientRequestIdFor503OPRRetry() throws Exception { + testClientRequestIdForStatusRetry(503, + "Operations per second is over the account limit.", "OPR"); } @Test - public void testClientRequestIdFor4XXRetry() throws Exception { + public void testClientRequestIdFor503OtherRetry() throws Exception { + testClientRequestIdForStatusRetry(503, "Other.", "503"); + } + + + private void testClientRequestIdForStatusRetry(int status, + String serverErrorMessage, + String keyExpected) throws Exception { AbfsClient abfsClient = Mockito.mock(AbfsClient.class); ExponentialRetryPolicy retryPolicy = Mockito.mock( @@ -399,11 +170,15 @@ public void testClientRequestIdFor4XXRetry() throws Exception { Mockito.doAnswer(answer -> { if (statusCount[0] <= 5) { statusCount[0]++; - return 400; + return status; } return 200; }).when(httpOperation).getStatusCode(); + Mockito.doReturn(serverErrorMessage) + .when(httpOperation) + .getStorageErrorMessage(); + TracingContext tracingContext = Mockito.mock(TracingContext.class); Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); @@ -412,7 +187,7 @@ public void testClientRequestIdFor4XXRetry() throws Exception { Mockito.doAnswer(invocationOnMock -> { if (count[0] == 1) { Assertions.assertThat((String) invocationOnMock.getArgument(1)) - .isEqualTo("400"); + .isEqualTo(keyExpected); } count[0]++; return null; @@ -423,39 +198,7 @@ public void testClientRequestIdFor4XXRetry() throws Exception { } - @Test - public void testClientRequestIdFor500Retry() throws Exception { - testClientRequestIdFor5XXRetry(500, "", "500"); - } - - @Test - public void testClientRequestIdFor503INGRetry() throws Exception { - testClientRequestIdFor5XXRetry(503, "Ingress is over the account limit.", - "ING"); - } - - @Test - public void testClientRequestIdFor503egrRetry() throws Exception { - testClientRequestIdFor5XXRetry(503, "Egress is over the account limit.", - "EGR"); - } - - @Test - public void testClientRequestIdFor503OPRRetry() throws Exception { - testClientRequestIdFor5XXRetry(503, - "Operations per second is over the account limit.", "OPR"); - } - - @Test - public void testClientRequestIdFor503OtherRetry() throws Exception { - testClientRequestIdFor5XXRetry(503, "Other.", "503"); - } - - - private void testClientRequestIdFor5XXRetry(int status, - String serverErrorMessage, - String keyExpected) throws Exception { - + private void testClientRequestIdForTimeoutRetry(Exception[] exceptions, String[] abbreviationsExpected, int len) throws Exception { AbfsClient abfsClient = Mockito.mock(AbfsClient.class); ExponentialRetryPolicy retryPolicy = Mockito.mock( ExponentialRetryPolicy.class); @@ -473,25 +216,17 @@ private void testClientRequestIdFor5XXRetry(int status, AbfsHttpOperation httpOperation = Mockito.mock(AbfsHttpOperation.class); addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); - Mockito.doNothing() + Stubber stubber = Mockito.doThrow(exceptions[0]); + for(int iteration = 1; iteration < len; iteration++) { + stubber.doThrow(exceptions[iteration]); + } + stubber .doNothing() .when(httpOperation) .processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); - int[] statusCount = new int[1]; - statusCount[0] = 0; - Mockito.doAnswer(answer -> { - if (statusCount[0] <= 5) { - statusCount[0]++; - return status; - } - return 200; - }).when(httpOperation).getStatusCode(); - - Mockito.doReturn(serverErrorMessage) - .when(httpOperation) - .getStorageErrorMessage(); + Mockito.doReturn(200).when(httpOperation).getStatusCode(); TracingContext tracingContext = Mockito.mock(TracingContext.class); Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); @@ -499,17 +234,16 @@ private void testClientRequestIdFor5XXRetry(int status, int[] count = new int[1]; count[0] = 0; Mockito.doAnswer(invocationOnMock -> { - if (count[0] == 1) { + if(count[0] > 0 && count[0] <= len) { Assertions.assertThat((String) invocationOnMock.getArgument(1)) - .isEqualTo(keyExpected); + .isEqualTo(abbreviationsExpected[count[0] - 1]); } count[0]++; return null; }).when(tracingContext).constructHeader(any(), any()); abfsRestOperation.execute(tracingContext); - Assertions.assertThat(count[0]).isEqualTo(2); - + Assertions.assertThat(count[0]).isEqualTo(len + 1); } private void addMockBehaviourToRestOpAndHttpOp(final AbfsRestOperation abfsRestOperation, From 1c3f2ee705f283cca72bdff89e4a33421b23b665 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Sat, 14 Jan 2023 01:38:03 -0800 Subject: [PATCH 12/38] added javadocs in RetryReason --- .../fs/azurebfs/services/RetryReason.java | 50 +++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index 6ab02bf4cfb7e..1a028fb85bbf1 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -24,6 +24,10 @@ import java.util.ArrayList; import java.util.List; +/** + * In case of retry, this enum would give the information on the reason for + * previous API call. + * */ public enum RetryReason { CONNECTION_TIMEOUT(2, ((ex, statusCode, serverErrorMessage) -> { if(ex != null && "connect timed out".equalsIgnoreCase( @@ -99,16 +103,32 @@ public enum RetryReason { private int rank = 0; + /** + * Constructor to have rank and the implementation of {@link RetryReasonAbbreviationCreator}. + * @param rank rank of a given enum. For example SocketTimeoutException is + * subclass of IOException. Rank of SocketTimeoutException enum has to be + * more than that of IOException enum. + * @param abbreviationCreator The implementation of {@link RetryReasonAbbreviationCreator} + * which would give the information if a given enum can be mapped to an error or not. + * */ RetryReason(int rank, RetryReasonAbbreviationCreator abbreviationCreator) { this.rank = rank; this.retryReasonAbbreviationCreator = abbreviationCreator; } - private static List retryReasonLSortedist; + private static List retryReasonSortedList; + /** + * Synchronized method to assign sorted list in {@link RetryReason#retryReasonSortedList}. + * Method would check if list is assigned or not. If yes, method would return. This is required + * because multiple threads could be waiting to get into this method, and once a thread is done + * with this method, other thread would get into this method. Since the list would be assigned by + * first thread, the second thread need not run the whole mechanism of sorting. + * The enums are sorted on the ascending order of their rank. + * */ private synchronized static void sortRetryReason() { - if (retryReasonLSortedist != null) { + if (retryReasonSortedList != null) { return; } List list = new ArrayList<>(); @@ -118,18 +138,30 @@ private synchronized static void sortRetryReason() { list.sort((c1, c2) -> { return c1.rank - c2.rank; }); - retryReasonLSortedist = list; + retryReasonSortedList = list; } - static String getAbbreviation(Exception ex, Integer statusCode, String storageStatusCode) { + /** + * Method to get correct abbreviation for a given set of exception, statusCode, + * storageStatusCode. + * Method would iterate through the {@link RetryReason#retryReasonSortedList}, + * and would return the abbreviation returned by highest enum to be applicable on the group. + * For example, if SocketTimeoutException(rank 2) and IOException(rank 0) can be + * applied on the group, the abbreviation of SocketTimeoutException has to be returned. + * + * @param ex exception caught during server communication. + * @param statusCode statusCode in the server response. + * @param storageErrorMessage storageErrorMessage in the server response. + * */ + static String getAbbreviation(Exception ex, Integer statusCode, String storageErrorMessage) { String result = null; - if (retryReasonLSortedist == null) { + if (retryReasonSortedList == null) { sortRetryReason(); } - for (RetryReason retryReason : retryReasonLSortedist) { - String enumCaputredAndAbbreviate = retryReason.retryReasonAbbreviationCreator.capturableAndGetAbbreviation(ex, statusCode, storageStatusCode); - if (enumCaputredAndAbbreviate != null) { - result = enumCaputredAndAbbreviate; + for (RetryReason retryReason : retryReasonSortedList) { + String enumCapturedAndAbbreviate = retryReason.retryReasonAbbreviationCreator.capturableAndGetAbbreviation(ex, statusCode, storageErrorMessage); + if (enumCapturedAndAbbreviate != null) { + result = enumCapturedAndAbbreviate; } } return result; From 9201ab7963365113fed618ee25a36cab21c07b9c Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Sat, 14 Jan 2023 01:52:25 -0800 Subject: [PATCH 13/38] removal of non-required new-lines --- .../hadoop/fs/azurebfs/services/TestAbfsRestOperation.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java index 66b2893a8f209..34fd6d2861861 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java @@ -41,7 +41,6 @@ public class TestAbfsRestOperation { @Test public void testClientRequestIdForConnectTimeoutRetry() throws Exception { - Exception[] exceptions = new Exception[1]; String[] abbreviations = new String[1]; exceptions[0] = new SocketTimeoutException("connect timed out"); @@ -278,5 +277,4 @@ private void addMockBehaviourToAbfsClient(final AbfsClient abfsClient, Mockito.doReturn(false).when(retryPolicy).shouldRetry(1, 200); Mockito.doReturn(false).when(retryPolicy).shouldRetry(2, 200); } - } From 77eb7908abceedc49a3b67e9e58a43657fb4a204 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Sat, 14 Jan 2023 01:54:28 -0800 Subject: [PATCH 14/38] small refactors --- .../fs/azurebfs/services/RetryReason.java | 24 +++++++++++-------- .../RetryReasonAbbreviationCreator.java | 5 +++- .../services/TestAbfsRestOperation.java | 12 ++++++---- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index 1a028fb85bbf1..6ccdd47aa50b2 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -30,34 +30,34 @@ * */ public enum RetryReason { CONNECTION_TIMEOUT(2, ((ex, statusCode, serverErrorMessage) -> { - if(ex != null && "connect timed out".equalsIgnoreCase( + if (ex != null && "connect timed out".equalsIgnoreCase( ex.getMessage())) { return "CT"; } return null; })), READ_TIMEOUT(2, ((exceptionCaptured, statusCode, serverErrorMessage) -> { - if(exceptionCaptured != null && "Read timed out".equalsIgnoreCase( + if (exceptionCaptured != null && "Read timed out".equalsIgnoreCase( exceptionCaptured.getMessage())) { return "RT"; } return null; })), UNKNOWN_HOST(2, ((ex, statusCode, serverErrorMessage) -> { - if(ex instanceof UnknownHostException) { + if (ex instanceof UnknownHostException) { return "UH"; } return null; })), CONNECTION_RESET(2, ((exceptionCaptured, statusCode, serverErrorMessage) -> { - if(exceptionCaptured != null && exceptionCaptured.getMessage() != null + if (exceptionCaptured != null && exceptionCaptured.getMessage() != null && exceptionCaptured.getMessage().contains("Connection reset")) { return "CR"; } return null; })), STATUS_5XX(0, ((ex, statusCode, serverErrorMessage) -> { - if(statusCode == null || statusCode / 100 != 5) { + if (statusCode == null || statusCode / 100 != 5) { return null; } if (statusCode == 503) { @@ -81,19 +81,19 @@ public enum RetryReason { return statusCode + ""; })), STATUS_4XX(0, ((ex, statusCode, serverErrorMessage) -> { - if(statusCode == null || statusCode / 100 != 4) { + if (statusCode == null || statusCode / 100 != 4) { return null; } return statusCode + ""; })), UNKNOWN_SOCKET_EXCEPTION(1, ((ex, statusCode, serverErrorMessage) -> { - if(ex instanceof SocketException) { + if (ex instanceof SocketException) { return "SE"; } return null; })), UNKNOWN_IO_EXCEPTION(0, ((ex, statusCode, serverErrorMessage) -> { - if(ex instanceof IOException) { + if (ex instanceof IOException) { return "IOE"; } return null; @@ -153,13 +153,17 @@ private synchronized static void sortRetryReason() { * @param statusCode statusCode in the server response. * @param storageErrorMessage storageErrorMessage in the server response. * */ - static String getAbbreviation(Exception ex, Integer statusCode, String storageErrorMessage) { + static String getAbbreviation(Exception ex, + Integer statusCode, + String storageErrorMessage) { String result = null; if (retryReasonSortedList == null) { sortRetryReason(); } for (RetryReason retryReason : retryReasonSortedList) { - String enumCapturedAndAbbreviate = retryReason.retryReasonAbbreviationCreator.capturableAndGetAbbreviation(ex, statusCode, storageErrorMessage); + String enumCapturedAndAbbreviate + = retryReason.retryReasonAbbreviationCreator.capturableAndGetAbbreviation( + ex, statusCode, storageErrorMessage); if (enumCapturedAndAbbreviate != null) { result = enumCapturedAndAbbreviate; } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java index 283f569e812fe..6754848c162c2 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java @@ -24,6 +24,7 @@ * response. * */ public interface RetryReasonAbbreviationCreator { + /** * Returns an abbreviation if the {@link RetryReason} enum can be applied on * the server response. @@ -33,5 +34,7 @@ public interface RetryReasonAbbreviationCreator { * @return

  1. null if the enum can not be used on the server response
  2. *
  3. abbreviation corresponding to the server response.
* */ - String capturableAndGetAbbreviation(Exception ex, Integer statusCode, String serverErrorMessage); + String capturableAndGetAbbreviation(Exception ex, + Integer statusCode, + String serverErrorMessage); } diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java index 34fd6d2861861..c1afce63c9f54 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java @@ -49,7 +49,8 @@ public void testClientRequestIdForConnectTimeoutRetry() throws Exception { } @Test - public void testClientRequestIdForConnectAndReadTimeoutRetry() throws Exception { + public void testClientRequestIdForConnectAndReadTimeoutRetry() + throws Exception { Exception[] exceptions = new Exception[2]; String[] abbreviations = new String[2]; exceptions[0] = new SocketTimeoutException("connect timed out"); @@ -108,6 +109,7 @@ public void testClientRequestIdForIOERetry() throws Exception { public void testClientRequestIdFor400Retry() throws Exception { testClientRequestIdForStatusRetry(400, "", "400"); } + @Test public void testClientRequestIdFor500Retry() throws Exception { testClientRequestIdForStatusRetry(500, "", "500"); @@ -197,7 +199,9 @@ private void testClientRequestIdForStatusRetry(int status, } - private void testClientRequestIdForTimeoutRetry(Exception[] exceptions, String[] abbreviationsExpected, int len) throws Exception { + private void testClientRequestIdForTimeoutRetry(Exception[] exceptions, + String[] abbreviationsExpected, + int len) throws Exception { AbfsClient abfsClient = Mockito.mock(AbfsClient.class); ExponentialRetryPolicy retryPolicy = Mockito.mock( ExponentialRetryPolicy.class); @@ -216,7 +220,7 @@ private void testClientRequestIdForTimeoutRetry(Exception[] exceptions, String[] addMockBehaviourToRestOpAndHttpOp(abfsRestOperation, httpOperation); Stubber stubber = Mockito.doThrow(exceptions[0]); - for(int iteration = 1; iteration < len; iteration++) { + for (int iteration = 1; iteration < len; iteration++) { stubber.doThrow(exceptions[iteration]); } stubber @@ -233,7 +237,7 @@ private void testClientRequestIdForTimeoutRetry(Exception[] exceptions, String[] int[] count = new int[1]; count[0] = 0; Mockito.doAnswer(invocationOnMock -> { - if(count[0] > 0 && count[0] <= len) { + if (count[0] > 0 && count[0] <= len) { Assertions.assertThat((String) invocationOnMock.getArgument(1)) .isEqualTo(abbreviationsExpected[count[0] - 1]); } From 32e69cbdbe3b3a7c6be65a1d2f694bee17798677 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Mon, 16 Jan 2023 20:00:39 -0800 Subject: [PATCH 15/38] checkstyle: magic number --- .../azurebfs/constants/AbfsHttpConstants.java | 9 +++++++ .../fs/azurebfs/services/RetryReason.java | 13 +++++---- .../fs/azurebfs/utils/TracingContext.java | 1 - .../services/TestAbfsRestOperation.java | 27 +++++++++++-------- 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/constants/AbfsHttpConstants.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/constants/AbfsHttpConstants.java index 5cf7ec565b59e..1dc819a1401aa 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/constants/AbfsHttpConstants.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/constants/AbfsHttpConstants.java @@ -111,6 +111,15 @@ public final class AbfsHttpConstants { public static final char CHAR_EQUALS = '='; public static final char CHAR_STAR = '*'; public static final char CHAR_PLUS = '+'; + /** + * Value that differentiates categories of the http_status.
+ * 100 - 199 : Informational responses
+ * 200 - 299 : Successful responses
+ * 300 - 399 : Redirection messages
+ * 400 - 499 : Client error responses
+ * 500 - 599 : Server error responses
+ * */ + public static final Integer HTTP_STATUS_CATEGORY_QUOTIENT = 100; private AbfsHttpConstants() {} } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index 6ccdd47aa50b2..0cb721ce4c9e4 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -24,6 +24,9 @@ import java.util.ArrayList; import java.util.List; +import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; +import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; + /** * In case of retry, this enum would give the information on the reason for * previous API call. @@ -57,10 +60,10 @@ public enum RetryReason { return null; })), STATUS_5XX(0, ((ex, statusCode, serverErrorMessage) -> { - if (statusCode == null || statusCode / 100 != 5) { + if (statusCode == null || statusCode / HTTP_STATUS_CATEGORY_QUOTIENT != 5) { return null; } - if (statusCode == 503) { + if (statusCode == HTTP_UNAVAILABLE) { //ref: https://github.com/apache/hadoop/pull/4564/files#diff-75a2f54df6618d4015c63812e6a9916ddfb475d246850edfd2a6f57e36805e79 serverErrorMessage = serverErrorMessage.split(System.lineSeparator(), 2)[0]; @@ -76,12 +79,12 @@ public enum RetryReason { serverErrorMessage)) { return "OPR"; } - return "503"; + return HTTP_UNAVAILABLE + ""; } return statusCode + ""; })), STATUS_4XX(0, ((ex, statusCode, serverErrorMessage) -> { - if (statusCode == null || statusCode / 100 != 4) { + if (statusCode == null || statusCode / HTTP_STATUS_CATEGORY_QUOTIENT != 4) { return null; } return statusCode + ""; @@ -127,7 +130,7 @@ public enum RetryReason { * first thread, the second thread need not run the whole mechanism of sorting. * The enums are sorted on the ascending order of their rank. * */ - private synchronized static void sortRetryReason() { + private static synchronized void sortRetryReason() { if (retryReasonSortedList != null) { return; } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java index 2fd5e45f6ff32..00ec0f1777232 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java @@ -18,7 +18,6 @@ package org.apache.hadoop.fs.azurebfs.utils; -import java.util.List; import java.util.UUID; import org.slf4j.Logger; diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java index c1afce63c9f54..6697d31a03e70 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java @@ -33,6 +33,10 @@ import org.apache.hadoop.fs.azurebfs.utils.TracingContext; +import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; +import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR; +import static java.net.HttpURLConnection.HTTP_OK; +import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; import static org.apache.hadoop.fs.azurebfs.services.AuthType.OAuth; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.nullable; @@ -107,38 +111,39 @@ public void testClientRequestIdForIOERetry() throws Exception { @Test public void testClientRequestIdFor400Retry() throws Exception { - testClientRequestIdForStatusRetry(400, "", "400"); + testClientRequestIdForStatusRetry(HTTP_BAD_REQUEST, "", "400"); } @Test public void testClientRequestIdFor500Retry() throws Exception { - testClientRequestIdForStatusRetry(500, "", "500"); + testClientRequestIdForStatusRetry(HTTP_INTERNAL_ERROR, "", "500"); } @Test public void testClientRequestIdFor503INGRetry() throws Exception { - testClientRequestIdForStatusRetry(503, "Ingress is over the account limit.", + testClientRequestIdForStatusRetry(HTTP_UNAVAILABLE, + "Ingress is over the account limit.", "ING"); } @Test public void testClientRequestIdFor503egrRetry() throws Exception { - testClientRequestIdForStatusRetry(503, "Egress is over the account limit.", + testClientRequestIdForStatusRetry(HTTP_UNAVAILABLE, + "Egress is over the account limit.", "EGR"); } @Test public void testClientRequestIdFor503OPRRetry() throws Exception { - testClientRequestIdForStatusRetry(503, + testClientRequestIdForStatusRetry(HTTP_UNAVAILABLE, "Operations per second is over the account limit.", "OPR"); } @Test public void testClientRequestIdFor503OtherRetry() throws Exception { - testClientRequestIdForStatusRetry(503, "Other.", "503"); + testClientRequestIdForStatusRetry(HTTP_UNAVAILABLE, "Other.", "503"); } - private void testClientRequestIdForStatusRetry(int status, String serverErrorMessage, String keyExpected) throws Exception { @@ -173,7 +178,7 @@ private void testClientRequestIdForStatusRetry(int status, statusCount[0]++; return status; } - return 200; + return HTTP_OK; }).when(httpOperation).getStatusCode(); Mockito.doReturn(serverErrorMessage) @@ -229,7 +234,7 @@ private void testClientRequestIdForTimeoutRetry(Exception[] exceptions, .processResponse(nullable(byte[].class), nullable(int.class), nullable(int.class)); - Mockito.doReturn(200).when(httpOperation).getStatusCode(); + Mockito.doReturn(HTTP_OK).when(httpOperation).getStatusCode(); TracingContext tracingContext = Mockito.mock(TracingContext.class); Mockito.doNothing().when(tracingContext).setRetryCount(nullable(int.class)); @@ -278,7 +283,7 @@ private void addMockBehaviourToAbfsClient(final AbfsClient abfsClient, Mockito.doReturn(true) .when(retryPolicy) .shouldRetry(nullable(Integer.class), nullable(Integer.class)); - Mockito.doReturn(false).when(retryPolicy).shouldRetry(1, 200); - Mockito.doReturn(false).when(retryPolicy).shouldRetry(2, 200); + Mockito.doReturn(false).when(retryPolicy).shouldRetry(1, HTTP_OK); + Mockito.doReturn(false).when(retryPolicy).shouldRetry(2, HTTP_OK); } } From 7f77eadcd7ffd7fe1f4ee4c7aa3fe071ca43acb7 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Wed, 18 Jan 2023 04:57:32 -0800 Subject: [PATCH 16/38] review refactors --- .../fs/azurebfs/services/RetryReason.java | 50 ++++++++++--------- .../fs/azurebfs/utils/TracingContext.java | 3 -- .../services/TestAbfsRestOperation.java | 2 - 3 files changed, 26 insertions(+), 29 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index 0cb721ce4c9e4..719f07487a6a7 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -32,13 +32,14 @@ * previous API call. * */ public enum RetryReason { - CONNECTION_TIMEOUT(2, ((ex, statusCode, serverErrorMessage) -> { - if (ex != null && "connect timed out".equalsIgnoreCase( - ex.getMessage())) { - return "CT"; - } - return null; - })), + CONNECTION_TIMEOUT(2, + ((exceptionCaptured, statusCode, serverErrorMessage) -> { + if (exceptionCaptured != null && "connect timed out".equalsIgnoreCase( + exceptionCaptured.getMessage())) { + return "CT"; + } + return null; + })), READ_TIMEOUT(2, ((exceptionCaptured, statusCode, serverErrorMessage) -> { if (exceptionCaptured != null && "Read timed out".equalsIgnoreCase( exceptionCaptured.getMessage())) { @@ -46,8 +47,8 @@ public enum RetryReason { } return null; })), - UNKNOWN_HOST(2, ((ex, statusCode, serverErrorMessage) -> { - if (ex instanceof UnknownHostException) { + UNKNOWN_HOST(2, ((exceptionCaptured, statusCode, serverErrorMessage) -> { + if (exceptionCaptured instanceof UnknownHostException) { return "UH"; } return null; @@ -59,12 +60,11 @@ public enum RetryReason { } return null; })), - STATUS_5XX(0, ((ex, statusCode, serverErrorMessage) -> { + STATUS_5XX(0, ((exceptionCaptured, statusCode, serverErrorMessage) -> { if (statusCode == null || statusCode / HTTP_STATUS_CATEGORY_QUOTIENT != 5) { return null; } if (statusCode == HTTP_UNAVAILABLE) { - //ref: https://github.com/apache/hadoop/pull/4564/files#diff-75a2f54df6618d4015c63812e6a9916ddfb475d246850edfd2a6f57e36805e79 serverErrorMessage = serverErrorMessage.split(System.lineSeparator(), 2)[0]; if ("Ingress is over the account limit.".equalsIgnoreCase( @@ -83,24 +83,26 @@ public enum RetryReason { } return statusCode + ""; })), - STATUS_4XX(0, ((ex, statusCode, serverErrorMessage) -> { + STATUS_4XX(0, ((exceptionCaptured, statusCode, serverErrorMessage) -> { if (statusCode == null || statusCode / HTTP_STATUS_CATEGORY_QUOTIENT != 4) { return null; } return statusCode + ""; })), - UNKNOWN_SOCKET_EXCEPTION(1, ((ex, statusCode, serverErrorMessage) -> { - if (ex instanceof SocketException) { - return "SE"; - } - return null; - })), - UNKNOWN_IO_EXCEPTION(0, ((ex, statusCode, serverErrorMessage) -> { - if (ex instanceof IOException) { - return "IOE"; - } - return null; - })); + UNKNOWN_SOCKET_EXCEPTION(1, + ((exceptionCaptured, statusCode, serverErrorMessage) -> { + if (exceptionCaptured instanceof SocketException) { + return "SE"; + } + return null; + })), + UNKNOWN_IO_EXCEPTION(0, + ((exceptionCaptured, statusCode, serverErrorMessage) -> { + if (exceptionCaptured instanceof IOException) { + return "IOE"; + } + return null; + })); private RetryReasonAbbreviationCreator retryReasonAbbreviationCreator = null; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java index 00ec0f1777232..9a2ccda36fbb0 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java @@ -67,9 +67,6 @@ public class TracingContext { public static final int MAX_CLIENT_CORRELATION_ID_LENGTH = 72; public static final String CLIENT_CORRELATION_ID_PATTERN = "[a-zA-Z0-9-]*"; - //x-ms-client-request-id can have maximum 1KB string - private static final Integer MAX_CLIENT_REQUEST_ID = 1024; - /** * Initialize TracingContext * @param clientCorrelationID Provided over config by client diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java index 6697d31a03e70..05d16cdc8e215 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java @@ -262,8 +262,6 @@ private void addMockBehaviourToRestOpAndHttpOp(final AbfsRestOperation abfsRestO .setRequestProperty(nullable(String.class), nullable(String.class)); Mockito.doReturn(httpURLConnection).when(httpOperation).getConnection(); Mockito.doReturn("").when(abfsRestOperation).getClientLatency(); - - //new AbfsHttpOperation(null, "PUT", new ArrayList<>())); Mockito.doReturn(httpOperation).when(abfsRestOperation).getHttpOperation(); } From 90fce12b948791d00068e91fa997720966ba7a3a Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Tue, 21 Feb 2023 21:19:55 -0800 Subject: [PATCH 17/38] review WIP --- .../azurebfs/constants/AbfsHttpConstants.java | 14 ++++---- .../azurebfs/services/AbfsRestOperation.java | 16 ++++++--- .../fs/azurebfs/services/RetryReason.java | 35 ++++++++++--------- .../services/RetryReasonConstants.java | 7 ++++ ...=> TestAbfsRestOperationMockFailures.java} | 4 +-- 5 files changed, 47 insertions(+), 29 deletions(-) create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java rename hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/{TestAbfsRestOperation.java => TestAbfsRestOperationMockFailures.java} (98%) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/constants/AbfsHttpConstants.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/constants/AbfsHttpConstants.java index 1dc819a1401aa..33024f06c7079 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/constants/AbfsHttpConstants.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/constants/AbfsHttpConstants.java @@ -112,12 +112,14 @@ public final class AbfsHttpConstants { public static final char CHAR_STAR = '*'; public static final char CHAR_PLUS = '+'; /** - * Value that differentiates categories of the http_status.
- * 100 - 199 : Informational responses
- * 200 - 299 : Successful responses
- * 300 - 399 : Redirection messages
- * 400 - 499 : Client error responses
- * 500 - 599 : Server error responses
+ * Value that differentiates categories of the http_status. + *
+   * 100 - 199 : Informational responses
+   * 200 - 299 : Successful responses
+   * 300 - 399 : Redirection messages
+   * 400 - 499 : Client error responses
+   * 500 - 599 : Server error responses
+   * 
* */ public static final Integer HTTP_STATUS_CATEGORY_QUOTIENT = 100; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java index 702060c93aeab..e076ac76c4a23 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsRestOperation.java @@ -74,7 +74,11 @@ public class AbfsRestOperation { private AbfsHttpOperation result; private AbfsCounters abfsCounters; - private String failureReason = null; + /** + * This variable contains the reason of last API call within the same + * AbfsRestOperation object. + * */ + private String failureReason; /** * Checks if there is non-null HTTP response. @@ -242,7 +246,7 @@ private void completeExecute(TracingContext tracingContext) @VisibleForTesting String getClientLatency() { - return this.client.getAbfsPerfTracker().getClientLatency(); + return client.getAbfsPerfTracker().getClientLatency(); } /** @@ -256,7 +260,7 @@ private boolean executeHttpOperation(final int retryCount, try { // initialize the HTTP request and open the connection - httpOperation = getHttpOperation(); + httpOperation = createHttpOperation(); incrementCounter(AbfsStatistic.CONNECTIONS_MADE, 1); tracingContext.constructHeader(httpOperation, failureReason); @@ -347,8 +351,12 @@ private boolean executeHttpOperation(final int retryCount, return true; } + /** + * Creates new object of {@link AbfsHttpOperation} with the url, method, and + * requestHeaders fields of the AbfsRestOperation object. + * */ @VisibleForTesting - AbfsHttpOperation getHttpOperation() throws IOException { + AbfsHttpOperation createHttpOperation() throws IOException { return new AbfsHttpOperation(url, method, requestHeaders); } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index 719f07487a6a7..a7e45c162df03 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -23,9 +23,12 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.connectionTimeoutJdkMessage; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.readTimeoutJdkMessage; /** * In case of retry, this enum would give the information on the reason for @@ -34,18 +37,10 @@ public enum RetryReason { CONNECTION_TIMEOUT(2, ((exceptionCaptured, statusCode, serverErrorMessage) -> { - if (exceptionCaptured != null && "connect timed out".equalsIgnoreCase( - exceptionCaptured.getMessage())) { - return "CT"; - } - return null; + return buildFromExceptionMessage(exceptionCaptured, connectionTimeoutJdkMessage, "CT"); })), READ_TIMEOUT(2, ((exceptionCaptured, statusCode, serverErrorMessage) -> { - if (exceptionCaptured != null && "Read timed out".equalsIgnoreCase( - exceptionCaptured.getMessage())) { - return "RT"; - } - return null; + return buildFromExceptionMessage(exceptionCaptured, readTimeoutJdkMessage, "RT"); })), UNKNOWN_HOST(2, ((exceptionCaptured, statusCode, serverErrorMessage) -> { if (exceptionCaptured instanceof UnknownHostException) { @@ -54,11 +49,7 @@ public enum RetryReason { return null; })), CONNECTION_RESET(2, ((exceptionCaptured, statusCode, serverErrorMessage) -> { - if (exceptionCaptured != null && exceptionCaptured.getMessage() != null - && exceptionCaptured.getMessage().contains("Connection reset")) { - return "CR"; - } - return null; + return buildFromExceptionMessage(exceptionCaptured, "Connection reset", "CR"); })), STATUS_5XX(0, ((exceptionCaptured, statusCode, serverErrorMessage) -> { if (statusCode == null || statusCode / HTTP_STATUS_CATEGORY_QUOTIENT != 5) { @@ -104,6 +95,17 @@ public enum RetryReason { return null; })); + private static String buildFromExceptionMessage(final Exception exceptionCaptured, + final String search, + final String result) { + if (exceptionCaptured != null + && exceptionCaptured.getMessage() != null + && exceptionCaptured.getMessage().toLowerCase(Locale.US).contains(search.toLowerCase(Locale.US))) { + return result; + } + return null; + } + private RetryReasonAbbreviationCreator retryReasonAbbreviationCreator = null; private int rank = 0; @@ -116,8 +118,7 @@ public enum RetryReason { * @param abbreviationCreator The implementation of {@link RetryReasonAbbreviationCreator} * which would give the information if a given enum can be mapped to an error or not. * */ - RetryReason(int rank, - RetryReasonAbbreviationCreator abbreviationCreator) { + RetryReason(int rank, RetryReasonAbbreviationCreator abbreviationCreator) { this.rank = rank; this.retryReasonAbbreviationCreator = abbreviationCreator; } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java new file mode 100644 index 0000000000000..39dccc168a734 --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java @@ -0,0 +1,7 @@ +package org.apache.hadoop.fs.azurebfs.services; + +public class RetryReasonConstants { + public static final String connectionTimeoutJdkMessage = "connect timed out"; + public static final String readTimeoutJdkMessage = "Read timed out"; + +} diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperationMockFailures.java similarity index 98% rename from hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java rename to hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperationMockFailures.java index 05d16cdc8e215..6c2781ab6dac4 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperation.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperationMockFailures.java @@ -41,7 +41,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.nullable; -public class TestAbfsRestOperation { +public class TestAbfsRestOperationMockFailures { @Test public void testClientRequestIdForConnectTimeoutRetry() throws Exception { @@ -262,7 +262,7 @@ private void addMockBehaviourToRestOpAndHttpOp(final AbfsRestOperation abfsRestO .setRequestProperty(nullable(String.class), nullable(String.class)); Mockito.doReturn(httpURLConnection).when(httpOperation).getConnection(); Mockito.doReturn("").when(abfsRestOperation).getClientLatency(); - Mockito.doReturn(httpOperation).when(abfsRestOperation).getHttpOperation(); + Mockito.doReturn(httpOperation).when(abfsRestOperation).createHttpOperation(); } private void addMockBehaviourToAbfsClient(final AbfsClient abfsClient, From 06af7052d9916657616cdc6727a85ee3e5ad85be Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Tue, 21 Feb 2023 22:15:47 -0800 Subject: [PATCH 18/38] removing enums and having classes with implementation of RetryReasonAbbreviationCreator --- .../fs/azurebfs/services/RetryReason.java | 157 +++--------------- .../RetryReasonAbbreviationCreator.java | 13 ++ .../services/RetryReasonConstants.java | 2 + .../retryReason/ClientErrorRetryReason.java | 18 ++ .../ConnectionResetRetryReason.java | 16 ++ .../ConnectionTimeoutRetryReason.java | 16 ++ .../retryReason/ReadTimeoutRetryReason.java | 15 ++ .../retryReason/ServerErrorRetryReason.java | 36 ++++ .../retryReason/UnknownHostRetryReason.java | 18 ++ .../UnknownIOExceptionRetryReason.java | 19 +++ .../UnknownSocketExceptionRetryReason.java | 19 +++ 11 files changed, 196 insertions(+), 133 deletions(-) create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ClientErrorRetryReason.java create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ConnectionResetRetryReason.java create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ConnectionTimeoutRetryReason.java create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ReadTimeoutRetryReason.java create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ServerErrorRetryReason.java create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownHostRetryReason.java create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownIOExceptionRetryReason.java create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownSocketExceptionRetryReason.java diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index a7e45c162df03..fd7213d5cdad0 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -22,153 +22,44 @@ import java.net.SocketException; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.Locale; -import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; -import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; -import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.connectionTimeoutJdkMessage; -import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.readTimeoutJdkMessage; +import org.apache.hadoop.fs.azurebfs.services.retryReason.ClientErrorRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReason.ConnectionResetRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReason.ConnectionTimeoutRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReason.ReadTimeoutRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReason.ServerErrorRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReason.UnknownHostRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReason.UnknownIOExceptionRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReason.UnknownSocketExceptionRetryReason; + /** * In case of retry, this enum would give the information on the reason for * previous API call. * */ -public enum RetryReason { - CONNECTION_TIMEOUT(2, - ((exceptionCaptured, statusCode, serverErrorMessage) -> { - return buildFromExceptionMessage(exceptionCaptured, connectionTimeoutJdkMessage, "CT"); - })), - READ_TIMEOUT(2, ((exceptionCaptured, statusCode, serverErrorMessage) -> { - return buildFromExceptionMessage(exceptionCaptured, readTimeoutJdkMessage, "RT"); - })), - UNKNOWN_HOST(2, ((exceptionCaptured, statusCode, serverErrorMessage) -> { - if (exceptionCaptured instanceof UnknownHostException) { - return "UH"; - } - return null; - })), - CONNECTION_RESET(2, ((exceptionCaptured, statusCode, serverErrorMessage) -> { - return buildFromExceptionMessage(exceptionCaptured, "Connection reset", "CR"); - })), - STATUS_5XX(0, ((exceptionCaptured, statusCode, serverErrorMessage) -> { - if (statusCode == null || statusCode / HTTP_STATUS_CATEGORY_QUOTIENT != 5) { - return null; - } - if (statusCode == HTTP_UNAVAILABLE) { - serverErrorMessage = serverErrorMessage.split(System.lineSeparator(), - 2)[0]; - if ("Ingress is over the account limit.".equalsIgnoreCase( - serverErrorMessage)) { - return "ING"; - } - if ("Egress is over the account limit.".equalsIgnoreCase( - serverErrorMessage)) { - return "EGR"; - } - if ("Operations per second is over the account limit.".equalsIgnoreCase( - serverErrorMessage)) { - return "OPR"; - } - return HTTP_UNAVAILABLE + ""; - } - return statusCode + ""; - })), - STATUS_4XX(0, ((exceptionCaptured, statusCode, serverErrorMessage) -> { - if (statusCode == null || statusCode / HTTP_STATUS_CATEGORY_QUOTIENT != 4) { - return null; - } - return statusCode + ""; - })), - UNKNOWN_SOCKET_EXCEPTION(1, - ((exceptionCaptured, statusCode, serverErrorMessage) -> { - if (exceptionCaptured instanceof SocketException) { - return "SE"; - } - return null; - })), - UNKNOWN_IO_EXCEPTION(0, - ((exceptionCaptured, statusCode, serverErrorMessage) -> { - if (exceptionCaptured instanceof IOException) { - return "IOE"; - } - return null; - })); - - private static String buildFromExceptionMessage(final Exception exceptionCaptured, - final String search, - final String result) { - if (exceptionCaptured != null - && exceptionCaptured.getMessage() != null - && exceptionCaptured.getMessage().toLowerCase(Locale.US).contains(search.toLowerCase(Locale.US))) { - return result; - } - return null; - } +public class RetryReason { + private static List rankedReasons = new LinkedList() {{ + add(new ServerErrorRetryReason()); + add(new ClientErrorRetryReason()); + add(new UnknownIOExceptionRetryReason()); + add(new UnknownSocketExceptionRetryReason()); + add(new ConnectionTimeoutRetryReason()); + add(new ReadTimeoutRetryReason()); + add(new UnknownHostRetryReason()); + add(new ConnectionResetRetryReason()); + }}; - private RetryReasonAbbreviationCreator retryReasonAbbreviationCreator = null; - - private int rank = 0; - - /** - * Constructor to have rank and the implementation of {@link RetryReasonAbbreviationCreator}. - * @param rank rank of a given enum. For example SocketTimeoutException is - * subclass of IOException. Rank of SocketTimeoutException enum has to be - * more than that of IOException enum. - * @param abbreviationCreator The implementation of {@link RetryReasonAbbreviationCreator} - * which would give the information if a given enum can be mapped to an error or not. - * */ - RetryReason(int rank, RetryReasonAbbreviationCreator abbreviationCreator) { - this.rank = rank; - this.retryReasonAbbreviationCreator = abbreviationCreator; - } - - private static List retryReasonSortedList; - - /** - * Synchronized method to assign sorted list in {@link RetryReason#retryReasonSortedList}. - * Method would check if list is assigned or not. If yes, method would return. This is required - * because multiple threads could be waiting to get into this method, and once a thread is done - * with this method, other thread would get into this method. Since the list would be assigned by - * first thread, the second thread need not run the whole mechanism of sorting. - * The enums are sorted on the ascending order of their rank. - * */ - private static synchronized void sortRetryReason() { - if (retryReasonSortedList != null) { - return; - } - List list = new ArrayList<>(); - for (RetryReason reason : values()) { - list.add(reason); - } - list.sort((c1, c2) -> { - return c1.rank - c2.rank; - }); - retryReasonSortedList = list; - } - - /** - * Method to get correct abbreviation for a given set of exception, statusCode, - * storageStatusCode. - * Method would iterate through the {@link RetryReason#retryReasonSortedList}, - * and would return the abbreviation returned by highest enum to be applicable on the group. - * For example, if SocketTimeoutException(rank 2) and IOException(rank 0) can be - * applied on the group, the abbreviation of SocketTimeoutException has to be returned. - * - * @param ex exception caught during server communication. - * @param statusCode statusCode in the server response. - * @param storageErrorMessage storageErrorMessage in the server response. - * */ static String getAbbreviation(Exception ex, Integer statusCode, String storageErrorMessage) { String result = null; - if (retryReasonSortedList == null) { - sortRetryReason(); - } - for (RetryReason retryReason : retryReasonSortedList) { + + for(RetryReasonAbbreviationCreator retryReasonAbbreviationCreator : rankedReasons) { String enumCapturedAndAbbreviate - = retryReason.retryReasonAbbreviationCreator.capturableAndGetAbbreviation( + = retryReasonAbbreviationCreator.capturableAndGetAbbreviation( ex, statusCode, storageErrorMessage); if (enumCapturedAndAbbreviate != null) { result = enumCapturedAndAbbreviate; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java index 6754848c162c2..48c2b51eb5ffd 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java @@ -18,6 +18,8 @@ package org.apache.hadoop.fs.azurebfs.services; +import java.util.Locale; + /** * Interface to be implemented by each enum in {@link RetryReason}. The methods * of the interface define if the given enum can be applied on the given server @@ -37,4 +39,15 @@ public interface RetryReasonAbbreviationCreator { String capturableAndGetAbbreviation(Exception ex, Integer statusCode, String serverErrorMessage); + + default String buildFromExceptionMessage(final Exception exceptionCaptured, + final String search, + final String result) { + if (exceptionCaptured != null + && exceptionCaptured.getMessage() != null + && exceptionCaptured.getMessage().toLowerCase(Locale.US).contains(search.toLowerCase(Locale.US))) { + return result; + } + return null; + } } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java index 39dccc168a734..f7faa167c9821 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java @@ -3,5 +3,7 @@ public class RetryReasonConstants { public static final String connectionTimeoutJdkMessage = "connect timed out"; public static final String readTimeoutJdkMessage = "Read timed out"; + public static final String connectionResetMessage = "Connection reset"; + } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ClientErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ClientErrorRetryReason.java new file mode 100644 index 0000000000000..8f174027b5b1b --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ClientErrorRetryReason.java @@ -0,0 +1,18 @@ +package org.apache.hadoop.fs.azurebfs.services.retryReason; + +import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; + +import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; + +public class ClientErrorRetryReason implements RetryReasonAbbreviationCreator { + + @Override + public String capturableAndGetAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + if (statusCode == null || statusCode / HTTP_STATUS_CATEGORY_QUOTIENT != 4) { + return null; + } + return statusCode + ""; + } +} diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ConnectionResetRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ConnectionResetRetryReason.java new file mode 100644 index 0000000000000..cb42cad151008 --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ConnectionResetRetryReason.java @@ -0,0 +1,16 @@ +package org.apache.hadoop.fs.azurebfs.services.retryReason; + +import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; + +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.connectionResetMessage; + +public class ConnectionResetRetryReason implements + RetryReasonAbbreviationCreator { + + @Override + public String capturableAndGetAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + return buildFromExceptionMessage(ex, connectionResetMessage, "CR"); + } +} diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ConnectionTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ConnectionTimeoutRetryReason.java new file mode 100644 index 0000000000000..97e63a0b35238 --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ConnectionTimeoutRetryReason.java @@ -0,0 +1,16 @@ +package org.apache.hadoop.fs.azurebfs.services.retryReason; + +import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; + +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.connectionTimeoutJdkMessage; + +public class ConnectionTimeoutRetryReason implements + RetryReasonAbbreviationCreator { + + @Override + public String capturableAndGetAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + return buildFromExceptionMessage(ex, connectionTimeoutJdkMessage, "CT"); + } +} diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ReadTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ReadTimeoutRetryReason.java new file mode 100644 index 0000000000000..9686002d50b3a --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ReadTimeoutRetryReason.java @@ -0,0 +1,15 @@ +package org.apache.hadoop.fs.azurebfs.services.retryReason; + +import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; + +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.readTimeoutJdkMessage; + +public class ReadTimeoutRetryReason implements RetryReasonAbbreviationCreator { + + @Override + public String capturableAndGetAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + return buildFromExceptionMessage(ex, readTimeoutJdkMessage, "RT"); + } +} diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ServerErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ServerErrorRetryReason.java new file mode 100644 index 0000000000000..4332cd361f0de --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ServerErrorRetryReason.java @@ -0,0 +1,36 @@ +package org.apache.hadoop.fs.azurebfs.services.retryReason; + +import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; + +import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; +import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; + +public class ServerErrorRetryReason implements RetryReasonAbbreviationCreator { + + @Override + public String capturableAndGetAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + if (statusCode == null || statusCode / HTTP_STATUS_CATEGORY_QUOTIENT != 5) { + return null; + } + if (statusCode == HTTP_UNAVAILABLE) { + String splitedServerErrorMessage = serverErrorMessage.split(System.lineSeparator(), + 2)[0]; + if ("Ingress is over the account limit.".equalsIgnoreCase( + splitedServerErrorMessage)) { + return "ING"; + } + if ("Egress is over the account limit.".equalsIgnoreCase( + splitedServerErrorMessage)) { + return "EGR"; + } + if ("Operations per second is over the account limit.".equalsIgnoreCase( + splitedServerErrorMessage)) { + return "OPR"; + } + return HTTP_UNAVAILABLE + ""; + } + return statusCode + ""; + } +} diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownHostRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownHostRetryReason.java new file mode 100644 index 0000000000000..cdb3e36d36149 --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownHostRetryReason.java @@ -0,0 +1,18 @@ +package org.apache.hadoop.fs.azurebfs.services.retryReason; + +import java.net.UnknownHostException; + +import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; + +public class UnknownHostRetryReason implements RetryReasonAbbreviationCreator { + + @Override + public String capturableAndGetAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + if (ex instanceof UnknownHostException) { + return "UH"; + } + return null; + } +} diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownIOExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownIOExceptionRetryReason.java new file mode 100644 index 0000000000000..4eb30fbb4c3ba --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownIOExceptionRetryReason.java @@ -0,0 +1,19 @@ +package org.apache.hadoop.fs.azurebfs.services.retryReason; + +import java.io.IOException; + +import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; + +public class UnknownIOExceptionRetryReason implements + RetryReasonAbbreviationCreator { + + @Override + public String capturableAndGetAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + if (ex instanceof IOException) { + return "IOE"; + } + return null; + } +} diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownSocketExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownSocketExceptionRetryReason.java new file mode 100644 index 0000000000000..233f38494691d --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownSocketExceptionRetryReason.java @@ -0,0 +1,19 @@ +package org.apache.hadoop.fs.azurebfs.services.retryReason; + +import java.net.SocketException; + +import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; + +public class UnknownSocketExceptionRetryReason implements + RetryReasonAbbreviationCreator { + + @Override + public String capturableAndGetAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + if (ex instanceof SocketException) { + return "SE"; + } + return null; + } +} From 62179bcdaff5ebe55545bbfb9a7943101cb5f796 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Wed, 22 Feb 2023 01:52:14 -0800 Subject: [PATCH 19/38] method change in RetryReasonAbbreviationCreator --- .../ClientErrorRetryReason.java | 15 ++++++++--- .../ConnectionResetRetryReason.java | 13 +++++++--- .../ConnectionTimeoutRetryReason.java | 13 +++++++--- .../ReadTimeoutRetryReason.java | 13 +++++++--- .../fs/azurebfs/services/RetryReason.java | 22 +++------------- .../RetryReasonAbbreviationCreator.java | 16 +++++++----- .../ServerErrorRetryReason.java | 15 ++++++++--- .../services/UnknownHostRetryReason.java | 25 ++++++++++++++++++ .../UnknownIOExceptionRetryReason.java | 26 +++++++++++++++++++ .../UnknownSocketExceptionRetryReason.java | 26 +++++++++++++++++++ .../retryReason/UnknownHostRetryReason.java | 18 ------------- .../UnknownIOExceptionRetryReason.java | 19 -------------- .../UnknownSocketExceptionRetryReason.java | 19 -------------- 13 files changed, 142 insertions(+), 98 deletions(-) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{retryReason => }/ClientErrorRetryReason.java (53%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{retryReason => }/ConnectionResetRetryReason.java (56%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{retryReason => }/ConnectionTimeoutRetryReason.java (56%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{retryReason => }/ReadTimeoutRetryReason.java (51%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{retryReason => }/ServerErrorRetryReason.java (75%) create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java delete mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownHostRetryReason.java delete mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownIOExceptionRetryReason.java delete mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownSocketExceptionRetryReason.java diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ClientErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ClientErrorRetryReason.java similarity index 53% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ClientErrorRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ClientErrorRetryReason.java index 8f174027b5b1b..6566813769808 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ClientErrorRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ClientErrorRetryReason.java @@ -1,18 +1,25 @@ -package org.apache.hadoop.fs.azurebfs.services.retryReason; +package org.apache.hadoop.fs.azurebfs.services; import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; -public class ClientErrorRetryReason implements RetryReasonAbbreviationCreator { +class ClientErrorRetryReason implements RetryReasonAbbreviationCreator { @Override - public String capturableAndGetAbbreviation(final Exception ex, + public Boolean canCapture(final Exception ex, final Integer statusCode, final String serverErrorMessage) { if (statusCode == null || statusCode / HTTP_STATUS_CATEGORY_QUOTIENT != 4) { - return null; + return false; } + return true; + } + + @Override + public String getAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { return statusCode + ""; } } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ConnectionResetRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionResetRetryReason.java similarity index 56% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ConnectionResetRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionResetRetryReason.java index cb42cad151008..1a8337058d4a6 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ConnectionResetRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionResetRetryReason.java @@ -1,16 +1,23 @@ -package org.apache.hadoop.fs.azurebfs.services.retryReason; +package org.apache.hadoop.fs.azurebfs.services; import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.connectionResetMessage; -public class ConnectionResetRetryReason implements +class ConnectionResetRetryReason implements RetryReasonAbbreviationCreator { @Override - public String capturableAndGetAbbreviation(final Exception ex, + public Boolean canCapture(final Exception ex, final Integer statusCode, final String serverErrorMessage) { return buildFromExceptionMessage(ex, connectionResetMessage, "CR"); } + + @Override + public String getAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + return "CR"; + } } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ConnectionTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionTimeoutRetryReason.java similarity index 56% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ConnectionTimeoutRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionTimeoutRetryReason.java index 97e63a0b35238..861463192e710 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ConnectionTimeoutRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionTimeoutRetryReason.java @@ -1,14 +1,21 @@ -package org.apache.hadoop.fs.azurebfs.services.retryReason; +package org.apache.hadoop.fs.azurebfs.services; import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.connectionTimeoutJdkMessage; -public class ConnectionTimeoutRetryReason implements +class ConnectionTimeoutRetryReason implements RetryReasonAbbreviationCreator { @Override - public String capturableAndGetAbbreviation(final Exception ex, + public String getAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + return "CT"; + } + + @Override + public Boolean canCapture(final Exception ex, final Integer statusCode, final String serverErrorMessage) { return buildFromExceptionMessage(ex, connectionTimeoutJdkMessage, "CT"); diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ReadTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadTimeoutRetryReason.java similarity index 51% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ReadTimeoutRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadTimeoutRetryReason.java index 9686002d50b3a..3ed04b35b0abc 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ReadTimeoutRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadTimeoutRetryReason.java @@ -1,15 +1,22 @@ -package org.apache.hadoop.fs.azurebfs.services.retryReason; +package org.apache.hadoop.fs.azurebfs.services; import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.readTimeoutJdkMessage; -public class ReadTimeoutRetryReason implements RetryReasonAbbreviationCreator { +class ReadTimeoutRetryReason implements RetryReasonAbbreviationCreator { @Override - public String capturableAndGetAbbreviation(final Exception ex, + public Boolean canCapture(final Exception ex, final Integer statusCode, final String serverErrorMessage) { return buildFromExceptionMessage(ex, readTimeoutJdkMessage, "RT"); } + + @Override + public String getAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + return "RT"; + } } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index fd7213d5cdad0..325f7af9de787 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -18,22 +18,8 @@ package org.apache.hadoop.fs.azurebfs.services; -import java.io.IOException; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.ArrayList; import java.util.LinkedList; import java.util.List; -import java.util.Locale; - -import org.apache.hadoop.fs.azurebfs.services.retryReason.ClientErrorRetryReason; -import org.apache.hadoop.fs.azurebfs.services.retryReason.ConnectionResetRetryReason; -import org.apache.hadoop.fs.azurebfs.services.retryReason.ConnectionTimeoutRetryReason; -import org.apache.hadoop.fs.azurebfs.services.retryReason.ReadTimeoutRetryReason; -import org.apache.hadoop.fs.azurebfs.services.retryReason.ServerErrorRetryReason; -import org.apache.hadoop.fs.azurebfs.services.retryReason.UnknownHostRetryReason; -import org.apache.hadoop.fs.azurebfs.services.retryReason.UnknownIOExceptionRetryReason; -import org.apache.hadoop.fs.azurebfs.services.retryReason.UnknownSocketExceptionRetryReason; /** @@ -58,11 +44,9 @@ static String getAbbreviation(Exception ex, String result = null; for(RetryReasonAbbreviationCreator retryReasonAbbreviationCreator : rankedReasons) { - String enumCapturedAndAbbreviate - = retryReasonAbbreviationCreator.capturableAndGetAbbreviation( - ex, statusCode, storageErrorMessage); - if (enumCapturedAndAbbreviate != null) { - result = enumCapturedAndAbbreviate; + Boolean canCapture = retryReasonAbbreviationCreator.canCapture(ex, statusCode, storageErrorMessage); + if(canCapture) { + result = retryReasonAbbreviationCreator.getAbbreviation(ex, statusCode, storageErrorMessage); } } return result; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java index 48c2b51eb5ffd..198a571cffc97 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java @@ -25,29 +25,33 @@ * of the interface define if the given enum can be applied on the given server * response. * */ -public interface RetryReasonAbbreviationCreator { +interface RetryReasonAbbreviationCreator { /** * Returns an abbreviation if the {@link RetryReason} enum can be applied on * the server response. + * * @param ex exception captured in the server API call. * @param statusCode statusCode on the server response * @param serverErrorMessage serverErrorMessage on the server response. + * * @return
  1. null if the enum can not be used on the server response
  2. *
  3. abbreviation corresponding to the server response.
- * */ - String capturableAndGetAbbreviation(Exception ex, + */ + Boolean canCapture(Exception ex, Integer statusCode, String serverErrorMessage); - default String buildFromExceptionMessage(final Exception exceptionCaptured, + String getAbbreviation(Exception ex, Integer statusCode, String serverErrorMessage); + + default Boolean buildFromExceptionMessage(final Exception exceptionCaptured, final String search, final String result) { if (exceptionCaptured != null && exceptionCaptured.getMessage() != null && exceptionCaptured.getMessage().toLowerCase(Locale.US).contains(search.toLowerCase(Locale.US))) { - return result; + return true; } - return null; + return false; } } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ServerErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ServerErrorRetryReason.java similarity index 75% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ServerErrorRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ServerErrorRetryReason.java index 4332cd361f0de..701d11077beab 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/ServerErrorRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ServerErrorRetryReason.java @@ -1,19 +1,26 @@ -package org.apache.hadoop.fs.azurebfs.services.retryReason; +package org.apache.hadoop.fs.azurebfs.services; import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; -public class ServerErrorRetryReason implements RetryReasonAbbreviationCreator { +class ServerErrorRetryReason implements RetryReasonAbbreviationCreator { @Override - public String capturableAndGetAbbreviation(final Exception ex, + public Boolean canCapture(final Exception ex, final Integer statusCode, final String serverErrorMessage) { if (statusCode == null || statusCode / HTTP_STATUS_CATEGORY_QUOTIENT != 5) { - return null; + return false; } + return true; + } + + @Override + public String getAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { if (statusCode == HTTP_UNAVAILABLE) { String splitedServerErrorMessage = serverErrorMessage.split(System.lineSeparator(), 2)[0]; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java new file mode 100644 index 0000000000000..e12645a757581 --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java @@ -0,0 +1,25 @@ +package org.apache.hadoop.fs.azurebfs.services; + +import java.net.UnknownHostException; + +import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; + +class UnknownHostRetryReason implements RetryReasonAbbreviationCreator { + + @Override + public Boolean canCapture(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + if (ex instanceof UnknownHostException) { + return true; + } + return false; + } + + @Override + public String getAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + return "UH"; + } +} diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java new file mode 100644 index 0000000000000..c200dba8e34ff --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java @@ -0,0 +1,26 @@ +package org.apache.hadoop.fs.azurebfs.services; + +import java.io.IOException; + +import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; + +class UnknownIOExceptionRetryReason implements + RetryReasonAbbreviationCreator { + + @Override + public Boolean canCapture(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + if (ex instanceof IOException) { + return true; + } + return false; + } + + @Override + public String getAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + return "IOE"; + } +} diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java new file mode 100644 index 0000000000000..a929179877107 --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java @@ -0,0 +1,26 @@ +package org.apache.hadoop.fs.azurebfs.services; + +import java.net.SocketException; + +import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; + +class UnknownSocketExceptionRetryReason implements + RetryReasonAbbreviationCreator { + + @Override + public Boolean canCapture(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + if (ex instanceof SocketException) { + return true; + } + return false; + } + + @Override + public String getAbbreviation(final Exception ex, + final Integer statusCode, + final String serverErrorMessage) { + return "SE"; + } +} diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownHostRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownHostRetryReason.java deleted file mode 100644 index cdb3e36d36149..0000000000000 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownHostRetryReason.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.apache.hadoop.fs.azurebfs.services.retryReason; - -import java.net.UnknownHostException; - -import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; - -public class UnknownHostRetryReason implements RetryReasonAbbreviationCreator { - - @Override - public String capturableAndGetAbbreviation(final Exception ex, - final Integer statusCode, - final String serverErrorMessage) { - if (ex instanceof UnknownHostException) { - return "UH"; - } - return null; - } -} diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownIOExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownIOExceptionRetryReason.java deleted file mode 100644 index 4eb30fbb4c3ba..0000000000000 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownIOExceptionRetryReason.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.apache.hadoop.fs.azurebfs.services.retryReason; - -import java.io.IOException; - -import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; - -public class UnknownIOExceptionRetryReason implements - RetryReasonAbbreviationCreator { - - @Override - public String capturableAndGetAbbreviation(final Exception ex, - final Integer statusCode, - final String serverErrorMessage) { - if (ex instanceof IOException) { - return "IOE"; - } - return null; - } -} diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownSocketExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownSocketExceptionRetryReason.java deleted file mode 100644 index 233f38494691d..0000000000000 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReason/UnknownSocketExceptionRetryReason.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.apache.hadoop.fs.azurebfs.services.retryReason; - -import java.net.SocketException; - -import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; - -public class UnknownSocketExceptionRetryReason implements - RetryReasonAbbreviationCreator { - - @Override - public String capturableAndGetAbbreviation(final Exception ex, - final Integer statusCode, - final String serverErrorMessage) { - if (ex instanceof SocketException) { - return "SE"; - } - return null; - } -} From 270545d2f29d783eb33df056be6d15f0900f48bc Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Wed, 22 Feb 2023 02:18:48 -0800 Subject: [PATCH 20/38] asf license --- .../services/ClientErrorRetryReason.java | 20 +++++++++++++++++-- .../services/ConnectionResetRetryReason.java | 20 +++++++++++++++++-- .../ConnectionTimeoutRetryReason.java | 19 +++++++++++++++++- .../services/ReadTimeoutRetryReason.java | 20 +++++++++++++++++-- .../services/ServerErrorRetryReason.java | 20 +++++++++++++++++-- .../services/UnknownHostRetryReason.java | 20 +++++++++++++++++-- .../UnknownIOExceptionRetryReason.java | 19 +++++++++++++++++- .../UnknownSocketExceptionRetryReason.java | 19 +++++++++++++++++- 8 files changed, 144 insertions(+), 13 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ClientErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ClientErrorRetryReason.java index 6566813769808..68b45b24deb64 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ClientErrorRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ClientErrorRetryReason.java @@ -1,6 +1,22 @@ -package org.apache.hadoop.fs.azurebfs.services; +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; +package org.apache.hadoop.fs.azurebfs.services; import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionResetRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionResetRetryReason.java index 1a8337058d4a6..4b604e78aa986 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionResetRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionResetRetryReason.java @@ -1,6 +1,22 @@ -package org.apache.hadoop.fs.azurebfs.services; +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; +package org.apache.hadoop.fs.azurebfs.services; import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.connectionResetMessage; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionTimeoutRetryReason.java index 861463192e710..61d7d66f2137a 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionTimeoutRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionTimeoutRetryReason.java @@ -1,6 +1,23 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.hadoop.fs.azurebfs.services; -import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.connectionTimeoutJdkMessage; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadTimeoutRetryReason.java index 3ed04b35b0abc..59b87a432556b 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadTimeoutRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadTimeoutRetryReason.java @@ -1,6 +1,22 @@ -package org.apache.hadoop.fs.azurebfs.services; +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; +package org.apache.hadoop.fs.azurebfs.services; import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.readTimeoutJdkMessage; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ServerErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ServerErrorRetryReason.java index 701d11077beab..da349a211f15a 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ServerErrorRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ServerErrorRetryReason.java @@ -1,6 +1,22 @@ -package org.apache.hadoop.fs.azurebfs.services; +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; +package org.apache.hadoop.fs.azurebfs.services; import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java index e12645a757581..e3e90452269fa 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java @@ -1,9 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.hadoop.fs.azurebfs.services; import java.net.UnknownHostException; -import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; - class UnknownHostRetryReason implements RetryReasonAbbreviationCreator { @Override diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java index c200dba8e34ff..18ffa0b778532 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java @@ -1,8 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.hadoop.fs.azurebfs.services; import java.io.IOException; -import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; class UnknownIOExceptionRetryReason implements RetryReasonAbbreviationCreator { diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java index a929179877107..1a355ac0fc161 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java @@ -1,8 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.hadoop.fs.azurebfs.services; import java.net.SocketException; -import org.apache.hadoop.fs.azurebfs.services.RetryReasonAbbreviationCreator; class UnknownSocketExceptionRetryReason implements RetryReasonAbbreviationCreator { From de424e39d3abdea18572b001b5bea4ddb62ed4b1 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Wed, 22 Feb 2023 03:58:47 -0800 Subject: [PATCH 21/38] javadocs + small refactors --- .../services/ClientErrorRetryReason.java | 3 +- .../services/ConnectionResetRetryReason.java | 5 ++- .../ConnectionTimeoutRetryReason.java | 5 ++- .../services/ReadTimeoutRetryReason.java | 5 ++- .../fs/azurebfs/services/RetryReason.java | 2 +- .../RetryReasonAbbreviationCreator.java | 36 ++++++++++++------- .../services/ServerErrorRetryReason.java | 3 +- .../services/UnknownHostRetryReason.java | 3 +- .../UnknownIOExceptionRetryReason.java | 3 +- .../UnknownSocketExceptionRetryReason.java | 3 +- 10 files changed, 36 insertions(+), 32 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ClientErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ClientErrorRetryReason.java index 68b45b24deb64..8ebc81ae331ae 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ClientErrorRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ClientErrorRetryReason.java @@ -33,8 +33,7 @@ public Boolean canCapture(final Exception ex, } @Override - public String getAbbreviation(final Exception ex, - final Integer statusCode, + public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { return statusCode + ""; } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionResetRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionResetRetryReason.java index 4b604e78aa986..ddc45da99ed11 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionResetRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionResetRetryReason.java @@ -27,12 +27,11 @@ class ConnectionResetRetryReason implements public Boolean canCapture(final Exception ex, final Integer statusCode, final String serverErrorMessage) { - return buildFromExceptionMessage(ex, connectionResetMessage, "CR"); + return checkExceptionMessage(ex, connectionResetMessage); } @Override - public String getAbbreviation(final Exception ex, - final Integer statusCode, + public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { return "CR"; } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionTimeoutRetryReason.java index 61d7d66f2137a..2e291c4f82188 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionTimeoutRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionTimeoutRetryReason.java @@ -25,8 +25,7 @@ class ConnectionTimeoutRetryReason implements RetryReasonAbbreviationCreator { @Override - public String getAbbreviation(final Exception ex, - final Integer statusCode, + public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { return "CT"; } @@ -35,6 +34,6 @@ public String getAbbreviation(final Exception ex, public Boolean canCapture(final Exception ex, final Integer statusCode, final String serverErrorMessage) { - return buildFromExceptionMessage(ex, connectionTimeoutJdkMessage, "CT"); + return checkExceptionMessage(ex, connectionTimeoutJdkMessage); } } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadTimeoutRetryReason.java index 59b87a432556b..2466bf5f7bcf0 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadTimeoutRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadTimeoutRetryReason.java @@ -26,12 +26,11 @@ class ReadTimeoutRetryReason implements RetryReasonAbbreviationCreator { public Boolean canCapture(final Exception ex, final Integer statusCode, final String serverErrorMessage) { - return buildFromExceptionMessage(ex, readTimeoutJdkMessage, "RT"); + return checkExceptionMessage(ex, readTimeoutJdkMessage); } @Override - public String getAbbreviation(final Exception ex, - final Integer statusCode, + public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { return "RT"; } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index 325f7af9de787..0f9435010c93a 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -46,7 +46,7 @@ static String getAbbreviation(Exception ex, for(RetryReasonAbbreviationCreator retryReasonAbbreviationCreator : rankedReasons) { Boolean canCapture = retryReasonAbbreviationCreator.canCapture(ex, statusCode, storageErrorMessage); if(canCapture) { - result = retryReasonAbbreviationCreator.getAbbreviation(ex, statusCode, storageErrorMessage); + result = retryReasonAbbreviationCreator.getAbbreviation(statusCode, storageErrorMessage); } } return result; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java index 198a571cffc97..ace1fd3495302 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java @@ -21,32 +21,44 @@ import java.util.Locale; /** - * Interface to be implemented by each enum in {@link RetryReason}. The methods - * of the interface define if the given enum can be applied on the given server - * response. + * Provides methods to define if given exception can be categorised to certain category. + * Each category has a different implementation of the interface. * */ interface RetryReasonAbbreviationCreator { /** - * Returns an abbreviation if the {@link RetryReason} enum can be applied on - * the server response. + * Returns if given server response error can be converted to an abbreviation + * by the implementation. * - * @param ex exception captured in the server API call. + * @param ex exception captured in the server response. * @param statusCode statusCode on the server response * @param serverErrorMessage serverErrorMessage on the server response. * - * @return

  1. null if the enum can not be used on the server response
  2. - *
  3. abbreviation corresponding to the server response.
+ * @return
  1. true if server response error can be converted to abbreviation by the implementation
  2. + *
  3. false if response error can not be abbreviated by the implementation
*/ Boolean canCapture(Exception ex, Integer statusCode, String serverErrorMessage); - String getAbbreviation(Exception ex, Integer statusCode, String serverErrorMessage); + /** + * Returns the abbreviation corresponding to the server response error. + * + * @param statusCode statusCode on the server response + * @param serverErrorMessage serverErrorMessage on the server response. + * + * @return abbreviation on the basis of the statusCode and the serverErrorMessage + */ + String getAbbreviation(Integer statusCode, String serverErrorMessage); - default Boolean buildFromExceptionMessage(final Exception exceptionCaptured, - final String search, - final String result) { + /** + * Checks if a required search-string is in the exception's message. + */ + default Boolean checkExceptionMessage(final Exception exceptionCaptured, + final String search) { + if(search == null) { + return false; + } if (exceptionCaptured != null && exceptionCaptured.getMessage() != null && exceptionCaptured.getMessage().toLowerCase(Locale.US).contains(search.toLowerCase(Locale.US))) { diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ServerErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ServerErrorRetryReason.java index da349a211f15a..4064d7f75798b 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ServerErrorRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ServerErrorRetryReason.java @@ -34,8 +34,7 @@ public Boolean canCapture(final Exception ex, } @Override - public String getAbbreviation(final Exception ex, - final Integer statusCode, + public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { if (statusCode == HTTP_UNAVAILABLE) { String splitedServerErrorMessage = serverErrorMessage.split(System.lineSeparator(), diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java index e3e90452269fa..471314cf81027 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java @@ -33,8 +33,7 @@ public Boolean canCapture(final Exception ex, } @Override - public String getAbbreviation(final Exception ex, - final Integer statusCode, + public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { return "UH"; } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java index 18ffa0b778532..ceb55176cf20b 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java @@ -35,8 +35,7 @@ public Boolean canCapture(final Exception ex, } @Override - public String getAbbreviation(final Exception ex, - final Integer statusCode, + public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { return "IOE"; } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java index 1a355ac0fc161..848df15016303 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java @@ -35,8 +35,7 @@ public Boolean canCapture(final Exception ex, } @Override - public String getAbbreviation(final Exception ex, - final Integer statusCode, + public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { return "SE"; } From 94810b8fb4f6b09bde23610e6c818e5154877f8e Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Wed, 22 Feb 2023 21:46:00 -0800 Subject: [PATCH 22/38] fixed access modifier, only public method in abstract class is captureAndGetAbbreviation. This method will give abbreviation only if the implementation is actionable on the exception. --- .../fs/azurebfs/services/RetryReason.java | 24 +++++++++++++++---- .../ClientErrorRetryReason.java | 6 +++-- .../ConnectionResetRetryReason.java | 6 +++-- .../ConnectionTimeoutRetryReason.java | 6 +++-- .../ReadTimeoutRetryReason.java | 6 +++-- .../RetryReasonAbbreviationCreator.java | 17 +++++++++---- .../ServerErrorRetryReason.java | 6 +++-- .../UnknownHostRetryReason.java | 6 +++-- .../UnknownIOExceptionRetryReason.java | 6 +++-- .../UnknownSocketExceptionRetryReason.java | 6 +++-- 10 files changed, 63 insertions(+), 26 deletions(-) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{ => retryReasonAbbreviationCreation}/ClientErrorRetryReason.java (83%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{ => retryReasonAbbreviationCreation}/ConnectionResetRetryReason.java (84%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{ => retryReasonAbbreviationCreation}/ConnectionTimeoutRetryReason.java (84%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{ => retryReasonAbbreviationCreation}/ReadTimeoutRetryReason.java (82%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{ => retryReasonAbbreviationCreation}/RetryReasonAbbreviationCreator.java (79%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{ => retryReasonAbbreviationCreation}/ServerErrorRetryReason.java (88%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{ => retryReasonAbbreviationCreation}/UnknownHostRetryReason.java (81%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{ => retryReasonAbbreviationCreation}/UnknownIOExceptionRetryReason.java (83%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{ => retryReasonAbbreviationCreation}/UnknownSocketExceptionRetryReason.java (83%) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index 0f9435010c93a..c27ea440449cd 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -21,13 +21,25 @@ import java.util.LinkedList; import java.util.List; +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.ClientErrorRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.ConnectionResetRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.ConnectionTimeoutRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.ReadTimeoutRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.ServerErrorRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.UnknownHostRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.UnknownIOExceptionRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.UnknownSocketExceptionRetryReason; + /** * In case of retry, this enum would give the information on the reason for * previous API call. * */ public class RetryReason { - private static List rankedReasons = new LinkedList() {{ + + private static List rankedReasons + = new LinkedList() {{ add(new ServerErrorRetryReason()); add(new ClientErrorRetryReason()); add(new UnknownIOExceptionRetryReason()); @@ -43,10 +55,12 @@ static String getAbbreviation(Exception ex, String storageErrorMessage) { String result = null; - for(RetryReasonAbbreviationCreator retryReasonAbbreviationCreator : rankedReasons) { - Boolean canCapture = retryReasonAbbreviationCreator.canCapture(ex, statusCode, storageErrorMessage); - if(canCapture) { - result = retryReasonAbbreviationCreator.getAbbreviation(statusCode, storageErrorMessage); + for (RetryReasonAbbreviationCreator retryReasonAbbreviationCreator : rankedReasons) { + final String abbreviation + = retryReasonAbbreviationCreator.captureAndGetAbbreviation(ex, + statusCode, storageErrorMessage); + if (abbreviation != null) { + result = abbreviation; } } return result; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ClientErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ClientErrorRetryReason.java similarity index 83% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ClientErrorRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ClientErrorRetryReason.java index 8ebc81ae331ae..6739639f65533 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ClientErrorRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ClientErrorRetryReason.java @@ -16,11 +16,13 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services; +package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; + +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; -class ClientErrorRetryReason implements RetryReasonAbbreviationCreator { +public class ClientErrorRetryReason extends RetryReasonAbbreviationCreator { @Override public Boolean canCapture(final Exception ex, diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionResetRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ConnectionResetRetryReason.java similarity index 84% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionResetRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ConnectionResetRetryReason.java index ddc45da99ed11..e1dc5bafaca40 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionResetRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ConnectionResetRetryReason.java @@ -16,11 +16,13 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services; +package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; + +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.connectionResetMessage; -class ConnectionResetRetryReason implements +public class ConnectionResetRetryReason extends RetryReasonAbbreviationCreator { @Override diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ConnectionTimeoutRetryReason.java similarity index 84% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionTimeoutRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ConnectionTimeoutRetryReason.java index 2e291c4f82188..bcd9e4fb8ec66 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ConnectionTimeoutRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ConnectionTimeoutRetryReason.java @@ -16,12 +16,14 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services; +package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; + import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.connectionTimeoutJdkMessage; -class ConnectionTimeoutRetryReason implements +public class ConnectionTimeoutRetryReason extends RetryReasonAbbreviationCreator { @Override diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ReadTimeoutRetryReason.java similarity index 82% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadTimeoutRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ReadTimeoutRetryReason.java index 2466bf5f7bcf0..c15d97cf8ed00 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadTimeoutRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ReadTimeoutRetryReason.java @@ -16,11 +16,13 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services; +package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; + +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.readTimeoutJdkMessage; -class ReadTimeoutRetryReason implements RetryReasonAbbreviationCreator { +public class ReadTimeoutRetryReason extends RetryReasonAbbreviationCreator { @Override public Boolean canCapture(final Exception ex, diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/RetryReasonAbbreviationCreator.java similarity index 79% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/RetryReasonAbbreviationCreator.java index ace1fd3495302..aede2fb38030f 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonAbbreviationCreator.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/RetryReasonAbbreviationCreator.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services; +package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; import java.util.Locale; @@ -24,7 +24,7 @@ * Provides methods to define if given exception can be categorised to certain category. * Each category has a different implementation of the interface. * */ -interface RetryReasonAbbreviationCreator { +public abstract class RetryReasonAbbreviationCreator { /** * Returns if given server response error can be converted to an abbreviation @@ -37,7 +37,7 @@ interface RetryReasonAbbreviationCreator { * @return
  1. true if server response error can be converted to abbreviation by the implementation
  2. *
  3. false if response error can not be abbreviated by the implementation
*/ - Boolean canCapture(Exception ex, + abstract Boolean canCapture(Exception ex, Integer statusCode, String serverErrorMessage); @@ -49,12 +49,19 @@ Boolean canCapture(Exception ex, * * @return abbreviation on the basis of the statusCode and the serverErrorMessage */ - String getAbbreviation(Integer statusCode, String serverErrorMessage); + abstract String getAbbreviation(Integer statusCode, String serverErrorMessage); + + public String captureAndGetAbbreviation(Exception ex, Integer statusCode, String serverErrorMessage) { + if(canCapture(ex, statusCode, serverErrorMessage)) { + return getAbbreviation(statusCode, serverErrorMessage); + } + return null; + } /** * Checks if a required search-string is in the exception's message. */ - default Boolean checkExceptionMessage(final Exception exceptionCaptured, + Boolean checkExceptionMessage(final Exception exceptionCaptured, final String search) { if(search == null) { return false; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ServerErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ServerErrorRetryReason.java similarity index 88% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ServerErrorRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ServerErrorRetryReason.java index 4064d7f75798b..75c0d7b7c121f 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ServerErrorRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ServerErrorRetryReason.java @@ -16,12 +16,14 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services; +package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; + +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; -class ServerErrorRetryReason implements RetryReasonAbbreviationCreator { +public class ServerErrorRetryReason extends RetryReasonAbbreviationCreator { @Override public Boolean canCapture(final Exception ex, diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownHostRetryReason.java similarity index 81% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownHostRetryReason.java index 471314cf81027..0afe6aac07ffd 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownHostRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownHostRetryReason.java @@ -16,11 +16,13 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services; +package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; import java.net.UnknownHostException; -class UnknownHostRetryReason implements RetryReasonAbbreviationCreator { +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; + +public class UnknownHostRetryReason extends RetryReasonAbbreviationCreator { @Override public Boolean canCapture(final Exception ex, diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownIOExceptionRetryReason.java similarity index 83% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownIOExceptionRetryReason.java index ceb55176cf20b..5c029d80e5bbd 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownIOExceptionRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownIOExceptionRetryReason.java @@ -16,12 +16,14 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services; +package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; import java.io.IOException; +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; -class UnknownIOExceptionRetryReason implements + +public class UnknownIOExceptionRetryReason extends RetryReasonAbbreviationCreator { @Override diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownSocketExceptionRetryReason.java similarity index 83% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownSocketExceptionRetryReason.java index 848df15016303..b5fcf3344f536 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/UnknownSocketExceptionRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownSocketExceptionRetryReason.java @@ -16,12 +16,14 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services; +package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; import java.net.SocketException; +import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; -class UnknownSocketExceptionRetryReason implements + +public class UnknownSocketExceptionRetryReason extends RetryReasonAbbreviationCreator { @Override From dad7b61327d44be350888b2440579f44e2a933c4 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Wed, 22 Feb 2023 22:14:16 -0800 Subject: [PATCH 23/38] javadoc for RetryReason; package name change --- .../fs/azurebfs/services/RetryReason.java | 57 +++++++++++++------ .../ClientErrorRetryReason.java | 6 +- .../ConnectionResetRetryReason.java | 6 +- .../ConnectionTimeoutRetryReason.java | 6 +- .../ReadTimeoutRetryReason.java | 6 +- .../RetryReasonCategory.java} | 4 +- .../ServerErrorRetryReason.java | 6 +- .../UnknownHostRetryReason.java | 6 +- .../UnknownIOExceptionRetryReason.java | 6 +- .../UnknownSocketExceptionRetryReason.java | 6 +- 10 files changed, 59 insertions(+), 50 deletions(-) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{retryReasonAbbreviationCreation => retryReasonCategories}/ClientErrorRetryReason.java (83%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{retryReasonAbbreviationCreation => retryReasonCategories}/ConnectionResetRetryReason.java (85%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{retryReasonAbbreviationCreation => retryReasonCategories}/ConnectionTimeoutRetryReason.java (85%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{retryReasonAbbreviationCreation => retryReasonCategories}/ReadTimeoutRetryReason.java (82%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{retryReasonAbbreviationCreation/RetryReasonAbbreviationCreator.java => retryReasonCategories/RetryReasonCategory.java} (95%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{retryReasonAbbreviationCreation => retryReasonCategories}/ServerErrorRetryReason.java (88%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{retryReasonAbbreviationCreation => retryReasonCategories}/UnknownHostRetryReason.java (81%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{retryReasonAbbreviationCreation => retryReasonCategories}/UnknownIOExceptionRetryReason.java (84%) rename hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/{retryReasonAbbreviationCreation => retryReasonCategories}/UnknownSocketExceptionRetryReason.java (84%) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index c27ea440449cd..b7b5a2a57df3b 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -21,25 +21,46 @@ import java.util.LinkedList; import java.util.List; -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.ClientErrorRetryReason; -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.ConnectionResetRetryReason; -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.ConnectionTimeoutRetryReason; -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.ReadTimeoutRetryReason; -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.ServerErrorRetryReason; -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.UnknownHostRetryReason; -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.UnknownIOExceptionRetryReason; -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.UnknownSocketExceptionRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonCategories.ClientErrorRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonCategories.ConnectionResetRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonCategories.ConnectionTimeoutRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonCategories.ReadTimeoutRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonCategories.RetryReasonCategory; +import org.apache.hadoop.fs.azurebfs.services.retryReasonCategories.ServerErrorRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonCategories.UnknownHostRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonCategories.UnknownIOExceptionRetryReason; +import org.apache.hadoop.fs.azurebfs.services.retryReasonCategories.UnknownSocketExceptionRetryReason; /** - * In case of retry, this enum would give the information on the reason for - * previous API call. + * This utility class exposes methods to convert a server response-error to a + * category of error. * */ -public class RetryReason { +class RetryReason { - private static List rankedReasons - = new LinkedList() {{ + /** + * Linked-list of the implementations of RetryReasonCategory. The objects in the + * list are arranged by the rank of their significance. + *
    + *
  • ServerError (statusCode==5XX), ClientError (statusCode==4XX) are + * independent of other retryReason categories.
  • + *
  • Since {@link java.net.SocketException} is subclass of + * {@link java.io.IOException}, + * hence, {@link UnknownIOExceptionRetryReason} is placed before + * {@link UnknownSocketExceptionRetryReason}
  • + *
  • Since, connectionTimeout, readTimeout, and connectionReset are + * {@link java.net.SocketException} exceptions with different messages, + * hence, {@link ConnectionTimeoutRetryReason}, {@link ReadTimeoutRetryReason}, + * {@link ConnectionResetRetryReason} are above {@link UnknownSocketExceptionRetryReason}. + * There is no order between the three reasons as they are differentiated + * by exception-message.
  • + *
  • Since, {@link java.net.UnknownHostException} is subclass of + * {@link java.io.IOException}, {@link UnknownHostRetryReason} is placed + * over {@link UnknownIOExceptionRetryReason}
  • + *
+ * */ + private static List rankedReasonCategories + = new LinkedList() {{ add(new ServerErrorRetryReason()); add(new ClientErrorRetryReason()); add(new UnknownIOExceptionRetryReason()); @@ -50,14 +71,18 @@ public class RetryReason { add(new ConnectionResetRetryReason()); }}; + private RetryReason() { + + } + static String getAbbreviation(Exception ex, Integer statusCode, String storageErrorMessage) { String result = null; - for (RetryReasonAbbreviationCreator retryReasonAbbreviationCreator : rankedReasons) { + for (RetryReasonCategory retryReasonCategory : rankedReasonCategories) { final String abbreviation - = retryReasonAbbreviationCreator.captureAndGetAbbreviation(ex, + = retryReasonCategory.captureAndGetAbbreviation(ex, statusCode, storageErrorMessage); if (abbreviation != null) { result = abbreviation; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ClientErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ClientErrorRetryReason.java similarity index 83% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ClientErrorRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ClientErrorRetryReason.java index 6739639f65533..5dfc1a6a7e974 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ClientErrorRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ClientErrorRetryReason.java @@ -16,13 +16,11 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; - -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; +package org.apache.hadoop.fs.azurebfs.services.retryReasonCategories; import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; -public class ClientErrorRetryReason extends RetryReasonAbbreviationCreator { +public class ClientErrorRetryReason extends RetryReasonCategory { @Override public Boolean canCapture(final Exception ex, diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ConnectionResetRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionResetRetryReason.java similarity index 85% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ConnectionResetRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionResetRetryReason.java index e1dc5bafaca40..0d148504a450b 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ConnectionResetRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionResetRetryReason.java @@ -16,14 +16,12 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; - -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; +package org.apache.hadoop.fs.azurebfs.services.retryReasonCategories; import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.connectionResetMessage; public class ConnectionResetRetryReason extends - RetryReasonAbbreviationCreator { + RetryReasonCategory { @Override public Boolean canCapture(final Exception ex, diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ConnectionTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionTimeoutRetryReason.java similarity index 85% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ConnectionTimeoutRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionTimeoutRetryReason.java index bcd9e4fb8ec66..9754fa469f43e 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ConnectionTimeoutRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionTimeoutRetryReason.java @@ -16,15 +16,13 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; +package org.apache.hadoop.fs.azurebfs.services.retryReasonCategories; -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; - import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.connectionTimeoutJdkMessage; public class ConnectionTimeoutRetryReason extends - RetryReasonAbbreviationCreator { + RetryReasonCategory { @Override public String getAbbreviation(final Integer statusCode, diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ReadTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ReadTimeoutRetryReason.java similarity index 82% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ReadTimeoutRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ReadTimeoutRetryReason.java index c15d97cf8ed00..06eb570bdff3e 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ReadTimeoutRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ReadTimeoutRetryReason.java @@ -16,13 +16,11 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; - -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; +package org.apache.hadoop.fs.azurebfs.services.retryReasonCategories; import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.readTimeoutJdkMessage; -public class ReadTimeoutRetryReason extends RetryReasonAbbreviationCreator { +public class ReadTimeoutRetryReason extends RetryReasonCategory { @Override public Boolean canCapture(final Exception ex, diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/RetryReasonAbbreviationCreator.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/RetryReasonCategory.java similarity index 95% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/RetryReasonAbbreviationCreator.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/RetryReasonCategory.java index aede2fb38030f..cef446222efbf 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/RetryReasonAbbreviationCreator.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/RetryReasonCategory.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; +package org.apache.hadoop.fs.azurebfs.services.retryReasonCategories; import java.util.Locale; @@ -24,7 +24,7 @@ * Provides methods to define if given exception can be categorised to certain category. * Each category has a different implementation of the interface. * */ -public abstract class RetryReasonAbbreviationCreator { +public abstract class RetryReasonCategory { /** * Returns if given server response error can be converted to an abbreviation diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ServerErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java similarity index 88% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ServerErrorRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java index 75c0d7b7c121f..5711089cefc9b 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/ServerErrorRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java @@ -16,14 +16,12 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; - -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; +package org.apache.hadoop.fs.azurebfs.services.retryReasonCategories; import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; -public class ServerErrorRetryReason extends RetryReasonAbbreviationCreator { +public class ServerErrorRetryReason extends RetryReasonCategory { @Override public Boolean canCapture(final Exception ex, diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownHostRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownHostRetryReason.java similarity index 81% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownHostRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownHostRetryReason.java index 0afe6aac07ffd..637f736488e31 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownHostRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownHostRetryReason.java @@ -16,13 +16,11 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; +package org.apache.hadoop.fs.azurebfs.services.retryReasonCategories; import java.net.UnknownHostException; -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; - -public class UnknownHostRetryReason extends RetryReasonAbbreviationCreator { +public class UnknownHostRetryReason extends RetryReasonCategory { @Override public Boolean canCapture(final Exception ex, diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownIOExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownIOExceptionRetryReason.java similarity index 84% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownIOExceptionRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownIOExceptionRetryReason.java index 5c029d80e5bbd..47c843eb964f9 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownIOExceptionRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownIOExceptionRetryReason.java @@ -16,15 +16,13 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; +package org.apache.hadoop.fs.azurebfs.services.retryReasonCategories; import java.io.IOException; -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; - public class UnknownIOExceptionRetryReason extends - RetryReasonAbbreviationCreator { + RetryReasonCategory { @Override public Boolean canCapture(final Exception ex, diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownSocketExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownSocketExceptionRetryReason.java similarity index 84% rename from hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownSocketExceptionRetryReason.java rename to hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownSocketExceptionRetryReason.java index b5fcf3344f536..8e9cd24c357b6 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonAbbreviationCreation/UnknownSocketExceptionRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownSocketExceptionRetryReason.java @@ -16,15 +16,13 @@ * limitations under the License. */ -package org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation; +package org.apache.hadoop.fs.azurebfs.services.retryReasonCategories; import java.net.SocketException; -import org.apache.hadoop.fs.azurebfs.services.retryReasonAbbreviationCreation.RetryReasonAbbreviationCreator; - public class UnknownSocketExceptionRetryReason extends - RetryReasonAbbreviationCreator { + RetryReasonCategory { @Override public Boolean canCapture(final Exception ex, From ac5593e1be361a4c01c6e5c760248c020dd60521 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Wed, 22 Feb 2023 22:44:17 -0800 Subject: [PATCH 24/38] RetryReasonConstants --- .../services/AzureServiceErrorCode.java | 4 ++++ .../services/RetryReasonConstants.java | 16 +++++++++++--- .../ConnectionResetRetryReason.java | 7 +++--- .../ConnectionTimeoutRetryReason.java | 7 +++--- .../ReadTimeoutRetryReason.java | 7 +++--- .../ServerErrorRetryReason.java | 18 ++++++++++----- .../UnknownHostRetryReason.java | 4 +++- .../UnknownIOExceptionRetryReason.java | 4 +++- .../UnknownSocketExceptionRetryReason.java | 4 +++- .../fs/azurebfs/services/TestRetryReason.java | 22 +++++++++++++++++++ 10 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestRetryReason.java diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/contracts/services/AzureServiceErrorCode.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/contracts/services/AzureServiceErrorCode.java index 8bc31c4f92b2a..8a5e9db8553d8 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/contracts/services/AzureServiceErrorCode.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/contracts/services/AzureServiceErrorCode.java @@ -66,6 +66,10 @@ public String getErrorCode() { return this.errorCode; } + public String getErrorMessage() { + return this.errorMessage; + } + public static List getAzureServiceCode(int httpStatusCode) { List errorCodes = new ArrayList<>(); if (httpStatusCode == UNKNOWN.httpStatusCode) { diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java index f7faa167c9821..6f7d60ab2b77c 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java @@ -1,9 +1,19 @@ package org.apache.hadoop.fs.azurebfs.services; public class RetryReasonConstants { - public static final String connectionTimeoutJdkMessage = "connect timed out"; - public static final String readTimeoutJdkMessage = "Read timed out"; - public static final String connectionResetMessage = "Connection reset"; + public static final String CONNECTION_TIMEOUT_JDK_MESSAGE = "connect timed out"; + public static final String READ_TIMEOUT_JDK_MESSAGE = "Read timed out"; + public static final String CONNECTION_RESET_MESSAGE = "Connection reset"; + public static final String OPERATION_BREACH_MESSAGE = "Operations per second is over the account limit."; + public static final String CONNECTION_RESET_ABBREVIATION = "CR"; + public static final String CONNECTION_TIMEOUT_ABBREVIATION = "CT"; + public static final String READ_TIMEOUT_ABBREVIATION = "RT"; + public static final String INGRESS_LIMIT_BREACH_ABBREVIATION = "ING"; + public static final String EGRESS_LIMIT_BREACH_ABBREVIATION = "EGR"; + public static final String OPERATION_LIMIT_BREACH_ABBREVIATION = "OPR"; + public static final String UNKNOWN_HOST_EXCEPTION_ABBREVIATION = "UH"; + public static final String IO_EXCEPTION_ABBREVIATION = "IOE"; + public static final String SOCKET_EXCEPTION_ABBREVIATION = "SE"; } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionResetRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionResetRetryReason.java index 0d148504a450b..35b2211a9753b 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionResetRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionResetRetryReason.java @@ -18,7 +18,8 @@ package org.apache.hadoop.fs.azurebfs.services.retryReasonCategories; -import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.connectionResetMessage; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_RESET_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_RESET_MESSAGE; public class ConnectionResetRetryReason extends RetryReasonCategory { @@ -27,12 +28,12 @@ public class ConnectionResetRetryReason extends public Boolean canCapture(final Exception ex, final Integer statusCode, final String serverErrorMessage) { - return checkExceptionMessage(ex, connectionResetMessage); + return checkExceptionMessage(ex, CONNECTION_RESET_MESSAGE); } @Override public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { - return "CR"; + return CONNECTION_RESET_ABBREVIATION; } } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionTimeoutRetryReason.java index 9754fa469f43e..2f7fdcf9e495e 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionTimeoutRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionTimeoutRetryReason.java @@ -19,7 +19,8 @@ package org.apache.hadoop.fs.azurebfs.services.retryReasonCategories; -import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.connectionTimeoutJdkMessage; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_TIMEOUT_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_TIMEOUT_JDK_MESSAGE; public class ConnectionTimeoutRetryReason extends RetryReasonCategory { @@ -27,13 +28,13 @@ public class ConnectionTimeoutRetryReason extends @Override public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { - return "CT"; + return CONNECTION_TIMEOUT_ABBREVIATION; } @Override public Boolean canCapture(final Exception ex, final Integer statusCode, final String serverErrorMessage) { - return checkExceptionMessage(ex, connectionTimeoutJdkMessage); + return checkExceptionMessage(ex, CONNECTION_TIMEOUT_JDK_MESSAGE); } } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ReadTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ReadTimeoutRetryReason.java index 06eb570bdff3e..fdf438b50a8e5 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ReadTimeoutRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ReadTimeoutRetryReason.java @@ -18,7 +18,8 @@ package org.apache.hadoop.fs.azurebfs.services.retryReasonCategories; -import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.readTimeoutJdkMessage; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.READ_TIMEOUT_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.READ_TIMEOUT_JDK_MESSAGE; public class ReadTimeoutRetryReason extends RetryReasonCategory { @@ -26,12 +27,12 @@ public class ReadTimeoutRetryReason extends RetryReasonCategory { public Boolean canCapture(final Exception ex, final Integer statusCode, final String serverErrorMessage) { - return checkExceptionMessage(ex, readTimeoutJdkMessage); + return checkExceptionMessage(ex, READ_TIMEOUT_JDK_MESSAGE); } @Override public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { - return "RT"; + return READ_TIMEOUT_ABBREVIATION; } } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java index 5711089cefc9b..812bbf4fd7e32 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java @@ -20,6 +20,12 @@ import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; +import static org.apache.hadoop.fs.azurebfs.contracts.services.AzureServiceErrorCode.EGRESS_OVER_ACCOUNT_LIMIT; +import static org.apache.hadoop.fs.azurebfs.contracts.services.AzureServiceErrorCode.INGRESS_OVER_ACCOUNT_LIMIT; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.EGRESS_LIMIT_BREACH_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.INGRESS_LIMIT_BREACH_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.OPERATION_BREACH_MESSAGE; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.OPERATION_LIMIT_BREACH_ABBREVIATION; public class ServerErrorRetryReason extends RetryReasonCategory { @@ -39,17 +45,17 @@ public String getAbbreviation(final Integer statusCode, if (statusCode == HTTP_UNAVAILABLE) { String splitedServerErrorMessage = serverErrorMessage.split(System.lineSeparator(), 2)[0]; - if ("Ingress is over the account limit.".equalsIgnoreCase( + if (INGRESS_OVER_ACCOUNT_LIMIT.getErrorMessage().equalsIgnoreCase( splitedServerErrorMessage)) { - return "ING"; + return INGRESS_LIMIT_BREACH_ABBREVIATION; } - if ("Egress is over the account limit.".equalsIgnoreCase( + if (EGRESS_OVER_ACCOUNT_LIMIT.getErrorMessage().equalsIgnoreCase( splitedServerErrorMessage)) { - return "EGR"; + return EGRESS_LIMIT_BREACH_ABBREVIATION; } - if ("Operations per second is over the account limit.".equalsIgnoreCase( + if (OPERATION_BREACH_MESSAGE.equalsIgnoreCase( splitedServerErrorMessage)) { - return "OPR"; + return OPERATION_LIMIT_BREACH_ABBREVIATION; } return HTTP_UNAVAILABLE + ""; } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownHostRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownHostRetryReason.java index 637f736488e31..4a937dd51a7be 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownHostRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownHostRetryReason.java @@ -20,6 +20,8 @@ import java.net.UnknownHostException; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.UNKNOWN_HOST_EXCEPTION_ABBREVIATION; + public class UnknownHostRetryReason extends RetryReasonCategory { @Override @@ -35,6 +37,6 @@ public Boolean canCapture(final Exception ex, @Override public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { - return "UH"; + return UNKNOWN_HOST_EXCEPTION_ABBREVIATION; } } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownIOExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownIOExceptionRetryReason.java index 47c843eb964f9..73ee16f39283a 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownIOExceptionRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownIOExceptionRetryReason.java @@ -20,6 +20,8 @@ import java.io.IOException; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.IO_EXCEPTION_ABBREVIATION; + public class UnknownIOExceptionRetryReason extends RetryReasonCategory { @@ -37,6 +39,6 @@ public Boolean canCapture(final Exception ex, @Override public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { - return "IOE"; + return IO_EXCEPTION_ABBREVIATION; } } diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownSocketExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownSocketExceptionRetryReason.java index 8e9cd24c357b6..abf84987616f4 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownSocketExceptionRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownSocketExceptionRetryReason.java @@ -20,6 +20,8 @@ import java.net.SocketException; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.SOCKET_EXCEPTION_ABBREVIATION; + public class UnknownSocketExceptionRetryReason extends RetryReasonCategory { @@ -37,6 +39,6 @@ public Boolean canCapture(final Exception ex, @Override public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { - return "SE"; + return SOCKET_EXCEPTION_ABBREVIATION; } } diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestRetryReason.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestRetryReason.java new file mode 100644 index 0000000000000..3d67fed6a7dfb --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestRetryReason.java @@ -0,0 +1,22 @@ +package org.apache.hadoop.fs.azurebfs.services; + +import java.net.SocketException; + +import org.assertj.core.api.Assertions; +import org.junit.Test; + +public class TestRetryReason { + + @Test + public void test4xxStatusRetryReason() { + Assertions.assertThat(RetryReason.getAbbreviation(null, 403, null)) + .describedAs("Abbreviation for 4xx should be equal to 4xx") + .isEqualTo("403"); + } + + @Test + public void testConnectionResetRetryReason() { + SocketException connReset = new SocketException("connection reset by peer"); + Assertions.assertThat(RetryReason.getAbbreviation(connReset, null, null)).describedAs(""); + } +} From 77aaa01f602f8689688d6b5df8239fec5f7720b8 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Wed, 22 Feb 2023 22:45:49 -0800 Subject: [PATCH 25/38] asf license in RetryReasonConstants --- .../services/RetryReasonConstants.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java index 6f7d60ab2b77c..60674d90ac632 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java @@ -1,3 +1,21 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.hadoop.fs.azurebfs.services; public class RetryReasonConstants { @@ -14,6 +32,4 @@ public class RetryReasonConstants { public static final String UNKNOWN_HOST_EXCEPTION_ABBREVIATION = "UH"; public static final String IO_EXCEPTION_ABBREVIATION = "IOE"; public static final String SOCKET_EXCEPTION_ABBREVIATION = "SE"; - - } From c49ab4408768122ec58a135bc93d3d62e4f59028 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Wed, 22 Feb 2023 22:51:23 -0800 Subject: [PATCH 26/38] constants in TestAbfsRestOperationMockFailures --- .../TestAbfsRestOperationMockFailures.java | 51 ++++++++++++------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperationMockFailures.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperationMockFailures.java index 6c2781ab6dac4..bfa524a25e600 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperationMockFailures.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestAbfsRestOperationMockFailures.java @@ -37,7 +37,22 @@ import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR; import static java.net.HttpURLConnection.HTTP_OK; import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; +import static org.apache.hadoop.fs.azurebfs.contracts.services.AzureServiceErrorCode.EGRESS_OVER_ACCOUNT_LIMIT; +import static org.apache.hadoop.fs.azurebfs.contracts.services.AzureServiceErrorCode.INGRESS_OVER_ACCOUNT_LIMIT; import static org.apache.hadoop.fs.azurebfs.services.AuthType.OAuth; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_RESET_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_RESET_MESSAGE; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_TIMEOUT_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_TIMEOUT_JDK_MESSAGE; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.EGRESS_LIMIT_BREACH_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.INGRESS_LIMIT_BREACH_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.IO_EXCEPTION_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.OPERATION_BREACH_MESSAGE; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.OPERATION_LIMIT_BREACH_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.READ_TIMEOUT_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.READ_TIMEOUT_JDK_MESSAGE; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.SOCKET_EXCEPTION_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.UNKNOWN_HOST_EXCEPTION_ABBREVIATION; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.nullable; @@ -47,8 +62,8 @@ public class TestAbfsRestOperationMockFailures { public void testClientRequestIdForConnectTimeoutRetry() throws Exception { Exception[] exceptions = new Exception[1]; String[] abbreviations = new String[1]; - exceptions[0] = new SocketTimeoutException("connect timed out"); - abbreviations[0] = "CT"; + exceptions[0] = new SocketTimeoutException(CONNECTION_TIMEOUT_JDK_MESSAGE); + abbreviations[0] = CONNECTION_TIMEOUT_ABBREVIATION; testClientRequestIdForTimeoutRetry(exceptions, abbreviations, 1); } @@ -57,10 +72,10 @@ public void testClientRequestIdForConnectAndReadTimeoutRetry() throws Exception { Exception[] exceptions = new Exception[2]; String[] abbreviations = new String[2]; - exceptions[0] = new SocketTimeoutException("connect timed out"); - abbreviations[0] = "CT"; - exceptions[1] = new SocketTimeoutException("Read timed out"); - abbreviations[1] = "RT"; + exceptions[0] = new SocketTimeoutException(CONNECTION_TIMEOUT_JDK_MESSAGE); + abbreviations[0] = CONNECTION_TIMEOUT_ABBREVIATION; + exceptions[1] = new SocketTimeoutException(READ_TIMEOUT_JDK_MESSAGE); + abbreviations[1] = READ_TIMEOUT_ABBREVIATION; testClientRequestIdForTimeoutRetry(exceptions, abbreviations, 1); } @@ -68,8 +83,8 @@ public void testClientRequestIdForConnectAndReadTimeoutRetry() public void testClientRequestIdForReadTimeoutRetry() throws Exception { Exception[] exceptions = new Exception[1]; String[] abbreviations = new String[1]; - exceptions[0] = new SocketTimeoutException("Read timed out"); - abbreviations[0] = "RT"; + exceptions[0] = new SocketTimeoutException(READ_TIMEOUT_JDK_MESSAGE); + abbreviations[0] = READ_TIMEOUT_ABBREVIATION; testClientRequestIdForTimeoutRetry(exceptions, abbreviations, 1); } @@ -78,7 +93,7 @@ public void testClientRequestIdForUnknownHostRetry() throws Exception { Exception[] exceptions = new Exception[1]; String[] abbreviations = new String[1]; exceptions[0] = new UnknownHostException(); - abbreviations[0] = "UH"; + abbreviations[0] = UNKNOWN_HOST_EXCEPTION_ABBREVIATION; testClientRequestIdForTimeoutRetry(exceptions, abbreviations, 1); } @@ -86,8 +101,8 @@ public void testClientRequestIdForUnknownHostRetry() throws Exception { public void testClientRequestIdForConnectionResetRetry() throws Exception { Exception[] exceptions = new Exception[1]; String[] abbreviations = new String[1]; - exceptions[0] = new SocketTimeoutException("Connection reset by peer"); - abbreviations[0] = "CR"; + exceptions[0] = new SocketTimeoutException(CONNECTION_RESET_MESSAGE + " by peer"); + abbreviations[0] = CONNECTION_RESET_ABBREVIATION; testClientRequestIdForTimeoutRetry(exceptions, abbreviations, 1); } @@ -96,7 +111,7 @@ public void testClientRequestIdForUnknownSocketExRetry() throws Exception { Exception[] exceptions = new Exception[1]; String[] abbreviations = new String[1]; exceptions[0] = new SocketException("unknown"); - abbreviations[0] = "SE"; + abbreviations[0] = SOCKET_EXCEPTION_ABBREVIATION; testClientRequestIdForTimeoutRetry(exceptions, abbreviations, 1); } @@ -105,7 +120,7 @@ public void testClientRequestIdForIOERetry() throws Exception { Exception[] exceptions = new Exception[1]; String[] abbreviations = new String[1]; exceptions[0] = new InterruptedIOException(); - abbreviations[0] = "IOE"; + abbreviations[0] = IO_EXCEPTION_ABBREVIATION; testClientRequestIdForTimeoutRetry(exceptions, abbreviations, 1); } @@ -122,21 +137,21 @@ public void testClientRequestIdFor500Retry() throws Exception { @Test public void testClientRequestIdFor503INGRetry() throws Exception { testClientRequestIdForStatusRetry(HTTP_UNAVAILABLE, - "Ingress is over the account limit.", - "ING"); + INGRESS_OVER_ACCOUNT_LIMIT.getErrorMessage(), + INGRESS_LIMIT_BREACH_ABBREVIATION); } @Test public void testClientRequestIdFor503egrRetry() throws Exception { testClientRequestIdForStatusRetry(HTTP_UNAVAILABLE, - "Egress is over the account limit.", - "EGR"); + EGRESS_OVER_ACCOUNT_LIMIT.getErrorMessage(), + EGRESS_LIMIT_BREACH_ABBREVIATION); } @Test public void testClientRequestIdFor503OPRRetry() throws Exception { testClientRequestIdForStatusRetry(HTTP_UNAVAILABLE, - "Operations per second is over the account limit.", "OPR"); + OPERATION_BREACH_MESSAGE, OPERATION_LIMIT_BREACH_ABBREVIATION); } @Test From e1d38a000ebf8f8d9964f600ebd4278751ce570d Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Wed, 22 Feb 2023 23:27:41 -0800 Subject: [PATCH 27/38] TestRetryReason --- .../ServerErrorRetryReason.java | 2 +- .../fs/azurebfs/services/TestRetryReason.java | 115 +++++++++++++++++- 2 files changed, 114 insertions(+), 3 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java index 812bbf4fd7e32..ca5a52594ee10 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java @@ -42,7 +42,7 @@ public Boolean canCapture(final Exception ex, @Override public String getAbbreviation(final Integer statusCode, final String serverErrorMessage) { - if (statusCode == HTTP_UNAVAILABLE) { + if (statusCode == HTTP_UNAVAILABLE && serverErrorMessage != null) { String splitedServerErrorMessage = serverErrorMessage.split(System.lineSeparator(), 2)[0]; if (INGRESS_OVER_ACCOUNT_LIMIT.getErrorMessage().equalsIgnoreCase( diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestRetryReason.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestRetryReason.java index 3d67fed6a7dfb..6099a818f2476 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestRetryReason.java @@ -1,10 +1,49 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.hadoop.fs.azurebfs.services; +import java.io.IOException; import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; import org.assertj.core.api.Assertions; import org.junit.Test; +import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR; +import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; +import static org.apache.hadoop.fs.azurebfs.contracts.services.AzureServiceErrorCode.EGRESS_OVER_ACCOUNT_LIMIT; +import static org.apache.hadoop.fs.azurebfs.contracts.services.AzureServiceErrorCode.INGRESS_OVER_ACCOUNT_LIMIT; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_RESET_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_RESET_MESSAGE; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_TIMEOUT_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_TIMEOUT_JDK_MESSAGE; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.EGRESS_LIMIT_BREACH_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.INGRESS_LIMIT_BREACH_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.IO_EXCEPTION_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.OPERATION_BREACH_MESSAGE; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.OPERATION_LIMIT_BREACH_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.READ_TIMEOUT_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.READ_TIMEOUT_JDK_MESSAGE; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.SOCKET_EXCEPTION_ABBREVIATION; +import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.UNKNOWN_HOST_EXCEPTION_ABBREVIATION; + public class TestRetryReason { @Test @@ -16,7 +55,79 @@ public void test4xxStatusRetryReason() { @Test public void testConnectionResetRetryReason() { - SocketException connReset = new SocketException("connection reset by peer"); - Assertions.assertThat(RetryReason.getAbbreviation(connReset, null, null)).describedAs(""); + SocketException connReset = new SocketException(CONNECTION_RESET_MESSAGE.toUpperCase()); + Assertions.assertThat(RetryReason.getAbbreviation(connReset, null, null)).isEqualTo(CONNECTION_RESET_ABBREVIATION); + } + + @Test + public void testConnectionTimeoutRetryReason() { + SocketTimeoutException connectionTimeoutException = new SocketTimeoutException(CONNECTION_TIMEOUT_JDK_MESSAGE); + Assertions.assertThat(RetryReason.getAbbreviation(connectionTimeoutException, null, null)).isEqualTo( + CONNECTION_TIMEOUT_ABBREVIATION + ); + } + + @Test + public void testReadTimeoutRetryReason() { + SocketTimeoutException connectionTimeoutException = new SocketTimeoutException(READ_TIMEOUT_JDK_MESSAGE); + Assertions.assertThat(RetryReason.getAbbreviation(connectionTimeoutException, null, null)).isEqualTo( + READ_TIMEOUT_ABBREVIATION + ); + } + + @Test + public void testEgressLimitRetryReason() { + Assertions.assertThat(RetryReason.getAbbreviation(null, HTTP_UNAVAILABLE, EGRESS_OVER_ACCOUNT_LIMIT.getErrorMessage())).isEqualTo( + EGRESS_LIMIT_BREACH_ABBREVIATION + ); + } + + @Test + public void testIngressLimitRetryReason() { + Assertions.assertThat(RetryReason.getAbbreviation(null, HTTP_UNAVAILABLE, INGRESS_OVER_ACCOUNT_LIMIT.getErrorMessage())).isEqualTo( + INGRESS_LIMIT_BREACH_ABBREVIATION + ); + } + + @Test + public void testOperationLimitRetryReason() { + Assertions.assertThat(RetryReason.getAbbreviation(null, HTTP_UNAVAILABLE, OPERATION_BREACH_MESSAGE)).isEqualTo( + OPERATION_LIMIT_BREACH_ABBREVIATION + ); + } + + @Test + public void test503UnknownRetryReason() { + Assertions.assertThat(RetryReason.getAbbreviation(null, HTTP_UNAVAILABLE, null)).isEqualTo( + "503" + ); + } + + @Test + public void test500RetryReason() { + Assertions.assertThat(RetryReason.getAbbreviation(null, HTTP_INTERNAL_ERROR, null)).isEqualTo( + "500" + ); + } + + @Test + public void testUnknownHostRetryReason() { + Assertions.assertThat(RetryReason.getAbbreviation(new UnknownHostException(), null, null)).isEqualTo( + UNKNOWN_HOST_EXCEPTION_ABBREVIATION + ); + } + + @Test + public void testUnknownIOExceptionRetryReason() { + Assertions.assertThat(RetryReason.getAbbreviation(new IOException(), null, null)).isEqualTo( + IO_EXCEPTION_ABBREVIATION + ); + } + + @Test + public void testUnknownSocketException() { + Assertions.assertThat(RetryReason.getAbbreviation(new SocketException(), null, null)).isEqualTo( + SOCKET_EXCEPTION_ABBREVIATION + ); } } From e37d2e26ce98e7c0bdeb571f3ec35f4566c3d798 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Thu, 23 Feb 2023 01:18:06 -0800 Subject: [PATCH 28/38] javadocs wip --- .../hadoop/fs/azurebfs/services/RetryReason.java | 15 ++++++++++++--- .../ClientErrorRetryReason.java | 3 +++ .../ConnectionResetRetryReason.java | 3 +++ .../ConnectionTimeoutRetryReason.java | 3 +++ .../ServerErrorRetryReason.java | 3 +++ 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index b7b5a2a57df3b..58930b60cf459 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -49,9 +49,9 @@ class RetryReason { * hence, {@link UnknownIOExceptionRetryReason} is placed before * {@link UnknownSocketExceptionRetryReason} *

  • Since, connectionTimeout, readTimeout, and connectionReset are - * {@link java.net.SocketException} exceptions with different messages, + * {@link java.net.SocketTimeoutException} exceptions with different messages, * hence, {@link ConnectionTimeoutRetryReason}, {@link ReadTimeoutRetryReason}, - * {@link ConnectionResetRetryReason} are above {@link UnknownSocketExceptionRetryReason}. + * {@link ConnectionResetRetryReason} are above {@link UnknownIOExceptionRetryReason}. * There is no order between the three reasons as they are differentiated * by exception-message.
  • *
  • Since, {@link java.net.UnknownHostException} is subclass of @@ -75,11 +75,20 @@ private RetryReason() { } + /** + * Method to get correct abbreviation for a given set of exception, statusCode, + * storageStatusCode. + * + * @param ex exception caught during server communication. + * @param statusCode statusCode in the server response. + * @param storageErrorMessage storageErrorMessage in the server response. + * + * @return abbreviation for the the given set of exception, statusCode, storageStatusCode. + * */ static String getAbbreviation(Exception ex, Integer statusCode, String storageErrorMessage) { String result = null; - for (RetryReasonCategory retryReasonCategory : rankedReasonCategories) { final String abbreviation = retryReasonCategory.captureAndGetAbbreviation(ex, diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ClientErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ClientErrorRetryReason.java index 5dfc1a6a7e974..ec2ae6d28892f 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ClientErrorRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ClientErrorRetryReason.java @@ -20,6 +20,9 @@ import static org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants.HTTP_STATUS_CATEGORY_QUOTIENT; +/** + * Category that can capture server-response errors for 4XX status-code. + * */ public class ClientErrorRetryReason extends RetryReasonCategory { @Override diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionResetRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionResetRetryReason.java index 35b2211a9753b..ce7bc56a990d6 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionResetRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionResetRetryReason.java @@ -21,6 +21,9 @@ import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_RESET_ABBREVIATION; import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_RESET_MESSAGE; +/** + * Category that can capture server-response errors for connection-reset exception. + * */ public class ConnectionResetRetryReason extends RetryReasonCategory { diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionTimeoutRetryReason.java index 2f7fdcf9e495e..41c88f30adb36 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionTimeoutRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ConnectionTimeoutRetryReason.java @@ -22,6 +22,9 @@ import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_TIMEOUT_ABBREVIATION; import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.CONNECTION_TIMEOUT_JDK_MESSAGE; +/** + * Category that can capture server-response errors for connection-timeout. + * */ public class ConnectionTimeoutRetryReason extends RetryReasonCategory { diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java index ca5a52594ee10..0e1fdd4a8d69a 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ServerErrorRetryReason.java @@ -27,6 +27,9 @@ import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.OPERATION_BREACH_MESSAGE; import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.OPERATION_LIMIT_BREACH_ABBREVIATION; +/** + * Category that can capture server-response errors for 5XX status-code. + * */ public class ServerErrorRetryReason extends RetryReasonCategory { @Override From 8c4ac80825337875acfb2644ad228f34d1f402e0 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Thu, 23 Feb 2023 05:00:22 -0800 Subject: [PATCH 29/38] javadocs on retry-categories --- .../retryReasonCategories/ReadTimeoutRetryReason.java | 3 +++ .../retryReasonCategories/UnknownHostRetryReason.java | 3 +++ .../retryReasonCategories/UnknownIOExceptionRetryReason.java | 3 +++ .../UnknownSocketExceptionRetryReason.java | 4 +++- 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ReadTimeoutRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ReadTimeoutRetryReason.java index fdf438b50a8e5..5ba14ff945514 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ReadTimeoutRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/ReadTimeoutRetryReason.java @@ -21,6 +21,9 @@ import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.READ_TIMEOUT_ABBREVIATION; import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.READ_TIMEOUT_JDK_MESSAGE; +/** + * Category that can capture server-response errors for read-timeout. + * */ public class ReadTimeoutRetryReason extends RetryReasonCategory { @Override diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownHostRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownHostRetryReason.java index 4a937dd51a7be..23ae4fd03d80f 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownHostRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownHostRetryReason.java @@ -22,6 +22,9 @@ import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.UNKNOWN_HOST_EXCEPTION_ABBREVIATION; +/** + * Category that can capture server-response errors for {@link UnknownHostException}. + * */ public class UnknownHostRetryReason extends RetryReasonCategory { @Override diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownIOExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownIOExceptionRetryReason.java index 73ee16f39283a..b633ca30e25af 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownIOExceptionRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownIOExceptionRetryReason.java @@ -23,6 +23,9 @@ import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.IO_EXCEPTION_ABBREVIATION; +/** + * Category that can capture server-response errors for {@link IOException}. + * */ public class UnknownIOExceptionRetryReason extends RetryReasonCategory { diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownSocketExceptionRetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownSocketExceptionRetryReason.java index abf84987616f4..fffca38d97395 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownSocketExceptionRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/UnknownSocketExceptionRetryReason.java @@ -22,7 +22,9 @@ import static org.apache.hadoop.fs.azurebfs.services.RetryReasonConstants.SOCKET_EXCEPTION_ABBREVIATION; - +/** + * Category that can capture server-response errors for {@link SocketException}. + * */ public class UnknownSocketExceptionRetryReason extends RetryReasonCategory { From 9799dbadd78ca32ed0e3c0cca2139788b2e7b4f6 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Sun, 26 Feb 2023 20:12:06 -0800 Subject: [PATCH 30/38] javadoc fix in the RetryReasonCategory --- .../RetryReasonCategory.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/RetryReasonCategory.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/RetryReasonCategory.java index cef446222efbf..e58b701ba08e1 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/RetryReasonCategory.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/RetryReasonCategory.java @@ -22,20 +22,19 @@ /** * Provides methods to define if given exception can be categorised to certain category. - * Each category has a different implementation of the interface. + * Each category has a different implementation of the abstract class. * */ public abstract class RetryReasonCategory { /** - * Returns if given server response error can be converted to an abbreviation - * by the implementation. + * Returns if given server response error can be categorised by the implementation. * * @param ex exception captured in the server response. * @param statusCode statusCode on the server response * @param serverErrorMessage serverErrorMessage on the server response. * - * @return
    1. true if server response error can be converted to abbreviation by the implementation
    2. - *
    3. false if response error can not be abbreviated by the implementation
    + * @return
    1. true if server response error can be categorised by the implementation
    2. + *
    3. false if response error can not be categorised by the implementation
    */ abstract Boolean canCapture(Exception ex, Integer statusCode, @@ -51,6 +50,17 @@ abstract Boolean canCapture(Exception ex, */ abstract String getAbbreviation(Integer statusCode, String serverErrorMessage); + /** + * Converts the server-error response to an abbreviation if the response can be + * categorised by the implementation. + * + * @param ex exception received while making API request + * @param statusCode statusCode received in the server-response + * @param serverErrorMessage error-message received in the server-response + * + * @return abbreviation if the server-response can be categorised by the implementation. + * null if the server-response can not be categorised by the implementation. + * */ public String captureAndGetAbbreviation(Exception ex, Integer statusCode, String serverErrorMessage) { if(canCapture(ex, statusCode, serverErrorMessage)) { return getAbbreviation(statusCode, serverErrorMessage); From 8aa5e1e6ae78a38bd30674699d72694170953a1f Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Sun, 26 Feb 2023 22:22:47 -0800 Subject: [PATCH 31/38] basic code for primaryRequestId over retry; test added. More tests WIP --- .../fs/azurebfs/utils/TracingContext.java | 16 ++++++++-- .../fs/azurebfs/TestTracingContext.java | 32 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java index 9a2ccda36fbb0..4c54efe490a75 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java @@ -62,6 +62,7 @@ public class TracingContext { private Listener listener = null; // null except when testing //final concatenated ID list set into x-ms-client-request-id header private String header = EMPTY_STRING; + private String primaryRequestIdForRetry; private static final Logger LOG = LoggerFactory.getLogger(AbfsClient.class); public static final int MAX_CLIENT_CORRELATION_ID_LENGTH = 72; @@ -161,8 +162,8 @@ public void constructHeader(AbfsHttpOperation httpOperation, String previousFail case ALL_ID_FORMAT: // Optional IDs (e.g. streamId) may be empty header = clientCorrelationID + ":" + clientRequestId + ":" + fileSystemID + ":" - + primaryRequestId + ":" + streamID + ":" + opType + ":" - + retryCount; + + getPrimaryRequestIdForHeader(previousFailure) + ":" + streamID + + ":" + opType + ":" + retryCount; header = addFailureReasons(header, previousFailure); break; case TWO_ID_FORMAT: @@ -175,6 +176,17 @@ public void constructHeader(AbfsHttpOperation httpOperation, String previousFail listener.callTracingHeaderValidator(header, format); } httpOperation.setRequestProperty(HttpHeaderConfigurations.X_MS_CLIENT_REQUEST_ID, header); + if(primaryRequestId.isEmpty() && previousFailure == null) { + String[] clientRequestIdParts = clientRequestId.split(":"); + primaryRequestIdForRetry = clientRequestIdParts[clientRequestIdParts.length - 1]; + } + } + + private String getPrimaryRequestIdForHeader(final String previousFailure) { + if(!primaryRequestId.isEmpty() || previousFailure == null) { + return primaryRequestId; + } + return primaryRequestIdForRetry; } private String addFailureReasons(final String header, diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java index b91a3e2208b57..df68df97c8860 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java @@ -23,6 +23,7 @@ import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; +import java.util.UUID; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; @@ -31,12 +32,14 @@ import org.junit.AssumptionViolatedException; import org.junit.Ignore; import org.junit.Test; +import org.mockito.Mockito; import org.apache.hadoop.fs.CommonPathCapabilities; import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.azurebfs.constants.AbfsHttpConstants; import org.apache.hadoop.fs.azurebfs.constants.FSOperationType; import org.apache.hadoop.fs.azurebfs.enums.Trilean; +import org.apache.hadoop.fs.azurebfs.services.AbfsHttpOperation; import org.apache.hadoop.fs.azurebfs.services.AbfsRestOperation; import org.apache.hadoop.fs.azurebfs.services.AuthType; import org.apache.hadoop.fs.azurebfs.utils.TracingContext; @@ -198,4 +201,33 @@ public void testExternalOps() throws Exception { fs.getAbfsStore().setNamespaceEnabled(Trilean.TRUE); fs.access(new Path("/"), FsAction.READ); } + + @Test + public void testRetryPrimaryRequestIdWhenInitiallySuppliedEmpty() throws Exception { + final AzureBlobFileSystem fs = getFileSystem(); + final String fileSystemId = UUID.randomUUID().toString(); + final String clientCorrelationId = "abcd"; + final TracingHeaderFormat tracingHeaderFormat = TracingHeaderFormat.ALL_ID_FORMAT; + TracingContext tracingContext = new TracingContext(clientCorrelationId, + fileSystemId, FSOperationType.CREATE_FILESYSTEM, tracingHeaderFormat, new TracingHeaderValidator( + fs.getAbfsStore().getAbfsConfiguration().getClientCorrelationId(), + fs.getFileSystemId(), FSOperationType.HAS_PATH_CAPABILITY, false, + 0)); + AbfsHttpOperation abfsHttpOperation = Mockito.mock(AbfsHttpOperation.class); + Mockito.doNothing().when(abfsHttpOperation).setRequestProperty(Mockito.anyString(), Mockito.anyString()); + tracingContext.constructHeader(abfsHttpOperation, null); + String header = tracingContext.getHeader(); + String clientRequestIdUsed = header.split(":")[1]; + String[] clientRequestIdUsedParts = clientRequestIdUsed.split("-"); + String assertionPrimaryId = clientRequestIdUsedParts[clientRequestIdUsedParts.length - 1]; + + tracingContext.constructHeader(abfsHttpOperation, "RT"); + header = tracingContext.getHeader(); + String primaryRequestId = header.split(":")[3]; + + Assertions.assertThat(primaryRequestId) + .describedAs("PrimaryRequestId in a retried request's " + + "tracingContext should be equal to last part of original " + + "request's clientRequestId UUID").isEqualTo(assertionPrimaryId); + } } From 003bbfb2641f1cea8ec352e6f9bbb2670bc7ed21 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Sun, 26 Feb 2023 23:45:39 -0800 Subject: [PATCH 32/38] testRetryPrimaryRequestIdWhenInitiallySuppliedNonEmpty; testRetryPrimaryRequestIdWhenInitiallySuppliedEmpty --- .../fs/azurebfs/utils/TracingContext.java | 2 +- .../fs/azurebfs/TestTracingContext.java | 46 +++++++++++++++++-- .../utils/TracingHeaderValidator.java | 3 ++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java index 4c54efe490a75..352bf4610b740 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java @@ -177,7 +177,7 @@ public void constructHeader(AbfsHttpOperation httpOperation, String previousFail } httpOperation.setRequestProperty(HttpHeaderConfigurations.X_MS_CLIENT_REQUEST_ID, header); if(primaryRequestId.isEmpty() && previousFailure == null) { - String[] clientRequestIdParts = clientRequestId.split(":"); + String[] clientRequestIdParts = clientRequestId.split("-"); primaryRequestIdForRetry = clientRequestIdParts[clientRequestIdParts.length - 1]; } } diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java index df68df97c8860..fae7b9dc8a262 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java @@ -205,13 +205,13 @@ public void testExternalOps() throws Exception { @Test public void testRetryPrimaryRequestIdWhenInitiallySuppliedEmpty() throws Exception { final AzureBlobFileSystem fs = getFileSystem(); - final String fileSystemId = UUID.randomUUID().toString(); - final String clientCorrelationId = "abcd"; + final String fileSystemId = fs.getFileSystemId(); + final String clientCorrelationId = fs.getClientCorrelationId(); final TracingHeaderFormat tracingHeaderFormat = TracingHeaderFormat.ALL_ID_FORMAT; TracingContext tracingContext = new TracingContext(clientCorrelationId, fileSystemId, FSOperationType.CREATE_FILESYSTEM, tracingHeaderFormat, new TracingHeaderValidator( fs.getAbfsStore().getAbfsConfiguration().getClientCorrelationId(), - fs.getFileSystemId(), FSOperationType.HAS_PATH_CAPABILITY, false, + fs.getFileSystemId(), FSOperationType.CREATE_FILESYSTEM, false, 0)); AbfsHttpOperation abfsHttpOperation = Mockito.mock(AbfsHttpOperation.class); Mockito.doNothing().when(abfsHttpOperation).setRequestProperty(Mockito.anyString(), Mockito.anyString()); @@ -221,6 +221,46 @@ fileSystemId, FSOperationType.CREATE_FILESYSTEM, tracingHeaderFormat, new Tracin String[] clientRequestIdUsedParts = clientRequestIdUsed.split("-"); String assertionPrimaryId = clientRequestIdUsedParts[clientRequestIdUsedParts.length - 1]; + tracingContext.setRetryCount(1); + tracingContext.setListener(new TracingHeaderValidator( + fs.getAbfsStore().getAbfsConfiguration().getClientCorrelationId(), + fs.getFileSystemId(), FSOperationType.CREATE_FILESYSTEM, false, + 1)); + + tracingContext.constructHeader(abfsHttpOperation, "RT"); + header = tracingContext.getHeader(); + String primaryRequestId = header.split(":")[3]; + + Assertions.assertThat(primaryRequestId) + .describedAs("PrimaryRequestId in a retried request's " + + "tracingContext should be equal to last part of original " + + "request's clientRequestId UUID").isEqualTo(assertionPrimaryId); + } + + @Test + public void testRetryPrimaryRequestIdWhenInitiallySuppliedNonEmpty() throws Exception { + final AzureBlobFileSystem fs = getFileSystem(); + final String fileSystemId = fs.getFileSystemId(); + final String clientCorrelationId = fs.getClientCorrelationId(); + final TracingHeaderFormat tracingHeaderFormat = TracingHeaderFormat.ALL_ID_FORMAT; + TracingContext tracingContext = new TracingContext(clientCorrelationId, + fileSystemId, FSOperationType.CREATE_FILESYSTEM, tracingHeaderFormat, new TracingHeaderValidator( + fs.getAbfsStore().getAbfsConfiguration().getClientCorrelationId(), + fs.getFileSystemId(), FSOperationType.CREATE_FILESYSTEM, false, + 0)); + tracingContext.setPrimaryRequestID(); + AbfsHttpOperation abfsHttpOperation = Mockito.mock(AbfsHttpOperation.class); + Mockito.doNothing().when(abfsHttpOperation).setRequestProperty(Mockito.anyString(), Mockito.anyString()); + tracingContext.constructHeader(abfsHttpOperation, null); + String header = tracingContext.getHeader(); + String assertionPrimaryId = header.split(":")[3];; + + tracingContext.setRetryCount(1); + tracingContext.setListener(new TracingHeaderValidator( + fs.getAbfsStore().getAbfsConfiguration().getClientCorrelationId(), + fs.getFileSystemId(), FSOperationType.CREATE_FILESYSTEM, false, + 1)); + tracingContext.constructHeader(abfsHttpOperation, "RT"); header = tracingContext.getHeader(); String primaryRequestId = header.split(":")[3]; diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/utils/TracingHeaderValidator.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/utils/TracingHeaderValidator.java index e195f1c381a94..b5cff5e56c00a 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/utils/TracingHeaderValidator.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/utils/TracingHeaderValidator.java @@ -130,6 +130,9 @@ private void validateBasicFormat(String[] idList) { } Assertions.assertThat(idList[5]).describedAs("Operation name incorrect") .isEqualTo(operation.toString()); + if(idList[6].contains("_")) { + idList[6] = idList[6].split("_")[0]; + } int retryCount = Integer.parseInt(idList[6]); Assertions.assertThat(retryCount) .describedAs("Retry was required due to issue on server side") From e3ba2941bb00c9b129be110022e4a6525168f167 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Mon, 27 Feb 2023 02:15:29 -0800 Subject: [PATCH 33/38] checkstyle issue --- .../fs/azurebfs/services/RetryReason.java | 2 +- .../services/RetryReasonConstants.java | 6 ++++- .../RetryReasonCategory.java | 12 ++++++---- .../retryReasonCategories/package-info.java | 23 +++++++++++++++++++ .../fs/azurebfs/services/TestRetryReason.java | 5 ++-- 5 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/package-info.java diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java index 58930b60cf459..ba187232fc341 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReason.java @@ -36,7 +36,7 @@ * This utility class exposes methods to convert a server response-error to a * category of error. * */ -class RetryReason { +final class RetryReason { /** * Linked-list of the implementations of RetryReasonCategory. The objects in the diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java index 60674d90ac632..8a0af183e30ae 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/RetryReasonConstants.java @@ -18,7 +18,11 @@ package org.apache.hadoop.fs.azurebfs.services; -public class RetryReasonConstants { +public final class RetryReasonConstants { + + private RetryReasonConstants() { + + } public static final String CONNECTION_TIMEOUT_JDK_MESSAGE = "connect timed out"; public static final String READ_TIMEOUT_JDK_MESSAGE = "Read timed out"; public static final String CONNECTION_RESET_MESSAGE = "Connection reset"; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/RetryReasonCategory.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/RetryReasonCategory.java index e58b701ba08e1..ec8db1c6af0d2 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/RetryReasonCategory.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/RetryReasonCategory.java @@ -61,8 +61,10 @@ abstract Boolean canCapture(Exception ex, * @return abbreviation if the server-response can be categorised by the implementation. * null if the server-response can not be categorised by the implementation. * */ - public String captureAndGetAbbreviation(Exception ex, Integer statusCode, String serverErrorMessage) { - if(canCapture(ex, statusCode, serverErrorMessage)) { + public String captureAndGetAbbreviation(Exception ex, + Integer statusCode, + String serverErrorMessage) { + if (canCapture(ex, statusCode, serverErrorMessage)) { return getAbbreviation(statusCode, serverErrorMessage); } return null; @@ -73,12 +75,14 @@ public String captureAndGetAbbreviation(Exception ex, Integer statusCode, String */ Boolean checkExceptionMessage(final Exception exceptionCaptured, final String search) { - if(search == null) { + if (search == null) { return false; } if (exceptionCaptured != null && exceptionCaptured.getMessage() != null - && exceptionCaptured.getMessage().toLowerCase(Locale.US).contains(search.toLowerCase(Locale.US))) { + && exceptionCaptured.getMessage() + .toLowerCase(Locale.US) + .contains(search.toLowerCase(Locale.US))) { return true; } return false; diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/package-info.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/package-info.java new file mode 100644 index 0000000000000..153641075d901 --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/retryReasonCategories/package-info.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@Private +@Evolving +package org.apache.hadoop.fs.azurebfs.services.retryReasonCategories; + +import org.apache.hadoop.classification.InterfaceAudience.Private; +import org.apache.hadoop.classification.InterfaceStability.Evolving; \ No newline at end of file diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestRetryReason.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestRetryReason.java index 6099a818f2476..76fcc6dc2c8a4 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestRetryReason.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/TestRetryReason.java @@ -26,6 +26,7 @@ import org.assertj.core.api.Assertions; import org.junit.Test; +import static java.net.HttpURLConnection.HTTP_FORBIDDEN; import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR; import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; import static org.apache.hadoop.fs.azurebfs.contracts.services.AzureServiceErrorCode.EGRESS_OVER_ACCOUNT_LIMIT; @@ -48,9 +49,9 @@ public class TestRetryReason { @Test public void test4xxStatusRetryReason() { - Assertions.assertThat(RetryReason.getAbbreviation(null, 403, null)) + Assertions.assertThat(RetryReason.getAbbreviation(null, HTTP_FORBIDDEN, null)) .describedAs("Abbreviation for 4xx should be equal to 4xx") - .isEqualTo("403"); + .isEqualTo(HTTP_FORBIDDEN + ""); } @Test From 59a47bf584f18d347c64bd9b64a08f32ee1784dc Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Mon, 27 Feb 2023 21:02:45 -0800 Subject: [PATCH 34/38] checkstyle --- .../apache/hadoop/fs/azurebfs/utils/TracingContext.java | 7 ++++--- .../org/apache/hadoop/fs/azurebfs/TestTracingContext.java | 3 +-- .../hadoop/fs/azurebfs/utils/TracingHeaderValidator.java | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java index 352bf4610b740..e3046d3b5a57a 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java @@ -176,14 +176,15 @@ public void constructHeader(AbfsHttpOperation httpOperation, String previousFail listener.callTracingHeaderValidator(header, format); } httpOperation.setRequestProperty(HttpHeaderConfigurations.X_MS_CLIENT_REQUEST_ID, header); - if(primaryRequestId.isEmpty() && previousFailure == null) { + if (primaryRequestId.isEmpty() && previousFailure == null) { String[] clientRequestIdParts = clientRequestId.split("-"); - primaryRequestIdForRetry = clientRequestIdParts[clientRequestIdParts.length - 1]; + primaryRequestIdForRetry = clientRequestIdParts[ + clientRequestIdParts.length - 1]; } } private String getPrimaryRequestIdForHeader(final String previousFailure) { - if(!primaryRequestId.isEmpty() || previousFailure == null) { + if (!primaryRequestId.isEmpty() || previousFailure == null) { return primaryRequestId; } return primaryRequestIdForRetry; diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java index fae7b9dc8a262..d77897bf86222 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java @@ -23,7 +23,6 @@ import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; -import java.util.UUID; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; @@ -253,7 +252,7 @@ fileSystemId, FSOperationType.CREATE_FILESYSTEM, tracingHeaderFormat, new Tracin Mockito.doNothing().when(abfsHttpOperation).setRequestProperty(Mockito.anyString(), Mockito.anyString()); tracingContext.constructHeader(abfsHttpOperation, null); String header = tracingContext.getHeader(); - String assertionPrimaryId = header.split(":")[3];; + String assertionPrimaryId = header.split(":")[3]; tracingContext.setRetryCount(1); tracingContext.setListener(new TracingHeaderValidator( diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/utils/TracingHeaderValidator.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/utils/TracingHeaderValidator.java index b5cff5e56c00a..7569c80d67c61 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/utils/TracingHeaderValidator.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/utils/TracingHeaderValidator.java @@ -130,7 +130,7 @@ private void validateBasicFormat(String[] idList) { } Assertions.assertThat(idList[5]).describedAs("Operation name incorrect") .isEqualTo(operation.toString()); - if(idList[6].contains("_")) { + if (idList[6].contains("_")) { idList[6] = idList[6].split("_")[0]; } int retryCount = Integer.parseInt(idList[6]); From 29edc5ed8a58f076bbc67c35111ea426a2382df5 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Mon, 27 Feb 2023 21:32:17 -0800 Subject: [PATCH 35/38] documentation --- .../fs/azurebfs/utils/TracingContext.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java index e3046d3b5a57a..d09cd4ebc7e14 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java @@ -153,8 +153,8 @@ public void setListener(Listener listener) { * X_MS_CLIENT_REQUEST_ID header of the http operation * @param httpOperation AbfsHttpOperation instance to set header into * connection - * @param previousFailure List of failures seen before this API trigger on - * same operation from AbfsClient. + * @param previousFailure Failure seen before this API trigger on + * same operation from AbfsClient. It shall be non-null if it is a retry-iteration. */ public void constructHeader(AbfsHttpOperation httpOperation, String previousFailure) { clientRequestId = UUID.randomUUID().toString(); @@ -162,7 +162,7 @@ public void constructHeader(AbfsHttpOperation httpOperation, String previousFail case ALL_ID_FORMAT: // Optional IDs (e.g. streamId) may be empty header = clientCorrelationID + ":" + clientRequestId + ":" + fileSystemID + ":" - + getPrimaryRequestIdForHeader(previousFailure) + ":" + streamID + + getPrimaryRequestIdForHeader(previousFailure != null) + ":" + streamID + ":" + opType + ":" + retryCount; header = addFailureReasons(header, previousFailure); break; @@ -176,6 +176,12 @@ public void constructHeader(AbfsHttpOperation httpOperation, String previousFail listener.callTracingHeaderValidator(header, format); } httpOperation.setRequestProperty(HttpHeaderConfigurations.X_MS_CLIENT_REQUEST_ID, header); + /* + * In case the primaryRequestId is an empty-string and if it is the first try to + * API call (previousFailure shall be null), maintain the last part of clientRequestId's + * UUID in primaryRequestIdForRetry. This field shall be used as primaryRequestId part + * of the x-ms-client-request-id header in case of retry of the same API-request. + * */ if (primaryRequestId.isEmpty() && previousFailure == null) { String[] clientRequestIdParts = clientRequestId.split("-"); primaryRequestIdForRetry = clientRequestIdParts[ @@ -183,8 +189,15 @@ public void constructHeader(AbfsHttpOperation httpOperation, String previousFail } } - private String getPrimaryRequestIdForHeader(final String previousFailure) { - if (!primaryRequestId.isEmpty() || previousFailure == null) { + /** + * Provide value to be used as primaryRequestId part of x-ms-client-request-id header. + * @param isRetry define if it's for a retry case. + * @return {@link #primaryRequestIdForRetry}:If the {@link #primaryRequestId} + * is an empty-string, and it's a retry iteration. + * {@link #primaryRequestId} for other cases. + * */ + private String getPrimaryRequestIdForHeader(final Boolean isRetry) { + if (!primaryRequestId.isEmpty() || !isRetry) { return primaryRequestId; } return primaryRequestIdForRetry; From 4a739aaf9f7e37a70f05e92c7a6afcc92c860e9d Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Mon, 27 Feb 2023 23:19:56 -0800 Subject: [PATCH 36/38] assertion description change --- .../java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java index d77897bf86222..f8bdfedb7e2e1 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java @@ -266,7 +266,6 @@ fileSystemId, FSOperationType.CREATE_FILESYSTEM, tracingHeaderFormat, new Tracin Assertions.assertThat(primaryRequestId) .describedAs("PrimaryRequestId in a retried request's " - + "tracingContext should be equal to last part of original " - + "request's clientRequestId UUID").isEqualTo(assertionPrimaryId); + + "tracingContext should be equal to PrimaryRequestId in the original request.").isEqualTo(assertionPrimaryId); } } From f6283a923451e48d7e49f7ddd0a65e2a9abeeb20 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Wed, 8 Mar 2023 19:52:30 -0800 Subject: [PATCH 37/38] comment, condition small refactor --- .../hadoop/fs/azurebfs/utils/TracingContext.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java index d09cd4ebc7e14..d0b3cce2c7fb4 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java @@ -153,8 +153,8 @@ public void setListener(Listener listener) { * X_MS_CLIENT_REQUEST_ID header of the http operation * @param httpOperation AbfsHttpOperation instance to set header into * connection - * @param previousFailure Failure seen before this API trigger on - * same operation from AbfsClient. It shall be non-null if it is a retry-iteration. + * @param previousFailure Failure seen before this API trigger on same operation + * from AbfsClient. */ public void constructHeader(AbfsHttpOperation httpOperation, String previousFailure) { clientRequestId = UUID.randomUUID().toString(); @@ -162,7 +162,7 @@ public void constructHeader(AbfsHttpOperation httpOperation, String previousFail case ALL_ID_FORMAT: // Optional IDs (e.g. streamId) may be empty header = clientCorrelationID + ":" + clientRequestId + ":" + fileSystemID + ":" - + getPrimaryRequestIdForHeader(previousFailure != null) + ":" + streamID + + getPrimaryRequestIdForHeader(retryCount > 0) + ":" + streamID + ":" + opType + ":" + retryCount; header = addFailureReasons(header, previousFailure); break; @@ -181,7 +181,7 @@ public void constructHeader(AbfsHttpOperation httpOperation, String previousFail * API call (previousFailure shall be null), maintain the last part of clientRequestId's * UUID in primaryRequestIdForRetry. This field shall be used as primaryRequestId part * of the x-ms-client-request-id header in case of retry of the same API-request. - * */ + */ if (primaryRequestId.isEmpty() && previousFailure == null) { String[] clientRequestIdParts = clientRequestId.split("-"); primaryRequestIdForRetry = clientRequestIdParts[ @@ -195,7 +195,7 @@ public void constructHeader(AbfsHttpOperation httpOperation, String previousFail * @return {@link #primaryRequestIdForRetry}:If the {@link #primaryRequestId} * is an empty-string, and it's a retry iteration. * {@link #primaryRequestId} for other cases. - * */ + */ private String getPrimaryRequestIdForHeader(final Boolean isRetry) { if (!primaryRequestId.isEmpty() || !isRetry) { return primaryRequestId; From ff93fee0653e5ddb298f818477c974638488a3fa Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Mon, 13 Mar 2023 20:43:47 -0700 Subject: [PATCH 38/38] javadoc + small refactor as per review --- .../apache/hadoop/fs/azurebfs/utils/TracingContext.java | 9 +++++++++ .../apache/hadoop/fs/azurebfs/TestTracingContext.java | 8 +++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java index d0b3cce2c7fb4..57e65b30b4630 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingContext.java @@ -62,6 +62,15 @@ public class TracingContext { private Listener listener = null; // null except when testing //final concatenated ID list set into x-ms-client-request-id header private String header = EMPTY_STRING; + + /** + * If {@link #primaryRequestId} is null, this field shall be set equal + * to the last part of the {@link #clientRequestId}'s UUID + * in {@link #constructHeader(AbfsHttpOperation, String)} only on the + * first API call for an operation. Subsequent retries for that operation + * will not change this field. In case {@link #primaryRequestId} is non-null, + * this field shall not be set. + */ private String primaryRequestIdForRetry; private static final Logger LOG = LoggerFactory.getLogger(AbfsClient.class); diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java index f8bdfedb7e2e1..23e65ed2dd246 100644 --- a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestTracingContext.java @@ -233,7 +233,8 @@ fileSystemId, FSOperationType.CREATE_FILESYSTEM, tracingHeaderFormat, new Tracin Assertions.assertThat(primaryRequestId) .describedAs("PrimaryRequestId in a retried request's " + "tracingContext should be equal to last part of original " - + "request's clientRequestId UUID").isEqualTo(assertionPrimaryId); + + "request's clientRequestId UUID") + .isEqualTo(assertionPrimaryId); } @Test @@ -265,7 +266,8 @@ fileSystemId, FSOperationType.CREATE_FILESYSTEM, tracingHeaderFormat, new Tracin String primaryRequestId = header.split(":")[3]; Assertions.assertThat(primaryRequestId) - .describedAs("PrimaryRequestId in a retried request's " - + "tracingContext should be equal to PrimaryRequestId in the original request.").isEqualTo(assertionPrimaryId); + .describedAs("PrimaryRequestId in a retried request's tracingContext " + + "should be equal to PrimaryRequestId in the original request.") + .isEqualTo(assertionPrimaryId); } }