// Copyright (C) 2018 The Android Open Source Project
//
// 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 com.google.gerrit.server.cache;

import static com.google.common.base.Preconditions.checkState;

import com.google.common.base.Objects;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.server.git.RefCache;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;

/**
 * Caches object instances for a request as {@link ThreadLocal} in the serving thread.
 *
 * <p>This class is intended to cache objects that have a high instantiation cost, are specific to
 * the current request and potentially need to be instantiated multiple times while serving a
 * request.
 *
 * <p>This is different from the key-value storage in {@code CurrentUser}: {@code CurrentUser}
 * offers a key-value storage by providing thread-safe {@code get} and {@code put} methods. Once the
 * value is retrieved through {@code get} there is not thread-safety anymore - apart from the
 * retrieved object guarantees. Depending on the implementation of {@code CurrentUser}, it might be
 * shared between the request serving thread as well as sub- or background treads.
 *
 * <p>In comparison to that, this class guarantees thread safety even on non-thread-safe objects as
 * its cache is tied to the serving thread only. While allowing to cache non-thread-safe objects, it
 * has the downside of not sharing any objects with background threads or executors.
 *
 * <p>Lastly, this class offers a cache, that requires callers to also provide a {@code Supplier} in
 * case the object is not present in the cache, while {@code CurrentUser} provides a storage where
 * just retrieving stored values is a valid operation.
 *
 * <p>To prevent OOM errors on requests that would cache a lot of objects, this class enforces an
 * internal limit after which no new elements are cached. All {@code get} calls are served by
 * invoking the {@code Supplier} after that.
 */
public class PerThreadCache implements AutoCloseable {
  private static final ThreadLocal<PerThreadCache> CACHE = new ThreadLocal<>();
  /**
   * Cache at maximum 25 values per thread. This value was chosen arbitrarily. Some endpoints (like
   * ListProjects) break the assumption that the data cached in a request is limited. To prevent
   * this class from accumulating an unbound number of objects, we enforce this limit.
   */
  private static final int PER_THREAD_CACHE_SIZE = 25;

  /**
   * System property for disabling caching specific key types. TODO: DO NOT MERGE into stable-3.2
   * onwards.
   */
  public static final String PER_THREAD_CACHE_DISABLED_TYPES_PROPERTY =
      "PerThreadCache_disabledTypes";

  /**
   * True when the current thread is associated with an incoming API request that is not changing
   * any repository /meta refs and therefore caching repo refs is safe. TODO: DO NOT MERGE into
   * stable-3.2 onwards.
   */
  private boolean allowRefCache;

  /**
   * Sets the request status flag to read-only temporarily. TODO: DO NOT MERGE into stable-3.2
   * onwards.
   */
  public interface ReadonlyRequestWindow extends AutoCloseable {

    /**
     * Close the request read-only status, restoring the previous value.
     *
     * <p>NOTE: If the previous status was not read-only, the cache is getting cleared for making
     * sure that all potential stale entries coming from a read-only windows are cleared.
     */
    @Override
    default void close() {}
  }

  private class ReadonlyRequestWindowImpl implements ReadonlyRequestWindow {
    private final boolean oldAllowRepoRefsCache;

    private ReadonlyRequestWindowImpl() {
      oldAllowRepoRefsCache = allowRefCache();
      allowRefCache(true);
    }

    @Override
    public void close() {
      allowRefCache(oldAllowRepoRefsCache);
    }
  }

  private final Map<Key<?>, Consumer<Object>> unloaders =
      Maps.newHashMapWithExpectedSize(PER_THREAD_CACHE_SIZE);

  /**
   * Unique key for key-value mappings stored in PerThreadCache. The key is based on the value's
   * class and a list of identifiers that in combination uniquely set the object apart form others
   * of the same class.
   */
  public static final class Key<T> {
    private final Class<T> clazz;
    private final ImmutableList<Object> identifiers;

