<commit_before>/*
 * Copyright 2018 The gRPC Authors
 *
 * Licensed 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 io.grpc.internal;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.math.LongMath.checkedAdd;

import com.google.common.annotations.VisibleForTesting;
import io.grpc.internal.RetriableStream.Throttle;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;

/**
 * Helper utility to work with service configs.
 */
public final class ServiceConfigUtil {

  private static final String SERVICE_CONFIG_METHOD_CONFIG_KEY = "methodConfig";
  private static final String SERVICE_CONFIG_LOAD_BALANCING_POLICY_KEY = "loadBalancingPolicy";
  private static final String SERVICE_CONFIG_LOAD_BALANCING_CONFIG_KEY = "loadBalancingConfig";
  private static final String XDS_CONFIG_BALANCER_NAME_KEY = "balancerName";
  private static final String XDS_CONFIG_CHILD_POLICY_KEY = "childPolicy";
  private static final String XDS_CONFIG_FALLBACK_POLICY_KEY = "fallbackPolicy";
  private static final String SERVICE_CONFIG_STICKINESS_METADATA_KEY = "stickinessMetadataKey";
  private static final String METHOD_CONFIG_NAME_KEY = "name";
  private static final String METHOD_CONFIG_TIMEOUT_KEY = "timeout";
  private static final String METHOD_CONFIG_WAIT_FOR_READY_KEY = "waitForReady";
  private static final String METHOD_CONFIG_MAX_REQUEST_MESSAGE_BYTES_KEY =
      "maxRequestMessageBytes";
  private static final String METHOD_CONFIG_MAX_RESPONSE_MESSAGE_BYTES_KEY =
      "maxResponseMessageBytes";
  private static final String METHOD_CONFIG_RETRY_POLICY_KEY = "retryPolicy";
  private static final String METHOD_CONFIG_HEDGING_POLICY_KEY = "hedgingPolicy";
  private static final String NAME_SERVICE_KEY = "service";
  private static final String NAME_METHOD_KEY = "method";
  private static final String RETRY_POLICY_MAX_ATTEMPTS_KEY = "maxAttempts";
  private static final String RETRY_POLICY_INITIAL_BACKOFF_KEY = "initialBackoff";
  private static final String RETRY_POLICY_MAX_BACKOFF_KEY = "maxBackoff";
  private static final String RETRY_POLICY_BACKOFF_MULTIPLIER_KEY = "backoffMultiplier";
  private static final String RETRY_POLICY_RETRYABLE_STATUS_CODES_KEY = "retryableStatusCodes";
  private static final String HEDGING_POLICY_MAX_ATTEMPTS_KEY = "maxAttempts";
  private static final String HEDGING_POLICY_HEDGING_DELAY_KEY = "hedgingDelay";
  private static final String HEDGING_POLICY_NON_FATAL_STATUS_CODES_KEY = "nonFatalStatusCodes";

  private static final long DURATION_SECONDS_MIN = -315576000000L;
  private static final long DURATION_SECONDS_MAX = 315576000000L;

  private ServiceConfigUtil() {}

  /**
   * Fetch the health-checked service name from service config. {@code null} if can't find one.
   */
  @Nullable
  public static String getHealthCheckedServiceName(@Nullable Map<String, Object> serviceConfig) {
    String healthCheckKey = "healthCheckConfig";
    String serviceNameKey = "serviceName";
    if (serviceConfig == null || !serviceConfig.containsKey(healthCheckKey)) {
      return null;
    }

    /* schema as follows
    {
      "healthCheckConfig": {
        // Service name to use in the health-checking request.
        "serviceName": string
      }
    }
    */
    Map<String, Object> healthCheck = getObject(serviceConfig, healthCheckKey);
    if (!healthCheck.containsKey(serviceNameKey)) {
      return null;
    }
    return getString(healthCheck, "serviceName");
  }

  @Nullable
  static Throttle getThrottlePolicy(@Nullable Map<String, Object> serviceConfig) {
    String retryThrottlingKey = "retryThrottling";
    if (serviceConfig == null || !serviceConfig.containsKey(retryThrottlingKey)) {
      return null;
    }

    /* schema as follows
    {
      "retryThrottling": {
        // The number of tokens starts at maxTokens. The token_count will always be
        // between 0 and maxTokens.
        //
        // This field is required and must be greater than zero.
        "maxTokens": number,

        // The amount of tokens to add on each successful RPC. Typically this will
        // be some number between 0 and 1, e.g., 0.1.
        //
        // This field is required and must be greater than zero. Up to 3 decimal
        // places are supported.
        "tokenRatio": number
      }
    }
    */

    Map<String, Object> throttling = getObject(serviceConfig, retryThrottlingKey);

    float maxTokens = getDouble(throttling, "maxTokens").floatValue();
    float tokenRatio = getDouble(throttling, "tokenRatio").floatValue();
    checkState(maxTokens > 0f, "maxToken should be greater than zero");
    checkState(tokenRatio > 0f, "tokenRatio should be greater than zero");
    return new Throttle(maxTokens, tokenRatio);
  }

