/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to you 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 org.apache.fluo.core.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Supplier;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
import org.apache.accumulo.core.client.ConditionalWriter;
import org.apache.accumulo.core.client.ConditionalWriter.Result;
import org.apache.accumulo.core.client.ConditionalWriter.Status;
import org.apache.accumulo.core.client.IteratorSetting;
import org.apache.accumulo.core.client.Scanner;
import org.apache.accumulo.core.client.TableNotFoundException;
import org.apache.accumulo.core.data.ColumnUpdate;
import org.apache.accumulo.core.data.Condition;
import org.apache.accumulo.core.data.ConditionalMutation;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.Mutation;
import org.apache.accumulo.core.data.Range;
import org.apache.accumulo.core.data.Value;
import org.apache.fluo.accumulo.iterators.PrewriteIterator;
import org.apache.fluo.accumulo.util.ColumnConstants;
import org.apache.fluo.accumulo.util.ColumnType;
import org.apache.fluo.accumulo.util.ReadLockUtil;
import org.apache.fluo.accumulo.values.DelLockValue;
import org.apache.fluo.accumulo.values.DelReadLockValue;
import org.apache.fluo.accumulo.values.LockValue;
import org.apache.fluo.accumulo.values.ReadLockValue;
import org.apache.fluo.api.client.AbstractTransactionBase;
import org.apache.fluo.api.client.Snapshot;
import org.apache.fluo.api.client.SnapshotBase;
import org.apache.fluo.api.client.scanner.ScannerBuilder;
import org.apache.fluo.api.data.Bytes;
import org.apache.fluo.api.data.Column;
import org.apache.fluo.api.data.RowColumn;
import org.apache.fluo.api.data.Span;
import org.apache.fluo.api.exceptions.AlreadySetException;
import org.apache.fluo.api.exceptions.CommitException;
import org.apache.fluo.api.exceptions.FluoException;
import org.apache.fluo.core.async.AsyncCommitObserver;
import org.apache.fluo.core.async.AsyncConditionalWriter;
import org.apache.fluo.core.async.AsyncTransaction;
import org.apache.fluo.core.async.SyncCommitObserver;
import org.apache.fluo.core.exceptions.AlreadyAcknowledgedException;
import org.apache.fluo.core.exceptions.StaleScanException;
import org.apache.fluo.core.impl.scanner.ScannerBuilderImpl;
import org.apache.fluo.core.oracle.Stamp;
import org.apache.fluo.core.util.ByteUtil;
import org.apache.fluo.core.util.ColumnUtil;
import org.apache.fluo.core.util.ConditionalFlutation;
import org.apache.fluo.core.util.FluoCondition;
import org.apache.fluo.core.util.Flutation;
import org.apache.fluo.core.util.Hex;
import org.apache.fluo.core.util.SpanUtil;
import org.apache.fluo.core.util.UtilWaitThread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.fluo.api.observer.Observer.NotificationType.STRONG;
import static org.apache.fluo.api.observer.Observer.NotificationType.WEAK;

/**
 * Transaction implementation
 */
public class TransactionImpl extends AbstractTransactionBase implements AsyncTransaction, Snapshot {

  public static final byte[] EMPTY = new byte[0];
  public static final Bytes EMPTY_BS = Bytes.of(EMPTY);
  private static final Bytes DELETE =
      Bytes.of("special delete object f804266bf94935edd45ae3e6c287b93c1814295c");
  private static final Bytes NTFY_VAL =
      Bytes.of("special ntfy value ce0c523e6e4dc093be8a2736b82eca1b95f97ed4");
  private static final Bytes RLOCK_VAL =
      Bytes.of("special rlock value 94da84e7796ff3b23b779805d820a33f1997cb8b");

  // added to avoid findbugs false positive
  private static final Supplier<Void> NULLS = () -> null;

  private static boolean isWrite(Bytes val) {
    return val != NTFY_VAL && val != RLOCK_VAL;
  }

  private static boolean isDelete(Bytes val) {
    return val == DELETE;
  }

  private static boolean isReadLock(Bytes val) {
    return val == RLOCK_VAL;
  }

  private enum TxStatus {
    OPEN, COMMIT_STARTED, COMMITTED, CLOSED
  }

  private final long startTs;
  private final Map<Bytes, Map<Column, Bytes>> updates = new HashMap<>();
  private final Map<Bytes, Set<Column>> weakNotifications = new HashMap<>();
  private final Set<Column> observedColumns;
  private final Environment env;
  private final Map<Bytes, Set<Column>> columnsRead = new HashMap<>();
  // Tracks row columns that were observed to have had a read lock in the past.
  private final Map<Bytes, Set<Column>> readLocksSeen = new HashMap<>();
  private final TxStats stats;
  private Notification notification;
  private Notification weakNotification;
  private TransactorNode tnode = null;
  private TxStatus status = TxStatus.OPEN;
  private boolean commitAttempted = false;

  public TransactionImpl(Environment env, Notification trigger, long startTs) {
    Objects.requireNonNull(env, "environment cannot be null");
    Preconditions.checkArgument(startTs >= 0, "startTs cannot be negative");
    this.env = env;
    this.stats = new TxStats(env);
    this.startTs = startTs;
    this.observedColumns = env.getConfiguredObservers().getObservedColumns(STRONG);

    if (trigger != null
        && env.getConfiguredObservers().getObservedColumns(WEAK).contains(trigger.getColumn())) {
      this.weakNotification = trigger;
    } else {
      this.notification = trigger;
    }

    if (notification != null) {
      Map<Column, Bytes> colUpdates = new HashMap<>();
      colUpdates.put(notification.getColumn(), NTFY_VAL);
      updates.put(notification.getRow(), colUpdates);
    }
  }

  public TransactionImpl(Environment env, Notification trigger) {
    this(env, trigger, allocateTimestamp(env).getTxTimestamp());
  }

  public TransactionImpl(Environment env) {
    this(env, null, allocateTimestamp(env).getTxTimestamp());
  }

  public TransactionImpl(Environment env, long startTs) {
    this(env, null, startTs);
  }

  private static Stamp allocateTimestamp(Environment env) {
    return env.getSharedResources().getTimestampTracker().allocateTimestamp();
  }

  @Override
  public Bytes get(Bytes row, Column column) {
    checkIfOpen();
    // TODO cache? precache?
    return get(row, Collections.singleton(column)).get(column);
  }

  @Override
  public Map<Column, Bytes> get(Bytes row, Set<Column> columns) {
    checkIfOpen();
    return getImpl(row, columns, kve -> {
    });
  }

  @Override
  public Map<Bytes, Map<Column, Bytes>> get(Collection<Bytes> rows, Set<Column> columns) {
    checkIfOpen();

    if (rows.isEmpty() || columns.isEmpty()) {
      return Collections.emptyMap();
    }

    env.getSharedResources().getVisCache().validate(columns);

    ParallelSnapshotScanner pss =
        new ParallelSnapshotScanner(rows, columns, env, startTs, stats, readLocksSeen);

    Map<Bytes, Map<Column, Bytes>> ret = pss.scan();

    for (Entry<Bytes, Map<Column, Bytes>> entry : ret.entrySet()) {
      updateColumnsRead(entry.getKey(), entry.getValue().keySet());
    }

    return ret;
  }

  @Override
  public Map<RowColumn, Bytes> get(Collection<RowColumn> rowColumns) {
    checkIfOpen();

    if (rowColumns.isEmpty()) {
      return Collections.emptyMap();
    }

    ParallelSnapshotScanner pss =
        new ParallelSnapshotScanner(rowColumns, env, startTs, stats, readLocksSeen);

    Map<Bytes, Map<Column, Bytes>> scan = pss.scan();
    Map<RowColumn, Bytes> ret = new HashMap<>();

    for (Entry<Bytes, Map<Column, Bytes>> entry : scan.entrySet()) {
      updateColumnsRead(entry.getKey(), entry.getValue().keySet());
      for (Entry<Column, Bytes> colVal : entry.getValue().entrySet()) {
        ret.put(new RowColumn(entry.getKey(), colVal.getKey()), colVal.getValue());
      }
    }

    return ret;
  }

  private Map<Column, Bytes> getImpl(Bytes row, Set<Column> columns,
      Consumer<Entry<Key, Value>> locksSeen) {

    // TODO push visibility filtering to server side?

    env.getSharedResources().getVisCache().validate(columns);

    boolean shouldCopy = false;

    for (Column column : columns) {
      if (column.isVisibilitySet()) {
        shouldCopy = true;
      }
    }

    SnapshotScanner.Opts opts;
    if (shouldCopy) {
      HashSet<Column> cols = new HashSet<>();
      for (Column column : columns) {
        if (column.isVisibilitySet()) {
          cols.add(new Column(column.getFamily(), column.getQualifier()));
        } else {
          cols.add(column);
        }
      }
      opts = new SnapshotScanner.Opts(Span.exact(row), columns, true);
    } else {
      opts = new SnapshotScanner.Opts(Span.exact(row), columns, true);
    }

    Map<Column, Bytes> ret = new HashMap<>();
    Set<Column> readLockCols = null;

    for (Entry<Key, Value> kve : new SnapshotScanner(env, opts, startTs, stats, locksSeen)) {

      Column col = ColumnUtil.convert(kve.getKey());
      if (shouldCopy && !columns.contains(col)) {
        continue;
      }

      if (ColumnType.from(kve.getKey()) == ColumnType.RLOCK) {
        if (readLockCols == null) {
          readLockCols = readLocksSeen.computeIfAbsent(row, k -> new HashSet<>());
        }
        readLockCols.add(col);
      } else {
        ret.put(col, Bytes.of(kve.getValue().get()));
      }
    }

    // only update columns read after successful read
    updateColumnsRead(row, columns);

    return ret;
  }

  @Override
  public ScannerBuilder scanner() {
    checkIfOpen();
    return new ScannerBuilderImpl(this);
  }

  private void updateColumnsRead(Bytes row, Set<Column> columns) {
    Set<Column> colsRead = columnsRead.get(row);
    if (colsRead == null) {
      colsRead = new HashSet<>();
      columnsRead.put(row, colsRead);
    }
    colsRead.addAll(columns);
  }

  void setReadLock(Bytes row, Column col) {
    checkIfOpen();
    Objects.requireNonNull(row);
    Objects.requireNonNull(col);

    if (col.getFamily().equals(ColumnConstants.NOTIFY_CF)) {
      throw new IllegalArgumentException(ColumnConstants.NOTIFY_CF + " is a reserved family");
    }

    env.getSharedResources().getVisCache().validate(col);

    Map<Column, Bytes> colUpdates = updates.computeIfAbsent(row, k -> new HashMap<>());
    Bytes curVal = colUpdates.get(col);
    if (curVal != null && (isWrite(curVal) || isDelete(curVal))) {
      throw new AlreadySetException("Attemped read lock after write lock " + row + " " + col);
    }

    colUpdates.put(col, RLOCK_VAL);
  }

  @Override
  public SnapshotBase withReadLock() {
    return new ReadLockSnapshot(this);
  }

  @Override
  public void set(Bytes row, Column col, Bytes value) throws AlreadySetException {
    checkIfOpen();
    Objects.requireNonNull(row);
    Objects.requireNonNull(col);
    Objects.requireNonNull(value);

    if (col.getFamily().equals(ColumnConstants.NOTIFY_CF)) {
      throw new IllegalArgumentException(ColumnConstants.NOTIFY_CF + " is a reserved family");
    }

    env.getSharedResources().getVisCache().validate(col);

    Map<Column, Bytes> colUpdates = updates.computeIfAbsent(row, k -> new HashMap<>());

    Bytes curVal = colUpdates.get(col);
    if (curVal != null && isWrite(curVal)) {
      throw new AlreadySetException("Value already set " + row + " " + col);
    }
    colUpdates.put(col, value);
  }

  @Override
  public void setWeakNotification(Bytes row, Column col) {
    checkIfOpen();
    Objects.requireNonNull(row);
    Objects.requireNonNull(col);

    if (!env.getConfiguredObservers().getObservedColumns(WEAK).contains(col)) {
      throw new IllegalArgumentException("Column not configured for weak notifications " + col);
    }

    env.getSharedResources().getVisCache().validate(col);

    Set<Column> columns = weakNotifications.get(row);
    if (columns == null) {
      columns = new HashSet<>();
      weakNotifications.put(row, columns);
    }

    columns.add(col);
  }

  @Override
  public void delete(Bytes row, Column col) throws AlreadySetException {
    checkIfOpen();
    Objects.requireNonNull(row);
    Objects.requireNonNull(col);
    set(row, col, DELETE);
  }

  private ConditionalFlutation prewrite(ConditionalFlutation cm, Bytes row, Column col, Bytes val,
      Bytes primaryRow, Column primaryColumn, boolean isTriggerRow) {
    IteratorSetting iterConf = new IteratorSetting(10, PrewriteIterator.class);
    PrewriteIterator.setSnaptime(iterConf, startTs);
    boolean isTrigger = isTriggerRow && col.equals(notification.getColumn());
    if (isTrigger) {
      PrewriteIterator.enableAckCheck(iterConf, notification.getTimestamp());
    }

    if (isReadLock(val)) {
      PrewriteIterator.setReadlock(iterConf);
    }

    Condition cond = new FluoCondition(env, col).setIterators(iterConf);

    if (cm == null) {
      cm = new ConditionalFlutation(env, row, cond);
    } else {
      cm.addCondition(cond);
    }

    if (isWrite(val) && !isDelete(val)) {
      cm.put(col, ColumnType.DATA.encode(startTs), val.toArray());
    }

    if (isReadLock(val)) {
      cm.put(col, ColumnType.RLOCK.encode(ReadLockUtil.encodeTs(startTs, false)),
          ReadLockValue.encode(primaryRow, primaryColumn, getTransactorID()));
    } else {
      cm.put(col, ColumnType.LOCK.encode(startTs), LockValue.encode(primaryRow, primaryColumn,
          isWrite(val), isDelete(val), isTriggerRow, getTransactorID()));
    }

    return cm;
  }

  private ConditionalFlutation prewrite(Bytes row, Column col, Bytes val, Bytes primaryRow,
      Column primaryColumn, boolean isTriggerRow) {
    return prewrite(null, row, col, val, primaryRow, primaryColumn, isTriggerRow);
  }

  private void prewrite(ConditionalFlutation cm, Column col, Bytes val, Bytes primaryRow,
      Column primaryColumn, boolean isTriggerRow) {
    prewrite(cm, null, col, val, primaryRow, primaryColumn, isTriggerRow);
  }

  public static class CommitData {
    ConditionalWriter cw;
    private Bytes prow;
    private Column pcol;
    private Bytes pval;

    private HashSet<Bytes> acceptedRows;
    private Map<Bytes, Set<Column>> rejected = null;

    private void addPrimaryToRejected() {
      rejected = Collections.singletonMap(prow, Collections.singleton(pcol));
    }

    private void addToRejected(Bytes row, Set<Column> columns) {
      if (rejected == null) {
        rejected = new HashMap<>();
      }

      Set<Column> ret = rejected.put(row, columns);
      if (ret != null) {
        throw new IllegalStateException();
      }
    }

    private Map<Bytes, Set<Column>> getRejected() {
      if (rejected == null) {
        return Collections.emptyMap();
      }

      return rejected;
    }

    @Override
    public String toString() {
      return prow + " " + pcol + " " + pval + " " + getRejected().size();
    }

    public String getShortCollisionMessage() {
      StringBuilder sb = new StringBuilder();
      if (!getRejected().isEmpty()) {
        int numCollisions = 0;
        for (Set<Column> cols : getRejected().values()) {
          numCollisions += cols.size();
        }

        sb.append("Collisions(");
        sb.append(numCollisions);
        sb.append("):");

        String sep = "";
        outer: for (Entry<Bytes, Set<Column>> entry : getRejected().entrySet()) {
          Bytes row = entry.getKey();
          for (Column col : entry.getValue()) {
            sb.append(sep);
            sep = ", ";
            Hex.encNonAscii(sb, row);
            sb.append(" ");
            Hex.encNonAscii(sb, col, " ");
            if (sb.length() > 100) {
              sb.append(" ...");
              break outer;
            }
          }
        }
      }

      return sb.toString();
    }

    // async stuff
    private AsyncConditionalWriter acw;
    private AsyncConditionalWriter bacw;
    private AsyncCommitObserver commitObserver;

  }

  private boolean isTriggerRow(Bytes row) {
    return notification != null && notification.getRow().equals(row);
  }

  public boolean preCommit(CommitData cd) {
    return preCommit(cd, null);
  }

  @VisibleForTesting
  public boolean preCommit(CommitData cd, RowColumn primary) {

    synchronized (this) {
      checkIfOpen();
      status = TxStatus.COMMIT_STARTED;
      commitAttempted = true;
    }

    SyncCommitObserver sco = new SyncCommitObserver();
    cd = setUpBeginCommitAsync(cd, sco, primary);
    if (cd != null) {
      beginCommitAsyncTest(cd);
    }
    try {
      sco.waitForCommit();
    } catch (AlreadyAcknowledgedException e) {
      throw e;
    } catch (CommitException e) {
      return false;
    }
    return true;
  }

  /**
   * This function helps handle the following case
   *
   * <OL>
   * <LI>TX1 locls r1 col1
   * <LI>TX1 fails before unlocking
   * <LI>TX2 attempts to write r1:col1 w/o reading it
   * </OL>
   *
   * <p>
   * In this case TX2 would not roll back TX1, because it never read the column. This function
   * attempts to handle this case if TX2 fails. Only doing this in case of failures is cheaper than
   * trying to always read unread columns.
   *
   * @param cd Commit data
   */
  private void readUnread(CommitData cd, Consumer<Entry<Key, Value>> locksSeen) {
    // TODO make async
    // TODO need to keep track of ranges read (not ranges passed in, but actual data read... user
    // may not iterate over entire range
    Map<Bytes, Set<Column>> columnsToRead = new HashMap<>();

    for (Entry<Bytes, Set<Column>> entry : cd.getRejected().entrySet()) {
      Set<Column> rowColsRead = columnsRead.get(entry.getKey());
      if (rowColsRead == null) {
        columnsToRead.put(entry.getKey(), entry.getValue());
      } else {
        HashSet<Column> colsToRead = new HashSet<>(entry.getValue());
        colsToRead.removeAll(rowColsRead);
        if (!colsToRead.isEmpty()) {
          columnsToRead.put(entry.getKey(), colsToRead);
        }
      }
    }

    for (Entry<Bytes, Set<Column>> entry : columnsToRead.entrySet()) {
      getImpl(entry.getKey(), entry.getValue(), locksSeen);
    }
  }

