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

co.cask.tephra.persist.TransactionSnapshot Maven / Gradle / Ivy

/*
 * Copyright © 2012-2014 Cask Data, Inc.
 *
 * 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 co.cask.tephra.persist;

import co.cask.tephra.ChangeId;
import co.cask.tephra.TransactionManager;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Set;
import java.util.TreeMap;

/**
 * Represents an in-memory snapshot of the full transaction state.
 */
public class TransactionSnapshot {
  private long timestamp;
  private long readPointer;
  private long writePointer;
  private Collection invalid;
  private NavigableMap inProgress;
  private Map> committingChangeSets;
  private Map> committedChangeSets;

  public TransactionSnapshot(long timestamp, long readPointer, long writePointer, Collection invalid,
                             NavigableMap inProgress,
                             Map> committing, Map> committed) {
    this.timestamp = timestamp;
    this.readPointer = readPointer;
    this.writePointer = writePointer;
    this.invalid = invalid;
    this.inProgress = inProgress;
    this.committingChangeSets = committing;
    this.committedChangeSets = committed;
  }

  /**
   * Returns the timestamp from when this snapshot was created.
   */
  public long getTimestamp() {
    return timestamp;
  }

  /**
   * Returns the read pointer at the time of the snapshot.
   */
  public long getReadPointer() {
    return readPointer;
  }

  /**
   * Returns the next write pointer at the time of the snapshot.
   */
  public long getWritePointer() {
    return writePointer;
  }

  /**
   * Returns the list of invalid write pointers at the time of the snapshot.
   */
  public Collection getInvalid() {
    return invalid;
  }

  /**
   * Returns the map of in-progress transaction write pointers at the time of the snapshot.
   * @return a map of write pointer to expiration timestamp (in milliseconds) for all transactions in-progress.
   */
  public Map getInProgress() {
    return inProgress;
  }

  /**
   * Returns a map of transaction write pointer to sets of changed row keys for transactions that had called
   * {@code InMemoryTransactionManager.canCommit(Transaction, Collection)} but not yet called
   * {@code InMemoryTransactionManager.commit(Transaction)} at the time of the snapshot.
   *
   * @return a map of transaction write pointer to set of changed row keys.
   */
  public Map> getCommittingChangeSets() {
    return committingChangeSets;
  }

  /**
   * Returns a map of transaction write pointer to set of changed row keys for transaction that had successfully called
   * {@code InMemoryTransactionManager.commit(Transaction)} at the time of the snapshot.
   *
   * @return a map of transaction write pointer to set of changed row keys.
   */
  public Map> getCommittedChangeSets() {
    return committedChangeSets;
  }

  /**
   * @return transaction id {@code X} such that any of the transactions newer than {@code X} might be invisible to
   *         some of the currently in-progress transactions or to those that will be started 

* NOTE: the returned tx id can be invalid. */ public long getVisibilityUpperBound() { // the readPointer of the oldest in-progress tx is the oldest in use // todo: potential problem with not moving visibility upper bound for the whole duration of long-running tx Map.Entry firstInProgress = inProgress.firstEntry(); if (firstInProgress == null) { // using readPointer as smallest visible when non txs are there return readPointer; } return firstInProgress.getValue().getVisibilityUpperBound(); } /** * Checks that this instance matches another {@code TransactionSnapshot} instance. Note that the equality check * ignores the snapshot timestamp value, but includes all other properties. * * @param obj the other instance to check for equality. * @return {@code true} if the instances are equal, {@code false} if not. */ @Override public boolean equals(Object obj) { if (!(obj instanceof TransactionSnapshot)) { return false; } TransactionSnapshot other = (TransactionSnapshot) obj; return readPointer == other.readPointer && writePointer == other.writePointer && invalid.equals(other.invalid) && inProgress.equals(other.inProgress) && committingChangeSets.equals(other.committingChangeSets) && committedChangeSets.equals(other.committedChangeSets); } @Override public String toString() { return Objects.toStringHelper(this) .add("timestamp", timestamp) .add("readPointer", readPointer) .add("writePointer", writePointer) .add("invalidSize", invalid.size()) .add("inProgressSize", inProgress.size()) .add("committingSize", committingChangeSets.size()) .add("committedSize", committedChangeSets.size()) .toString(); } @Override public int hashCode() { return Objects.hashCode(readPointer, writePointer, invalid, inProgress, committingChangeSets, committedChangeSets); } /** * Creates a new {@code TransactionSnapshot} instance with copies of all of the individual collections. * @param readPointer current transaction read pointer * @param writePointer current transaction write pointer * @param invalid current list of invalid write pointers * @param inProgress current map of in-progress write pointers to expiration timestamps * @param committing current map of write pointers to change sets which have passed {@code canCommit()} but not * yet committed * @param committed current map of write pointers to change sets which have committed * @return a new {@code TransactionSnapshot} instance */ public static TransactionSnapshot copyFrom(long snapshotTime, long readPointer, long writePointer, Collection invalid, NavigableMap inProgress, Map> committing, NavigableMap> committed) { // copy invalid IDs Collection invalidCopy = Lists.newArrayList(invalid); // copy in-progress IDs and expirations NavigableMap inProgressCopy = Maps.newTreeMap(inProgress); // for committing and committed maps, we need to copy each individual Set as well to prevent modification Map> committingCopy = Maps.newHashMap(); for (Map.Entry> entry : committing.entrySet()) { committingCopy.put(entry.getKey(), new HashSet(entry.getValue())); } NavigableMap> committedCopy = new TreeMap>(); for (Map.Entry> entry : committed.entrySet()) { committedCopy.put(entry.getKey(), new HashSet(entry.getValue())); } return new TransactionSnapshot(snapshotTime, readPointer, writePointer, invalidCopy, inProgressCopy, committingCopy, committedCopy); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy