// 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.group;

import static com.google.common.collect.ImmutableSet.toImmutableSet;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.ScheduleConfig;
import com.google.gerrit.server.config.ScheduleConfig.Schedule;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.group.db.GroupNameNotes;
import com.google.gerrit.server.index.group.GroupIndexer;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;

/**
 * Runnable to schedule periodic group reindexing.
 *
 * <p>Periodic group indexing is intended to run only on slaves. Replication to slaves happens on
 * Git level so that Gerrit is not aware of incoming replication events. But slaves need an updated
 * group index to resolve memberships of users for ACL validation. To keep the group index in slaves
 * up-to-date this class periodically scans the group refs in the All-Users repository to reindex
 * groups if they are stale. The ref states of the group refs are cached so that on each run deleted
 * groups can be detected and reindexed. This means callers of slaves may observe outdated group
 * information until the next indexing happens. The interval on which group indexing is done is
 * configurable by setting {@code index.scheduledIndexer.interval} in {@code gerrit.config}. By
 * default group indexing is done every 5 minutes.
 *
 * <p>This class is not able to detect group deletions that were replicated while the slave was
 * offline. This means if group refs are deleted while the slave is offline these groups are not
 * removed from the group index when the slave is started. However since group deletion is not
 * supported this should never happen and one can always do an offline reindex before starting the
 * slave.
 */
public class PeriodicGroupIndexer implements Runnable {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static class Module extends LifecycleModule {
    @Override
    protected void configure() {
      listener().to(Lifecycle.class);
    }
  }

  private static class Lifecycle implements LifecycleListener {
    private final Config cfg;
    private final WorkQueue queue;
    private final PeriodicGroupIndexer runner;

    @Inject
    Lifecycle(@GerritServerConfig Config cfg, WorkQueue queue, PeriodicGroupIndexer runner) {
      this.cfg = cfg;
      this.queue = queue;
      this.runner = runner;
    }

    @Override
    public void start() {
      boolean runOnStartup = cfg.getBoolean("index", "scheduledIndexer", "runOnStartup", true);
      if (runOnStartup) {
        runner.run();
      }

      boolean isEnabled = cfg.getBoolean("index", "scheduledIndexer", "enabled", true);
      if (!isEnabled) {
        logger.atWarning().log("index.scheduledIndexer is disabled");
        return;
      }

      Schedule schedule =
          ScheduleConfig.builder(cfg, "index")
              .setSubsection("scheduledIndexer")
              .buildSchedule()
              .orElseGet(() -> Schedule.createOrFail(TimeUnit.MINUTES.toMillis(5), "00:00"));
      queue.scheduleAtFixedRate(runner, schedule);
    }

    @Override
    public void stop() {
      // handled by WorkQueue.stop() already
    }
  }

  private final AllUsersName allUsersName;
  private final GitRepositoryManager repoManager;
  private final Provider<GroupIndexer> groupIndexerProvider;

  private ImmutableSet<AccountGroup.UUID> groupUuids;

  @Inject
  PeriodicGroupIndexer(
      AllUsersName allUsersName,
      GitRepositoryManager repoManager,
      Provider<GroupIndexer> groupIndexerProvider) {
    this.allUsersName = allUsersName;
    this.repoManager = repoManager;
    this.groupIndexerProvider = groupIndexerProvider;
  }

  @Override
  public synchronized void run() {
    try (Repository allUsers = repoManager.openRepository(allUsersName)) {
      ImmutableSet<AccountGroup.UUID> newGroupUuids =
          GroupNameNotes.loadAllGroups(allUsers).stream()
              .map(GroupReference::getUUID)
              .collect(toImmutableSet());
      GroupIndexer groupIndexer = groupIndexerProvider.get();
      int reindexCounter = 0;
      for (AccountGroup.UUID groupUuid : newGroupUuids) {
        if (groupIndexer.reindexIfStale(groupUuid)) {
          reindexCounter++;
        }
      }
      if (groupUuids != null) {
        // Check if any group was deleted since the last run and if yes remove these groups from the
        // index.
        for (AccountGroup.UUID groupUuid : Sets.difference(groupUuids, newGroupUuids)) {
          groupIndexer.index(groupUuid);
          reindexCounter++;
        }
      }
      groupUuids = newGroupUuids;
      logger.atInfo().log("Run group indexer, %s groups reindexed", reindexCounter);
    } catch (Throwable t) {
      logger.atSevere().withCause(t).log("Failed to reindex groups");
    }
  }
}