  private void checkForOrphanedReadLocks(CommitData cd, Map<Bytes, Set<Column>> locksResolved)
      throws Exception {

    if (readLocksSeen.isEmpty()) {
      return;
    }

    Map<Bytes, Set<Column>> rowColsToCheck = new HashMap<>();

    for (Entry<Bytes, Set<Column>> entry : cd.getRejected().entrySet()) {

      Set<Column> resolvedColumns =
          locksResolved.getOrDefault(entry.getKey(), Collections.emptySet());

      Set<Column> colsToCheck = null;
      Set<Column> readLockCols = readLocksSeen.get(entry.getKey());
      if (readLockCols != null) {
        for (Column candidate : Sets.intersection(readLockCols, entry.getValue())) {
          if (resolvedColumns.contains(candidate)) {
            // A write lock was seen and this is probably what caused the collision, no need to
            // check this column for read locks.
            continue;
          }

          if (!isReadLock(updates.getOrDefault(entry.getKey(), Collections.emptyMap())
              .getOrDefault(candidate, EMPTY_BS))) {
            if (colsToCheck == null) {
              colsToCheck = new HashSet<>();
            }
            colsToCheck.add(candidate);
          }
        }

        if (colsToCheck != null) {
          rowColsToCheck.put(entry.getKey(), colsToCheck);
        }
      }
    }

    if (!rowColsToCheck.isEmpty()) {

      long waitTime = SnapshotScanner.INITIAL_WAIT_TIME;

      boolean resolved = false;

      List<Entry<Key, Value>> openReadLocks = LockResolver.getOpenReadLocks(env, rowColsToCheck);

      long startTime = System.currentTimeMillis();

      while (!resolved) {
        resolved = LockResolver.resolveLocks(env, startTs, stats, openReadLocks, startTime);
        if (!resolved) {
          UtilWaitThread.sleep(waitTime);
          stats.incrementLockWaitTime(waitTime);
          waitTime = Math.min(SnapshotScanner.MAX_WAIT_TIME, waitTime * 2);

          openReadLocks = LockResolver.getOpenReadLocks(env, rowColsToCheck);
        }
      }
    }
  }

  private void checkForOrphanedLocks(CommitData cd) throws Exception {

    Map<Bytes, Set<Column>> locksSeen = new HashMap<>();

    readUnread(cd, kve -> {
      Bytes row = ByteUtil.toBytes(kve.getKey().getRowData());
      Column col = ColumnUtil.convert(kve.getKey());
      locksSeen.computeIfAbsent(row, k -> new HashSet<>()).add(col);
    });

    checkForOrphanedReadLocks(cd, locksSeen);
  }

  private boolean checkForAckCollision(ConditionalMutation cm) {
    Bytes row = Bytes.of(cm.getRow());

    if (isTriggerRow(row)) {
      List<ColumnUpdate> updates = cm.getUpdates();

      for (ColumnUpdate cu : updates) {
        // TODO avoid create col vis object
        Column col = new Column(Bytes.of(cu.getColumnFamily()), Bytes.of(cu.getColumnQualifier()),
            Bytes.of(cu.getColumnVisibility()));

        if (notification.getColumn().equals(col)) {
          // check to see if ACK exist after notification
          Key startKey = SpanUtil.toKey(notification.getRowColumn());
          startKey.setTimestamp(ColumnType.ACK.first());

          Key endKey = SpanUtil.toKey(notification.getRowColumn());
          endKey.setTimestamp(ColumnType.ACK.encode(notification.getTimestamp() + 1));

          Range range = new Range(startKey, endKey);

          try (Scanner scanner =
              env.getAccumuloClient().createScanner(env.getTable(), env.getAuthorizations())) {
            scanner.setRange(range);

            // TODO could use iterator that stops after 1st ACK. thought of using versioning iter
            // but
            // it scans to ACK
            if (scanner.iterator().hasNext()) {
              env.getSharedResources().getBatchWriter()
                  .writeMutationAsync(notification.newDelete(env));
              return true;
            }
          } catch (TableNotFoundException e) {
            // TODO proper exception handling
            throw new RuntimeException(e);
          }
        }
      }
    }

    return false;
  }

  public CommitData createCommitData() {
    CommitData cd = new CommitData();
    cd.cw = env.getSharedResources().getConditionalWriter();
    cd.acw = env.getSharedResources().getAsyncConditionalWriter();
    cd.bacw = env.getSharedResources().getBulkAsyncConditionalWriter();
    return cd;
  }

  @Override
  public synchronized void commit() throws CommitException {
    try {
      SyncCommitObserver sco = new SyncCommitObserver();
      commitAsync(sco);
      sco.waitForCommit();
    } finally {
      updates.clear();
      weakNotification = null;
      columnsRead.clear();
    }
  }

  void deleteWeakRow() {
    if (weakNotification != null) {
      env.getSharedResources().getBatchWriter()
          .writeMutation(weakNotification.newDelete(env, startTs));
    }
  }

  @Override
  public TxStats getStats() {
    return stats;
  }

  public long getStartTs() {
    return startTs;
  }

  /**
   * Sets the transactor of this transaction
   *
   * @param tnode TransactorNode
   * @return this Transaction
   */
  @VisibleForTesting
  public TransactionImpl setTransactor(TransactorNode tnode) {
    this.tnode = tnode;
    return this;
  }

  /**
   * Retrieves transactor ID by first getting/creating transactor (which is only done until
   * necessary)
   */
  private Long getTransactorID() {
    if (tnode == null) {
      tnode = env.getSharedResources().getTransactorNode();
    }
    return tnode.getTransactorID().getLongID();
  }

