// Copyright (C) 2008 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.project;

import static com.google.gerrit.server.project.ProjectCache.illegalState;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.toSet;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.common.hash.Hashing;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.CachedProjectConfig;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.index.project.ProjectIndexer;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.metrics.Counter2;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Description.Units;
import com.google.gerrit.metrics.Field;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.metrics.Timer0;
import com.google.gerrit.proto.Protos;
import com.google.gerrit.server.CacheRefreshExecutor;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.cache.proto.Cache;
import com.google.gerrit.server.cache.serialize.CacheSerializer;
import com.google.gerrit.server.cache.serialize.ObjectIdConverter;
import com.google.gerrit.server.cache.serialize.ProtobufSerializer;
import com.google.gerrit.server.cache.serialize.entities.CachedProjectConfigSerializer;
import com.google.gerrit.server.config.AllProjectsConfigProvider;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.time.Duration;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;

/**
 * Cache of project information, including access rights.
 *
 * <p>The data of a project is the project's project.config in refs/meta/config parsed out as an
 * immutable value. It's keyed purely by the refs/meta/config SHA-1. We also cache the same value
 * keyed by name. The latter mapping can become outdated, so data must be evicted explicitly.
 */
@Singleton
public class ProjectCacheImpl implements ProjectCache {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static final String CACHE_NAME = "projects";

  public static final String PERSISTED_CACHE_NAME = "persisted_projects";

  private static final String CACHE_LIST = "project_list";

  public static Module module() {
    return new CacheModule() {
      @Override
      protected void configure() {
        // We split the project cache into two parts for performance reasons:
        // 1) An in-memory part that has only the project name as key.
        // 2) A persisted part that has the name and revision as key.
        //
        // When loading dashboards or returning change query results we potentially
        // need to access hundreds of projects because each change could originate in
        // a different project and, through inheritance, require us to check even more
        // projects when evaluating permissions. It's not feasible to read the revision
        // of refs/meta/config from each of these repos as that would require opening
        // them all and reading their ref list or table.
        // At the same time, we want the persisted cache to be immutable and we want it
        // to be impossible that a value for a given key is out of date. We therefore
        // require a revision in the key. That is in line with the rest of the caches in
        // Gerrit.
        //
        // Splitting the cache into two chunks internally in this class allows us to retain
        // the existing performance guarantees of not requiring reads for the repo for values
        // cached in-memory but also to persist the cache which leads to a much improved
        // cold-start behavior and in-memory miss latency.
        cache(CACHE_NAME, Project.NameKey.class, CachedProjectConfig.class)
            .loader(InMemoryLoader.class)
            .refreshAfterWrite(Duration.ofMinutes(15))
            .expireAfterWrite(Duration.ofHours(1));

        persist(PERSISTED_CACHE_NAME, Cache.ProjectCacheKeyProto.class, CachedProjectConfig.class)
            .loader(PersistedLoader.class)
            .keySerializer(new ProtobufSerializer<>(Cache.ProjectCacheKeyProto.parser()))
            .valueSerializer(PersistedProjectConfigSerializer.INSTANCE)
            .diskLimit(1 << 30) // 1 GiB
            .version(2)
            .maximumWeight(0);

        cache(CACHE_LIST, ListKey.class, new TypeLiteral<ImmutableSortedSet<Project.NameKey>>() {})
            .maximumWeight(1)
            .loader(Lister.class);

        bind(ProjectCacheImpl.class);
        bind(ProjectCache.class).to(ProjectCacheImpl.class);

        install(
            new LifecycleModule() {
              @Override
              protected void configure() {
                listener().to(ProjectCacheWarmer.class);
              }
            });
      }
    };
  }

  private final AllProjectsName allProjectsName;
  private final AllUsersName allUsersName;
  private final LoadingCache<Project.NameKey, CachedProjectConfig> inMemoryProjectCache;
  private final LoadingCache<ListKey, ImmutableSortedSet<Project.NameKey>> list;
  private final Lock listLock;
  private final Provider<ProjectIndexer> indexer;
  private final Timer0 guessRelevantGroupsLatency;
  private final ProjectState.Factory projectStateFactory;

  @Inject
  ProjectCacheImpl(
      final AllProjectsName allProjectsName,
      final AllUsersName allUsersName,
      @Named(CACHE_NAME) LoadingCache<Project.NameKey, CachedProjectConfig> inMemoryProjectCache,
      @Named(CACHE_LIST) LoadingCache<ListKey, ImmutableSortedSet<Project.NameKey>> list,
      Provider<ProjectIndexer> indexer,
      MetricMaker metricMaker,
      ProjectState.Factory projectStateFactory) {
    this.allProjectsName = allProjectsName;
    this.allUsersName = allUsersName;
    this.inMemoryProjectCache = inMemoryProjectCache;
    this.list = list;
    this.listLock = new ReentrantLock(true /* fair */);
    this.indexer = indexer;
    this.projectStateFactory = projectStateFactory;

    this.guessRelevantGroupsLatency =
        metricMaker.newTimer(
            "group/guess_relevant_groups_latency",
            new Description("Latency for guessing relevant groups")
                .setCumulative()
                .setUnit(Units.NANOSECONDS));
  }

  @Override
  public ProjectState getAllProjects() {
    return get(allProjectsName).orElseThrow(illegalState(allProjectsName));
  }

  @Override
  public ProjectState getAllUsers() {
    return get(allUsersName).orElseThrow(illegalState(allUsersName));
  }

  @Override
  public Optional<ProjectState> get(@Nullable Project.NameKey projectName) {
    if (projectName == null) {
      return Optional.empty();
    }

    try {
      return Optional.of(inMemoryProjectCache.get(projectName)).map(projectStateFactory::create);
    } catch (ExecutionException e) {
      if ((e.getCause() instanceof RepositoryNotFoundException)) {
        logger.atFine().log("Cannot find project %s", projectName.get());
        return Optional.empty();
      }
      throw new StorageException(
          String.format("project state of project %s not available", projectName.get()), e);
    }
  }

  @Override
  public void evict(Project p) {
    evict(p.getNameKey());
  }

  @Override
  public void evict(Project.NameKey p) {
    if (p != null) {
      logger.atFine().log("Evict project '%s'", p.get());
      inMemoryProjectCache.invalidate(p);
    }
    indexer.get().index(p);
  }

  @Override
  public void remove(Project p) {
    remove(p.getNameKey());
  }

  @Override
  public void remove(Project.NameKey name) {
    listLock.lock();
    try {
      list.put(
          ListKey.ALL,
          ImmutableSortedSet.copyOf(Sets.difference(list.get(ListKey.ALL), ImmutableSet.of(name))));
    } catch (ExecutionException e) {
      logger.atWarning().withCause(e).log("Cannot list available projects");
    } finally {
      listLock.unlock();
    }
    evict(name);
  }

  @Override
  public void onCreateProject(Project.NameKey newProjectName) throws IOException {
    listLock.lock();
    try {
      list.put(
          ListKey.ALL,
          ImmutableSortedSet.copyOf(
              Sets.union(list.get(ListKey.ALL), ImmutableSet.of(newProjectName))));
    } catch (ExecutionException e) {
      logger.atWarning().withCause(e).log("Cannot list available projects");
    } finally {
      listLock.unlock();
    }
    indexer.get().index(newProjectName);
  }

  @Override
  public ImmutableSortedSet<Project.NameKey> all() {
    try {
      return list.get(ListKey.ALL);
    } catch (ExecutionException e) {
      logger.atWarning().withCause(e).log("Cannot list available projects");
      return ImmutableSortedSet.of();
    }
  }

  @Override
  public Set<AccountGroup.UUID> guessRelevantGroupUUIDs() {
    try (Timer0.Context ignored = guessRelevantGroupsLatency.start()) {
      return all().stream()
          .map(n -> inMemoryProjectCache.getIfPresent(n))
          .filter(Objects::nonNull)
          .flatMap(p -> p.getAllGroupUUIDs().stream())
          // getAllGroupUUIDs shouldn't really return null UUIDs, but harden
          // against them just in case there is a bug or corner case.
          .filter(id -> id != null && id.get() != null)
          .collect(toSet());
    }
  }

  @Override
  public ImmutableSortedSet<Project.NameKey> byName(String pfx) {
    Project.NameKey start = Project.nameKey(pfx);
    Project.NameKey end = Project.nameKey(pfx + Character.MAX_VALUE);
    try {
      // Right endpoint is exclusive, but U+FFFF is a non-character so no project ends with it.
      return list.get(ListKey.ALL).subSet(start, end);
    } catch (ExecutionException e) {
      logger.atWarning().withCause(e).log("Cannot look up projects for prefix %s", pfx);
      return ImmutableSortedSet.of();
    }
  }

  /**
   * Returns a {@code MurMur128} hash of the contents of {@code etc/All-Projects-project.config}.
   */
  public static byte[] allProjectsFileProjectConfigHash(Optional<StoredConfig> allProjectsConfig) {
    // Hash the contents of All-Projects-project.config
    // This is a way for administrators to orchestrate project.config changes across many Gerrit
    // instances.
    // When this file changes, we need to make sure we disregard persistently cached project
    // state.
    if (!allProjectsConfig.isPresent()) {
      // If the project.config file is not present, this is equal to an empty config file:
      return Hashing.murmur3_128().hashString("", UTF_8).asBytes();
    }
    try {
      allProjectsConfig.get().load();
    } catch (IOException | ConfigInvalidException e) {
      throw new IllegalStateException(e);
    }
    return Hashing.murmur3_128().hashString(allProjectsConfig.get().toText(), UTF_8).asBytes();
  }

  @Singleton
  static class InMemoryLoader extends CacheLoader<Project.NameKey, CachedProjectConfig> {
    private final LoadingCache<Cache.ProjectCacheKeyProto, CachedProjectConfig> persistedCache;
    private final GitRepositoryManager repoManager;
    private final ListeningExecutorService cacheRefreshExecutor;
    private final Counter2<String, Boolean> refreshCounter;
    private final AllProjectsName allProjectsName;
    private final AllProjectsConfigProvider allProjectsConfigProvider;

    @Inject
    InMemoryLoader(
        @Named(PERSISTED_CACHE_NAME)
            LoadingCache<Cache.ProjectCacheKeyProto, CachedProjectConfig> persistedCache,
        GitRepositoryManager repoManager,
        @CacheRefreshExecutor ListeningExecutorService cacheRefreshExecutor,
        MetricMaker metricMaker,
        AllProjectsName allProjectsName,
        AllProjectsConfigProvider allProjectsConfigProvider) {
      this.persistedCache = persistedCache;
      this.repoManager = repoManager;
      this.cacheRefreshExecutor = cacheRefreshExecutor;
      refreshCounter =
          metricMaker.newCounter(
              "caches/refresh_count",
              new Description("count").setRate(),
              Field.ofString("cache", Metadata.Builder::className).build(),
              Field.ofBoolean("outdated", Metadata.Builder::outdated).build());
      this.allProjectsName = allProjectsName;
      this.allProjectsConfigProvider = allProjectsConfigProvider;
    }

    @Override
    public CachedProjectConfig load(Project.NameKey key) throws IOException, ExecutionException {
      try (TraceTimer ignored =
              TraceContext.newTimer(
                  "Loading project from serialized cache",
                  Metadata.builder().projectName(key.get()).build());
          Repository git = repoManager.openRepository(key)) {
        Cache.ProjectCacheKeyProto.Builder keyProto =
            Cache.ProjectCacheKeyProto.newBuilder().setProject(key.get());
        Ref configRef = git.exactRef(RefNames.REFS_CONFIG);
        if (key.get().equals(allProjectsName.get())) {
          Optional<StoredConfig> allProjectsConfig = allProjectsConfigProvider.get(allProjectsName);
          byte[] fileHash = allProjectsFileProjectConfigHash(allProjectsConfig);
          keyProto.setGlobalConfigRevision(ByteString.copyFrom(fileHash));
        }
        if (configRef != null) {
          keyProto.setRevision(ObjectIdConverter.create().toByteString(configRef.getObjectId()));
        }
        return persistedCache.get(keyProto.build());
      }
    }