  @Nullable
  static Integer getMaxAttemptsFromRetryPolicy(Map<String, Object> retryPolicy) {
    if (!retryPolicy.containsKey(RETRY_POLICY_MAX_ATTEMPTS_KEY)) {
      return null;
    }
    return getDouble(retryPolicy, RETRY_POLICY_MAX_ATTEMPTS_KEY).intValue();
  }

  @Nullable
  static Long getInitialBackoffNanosFromRetryPolicy(Map<String, Object> retryPolicy) {
    if (!retryPolicy.containsKey(RETRY_POLICY_INITIAL_BACKOFF_KEY)) {
      return null;
    }
    String rawInitialBackoff = getString(retryPolicy, RETRY_POLICY_INITIAL_BACKOFF_KEY);
    try {
      return parseDuration(rawInitialBackoff);
    } catch (ParseException e) {
      throw new RuntimeException(e);
    }
  }

  @Nullable
  static Long getMaxBackoffNanosFromRetryPolicy(Map<String, Object> retryPolicy) {
    if (!retryPolicy.containsKey(RETRY_POLICY_MAX_BACKOFF_KEY)) {
      return null;
    }
    String rawMaxBackoff = getString(retryPolicy, RETRY_POLICY_MAX_BACKOFF_KEY);
    try {
      return parseDuration(rawMaxBackoff);
    } catch (ParseException e) {
      throw new RuntimeException(e);
    }
  }

  @Nullable
  static Double getBackoffMultiplierFromRetryPolicy(Map<String, Object> retryPolicy) {
    if (!retryPolicy.containsKey(RETRY_POLICY_BACKOFF_MULTIPLIER_KEY)) {
      return null;
    }
    return getDouble(retryPolicy, RETRY_POLICY_BACKOFF_MULTIPLIER_KEY);
  }

  @Nullable
  static List<String> getRetryableStatusCodesFromRetryPolicy(Map<String, Object> retryPolicy) {
    if (!retryPolicy.containsKey(RETRY_POLICY_RETRYABLE_STATUS_CODES_KEY)) {
      return null;
    }
    return checkStringList(getList(retryPolicy, RETRY_POLICY_RETRYABLE_STATUS_CODES_KEY));
  }

  @Nullable
  static Integer getMaxAttemptsFromHedgingPolicy(Map<String, Object> hedgingPolicy) {
    if (!hedgingPolicy.containsKey(HEDGING_POLICY_MAX_ATTEMPTS_KEY)) {
      return null;
    }
    return getDouble(hedgingPolicy, RETRY_POLICY_MAX_ATTEMPTS_KEY).intValue();
  }

  @Nullable
  static Long getHedgingDelayNanosFromHedgingPolicy(Map<String, Object> hedgingPolicy) {
    if (!hedgingPolicy.containsKey(HEDGING_POLICY_HEDGING_DELAY_KEY)) {
      return null;
    }
    String rawHedgingDelay = getString(hedgingPolicy, HEDGING_POLICY_HEDGING_DELAY_KEY);
    try {
      return parseDuration(rawHedgingDelay);
    } catch (ParseException e) {
      throw new RuntimeException(e);
    }
  }

  @Nullable
  static List<String> getNonFatalStatusCodesFromHedgingPolicy(Map<String, Object> hedgingPolicy) {
    if (!hedgingPolicy.containsKey(HEDGING_POLICY_NON_FATAL_STATUS_CODES_KEY)) {
      return null;
    }
    return checkStringList(getList(hedgingPolicy, HEDGING_POLICY_NON_FATAL_STATUS_CODES_KEY));
  }

  @Nullable
  static String getServiceFromName(Map<String, Object> name) {
    if (!name.containsKey(NAME_SERVICE_KEY)) {
      return null;
    }
    return getString(name, NAME_SERVICE_KEY);
  }<commit_msg>core: using correct key for hedging max attempts<commit_after>/*
 * Copyright 2018 The gRPC Authors
 *
 * Licensed 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 io.grpc.internal;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.math.LongMath.checkedAdd;

import com.google.common.annotations.VisibleForTesting;
import io.grpc.internal.RetriableStream.Throttle;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;

/**
 * Helper utility to work with service configs.
 */
public final class ServiceConfigUtil {