  private synchronized void close(boolean checkForStaleScan) {
    if (status != TxStatus.CLOSED) {
      status = TxStatus.CLOSED;

      if (checkForStaleScan && !commitAttempted) {
        Stamp stamp = env.getSharedResources().getOracleClient().getStamp();
        if (startTs < stamp.getGcTimestamp()) {
          throw new StaleScanException();
        }
      }

      env.getSharedResources().getTimestampTracker().removeTimestamp(startTs);
    }
  }

  @Override
  public void close() {
    close(true);
  }

  private synchronized void checkIfOpen() {
    if (status != TxStatus.OPEN) {
      throw new IllegalStateException("Transaction is no longer open! status = " + status);
    }
  }

  // CHECKSTYLE:OFF
  @Override
  protected void finalize() {
    // CHECKSTYLE:ON
    // TODO Log an error if transaction is not closed (See FLUO-486)
    close(false);
  }

  @Override
  public long getStartTimestamp() {
    return startTs;
  }

  @Override
  public int getSize() {
    // TODO could calculate as items are added/set
    int size = 0;

    for (Entry<Bytes, Map<Column, Bytes>> entry : updates.entrySet()) {
      size += entry.getKey().length();
      for (Entry<Column, Bytes> entry2 : entry.getValue().entrySet()) {
        Column c = entry2.getKey();
        size += c.getFamily().length();
        size += c.getQualifier().length();
        size += c.getVisibility().length();
        size += entry2.getValue().length();
      }
    }

    for (Entry<Bytes, Set<Column>> entry : columnsRead.entrySet()) {
      size += entry.getKey().length();
      for (Column c : entry.getValue()) {
        size += c.getFamily().length();
        size += c.getQualifier().length();
        size += c.getVisibility().length();
      }
    }

    return size;
  }

  abstract class CommitStep {
    private CommitStep nextStep;

    // the boolean indicates if the operation was successful.
    abstract CompletableFuture<Boolean> getMainOp(CommitData cd);

    // create and run this op in the event that the main op was a failure
    abstract CompletableFuture<Void> getFailureOp(CommitData cd);

    // set the next step to run if this step is successful
    CommitStep andThen(CommitStep next) {
      this.nextStep = next;
      return next;
    }


    CompletableFuture<Void> compose(CommitData cd) {
      return getMainOp(cd).thenComposeAsync(successful -> {
        if (successful) {
          if (nextStep != null) {
            return nextStep.compose(cd);
          } else {
            return CompletableFuture.completedFuture(null);
          }
        } else {
          return getFailureOp(cd);
        }
      }, env.getSharedResources().getAsyncCommitExecutor());
    }

  }

  abstract class ConditionalStep extends CommitStep {

    public abstract Collection<ConditionalMutation> createMutations(CommitData cd);

    public abstract Iterator<Result> handleUnknown(CommitData cd, Iterator<Result> results)
        throws Exception;

    public abstract boolean processResults(CommitData cd, Iterator<Result> results)
        throws Exception;

    public AsyncConditionalWriter getACW(CommitData cd) {
      return cd.acw;
    }

    @Override
    CompletableFuture<Boolean> getMainOp(CommitData cd) {
      // TODO not sure threading is correct
      Executor ace = env.getSharedResources().getAsyncCommitExecutor();
      return getACW(cd).apply(createMutations(cd)).thenCompose(results -> {
        // ugh icky that this is an iterator, forces copy to inspect.. could refactor async CW to
        // return collection
        ArrayList<Result> resultsList = new ArrayList<>();
        Iterators.addAll(resultsList, results);
        boolean containsUknown = false;
        for (Result result : resultsList) {
          try {
            containsUknown |= result.getStatus() == Status.UNKNOWN;
          } catch (Exception e) {
            throw new CompletionException(e);
          }
        }
        if (containsUknown) {
          // process unknown in sync executor
          Executor se = env.getSharedResources().getSyncCommitExecutor();
          return CompletableFuture.supplyAsync(() -> {
            try {
              return handleUnknown(cd, resultsList.iterator());
            } catch (Exception e) {
              throw new CompletionException(e);
            }
          }, se);
        } else {
          return CompletableFuture.completedFuture(resultsList.iterator());
        }
      }).thenApplyAsync(results -> {
        try {
          return processResults(cd, results);
        } catch (Exception e) {
          throw new CompletionException(e);
        }
      }, ace);
    }


  }

  class LockPrimaryStep extends ConditionalStep {

    @Override
    public Collection<ConditionalMutation> createMutations(CommitData cd) {
      return Collections
          .singleton(prewrite(cd.prow, cd.pcol, cd.pval, cd.prow, cd.pcol, isTriggerRow(cd.prow)));
    }

    @Override
    public Iterator<Result> handleUnknown(CommitData cd, Iterator<Result> results)
        throws Exception {

      Result result = Iterators.getOnlyElement(results);
      Status mutationStatus = result.getStatus();
      // TODO convert this code to async
      while (mutationStatus == Status.UNKNOWN) {
        TxInfo txInfo = TxInfo.getTransactionInfo(env, cd.prow, cd.pcol, startTs);

        switch (txInfo.status) {
          case LOCKED:
            return Collections
                .singleton(
                    new Result(Status.ACCEPTED, result.getMutation(), result.getTabletServer()))
                .iterator();
          case ROLLED_BACK:
            return Collections
                .singleton(
                    new Result(Status.REJECTED, result.getMutation(), result.getTabletServer()))
                .iterator();
          case UNKNOWN:
            // TODO async
            Result newResult = cd.cw.write(result.getMutation());
            mutationStatus = newResult.getStatus();
            if (mutationStatus != Status.UNKNOWN) {
              return Collections.singleton(newResult).iterator();
            }
            // TODO handle case were data other tx has lock
            break;
          case COMMITTED:
          default:
            throw new IllegalStateException(
                "unexpected tx state " + txInfo.status + " " + cd.prow + " " + cd.pcol);

        }
      }

      // TODO
      throw new IllegalStateException();
    }

    @Override
    public boolean processResults(CommitData cd, Iterator<Result> results) throws Exception {
      Result result = Iterators.getOnlyElement(results);
      return result.getStatus() == Status.ACCEPTED;
    }