    @Override
    public ListenableFuture<CachedProjectConfig> reload(
        Project.NameKey key, CachedProjectConfig oldState) throws Exception {
      try (TraceTimer ignored =
          TraceContext.newTimer(
              "Reload project", Metadata.builder().projectName(key.get()).build())) {
        try (Repository git = repoManager.openRepository(key)) {
          Ref configRef = git.exactRef(RefNames.REFS_CONFIG);
          if (configRef != null && configRef.getObjectId().equals(oldState.getRevision().get())) {
            refreshCounter.increment(CACHE_NAME, false);
            return Futures.immediateFuture(oldState);
          }
        }

        // Repository is not thread safe, so we have to open it on the thread that does the loading.
        // Just invoke the loader on the other thread.
        refreshCounter.increment(CACHE_NAME, true);
        return cacheRefreshExecutor.submit(() -> load(key));
      }
    }
  }

  @Singleton
  static class PersistedLoader
      extends CacheLoader<Cache.ProjectCacheKeyProto, CachedProjectConfig> {
    private final GitRepositoryManager repoManager;
    private final ProjectConfig.Factory projectConfigFactory;

    @Inject
    PersistedLoader(GitRepositoryManager repoManager, ProjectConfig.Factory projectConfigFactory) {
      this.repoManager = repoManager;
      this.projectConfigFactory = projectConfigFactory;
    }

    @Override
    public CachedProjectConfig load(Cache.ProjectCacheKeyProto key) throws Exception {
      Project.NameKey nameKey = Project.nameKey(key.getProject());
      ObjectId revision =
          key.getRevision().isEmpty()
              ? null
              : ObjectIdConverter.create().fromByteString(key.getRevision());
      try (TraceTimer ignored =
          TraceContext.newTimer(
              "Loading project from repo", Metadata.builder().projectName(nameKey.get()).build())) {
        try (Repository git = repoManager.openRepository(nameKey)) {
          ProjectConfig cfg = projectConfigFactory.create(nameKey);
          cfg.load(git, revision);
          return cfg.getCacheable();
        }
      }
    }
  }

  private enum PersistedProjectConfigSerializer implements CacheSerializer<CachedProjectConfig> {
    INSTANCE;

    @Override
    public byte[] serialize(CachedProjectConfig value) {
      return Protos.toByteArray(CachedProjectConfigSerializer.serialize(value));
    }

    @Override
    public CachedProjectConfig deserialize(byte[] in) {
      return CachedProjectConfigSerializer.deserialize(
          Protos.parseUnchecked(Cache.CachedProjectConfigProto.parser(), in));
    }
  }

  static class ListKey {
    static final ListKey ALL = new ListKey();

    private ListKey() {}
  }

  static class Lister extends CacheLoader<ListKey, ImmutableSortedSet<Project.NameKey>> {
    private final GitRepositoryManager mgr;

    @Inject
    Lister(GitRepositoryManager mgr) {
      this.mgr = mgr;
    }

    @Override
    public ImmutableSortedSet<Project.NameKey> load(ListKey key) throws Exception {
      try (TraceTimer timer = TraceContext.newTimer("Loading project list")) {
        return ImmutableSortedSet.copyOf(mgr.list());
      }
    }
  }

  @VisibleForTesting
  public void evictAllByName() {
    inMemoryProjectCache.invalidateAll();
  }

  @VisibleForTesting
  public long sizeAllByName() {
    return inMemoryProjectCache.size();
  }
}
