package com.atlassian.bitbucket.mesh.throttle;

import com.google.common.collect.ImmutableMap;

import java.util.Map;

import static com.atlassian.bitbucket.mesh.throttle.ThrottledResource.*;

/**
 * Constants for throttling
 */
public class ThrottlingConstants {

    public static final long MEM_1MB = 1024 * 1024;

    /**
     * How many intervals we will wait without a CPU before adaptive throttling reverts to fixed throttling
     */
    public static final int INTERVALS_MAX_WITHOUT_CPU = 4;

    /**
     * Defines the prefix which can be used to configure the number of tickets that should be available for a named
     * resource. Entries in application properties with this prefix will be preemptively configured during startup.
     *
     * @see SemaphoreThrottleService#initialize()
     */
    public static final String RESOURCE_PROP_PREFIX = "throttle.resource.";
    public static final String RESOURCE_PROP_SUFFIX_ADAPTIVE_CPU_HISTORICAL_WEIGHTING = ".adaptive.cpu.historical.weighting";
    public static final String RESOURCE_PROP_SUFFIX_ADAPTIVE_CPU_PER_TICKET = ".adaptive.cpu.per.ticket";
    public static final String RESOURCE_PROP_SUFFIX_ADAPTIVE_CPU_TARGET_USAGE = ".adaptive.cpu.target";
    public static final String RESOURCE_PROP_SUFFIX_ADAPTIVE_INTERVAL = ".adaptive.interval";
    public static final String RESOURCE_PROP_SUFFIX_ADAPTIVE_MEM_BACKSTOP_ENABLED = ".adaptive.mem.backstop.enabled";
    public static final String RESOURCE_PROP_SUFFIX_ADAPTIVE_MEM_PER_TICKET = ".adaptive.mem.per.ticket";
    public static final String RESOURCE_PROP_SUFFIX_ADAPTIVE_MEM_RESERVED = ".adaptive.mem.reserved";
    public static final String RESOURCE_PROP_SUFFIX_ADAPTIVE_MEM_WEBAPP = ".adaptive.mem.webapp";
    public static final String RESOURCE_PROP_SUFFIX_ADAPTIVE_LIMIT_MAX = ".adaptive.limit.max";
    public static final String RESOURCE_PROP_SUFFIX_ADAPTIVE_LIMIT_MIN = ".adaptive.limit.min";
    public static final String RESOURCE_PROP_SUFFIX_FIXED_LIMIT = ".fixed.limit";
    public static final String RESOURCE_PROP_SUFFIX_STRATEGY = ".strategy";
    public static final String RESOURCE_PROP_SUFFIX_TIMEOUT = ".timeout";
    public static final String RESOURCE_PROP_VALUE_ADAPTIVE_MEM_WEBAPP_JVM_MAX = "jvmmax";

    public static final String LOGGER_PREFIX_THROTTLING_PROFILE = "throttle.profile.";

    /**
     * If unspecified, the memory backstop for adaptive throttling is enabled
     */
    public static final boolean FALLBACK_ADAPTIVE_MEM_BACKSTOP_ENABLED = true;

    /**
     * If unspecified, each ticket is expected to take 256MB of memory
     */
    public static final int FALLBACK_ADAPTIVE_MEM_PER_TICKET = 256;

    /**
     * If unspecified, a weighting of 80% is given to the previously derived CPU usage when deriving the current
     * CPU usage.
     *
     * Tuned for scm-hosting only.
     */
    public static final double FALLBACK_ADAPTIVE_CPU_HISTORICAL_WEIGHTING = 0.8d;
    /**
     * If unspecified, each typical ticketed hosting operation is assumed to consume an average of 8% utilisation of a
     * single core during its lifetime.
     *
     * Tuned for scm-hosting only.
     */
    public static final double FALLBACK_ADAPTIVE_CPU_PER_TICKET = 0.08d / Runtime.getRuntime().availableProcessors();
    /**
     * If unspecified, adaptive throttling runs every 5 seconds.
     */
    public static final int FALLBACK_ADAPTIVE_INTERVAL_SECONDS = 5;
    /**
     * If unspecified, 75% CPU utilisation is targeted for adaptive throttling.
     * Tuned for scm-hosting only.
     */
    public static final double FALLBACK_ADAPTIVE_TARGET_CPU_USAGE = 0.75;
    /**
     * If unspecified, the maximum ticket count for adaptive throttling is 4 times the number of CPUs.
     * Tuned for scm-hosting only.
     */
    public static final double FALLBACK_ADAPTIVE_CPU_SCALE_MAX_TICKETS = 4.0;
    /**
     * If unspecified, the minimum ticket count for adaptive throttling is 1 times the number of CPUs.
     * Tuned for scm-hosting only.
     */
    public static final double FALLBACK_ADAPTIVE_CPU_SCALE_MIN_TICKETS = 1.0;
    /**
     * If unspecified, the maximum ticket count for adaptive throttling.
     * Tuned for scm-hosting only.
     */
    public static final double FALLBACK_ADAPTIVE_TICKETS =
            FALLBACK_ADAPTIVE_CPU_SCALE_MAX_TICKETS * Runtime.getRuntime().availableProcessors();
    /**
     * If unspecified, the resource-specific total ticket count for fixed throttling
     */
    public static final Map<ThrottledResource, Integer> FALLBACK_FIXED_TICKETS = ImmutableMap.of(
            PACK, (int) Math.round(1.5 * Runtime.getRuntime().availableProcessors()),
            MIRROR_PACK, 2 * Runtime.getRuntime().availableProcessors(),
            COMMAND, 25,
            LFS, 80);
    /**
     * If unspecified, the resource-specific timeouts for throttled operations currently being queued
     */
    public static final Map<ThrottledResource, Integer> FALLBACK_TICKET_TIMEOUT_SECONDS = ImmutableMap.of(
            PACK, 300,
            MIRROR_PACK, 3600,
            COMMAND, 2,
            LFS, 0);
}