    @Override
    CompletableFuture<Void> getFailureOp(CommitData cd) {
      // TODO can this be simplified by pushing some code to the superclass?
      return CompletableFuture.supplyAsync(() -> {
        final ConditionalMutation pcm = Iterables.getOnlyElement(createMutations(cd));

        cd.addPrimaryToRejected();
        getStats().setRejected(cd.getRejected());
        // TODO do async
        try {
          checkForOrphanedLocks(cd);
        } catch (Exception e) {
          throw new CompletionException(e);
        }
        if (checkForAckCollision(pcm)) {
          cd.commitObserver.alreadyAcknowledged();
        } else {
          cd.commitObserver.commitFailed(cd.getShortCollisionMessage());
        }

        return null;
      }, env.getSharedResources().getSyncCommitExecutor());
    }

  }

  class LockOtherStep extends ConditionalStep {

    @Override
    public AsyncConditionalWriter getACW(CommitData cd) {
      return cd.bacw;
    }


    @Override
    public Collection<ConditionalMutation> createMutations(CommitData cd) {

      ArrayList<ConditionalMutation> mutations = new ArrayList<>();

      for (Entry<Bytes, Map<Column, Bytes>> rowUpdates : updates.entrySet()) {
        ConditionalFlutation cm = null;

        for (Entry<Column, Bytes> colUpdates : rowUpdates.getValue().entrySet()) {
          if (cm == null) {
            cm = prewrite(rowUpdates.getKey(), colUpdates.getKey(), colUpdates.getValue(), cd.prow,
                cd.pcol, false);
          } else {
            prewrite(cm, colUpdates.getKey(), colUpdates.getValue(), cd.prow, cd.pcol, false);
          }
        }

        mutations.add(cm);
      }

      cd.acceptedRows = new HashSet<>();

      return mutations;
    }

    @Override
    public Iterator<Result> handleUnknown(CommitData cd, Iterator<Result> results) {
      // TODO this step does not currently handle unknown
      return results;
    }

    @Override
    public boolean processResults(CommitData cd, Iterator<Result> results) throws Exception {

      while (results.hasNext()) {
        Result result = results.next();
        // TODO handle unknown?
        Bytes row = Bytes.of(result.getMutation().getRow());
        if (result.getStatus() == Status.ACCEPTED) {
          cd.acceptedRows.add(row);
        } else {
          cd.addToRejected(row, updates.get(row).keySet());
        }
      }

      return cd.getRejected().isEmpty();
    }

    @Override
    CompletableFuture<Void> getFailureOp(CommitData cd) {
      return CompletableFuture.supplyAsync(() -> {
        getStats().setRejected(cd.getRejected());
        try {
          // Does this need to be async?
          checkForOrphanedLocks(cd);
        } catch (Exception e) {
          throw new CompletionException(e);
        }
        return null;
      }, env.getSharedResources().getSyncCommitExecutor()).thenCompose(v -> rollbackLocks(cd));
    }
  }

  abstract class BatchWriterStep extends CommitStep {
    public abstract Collection<Mutation> createMutations(CommitData cd);

    @Override
    CompletableFuture<Boolean> getMainOp(CommitData cd) {
      return env.getSharedResources().getBatchWriter()
          .writeMutationsAsyncFuture(createMutations(cd)).thenApply(v -> true);
    }

    @Override
    CompletableFuture<Void> getFailureOp(CommitData cd) {
      throw new IllegalStateException("Failure not expected");
    }
  }



  private CompletableFuture<Void> rollbackLocks(CommitData cd) {
    CommitStep firstStep = new RollbackOtherLocks();
    firstStep.andThen(new RollbackPrimaryLock());

    return firstStep.compose(cd)
        .thenRun(() -> cd.commitObserver.commitFailed(cd.getShortCollisionMessage()));

  }


  class RollbackOtherLocks extends BatchWriterStep {

    @Override
    public Collection<Mutation> createMutations(CommitData cd) {
      // roll back locks

      // TODO let rollback be done lazily? this makes GC more difficult

      Flutation m;

      ArrayList<Mutation> mutations = new ArrayList<>(cd.acceptedRows.size());
      for (Bytes row : cd.acceptedRows) {
        m = new Flutation(env, row);
        for (Entry<Column, Bytes> entry : updates.get(row).entrySet()) {
          if (isReadLock(entry.getValue())) {
            m.put(entry.getKey(), ColumnType.RLOCK.encode(ReadLockUtil.encodeTs(startTs, true)),
                DelReadLockValue.encodeRollback());
          } else {
            m.put(entry.getKey(), ColumnType.DEL_LOCK.encode(startTs),
                DelLockValue.encodeRollback(false, true));
          }
        }
        mutations.add(m);
      }

      return mutations;
    }
  }

  class RollbackPrimaryLock extends BatchWriterStep {

    @Override
    public Collection<Mutation> createMutations(CommitData cd) {
      // mark transaction as complete for garbage collection purposes
      Flutation m = new Flutation(env, cd.prow);

      m.put(cd.pcol, ColumnType.DEL_LOCK.encode(startTs),
          DelLockValue.encodeRollback(startTs, true, true));
      m.put(cd.pcol, ColumnType.TX_DONE.encode(startTs), EMPTY);

      return Collections.singletonList(m);
    }
  }

  class CommittedTestStep extends CommitStep {
    @Override
    CompletableFuture<Boolean> getMainOp(CommitData cd) {
      cd.commitObserver.committed();
      return CompletableFuture.completedFuture(true);
    }

    @Override
    CompletableFuture<Void> getFailureOp(CommitData cd) {
      throw new IllegalStateException("Failure not expected");
    }
  }

  @VisibleForTesting
  public boolean commitPrimaryColumn(CommitData cd, Stamp commitStamp) {

    SyncCommitObserver sco = new SyncCommitObserver();
    cd.commitObserver = sco;
    try {
      CommitStep firstStep = new GetCommitStampStepTest(commitStamp);

      firstStep.andThen(new WriteNotificationsStep()).andThen(new CommitPrimaryStep())
          .andThen(new CommittedTestStep());

      firstStep.compose(cd).exceptionally(throwable -> {
        setFailed(cd, throwable);
        return null;
      });
      sco.waitForCommit();
    } catch (CommitException e) {
      return false;
    } catch (Exception e) {
      throw new FluoException(e);
    }
    return true;
  }

  class GetCommitStampStep extends CommitStep {
    protected CompletableFuture<Stamp> getStampOp() {
      return env.getSharedResources().getOracleClient().getStampAsync();
    }

    @Override
    CompletableFuture<Boolean> getMainOp(CommitData cd) {

      return getStampOp().thenApply(commitStamp -> {
        if (startTs < commitStamp.getGcTimestamp()) {
          return false;
        } else {
          getStats().setCommitTs(commitStamp.getTxTimestamp());
          return true;
        }
      });
    }

    @Override
    CompletableFuture<Void> getFailureOp(CommitData cd) {
      return rollbackLocks(cd);
    }

  }

  class GetCommitStampStepTest extends GetCommitStampStep {
    private final Stamp testStamp;

    public GetCommitStampStepTest(Stamp testStamp) {
      this.testStamp = testStamp;
    }

    @Override
    protected CompletableFuture<Stamp> getStampOp() {
      return CompletableFuture.completedFuture(testStamp);
    }

  }

  class WriteNotificationsStep extends BatchWriterStep {

    @Override
    public Collection<Mutation> createMutations(CommitData cd) {
      long commitTs = getStats().getCommitTs();
      HashMap<Bytes, Mutation> mutations = new HashMap<>();

      if (observedColumns.contains(cd.pcol) && isWrite(cd.pval) && !isDelete(cd.pval)) {
        Flutation m = new Flutation(env, cd.prow);
        Notification.put(env, m, cd.pcol, commitTs);
        mutations.put(cd.prow, m);
      }

      for (Entry<Bytes, Map<Column, Bytes>> rowUpdates : updates.entrySet()) {

        for (Entry<Column, Bytes> colUpdates : rowUpdates.getValue().entrySet()) {
          if (observedColumns.contains(colUpdates.getKey())) {
            Bytes val = colUpdates.getValue();
            if (isWrite(val) && !isDelete(val)) {
              Mutation m = mutations.get(rowUpdates.getKey());
              if (m == null) {
                m = new Flutation(env, rowUpdates.getKey());
                mutations.put(rowUpdates.getKey(), m);
              }
              Notification.put(env, m, colUpdates.getKey(), commitTs);
            }
          }
        }
      }

      for (Entry<Bytes, Set<Column>> entry : weakNotifications.entrySet()) {
        Mutation m = mutations.get(entry.getKey());
        if (m == null) {
          m = new Flutation(env, entry.getKey());
          mutations.put(entry.getKey(), m);
        }
        for (Column col : entry.getValue()) {
          Notification.put(env, m, col, commitTs);
        }
      }
      return mutations.values();
    }

  }

  class CommitPrimaryStep extends ConditionalStep {

    @Override
    public Collection<ConditionalMutation> createMutations(CommitData cd) {
      long commitTs = getStats().getCommitTs();
      IteratorSetting iterConf = new IteratorSetting(10, PrewriteIterator.class);
      PrewriteIterator.setSnaptime(iterConf, startTs);
      boolean isTrigger = isTriggerRow(cd.prow) && cd.pcol.equals(notification.getColumn());

      Condition lockCheck =
          new FluoCondition(env, cd.pcol).setIterators(iterConf).setValue(LockValue.encode(cd.prow,
              cd.pcol, isWrite(cd.pval), isDelete(cd.pval), isTrigger, getTransactorID()));
      final ConditionalMutation delLockMutation = new ConditionalFlutation(env, cd.prow, lockCheck);

      ColumnUtil.commitColumn(env, isTrigger, true, cd.pcol, isWrite(cd.pval), isDelete(cd.pval),
          isReadLock(cd.pval), startTs, commitTs, observedColumns, delLockMutation);

      return Collections.singletonList(delLockMutation);
    }

    @Override
    public Iterator<Result> handleUnknown(CommitData cd, Iterator<Result> results)
        throws Exception {
      // the code for handing this is synchronous and needs to be handled in another thread pool
      // TODO - how do we do the above without return a CF?
      long commitTs = getStats().getCommitTs();
      Result result = Iterators.getOnlyElement(results);
      Status ms = result.getStatus();

      while (ms == Status.UNKNOWN) {

        // TODO async
        TxInfo txInfo = TxInfo.getTransactionInfo(env, cd.prow, cd.pcol, startTs);

        switch (txInfo.status) {
          case COMMITTED:
            if (txInfo.commitTs != commitTs) {
              throw new IllegalStateException(
                  cd.prow + " " + cd.pcol + " " + txInfo.commitTs + "!=" + commitTs);
            }
            ms = Status.ACCEPTED;
            break;
          case LOCKED:
            // TODO async
            ConditionalMutation delLockMutation = result.getMutation();
            ms = cd.cw.write(delLockMutation).getStatus();
            break;
          default:
            ms = Status.REJECTED;
        }
      }
      Result newResult = new Result(ms, result.getMutation(), result.getTabletServer());
      return Collections.singletonList(newResult).iterator();
    }

    @Override
    public boolean processResults(CommitData cd, Iterator<Result> results) throws Exception {
      Result result = Iterators.getOnlyElement(results);
      return result.getStatus() == Status.ACCEPTED;
    }

    @Override
    CompletableFuture<Void> getFailureOp(CommitData cd) {
      cd.commitObserver.commitFailed(cd.getShortCollisionMessage());
      return CompletableFuture.completedFuture(NULLS.get());
    }

  }

  @VisibleForTesting
  public boolean finishCommit(CommitData cd, Stamp commitStamp) {
    cd.commitObserver = new SyncCommitObserver();

    getStats().setCommitTs(commitStamp.getTxTimestamp());

    CommitStep firstStep = new DeleteLocksStep();
    firstStep.andThen(new FinishCommitStep());
    firstStep.compose(cd).exceptionally(throwable -> {
      System.err.println("Unexpected exception in finish commit test method : ");
      throwable.printStackTrace();
      return null;
    });

    return true;
  }


  class DeleteLocksStep extends BatchWriterStep {