    /**
     * Returns a key based on the value's class and an identifier that uniquely identify the value.
     * The identifier needs to implement {@code equals()} and {@hashCode()}.
     */
    public static <T> Key<T> create(Class<T> clazz, Object identifier) {
      return new Key<>(clazz, ImmutableList.of(identifier));
    }

    /**
     * Returns a key based on the value's class and a set of identifiers that uniquely identify the
     * value. Identifiers need to implement {@code equals()} and {@hashCode()}.
     */
    public static <T> Key<T> create(Class<T> clazz, Object... identifiers) {
      return new Key<>(clazz, ImmutableList.copyOf(identifiers));
    }

    private Key(Class<T> clazz, ImmutableList<Object> identifiers) {
      this.clazz = clazz;
      this.identifiers = identifiers;
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(clazz, identifiers);
    }

    @Override
    public boolean equals(Object o) {
      if (!(o instanceof Key)) {
        return false;
      }
      Key<?> other = (Key<?>) o;
      return this.clazz == other.clazz && this.identifiers.equals(other.identifiers);
    }
  }

  /**
   * Creates a thread-local cache associated to an incoming HTTP request.
   *
   * <p>The request is considered as read-only if the associated method is GET or HEAD.
   *
   * @param httpRequest HTTP request associated with the thread-local cache
   * @return thread-local cache
   */
  public static PerThreadCache create(@Nullable HttpServletRequest httpRequest) {
    checkState(CACHE.get() == null, "called create() twice on the same request");
    PerThreadCache cache = new PerThreadCache(httpRequest, false);
    CACHE.set(cache);
    return cache;
  }

  /**
   * Creates a thread-local cache associated to an incoming read-only request.
   *
   * @return thread-local cache
   */
  public static PerThreadCache createReadOnly() {
    checkState(CACHE.get() == null, "called create() twice on the same request");
    PerThreadCache cache = new PerThreadCache(null, true);
    CACHE.set(cache);
    return cache;
  }

  @Nullable
  public static PerThreadCache get() {
    return CACHE.get();
  }

  /**
   * Return a cached value associated with a key fetched with a loader and released with an unloader
   * function.
   *
   * @param <T> The data type of the cached value
   * @param key the key associated with the value
   * @param loader the loader function for fetching the value from the key
   * @param unloader the unloader function for releasing the value when unloaded from the cache
   * @return Optional of the cached value or empty if the value could not be cached for any reason
   *     (e.g. cache full)
   */
  public static <T> Optional<T> get(Key<T> key, Supplier<T> loader, Consumer<T> unloader) {
    return Optional.ofNullable(get()).flatMap(c -> c.getWithLoader(key, loader, unloader));
  }

  /**
   * Legacy way for retrieving a cached element through a loader.
   *
   * <p>This method is deprecated because it was error-prone due to the unclear ownership of the
   * objects created through the loader. When the cache has space available, the entries are loaded
   * and cached, hence owned and reused by the cache.
   *
   * <p>When the cache is full, this method just short-circuit to the invocation of the loader and
   * the objects created aren't owned or stored by the cache, leaving the space for potential memory
   * and resources leaks.
   *
   * <p>Because of the unclear semantics of the method (who owns the instances? are they reused?)
   * this is now deprecated the the caller should use instead the {@link PerThreadCache#get(Key,
   * Supplier, Consumer)} which has a clear ownership policy.
   *
   * @deprecated use {@link PerThreadCache#get(Key, Supplier, Consumer)}
   */
  public static <T> T getOrCompute(Key<T> key, Supplier<T> loader) {
    PerThreadCache cache = get();
    return cache != null ? cache.get(key, loader) : loader.get();
  }

  private final Map<Key<?>, Object> cache = Maps.newHashMapWithExpectedSize(PER_THREAD_CACHE_SIZE);
  private final ImmutableSet<String> disabledTypes;