  private static final String SERVICE_CONFIG_METHOD_CONFIG_KEY = "methodConfig";
  private static final String SERVICE_CONFIG_LOAD_BALANCING_POLICY_KEY = "loadBalancingPolicy";
  private static final String SERVICE_CONFIG_LOAD_BALANCING_CONFIG_KEY = "loadBalancingConfig";
  private static final String XDS_CONFIG_BALANCER_NAME_KEY = "balancerName";
  private static final String XDS_CONFIG_CHILD_POLICY_KEY = "childPolicy";
  private static final String XDS_CONFIG_FALLBACK_POLICY_KEY = "fallbackPolicy";
  private static final String SERVICE_CONFIG_STICKINESS_METADATA_KEY = "stickinessMetadataKey";
  private static final String METHOD_CONFIG_NAME_KEY = "name";
  private static final String METHOD_CONFIG_TIMEOUT_KEY = "timeout";
  private static final String METHOD_CONFIG_WAIT_FOR_READY_KEY = "waitForReady";
  private static final String METHOD_CONFIG_MAX_REQUEST_MESSAGE_BYTES_KEY =
      "maxRequestMessageBytes";
  private static final String METHOD_CONFIG_MAX_RESPONSE_MESSAGE_BYTES_KEY =
      "maxResponseMessageBytes";
  private static final String METHOD_CONFIG_RETRY_POLICY_KEY = "retryPolicy";
  private static final String METHOD_CONFIG_HEDGING_POLICY_KEY = "hedgingPolicy";
  private static final String NAME_SERVICE_KEY = "service";
  private static final String NAME_METHOD_KEY = "method";
  private static final String RETRY_POLICY_MAX_ATTEMPTS_KEY = "maxAttempts";
  private static final String RETRY_POLICY_INITIAL_BACKOFF_KEY = "initialBackoff";
  private static final String RETRY_POLICY_MAX_BACKOFF_KEY = "maxBackoff";
  private static final String RETRY_POLICY_BACKOFF_MULTIPLIER_KEY = "backoffMultiplier";
  private static final String RETRY_POLICY_RETRYABLE_STATUS_CODES_KEY = "retryableStatusCodes";
  private static final String HEDGING_POLICY_MAX_ATTEMPTS_KEY = "maxAttempts";
  private static final String HEDGING_POLICY_HEDGING_DELAY_KEY = "hedgingDelay";
  private static final String HEDGING_POLICY_NON_FATAL_STATUS_CODES_KEY = "nonFatalStatusCodes";

  private static final long DURATION_SECONDS_MIN = -315576000000L;
  private static final long DURATION_SECONDS_MAX = 315576000000L;

  private ServiceConfigUtil() {}

  /**
   * Fetch the health-checked service name from service config. {@code null} if can't find one.
   */
  @Nullable
  public static String getHealthCheckedServiceName(@Nullable Map<String, Object> serviceConfig) {
    String healthCheckKey = "healthCheckConfig";
    String serviceNameKey = "serviceName";
    if (serviceConfig == null || !serviceConfig.containsKey(healthCheckKey)) {
      return null;
    }

    /* schema as follows
    {
      "healthCheckConfig": {
        // Service name to use in the health-checking request.
        "serviceName": string
      }
    }
    */
    Map<String, Object> healthCheck = getObject(serviceConfig, healthCheckKey);
    if (!healthCheck.containsKey(serviceNameKey)) {
      return null;
    }
    return getString(healthCheck, "serviceName");
  }

  @Nullable
  static Throttle getThrottlePolicy(@Nullable Map<String, Object> serviceConfig) {
    String retryThrottlingKey = "retryThrottling";
    if (serviceConfig == null || !serviceConfig.containsKey(retryThrottlingKey)) {
      return null;
    }

    /* schema as follows
    {
      "retryThrottling": {
        // The number of tokens starts at maxTokens. The token_count will always be
        // between 0 and maxTokens.
        //
        // This field is required and must be greater than zero.
        "maxTokens": number,

        // The amount of tokens to add on each successful RPC. Typically this will
        // be some number between 0 and 1, e.g., 0.1.
        //
        // This field is required and must be greater than zero. Up to 3 decimal
        // places are supported.
        "tokenRatio": number
      }
    }
    */

    Map<String, Object> throttling = getObject(serviceConfig, retryThrottlingKey);

    float maxTokens = getDouble(throttling, "maxTokens").floatValue();
    float tokenRatio = getDouble(throttling, "tokenRatio").floatValue();
    checkState(maxTokens > 0f, "maxToken should be greater than zero");
    checkState(tokenRatio > 0f, "tokenRatio should be greater than zero");
    return new Throttle(maxTokens, tokenRatio);
  }