    @Override
    public Collection<Mutation> createMutations(CommitData cd) {
      long commitTs = getStats().getCommitTs();
      ArrayList<Mutation> mutations = new ArrayList<>(updates.size() + 1);
      for (Entry<Bytes, Map<Column, Bytes>> rowUpdates : updates.entrySet()) {
        Flutation m = new Flutation(env, rowUpdates.getKey());
        boolean isTriggerRow = isTriggerRow(rowUpdates.getKey());
        for (Entry<Column, Bytes> colUpdates : rowUpdates.getValue().entrySet()) {
          ColumnUtil.commitColumn(env,
              isTriggerRow && colUpdates.getKey().equals(notification.getColumn()), false,
              colUpdates.getKey(), isWrite(colUpdates.getValue()), isDelete(colUpdates.getValue()),
              isReadLock(colUpdates.getValue()), startTs, commitTs, observedColumns, m);
        }

        mutations.add(m);
      }

      return mutations;
    }

  }

  class FinishCommitStep extends BatchWriterStep {

    @Override
    CompletableFuture<Boolean> getMainOp(CommitData cd) {
      return super.getMainOp(cd).thenApply(b -> {
        Preconditions.checkArgument(b);
        cd.commitObserver.committed();
        return true;
      });
    }

    @Override
    public Collection<Mutation> createMutations(CommitData cd) {
      long commitTs = getStats().getCommitTs();
      ArrayList<Mutation> afterFlushMutations = new ArrayList<>(2);

      Flutation m = new Flutation(env, cd.prow);
      // mark transaction as complete for garbage collection purposes
      m.put(cd.pcol, ColumnType.TX_DONE.encode(commitTs), EMPTY);
      afterFlushMutations.add(m);

      if (weakNotification != null) {
        afterFlushMutations.add(weakNotification.newDelete(env, startTs));
      }

      if (notification != null) {
        afterFlushMutations.add(notification.newDelete(env, startTs));
      }

      return afterFlushMutations;
    }

  }

  @Override
  public synchronized void commitAsync(AsyncCommitObserver commitCallback) {

    checkIfOpen();
    status = TxStatus.COMMIT_STARTED;
    commitAttempted = true;

    try {
      CommitData cd = createCommitData();
      cd = setUpBeginCommitAsync(cd, commitCallback, null);
      if (cd != null) {
        beginCommitAsync(cd);
      }
    } catch (Exception e) {
      e.printStackTrace();
      commitCallback.failed(e);
    }
  }

  private CommitData setUpBeginCommitAsync(CommitData cd, AsyncCommitObserver commitCallback,
      RowColumn primary) {
    if (updates.isEmpty()) {
      // TODO do async
      deleteWeakRow();
      commitCallback.committed();
      return null;
    }

    for (Map<Column, Bytes> cols : updates.values()) {
      stats.incrementEntriesSet(cols.size());
    }

    Bytes primRow = null;
    Column primCol = null;

    if (primary != null) {
      primRow = primary.getRow();
      primCol = primary.getColumn();
      if (notification != null && !primary.equals(notification.getRowColumn())) {
        throw new IllegalArgumentException("Primary must be notification");
      }
    } else if (notification != null) {
      primRow = notification.getRow();
      primCol = notification.getColumn();
    } else {

      outer: for (Entry<Bytes, Map<Column, Bytes>> entry : updates.entrySet()) {
        for (Entry<Column, Bytes> entry2 : entry.getValue().entrySet()) {
          if (!isReadLock(entry2.getValue())) {
            primRow = entry.getKey();
            primCol = entry2.getKey();
            break outer;
          }
        }
      }

      if (primRow == null) {
        // there are only read locks, so nothing to write
        deleteWeakRow();
        commitCallback.committed();
        return null;
      }
    }

    // get a primary column
    cd.prow = primRow;
    Map<Column, Bytes> colSet = updates.get(cd.prow);
    cd.pcol = primCol;
    cd.pval = colSet.remove(primCol);
    if (colSet.isEmpty()) {
      updates.remove(cd.prow);
    }

    cd.commitObserver = commitCallback;

    return cd;
  }

  private void setFailed(CommitData cd, Throwable throwable) {
    try {
      cd.commitObserver.failed(throwable);
    } catch (RuntimeException e) {
      Logger log = LoggerFactory.getLogger(TransactionImpl.class);
      log.error("Failed to set tx failure (startTs=" + startTs + ") cause ", e);
      log.error("Failed to set tx failure (startTs=" + startTs + ") lost throwable ", throwable);
    }
  }

  private void beginCommitAsync(CommitData cd) {

    // Notification are written between GetCommitStampStep and CommitPrimaryStep for the following
    // reasons :
    // * At this point all columns are locked, this guarantees that anything triggering as a
    // result of this transaction will see all of this transactions changes.
    // * The transaction is not yet committed. If the process dies at this point whatever
    // was running this transaction should rerun and recreate all of the notifications.
    // The next transactions will rerun because this transaction will have to be rolled back.
    // * If notifications are written in the 2nd phase of commit, then when the 2nd phase
    // partially succeeds notifications may never be written. Because in the case of failure
    // notifications would not be written until a column is read and it may never be read.
    // See https://github.com/fluo-io/fluo/issues/642
    //
    // Its very important the notifications which trigger an observer are deleted after the 2nd
    // phase of commit finishes.

    CommitStep firstStep = new LockPrimaryStep();

    firstStep.andThen(new LockOtherStep()).andThen(new GetCommitStampStep())
        .andThen(new WriteNotificationsStep()).andThen(new CommitPrimaryStep())
        .andThen(new DeleteLocksStep()).andThen(new FinishCommitStep());

    firstStep.compose(cd).exceptionally(throwable -> {
      setFailed(cd, throwable);
      return null;
    });
  }

  private void beginCommitAsyncTest(CommitData cd) {

    CommitStep firstStep = new LockPrimaryStep();

    firstStep.andThen(new LockOtherStep()).andThen(new CommittedTestStep());

    firstStep.compose(cd).exceptionally(throwable -> {
      setFailed(cd, throwable);
      return null;
    });
  }

  public SnapshotScanner newSnapshotScanner(Span span, Collection<Column> columns) {
    return new SnapshotScanner(env, new SnapshotScanner.Opts(span, columns, false), startTs, stats,
        kve -> {
        });
  }
}
