// Copyright (C) 2016 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.notedb;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher;
import com.google.common.base.Predicates;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.primitives.Ints;
import com.google.common.util.concurrent.Runnables;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gwtorm.server.OrmException;

import com.github.rholder.retry.RetryException;
import com.github.rholder.retry.Retryer;
import com.github.rholder.retry.RetryerBuilder;
import com.github.rholder.retry.StopStrategies;
import com.github.rholder.retry.WaitStrategies;

import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Class for managing an incrementing sequence backed by a git repository.
 * <p>
 * The current sequence number is stored as UTF-8 text in a blob pointed to
 * by a ref in the {@code refs/sequences/*} namespace. Multiple processes can
 * share the same sequence by incrementing the counter using normal git ref
 * updates. To amortize the cost of these ref updates, processes can increment
 * the counter by a larger number and hand out numbers from that range in memory
 * until they run out. This means concurrent processes will hand out somewhat
 * non-monotonic numbers.
 */
public class RepoSequence {
  public interface Seed {
    int get() throws OrmException;
  }

  @VisibleForTesting
  static RetryerBuilder<RefUpdate.Result> retryerBuilder() {
    return RetryerBuilder.<RefUpdate.Result> newBuilder()
        .retryIfResult(Predicates.equalTo(RefUpdate.Result.LOCK_FAILURE))
        .withWaitStrategy(
            WaitStrategies.join(
              WaitStrategies.exponentialWait(5, TimeUnit.SECONDS),
              WaitStrategies.randomWait(50, TimeUnit.MILLISECONDS)))
        .withStopStrategy(StopStrategies.stopAfterDelay(30, TimeUnit.SECONDS));
  }

  private static Retryer<RefUpdate.Result> RETRYER = retryerBuilder().build();

  private final GitRepositoryManager repoManager;
  private final Project.NameKey projectName;
  private final String refName;
  private final Seed seed;
  private final int batchSize;
  private final Runnable afterReadRef;
  private final Retryer<RefUpdate.Result> retryer;

  // Protects all non-final fields.
  private final Lock counterLock;

  private int limit;
  private int counter;

  @VisibleForTesting
  int acquireCount;

  public RepoSequence(
      GitRepositoryManager repoManager,
      Project.NameKey projectName,
      String name,
      Seed seed,
      int batchSize) {
    this(repoManager, projectName, name, seed, batchSize, Runnables.doNothing(),
        RETRYER);
  }

  @VisibleForTesting
  RepoSequence(
      GitRepositoryManager repoManager,
      Project.NameKey projectName,
      String name,
      Seed seed,
      int batchSize,
      Runnable afterReadRef,
      Retryer<RefUpdate.Result> retryer) {
    this.repoManager = checkNotNull(repoManager, "repoManager");
    this.projectName = checkNotNull(projectName, "projectName");
    this.refName = RefNames.REFS_SEQUENCES + checkNotNull(name, "name");
    this.seed = checkNotNull(seed, "seed");

    checkArgument(batchSize > 0, "expected batchSize > 0, got: %s", batchSize);
    this.batchSize = batchSize;
    this.afterReadRef = checkNotNull(afterReadRef, "afterReadRef");
    this.retryer = checkNotNull(retryer, "retryer");

    counterLock = new ReentrantLock(true);
  }

  public int next() throws OrmException {
    counterLock.lock();
    try {
      if (counter >= limit) {
        acquire(batchSize);
      }
      return counter++;
    } finally {
      counterLock.unlock();
    }
  }

  public ImmutableList<Integer> next(int count) throws OrmException {
    if (count == 0) {
      return ImmutableList.of();
    }
    checkArgument(count > 0, "count is negative: %s", count);
    counterLock.lock();
    try {
      List<Integer> ids = new ArrayList<>(count);
      while (counter < limit) {
        ids.add(counter++);
        if (ids.size() == count) {
          return ImmutableList.copyOf(ids);
        }
      }
      acquire(Math.max(count - ids.size(), batchSize));
      while (ids.size() < count) {
        ids.add(counter++);
      }
      return ImmutableList.copyOf(ids);
    } finally {
      counterLock.unlock();
    }
  }

  @VisibleForTesting
  public void set(int val) throws OrmException {
    // Don't bother spinning. This is only for tests, and a test that calls set
    // concurrently with other writes is doing it wrong.
    counterLock.lock();
    try {
      try (Repository repo = repoManager.openRepository(projectName);
          RevWalk rw = new RevWalk(repo)) {
        checkResult(store(repo, rw, null, val));
        counter = limit;
      } catch (IOException e) {
        throw new OrmException(e);
      }
    } finally {
      counterLock.unlock();
    }
  }

  private void acquire(int count) throws OrmException {
    try (Repository repo = repoManager.openRepository(projectName);
        RevWalk rw = new RevWalk(repo)) {
      TryAcquire attempt = new TryAcquire(repo, rw, count);
      checkResult(retryer.call(attempt));
      counter = attempt.next;
      limit = counter + count;
      acquireCount++;
    } catch (ExecutionException | RetryException e) {
      Throwables.throwIfInstanceOf(e.getCause(), OrmException.class);
      throw new OrmException(e);
    } catch (IOException e) {
      throw new OrmException(e);
    }
  }

  private void checkResult(RefUpdate.Result result) throws OrmException {
    if (result != RefUpdate.Result.NEW && result != RefUpdate.Result.FORCED) {
      throw new OrmException("failed to update " + refName + ": " + result);
    }
  }

  private class TryAcquire implements Callable<RefUpdate.Result> {
    private final Repository repo;
    private final RevWalk rw;
    private final int count;

    private int next;

    private TryAcquire(Repository repo, RevWalk rw, int count) {
      this.repo = repo;
      this.rw = rw;
      this.count = count;
    }

    @Override
    public RefUpdate.Result call() throws Exception {
      Ref ref = repo.exactRef(refName);
      afterReadRef.run();
      ObjectId oldId;
      if (ref == null) {
        oldId = ObjectId.zeroId();
        next = seed.get();
      } else {
        oldId = ref.getObjectId();
        next = parse(oldId);
      }
      return store(repo, rw, oldId, next + count);
    }

    private int parse(ObjectId id) throws IOException, OrmException {
      ObjectLoader ol = rw.getObjectReader().open(id, OBJ_BLOB);
      if (ol.getType() != OBJ_BLOB) {
        // In theory this should be thrown by open but not all implementations
        // may do it properly (certainly InMemoryRepository doesn't).
        throw new IncorrectObjectTypeException(id, OBJ_BLOB);
      }
      String str = CharMatcher.whitespace().trimFrom(
          new String(ol.getCachedBytes(), UTF_8));
      Integer val = Ints.tryParse(str);
      if (val == null) {
        throw new OrmException(
            "invalid value in " + refName + " blob at " + id.name());
      }
      return val;
    }
  }

  private RefUpdate.Result store(Repository repo, RevWalk rw,
      @Nullable ObjectId oldId, int val) throws IOException {
    ObjectId newId;
    try (ObjectInserter ins = repo.newObjectInserter()) {
      newId = ins.insert(OBJ_BLOB, Integer.toString(val).getBytes(UTF_8));
      ins.flush();
    }
    RefUpdate ru = repo.updateRef(refName);
    if (oldId != null) {
      ru.setExpectedOldObjectId(oldId);
    }
    ru.setNewObjectId(newId);
    ru.setForceUpdate(true); // Required for non-commitish updates.
    return ru.update(rw);
  }
}
