All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.scalar.db.common.TransactionDecorationTwoPhaseCommitTransactionManager Maven / Gradle / Ivy

Go to download

A universal transaction manager that achieves database-agnostic transactions and distributed transactions that span multiple databases

The newest version!
package com.scalar.db.common;

import com.google.common.annotations.VisibleForTesting;
import com.scalar.db.api.Delete;
import com.scalar.db.api.Get;
import com.scalar.db.api.Insert;
import com.scalar.db.api.Mutation;
import com.scalar.db.api.Put;
import com.scalar.db.api.Result;
import com.scalar.db.api.Scan;
import com.scalar.db.api.TwoPhaseCommitTransaction;
import com.scalar.db.api.Update;
import com.scalar.db.api.Upsert;
import com.scalar.db.common.error.CoreError;
import com.scalar.db.config.DatabaseConfig;
import com.scalar.db.exception.transaction.AbortException;
import com.scalar.db.exception.transaction.CommitException;
import com.scalar.db.exception.transaction.CrudException;
import com.scalar.db.exception.transaction.PreparationException;
import com.scalar.db.exception.transaction.RollbackException;
import com.scalar.db.exception.transaction.TransactionException;
import com.scalar.db.exception.transaction.UnknownTransactionStatusException;
import com.scalar.db.exception.transaction.ValidationException;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;

public abstract class TransactionDecorationTwoPhaseCommitTransactionManager
    extends AbstractTwoPhaseCommitTransactionManager
    implements TwoPhaseCommitTransactionDecoratorAddable {

  private final List transactionDecorators =
      new CopyOnWriteArrayList<>();

  public TransactionDecorationTwoPhaseCommitTransactionManager(DatabaseConfig config) {
    super(config);

    // Add the StateManagedTransaction decorator by default
    addTransactionDecorator(StateManagedTransaction::new);
  }

  protected TwoPhaseCommitTransaction decorate(TwoPhaseCommitTransaction transaction)
      throws TransactionException {
    TwoPhaseCommitTransaction decorated = transaction;
    for (TwoPhaseCommitTransactionDecorator transactionDecorator : transactionDecorators) {
      decorated = transactionDecorator.decorate(decorated);
    }
    return decorated;
  }

  @Override
  public void addTransactionDecorator(TwoPhaseCommitTransactionDecorator transactionDecorator) {
    transactionDecorators.add(transactionDecorator);
  }

  /**
   * This class is to unify the call sequence of the transaction object. It doesn't care about the
   * potential inconsistency between the status field on JVM memory and the underlying persistent
   * layer.
   */
  @VisibleForTesting
  static class StateManagedTransaction extends DecoratedTwoPhaseCommitTransaction {

    private enum Status {
      ACTIVE,
      PREPARED,
      PREPARE_FAILED,
      VALIDATED,
      VALIDATION_FAILED,
      COMMITTED,
      COMMIT_FAILED,
      ROLLED_BACK
    }

    private Status status;

    @VisibleForTesting
    StateManagedTransaction(TwoPhaseCommitTransaction transaction) {
      super(transaction);
      status = Status.ACTIVE;
    }

    @Override
    public Optional get(Get get) throws CrudException {
      checkIfActive();
      return super.get(get);
    }

    @Override
    public List scan(Scan scan) throws CrudException {
      checkIfActive();
      return super.scan(scan);
    }

    /** @deprecated As of release 3.13.0. Will be removed in release 5.0.0. */
    @Deprecated
    @Override
    public void put(Put put) throws CrudException {
      checkIfActive();
      super.put(put);
    }

    /** @deprecated As of release 3.13.0. Will be removed in release 5.0.0. */
    @Deprecated
    @Override
    public void put(List puts) throws CrudException {
      checkIfActive();
      super.put(puts);
    }

    @Override
    public void delete(Delete delete) throws CrudException {
      checkIfActive();
      super.delete(delete);
    }

    /** @deprecated As of release 3.13.0. Will be removed in release 5.0.0. */
    @Deprecated
    @Override
    public void delete(List deletes) throws CrudException {
      checkIfActive();
      super.delete(deletes);
    }

    @Override
    public void insert(Insert insert) throws CrudException {
      checkIfActive();
      super.insert(insert);
    }

    @Override
    public void upsert(Upsert upsert) throws CrudException {
      checkIfActive();
      super.upsert(upsert);
    }

    @Override
    public void update(Update update) throws CrudException {
      checkIfActive();
      super.update(update);
    }

    @Override
    public void mutate(List mutations) throws CrudException {
      checkIfActive();
      super.mutate(mutations);
    }

    @Override
    public void prepare() throws PreparationException {
      checkIfActive();
      try {
        super.prepare();
        status = Status.PREPARED;
      } catch (Exception e) {
        status = Status.PREPARE_FAILED;
        throw e;
      }
    }

    @Override
    public void validate() throws ValidationException {
      if (status != Status.PREPARED) {
        throw new IllegalStateException(CoreError.TRANSACTION_NOT_PREPARED.buildMessage(status));
      }

      try {
        super.validate();
        status = Status.VALIDATED;
      } catch (Exception e) {
        status = Status.VALIDATION_FAILED;
        throw e;
      }
    }

    @Override
    public void commit() throws CommitException, UnknownTransactionStatusException {
      if (status != Status.PREPARED && status != Status.VALIDATED) {
        throw new IllegalStateException(
            CoreError.TRANSACTION_NOT_PREPARED_OR_VALIDATED.buildMessage(status));
      }

      try {
        super.commit();
        status = Status.COMMITTED;
      } catch (Exception e) {
        status = Status.COMMIT_FAILED;
        throw e;
      }
    }

    @Override
    public void rollback() throws RollbackException {
      if (status == Status.COMMITTED || status == Status.ROLLED_BACK) {
        throw new IllegalStateException(
            CoreError.TRANSACTION_ALREADY_COMMITTED_OR_ROLLED_BACK.buildMessage(status));
      }
      try {
        super.rollback();
      } finally {
        status = Status.ROLLED_BACK;
      }
    }

    @Override
    public void abort() throws AbortException {
      if (status == Status.COMMITTED || status == Status.ROLLED_BACK) {
        throw new IllegalStateException(
            CoreError.TRANSACTION_ALREADY_COMMITTED_OR_ROLLED_BACK.buildMessage(status));
      }
      try {
        super.abort();
      } finally {
        status = Status.ROLLED_BACK;
      }
    }

    private void checkIfActive() {
      if (status != Status.ACTIVE) {
        throw new IllegalStateException(CoreError.TRANSACTION_NOT_ACTIVE.buildMessage(status));
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy