// Copyright (C) 2017 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.googlesource.gerrit.plugins.events.fsstore;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * An infrastructure to create updates to a FileValue using a 6 phase transaction which is multi
 * node/process (Multi-Master) safe. The 6 phases of the transaction are:
 *
 * <p>1) Intiate a unique ownerless transaction, locking and preventing the value from changing
 * while the transaction is still open.
 *
 * <p>2) Read the current locked file value
 *
 * <p>3) Create a proposed update file containing the new proposed value based on the value read in
 * phase 2.
 *
 * <p>4) Close the transaction with the new proposed value, locking in the new value in the
 * transaction.
 *
 * <p>5) Atomically commit the new value to the locked file from the transaction.
 *
 * <p>6) Clean up the transaction
 *
 * <p>Any actor may perform any/all of the above phases.
 */
public abstract class UpdatableFileValue<T> extends FileValue<T> {
  public static final Path CLOSED = Paths.get("closed");
  public static final Path INIT = Paths.get("init");
  public static final Path PRESERVED = Paths.get("preserved");
  public static final Path UPDATE = Paths.get("update");
  public static final Path VALUE = Paths.get("value");

  public static class BasePaths extends FsTransaction.BasePaths {
    public final Path update;
    public final Path preserved;

    public BasePaths(Path base) {
      super(base);
      update = base.resolve(UPDATE);
      preserved = base.resolve(PRESERVED);
    }
  }

  /** For Phase 1 */
  protected static class UpdateBuilder extends FsTransaction.Builder {
    String uuid = UUID.randomUUID().toString();
    Path udir = dir.resolve(uuid);

    public UpdateBuilder(BasePaths paths) throws IOException {
      super(paths);
      Files.createDirectories(udir); // build/<tmp>/<uuid>/
    }
  }

  /** For Phase 3 */
  protected static class NextBuilder extends FsTransaction.Builder {
    public NextBuilder(BasePaths paths, String next) throws IOException {
      super(paths);
      Path closed = dir.resolve(CLOSED);
      Files.createDirectory(closed);
      FileValue.prepare(closed.resolve(VALUE), next); // build/<tmp>/closed/value(next)
    }
  }

  /** Used to create the first value in the FS. Can handle contention, and existing values. */
  protected static class InitBuilder extends FsTransaction.Builder {
    public InitBuilder(BasePaths paths, String init) throws IOException {
      super(paths);
      FileValue.prepare(dir.resolve(INIT), init); // build/<tmp>/init(init)
    }
  }

  protected static class UpdatePaths {
    public final Path udir;
    public final Path closed;
    public final Path value;

    UpdatePaths(Path base, String uuid) {
      udir = base.resolve(uuid);
      closed = udir.resolve(CLOSED);
      value = closed.resolve(VALUE);
    }
  }

  /** Phase 2 -6 helper. */
  protected static class UniqueUpdate<T> {
    final UpdatableFileValue<T> updatable;
    final String uuid;
    final UpdatePaths upaths;
    final boolean ours;
    final T currentValue;
    final T next;

    long maxTries;

    long tries;
    boolean closed;
    boolean preserved;
    boolean committed;
    boolean finished;

    boolean myCommit;

    /** Advance through phase 2 */
    UniqueUpdate(UpdatableFileValue<T> updatable, String uuid, boolean ours, long maxTries)
        throws IOException {
      this.updatable = updatable;
      this.uuid = uuid;
      this.ours = ours;
      this.maxTries = maxTries;

      upaths = new UpdatePaths(updatable.paths.update, uuid);

      currentValue = spinGet();
      next = currentValue == null ? null : updatable.getToValue(currentValue);
    }

    /** Spin attempting phases 3 - 6 */
    protected void spinFinish() throws IOException {
      for (; tries < maxTries && !finished; tries++) {
        finish();
      }
    }

    /** Attempt advance through phases 3 - 6 */
    protected void finish() throws IOException {
      createAndProposeNext();
      commit();
      clean();
    }

    /** Contains phase 2 */
    protected T spinGet() throws IOException {
      IOException ioe = new IOException("No chance to read " + updatable.path);
      for (; tries < maxTries; tries++) {
        try {
          return updatable.get(); // Phase 2
        } catch (IOException e) {
          Nfs.throwIfNotStaleFileHandle(e);
          finished = !Files.exists(upaths.udir);
          if (finished) {
            // stale handle must have been caused by another actor completing instead
            return null;
          }
          ioe = e;
        }
      }
      throw ioe;
    }

    /** Contains phases 3 & 4 */
    protected void createAndProposeNext() throws IOException {
      if (!closed && !ours) {
        // In the default fast path (!closed && ours), we would not expect
        // it to be closed, so skip this check to get to the building faster.
        // Conversely, if not ours, a quick check here might allow us
        // to skip the slow building phase
        closed = Files.exists(upaths.closed);
      }
      if (!closed) {
        try (NextBuilder b =
            new NextBuilder(updatable.paths, updatable.serializer.fromGeneric(next))) { // Phase 3
          // Phase 4
          Fs.tryAtomicMove(b.dir, upaths.udir); // rename build/<tmp>/ -> update/<uuid>/
          // now there should be: update/<uuid>/closed/value(next)
        }

        // Do not use the result of the move to determine if it is closed.
        // The move result could provide false positives due to some filesystem
        // implementions allowing a second move to succeed after the transaction
        // has been finished and the first "closed" has been deleted under the
        // "delete" dir). Additionally, this check allows us to be able to detect
        // closes by other actors, not just ourselves.
        closed = Files.exists(upaths.closed);
      }
    }

    /** Contains phase 5 */
    protected void commit() throws IOException {
      if (!committed) {
        // Safe to perform this block (for performance reasons) even if we
        // have not detected "closed yet", since it can only actually succeed
        // when closed (operations depend on "closed" in paths).
        perserve();

        // rename update/<uuid>/closed/value(next) -> value
        committed = myCommit = Fs.tryAtomicMove(upaths.value, updatable.path); // Phase 5
        // now there should be: update/<uuid>/closed/ and: value (file)
      }
      if (!committed && closed) {
        committed = !Files.exists(upaths.value);
      }
    }

    /** Contains phase 6 */
    protected void clean() throws IOException {
      if (committed) {
        FsTransaction.renameAndDeleteUnique(upaths.udir, updatable.paths.delete); // Phase 6
        updatable.cleanPreserved();
      }
      finished = !Files.exists(upaths.udir);
    }

    /*
     * Creating an extra hard link to future "value" files keeps a filesystem reference to them
     * after the "value" file is replaced with a new "value" file. Keeping the reference around
     * allows readers on other nodes to still read the contents of the file without experiencing a
     * stale file handle exception over NFS. This can reduce the amount of spinning required for
     * readers.
     */
    protected void perserve() {
      if (!preserved) {
        preserved = Fs.tryCreateLink(updatable.paths.preserved.resolve(uuid), upaths.value);
      }
    }
  }

  protected final BasePaths paths;

  public UpdatableFileValue(Path base) {
    super(base.resolve(VALUE)); // value(val)
    this.paths = new BasePaths(base);
  }

  public void initFs(T init) throws IOException {
    super.init(init);
    Files.createDirectories(paths.preserved);
    while (!Files.exists(path)) {
      try (InitBuilder b = new InitBuilder(paths, serializer.fromGeneric(init))) {
        Fs.tryAtomicMove(b.dir, paths.update); // rename build/<tmp>/ -> update/
        // now there should be: update/init(init_value)
        if (!Files.exists(path)) {
          // using a non unique name, "init", to allow recovery below
          Fs.tryAtomicMove(paths.update.resolve(INIT), path); // rename update/init(init) -> value
          // now there should be: update/ and: value (file)
        }
      }
    }
    Fs.tryDelete(paths.update.resolve(INIT)); // cleanup
  }

  protected abstract T getToValue(T currentValue);

  protected UniqueUpdate<T> completeOngoing(long maxTries) throws IOException {
    if (shouldCompleteOngoing()) {
      Path ongoing = Nfs.getFirstDirEntry(paths.update);
      if (ongoing != null) {
        // Attempt to complete previous updates;
        return createUniqueUpdate(Fs.basename(ongoing).toString(), false, maxTries);
      }
    }
    return null;
  }

  protected boolean shouldCompleteOngoing() {
    // Collisions are expected, and we don't actually want to
    // complete them too often since it affects fairness
    // by potentially preventing slower actors from ever
    // committing.  We do however need to prevent deadlock from
    // a stale proposal, so we do need to complete proposals
    // that stay around too long.

    // Maximum delay incurred due to a server crash.
    FileTime expiry = Fs.getFileTimeAgo(10, TimeUnit.SECONDS);
    return Fs.isAllEntriesOlderThan(paths.update, expiry);
  }

  protected abstract UniqueUpdate<T> createUniqueUpdate(String uuid, boolean ours, long maxTries)
      throws IOException;

  protected void cleanPreserved() {
    // 1 second seems to be long enough even for slow readers (over a WAN) under high contention
    // ("value" file being updated by a fast writer), to avoid spinning on reads most of the time.
    FileTime expiry = Fs.getFileTimeAgo(1, TimeUnit.SECONDS);
    Fs.tryRecursiveDeleteEntriesOlderThan(paths.preserved, expiry, 5);
  }
}