  private PerThreadCache(@Nullable HttpServletRequest req, boolean alwaysCacheRepoRefs) {
    disabledTypes =
        ImmutableSet.copyOf(
            Splitter.on(',')
                .split(System.getProperty(PER_THREAD_CACHE_DISABLED_TYPES_PROPERTY, "")));

    allowRefCache =
        alwaysCacheRepoRefs
            || (req != null
                && (req.getMethod().equalsIgnoreCase("GET")
                    || req.getMethod().equalsIgnoreCase("HEAD")));
  }

  /**
   * Legacy way of retrieving an instance of {@code T} that was either loaded from the cache or
   * obtained from the provided {@link Supplier}.
   *
   * <p>This method is deprecated because it was error-prone due to the unclear ownership of the
   * objects created through the loader. When the cache has space available, the entries are loaded
   * and cached, hence owned and reused by the cache.
   *
   * <p>When the cache is full, this method just short-circuit to the invocation of the loader and
   * the objects created aren't owned or stored by the cache, leaving the space for potential memory
   * and resources leaks.
   *
   * <p>Because of the unclear semantics of the method (who owns the instances? are they reused?)
   * this is now deprecated the the caller should use instead the {@link PerThreadCache#get(Key,
   * Supplier, Consumer)} which has a clear ownership policy.
   *
   * @deprecated use {@link PerThreadCache#getWithLoader(Key, Supplier, Consumer)}
   */
  public <T> T get(Key<T> key, Supplier<T> loader) {
    return getWithLoader(key, loader, null).orElse(loader.get());
  }

  @SuppressWarnings("unchecked")
  public <T> Optional<T> getWithLoader(
      Key<T> key, Supplier<T> loader, @Nullable Consumer<T> unloader) {
    if (disabledTypes.contains(key.clazz.getCanonicalName())) {
      return Optional.empty();
    }

    T value = (T) cache.get(key);
    if (value == null && cache.size() < PER_THREAD_CACHE_SIZE) {
      value = loader.get();
      cache.put(key, value);
      if (unloader != null) {
        unloaders.put(key, (Consumer<Object>) unloader);
      }
    }
    return Optional.ofNullable(value);
  }

  /** Returns an instance of {@code T} that is already loaded from the cache or null otherwise. */
  @SuppressWarnings("unchecked")
  public <T> T get(Key<T> key) {
    return (T) cache.get(key);
  }

  /**
   * Returns true if the associated request is read-only and therefore the repo refs are safe to be
   * cached
   */
  public boolean allowRefCache() {
    return allowRefCache;
  }

  /**
   * Set the cache read-only request status temporarily, for enabling caching of all entries.
   *
   * @return {@link ReadonlyRequestWindow} associated with the incoming request
   */
  public static ReadonlyRequestWindow openReadonlyRequestWindow() {
    PerThreadCache perThreadCache = CACHE.get();
    return perThreadCache == null
        ? new ReadonlyRequestWindow() {}
        : perThreadCache.new ReadonlyRequestWindowImpl();
  }

  @Override
  public void close() {
    unload(unloaders.entrySet());
    CACHE.remove();
  }

  private void unload(Collection<Entry<Key<?>, Consumer<Object>>> entriesToUnload) {
    ImmutableSet<Entry<Key<?>, Consumer<Object>>> toUnload = ImmutableSet.copyOf(entriesToUnload);
    try {
      toUnload.stream().forEach(this::unload);
    } finally {
      toUnload.stream()
          .forEach(
              e -> {
                cache.remove(e.getKey());
                unloaders.remove(e.getKey());
              });
    }
  }

  private <T> void unload(Entry<Key<?>, Consumer<Object>> unloaderEntry) {
    Object valueToUnload = cache.get(unloaderEntry.getKey());
    unloaderEntry.getValue().accept(valueToUnload);
    cache.remove(unloaderEntry.getKey());
  }

  private void allowRefCache(boolean allowed) {
    allowRefCache = allowed;

    if (!allowRefCache) {
      unload(
          unloaders.entrySet().stream()
              .filter(e -> RefCache.class.isAssignableFrom(e.getKey().clazz))
              .collect(Collectors.toSet()));
    }
  }
}