  @Nullable
  static Integer getMaxAttemptsFromRetryPolicy(Map<String, Object> retryPolicy) {
    if (!retryPolicy.containsKey(RETRY_POLICY_MAX_ATTEMPTS_KEY)) {
      return null;
    }
    return getDouble(retryPolicy, RETRY_POLICY_MAX_ATTEMPTS_KEY).intValue();
  }

  @Nullable
  static Long getInitialBackoffNanosFromRetryPolicy(Map<String, Object> retryPolicy) {
    if (!retryPolicy.containsKey(RETRY_POLICY_INITIAL_BACKOFF_KEY)) {
      return null;
    }
    String rawInitialBackoff = getString(retryPolicy, RETRY_POLICY_INITIAL_BACKOFF_KEY);
    try {
      return parseDuration(rawInitialBackoff);
    } catch (ParseException e) {
      throw new RuntimeException(e);
    }
  }

  @Nullable
  static Long getMaxBackoffNanosFromRetryPolicy(Map<String, Object> retryPolicy) {
    if (!retryPolicy.containsKey(RETRY_POLICY_MAX_BACKOFF_KEY)) {
      return null;
    }
    String rawMaxBackoff = getString(retryPolicy, RETRY_POLICY_MAX_BACKOFF_KEY);
    try {
      return parseDuration(rawMaxBackoff);
    } catch (ParseException e) {
      throw new RuntimeException(e);
    }
  }

  @Nullable
  static Double getBackoffMultiplierFromRetryPolicy(Map<String, Object> retryPolicy) {
    if (!retryPolicy.containsKey(RETRY_POLICY_BACKOFF_MULTIPLIER_KEY)) {
      return null;
    }
    return getDouble(retryPolicy, RETRY_POLICY_BACKOFF_MULTIPLIER_KEY);
  }

  @Nullable
  static List<String> getRetryableStatusCodesFromRetryPolicy(Map<String, Object> retryPolicy) {
    if (!retryPolicy.containsKey(RETRY_POLICY_RETRYABLE_STATUS_CODES_KEY)) {
      return null;
    }
    return checkStringList(getList(retryPolicy, RETRY_POLICY_RETRYABLE_STATUS_CODES_KEY));
  }

  @Nullable
  static Integer getMaxAttemptsFromHedgingPolicy(Map<String, Object> hedgingPolicy) {
    if (!hedgingPolicy.containsKey(HEDGING_POLICY_MAX_ATTEMPTS_KEY)) {
      return null;
    }
    return getDouble(hedgingPolicy, HEDGING_POLICY_MAX_ATTEMPTS_KEY).intValue();
  }

  @Nullable
  static Long getHedgingDelayNanosFromHedgingPolicy(Map<String, Object> hedgingPolicy) {
    if (!hedgingPolicy.containsKey(HEDGING_POLICY_HEDGING_DELAY_KEY)) {
      return null;
    }
    String rawHedgingDelay = getString(hedgingPolicy, HEDGING_POLICY_HEDGING_DELAY_KEY);
    try {
      return parseDuration(rawHedgingDelay);
    } catch (ParseException e) {
      throw new RuntimeException(e);
    }
  }

  @Nullable
  static List<String> getNonFatalStatusCodesFromHedgingPolicy(Map<String, Object> hedgingPolicy) {
    if (!hedgingPolicy.containsKey(HEDGING_POLICY_NON_FATAL_STATUS_CODES_KEY)) {
      return null;
    }
    return checkStringList(getList(hedgingPolicy, HEDGING_POLICY_NON_FATAL_STATUS_CODES_KEY));
  }

  @Nullable
  static String getServiceFromName(Map<String, Object> name) {
    if (!name.containsKey(NAME_SERVICE_KEY)) {
      return null;
    }
    return getString(name, NAME_SERVICE_KEY);
  }
{'fraction_non_alphanumeric': 0.07833937162202292, 'fraction_numerical': 0.004751440280334977, 'mean_word_length': 4.466883116883117, 'pattern_counts': {'":': 10, '<': 33, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1215181', 'n_tokens_mistral': 5206, 'n_tokens_neox': 5152, 'n_words': 1233}