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

org.apache.tephra.Transaction Maven / Gradle / Ivy

There is a newer version: 0.16.1
Show newest version
/*
 * 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.tephra;

import java.util.Arrays;

/**
 * Transaction details
 */
// NOTE: this class should have minimal dependencies as it is used in HBase CPs and other places where minimal classes
//       are available
public class Transaction {
  private final long readPointer;
  private final long txId;
  private final long writePointer;
  private final long[] invalids;
  private final long[] inProgress;
  private final long firstShortInProgress;
  private final TransactionType type;
  private final long[] checkpointWritePointers;

  private VisibilityLevel visibilityLevel = VisibilityLevel.SNAPSHOT;

  private static final long[] NO_EXCLUDES = { };
  public static final long NO_TX_IN_PROGRESS = Long.MAX_VALUE;

  public static final Transaction ALL_VISIBLE_LATEST =
    new Transaction(Long.MAX_VALUE, Long.MAX_VALUE, NO_EXCLUDES, NO_EXCLUDES, NO_TX_IN_PROGRESS, TransactionType.SHORT);

  /**
   * Defines the possible visibility levels for read operations.
   *
   * 

*

    *
  • SNAPSHOT - uses the transaction's read snapshot, plus includes all write pointers from the * current transaction
  • *
  • SNAPSHOT_EXCLUDE_CURRENT - uses the transaction's read snapshot, plus includes all write * pointers from the current transaction, except the current write pointer * (see {@link #getWritePointer()})
  • *
  • SNAPSHOT_ALL - uses the transaction's read snapshot, plus includes all write pointers from the * current transaction. This visibility level will lead to raw fetch operations, where all versions * (including deletes) visible to current transaction are returned.
  • *
*

* *

The default value used is {@code SNAPSHOT}.

* * @see #setVisibility(VisibilityLevel) */ public enum VisibilityLevel { SNAPSHOT, SNAPSHOT_EXCLUDE_CURRENT, SNAPSHOT_ALL } /** * Creates a new short transaction. * @param readPointer read pointer for transaction * @param txId unique identifier for the transaction * @param invalids list of invalid transactions to exclude while reading * @param inProgress list of in-progress transactions to exclude while reading * @param firstShortInProgress earliest in-progress short transaction */ public Transaction(long readPointer, long txId, long[] invalids, long[] inProgress, long firstShortInProgress) { this(readPointer, txId, invalids, inProgress, firstShortInProgress, TransactionType.SHORT); } /** * Creates a new transaction. * @param readPointer read pointer for transaction * @param txId unique identifier for the transaction * @param invalids list of invalid transactions to exclude while reading * @param inProgress list of in-progress transactions to exclude while reading * @param firstShortInProgress earliest in-progress short transaction * @param type transaction type */ public Transaction(long readPointer, long txId, long[] invalids, long[] inProgress, long firstShortInProgress, TransactionType type) { this(readPointer, txId, txId, invalids, inProgress, firstShortInProgress, type, new long[0], VisibilityLevel.SNAPSHOT); } /** * Creates a new transaction. * @param readPointer read pointer for transaction * @param txId unique identifier for the transaction * @param writePointer the current pointer to be used for any writes. * For new transactions, this will be the same as {@code txId}. For checkpointed * transactions, this will be the most recent write pointer issued. * @param invalids list of invalid transactions to exclude while reading * @param inProgress list of in-progress transactions to exclude while reading * @param firstShortInProgress earliest in-progress short transaction * @param type transaction type * @param checkpointPointers the list of writer pointers added from checkpoints on the transaction * @param visibilityLevel the visibility level to use for transactional reads */ public Transaction(long readPointer, long txId, long writePointer, long[] invalids, long[] inProgress, long firstShortInProgress, TransactionType type, long[] checkpointPointers, VisibilityLevel visibilityLevel) { this.readPointer = readPointer; this.txId = txId; this.writePointer = writePointer; this.invalids = invalids; this.inProgress = inProgress; this.firstShortInProgress = firstShortInProgress; this.type = type; this.checkpointWritePointers = checkpointPointers; this.visibilityLevel = visibilityLevel; } /** * Creates a new transaction for a checkpoint operation, copying all members from the original transaction, * with the updated checkpoint write pointers. * * @param toCopy the original transaction containing the state to copy * @param writePointer the new write pointer to use for the transaction * @param checkpointPointers the list of write pointers added from checkpoints on the transaction */ public Transaction(Transaction toCopy, long writePointer, long[] checkpointPointers) { this(toCopy.getReadPointer(), toCopy.getTransactionId(), writePointer, toCopy.getInvalids(), toCopy.getInProgress(), toCopy.getFirstShortInProgress(), toCopy.getType(), checkpointPointers, toCopy.getVisibilityLevel()); } public long getReadPointer() { return readPointer; } /** * Returns the initial write pointer assigned to the transaction. This will remain the same for the life of the * transaction, and uniquely identifies it with the transaction service. This value should be provided * to identify the transaction when calling any transaction lifecycle methods on the transaction service. */ public long getTransactionId() { return txId; } /** * Returns the write pointer to be used in persisting any changes. After a checkpoint is performed, this will differ * from {@link #getTransactionId()}. This method should always be used when setting the timestamp for writes * in order to ensure that the correct value is used. */ public long getWritePointer() { return writePointer; } public long[] getInvalids() { return invalids; } public long[] getInProgress() { return inProgress; } public long getFirstInProgress() { return inProgress.length == 0 ? NO_TX_IN_PROGRESS : inProgress[0]; } public TransactionType getType() { return type; } /** * @return transaction id {@code X} such that any of the transactions newer than {@code X} may be invisible to this

* NOTE: the returned tx id can be invalid. */ public long getVisibilityUpperBound() { // NOTE: in some cases when we do not provide visibility guarantee, we set readPointer to MAX value, but // at same time we don't want that to case cleanup everything as this is used for tx janitor + ttl to see // what can be cleaned up. When non-tx mode is implemented better, we should not need this check return inProgress.length == 0 ? Math.min(txId - 1, readPointer) : inProgress[0] - 1; } public long getFirstShortInProgress() { return firstShortInProgress; } /** * Returns true if the given version corresponds to a transaction that was in-progress at the time this transaction * started. */ public boolean isInProgress(long version) { return Arrays.binarySearch(inProgress, version) >= 0; } /** * Returns true if the given version is present in one of the arrays of excluded versions (in-progress and * invalid transactions). */ public boolean isExcluded(long version) { return Arrays.binarySearch(inProgress, version) >= 0 || Arrays.binarySearch(invalids, version) >= 0; } /** * Returns true if the the given version corresponds to one of the checkpoint versions in the current * transaction. */ public boolean isCheckpoint(long version) { return Arrays.binarySearch(checkpointWritePointers, version) >= 0; } /** * Returns whether or not the given version should be visible to the current transaction. A version will be visible * if it was successfully committed prior to the current transaction starting, or was written by the current * transaction (using either the current write pointer or the write pointer from a prior checkpoint). * * @param version the data version to check for visibility * @return true if the version is visible, false if it should be hidden (filtered) * * @see #setVisibility(VisibilityLevel) to control whether the current write pointer is visible. */ public boolean isVisible(long version) { // either it was committed before or the change belongs to current tx return (version <= getReadPointer() && !isExcluded(version)) || (isCurrentWrite(version) && (visibilityLevel != VisibilityLevel.SNAPSHOT_EXCLUDE_CURRENT || writePointer != version)); } /** * Returns whether the given version was written by the current transaction. * * @param version the data version * @return true if version was written by current transaction, false otherwise. */ public boolean isCurrentWrite(long version) { return writePointer == version || txId == version || isCheckpoint(version); } /** * Sets the visibility level for read operations. */ public void setVisibility(VisibilityLevel level) { this.visibilityLevel = level; } /** * Returns the currently set visibility level. */ public VisibilityLevel getVisibilityLevel() { return visibilityLevel; } public boolean hasExcludes() { return invalids.length > 0 || inProgress.length > 0; } public int excludesSize() { return invalids.length + inProgress.length; } /** * Returns any prior write pointers used in the current transaction. A new write pointer is issued when the * {@code TransactionContext.checkpoint(Transaction)} operation is called, and the prior write pointer is added * to the array of checkpoint write pointers. ` */ public long[] getCheckpointWritePointers() { return checkpointWritePointers; } @Override public String toString() { return new StringBuilder(100) .append(Transaction.class.getSimpleName()) .append('{') .append("readPointer: ").append(readPointer) .append(", transactionId: ").append(txId) .append(", writePointer: ").append(writePointer) .append(", invalids: ").append(Arrays.toString(invalids)) .append(", inProgress: ").append(Arrays.toString(inProgress)) .append(", firstShortInProgress: ").append(firstShortInProgress) .append(", type: ").append(type) .append(", checkpointWritePointers: ").append(Arrays.toString(checkpointWritePointers)) .append(", visibilityLevel: ").append(visibilityLevel) .append('}') .toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy