public static TTransaction wrap(Transaction tx) { return new TTransaction(tx.getTransactionId(), tx.getReadPointer(), Longs.asList(tx.getInvalids()), Longs.asList(tx.getInProgress()), tx.getFirstShortInProgress(), getTTransactionType(tx.getType()), tx.getWritePointer(), Longs.asList(tx.getCheckpointWritePointers()), getTVisibilityLevel(tx.getVisibilityLevel())); }
@Override public boolean apply(Long version) { return tx.isVisible(version); } });
/** * 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)); }
/** * 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()); }
RevealingTransaction(Transaction tx, int timeout) { super(tx, tx.getWritePointer(), tx.getCheckpointWritePointers()); this.timeout = timeout; }
@Override public long getWritePointer() { Transaction tx = getCurrentTransaction(); return tx == null ? HConstants.LATEST_TIMESTAMP : tx.getWritePointer(); }
@Override public long getTransactionId() { Transaction tx = getCurrentTransaction(); return tx == null ? HConstants.LATEST_TIMESTAMP : tx.getTransactionId(); // First write pointer - won't change with checkpointing }
public static void write(DataOutput dataOutput, Transaction tx) throws IOException { dataOutput.writeLong(tx.getReadPointer()); dataOutput.writeLong(tx.getWritePointer()); dataOutput.writeLong(tx.getFirstShortInProgress()); write(dataOutput, tx.getInProgress()); write(dataOutput, tx.getInvalids()); }
} else if (tx.isVisible(kvTimestamp)) { if (tx.getVisibilityLevel() == Transaction.VisibilityLevel.SNAPSHOT_ALL && tx.isCurrentWrite(kvTimestamp)) {
@Override public Void execute(TransactionServiceThriftClient client) throws Exception { client.commit(tx.getTransactionId(), tx.getWritePointer()); return null; } });
Predicate<PartitionDetail> predicate) { List<Long> previousInProgress = partitionConsumerState.getVersionsToCheck(); Set<Long> noLongerInProgress = setDiff(previousInProgress, tx.getInProgress()); if (partitions.size() < limit) { scanUpTo = Math.min(tx.getWritePointer(), tx.getReadPointer() + 1); Long endTxId; try (Scanner scanner = partitionsTable.scanByIndex(WRITE_PTR_COL, for (long txId : tx.getInProgress()) { if (txId >= scanUpTo) { break;
Transaction tx = client.startShort(); if (verbose) { LOG.info("Started tx details: " + tx.toString()); } else { LOG.info("Started tx: " + tx.getTransactionId() + ", readPointer: " + tx.getReadPointer() + ", invalids: " + tx.getInvalids().length + ", inProgress: " + tx.getInProgress().length);
/** * Creates a new {@link Filter} for returning data only from visible transactions. * * @param tx the current transaction to apply. Only data visible to this transaction will be returned. * @param ttlByFamily map of time-to-live (TTL) (in milliseconds) by column family name * @param allowEmptyValues if {@code true} cells with empty {@code byte[]} values will be returned, if {@code false} * these will be interpreted as "delete" markers and the column will be filtered out * @param scanType the type of scan operation being performed * @param cellFilter if non-null, this filter will be applied to all cells visible to the current transaction, by * calling {@link Filter#filterKeyValue(org.apache.hadoop.hbase.Cell)}. If null, then * {@link Filter.ReturnCode#INCLUDE_AND_NEXT_COL} will be returned instead. */ public TransactionVisibilityFilter(Transaction tx, Map<byte[], Long> ttlByFamily, boolean allowEmptyValues, ScanType scanType, @Nullable Filter cellFilter) { this.tx = tx; this.oldestTsByFamily = Maps.newTreeMap(Bytes.BYTES_COMPARATOR); for (Map.Entry<byte[], Long> ttlEntry : ttlByFamily.entrySet()) { long familyTTL = ttlEntry.getValue(); oldestTsByFamily.put(ttlEntry.getKey(), familyTTL <= 0 ? 0 : tx.getVisibilityUpperBound() - familyTTL * TxConstants.MAX_TX_PER_MS); } this.allowEmptyValues = allowEmptyValues; this.clearDeletes = scanType == ScanType.COMPACT_DROP_DELETES || (scanType == ScanType.USER_SCAN && tx.getVisibilityLevel() != Transaction.VisibilityLevel.SNAPSHOT_ALL); this.cellFilter = cellFilter; }
if (stateWritePointer == transaction.getWritePointer()) { return CanConsume.NO; if (state == ConsumerEntryState.PROCESSED && transaction.isVisible(stateWritePointer)) { if (enqueueWritePointer < transaction.getFirstShortInProgress()) { return CanConsume.NO_INCLUDING_ALL_OLDER;
if (!readFilter.acceptOffset(offset) || stateWritePointer >= transaction.getWritePointer()) { return false; if (state == ConsumerEntryState.PROCESSED && transaction.isVisible(stateWritePointer)) {
@Override public PhoenixVisibilityLevel getVisibilityLevel() { VisibilityLevel visibilityLevel = null; Transaction tx = getCurrentTransaction(); assert(tx != null); visibilityLevel = tx.getVisibilityLevel(); PhoenixVisibilityLevel phoenixVisibilityLevel; switch (visibilityLevel) { case SNAPSHOT: phoenixVisibilityLevel = PhoenixVisibilityLevel.SNAPSHOT; break; case SNAPSHOT_EXCLUDE_CURRENT: phoenixVisibilityLevel = PhoenixVisibilityLevel.SNAPSHOT_EXCLUDE_CURRENT; break; case SNAPSHOT_ALL: phoenixVisibilityLevel = PhoenixVisibilityLevel.SNAPSHOT_ALL; default: phoenixVisibilityLevel = null; } return phoenixVisibilityLevel; }
/** * Returns the maximum transaction that can be removed from the invalid list for the state represented by the given * transaction. */ public static long getPruneUpperBound(Transaction tx) { // If there are no invalid transactions, and no in-progress transactions then we can prune the invalid list // up to the current read pointer if (tx.getInvalids().length == 0 && tx.getInProgress().length == 0) { return tx.getReadPointer() - 1; } long maxInvalidTx = tx.getInvalids().length > 0 ? tx.getInvalids()[tx.getInvalids().length - 1] : Transaction.NO_TX_IN_PROGRESS; long firstInProgress = tx.getFirstInProgress(); return Math.min(maxInvalidTx, firstInProgress - 1); }
private Transaction startTx(long expiration, TransactionType type, @Nullable String clientId) { Transaction tx; long txid; // guard against changes to the transaction log while processing this.logReadLock.lock(); try { synchronized (this) { ensureAvailable(); txid = getNextWritePointer(); tx = createTransaction(txid, type); addInProgressAndAdvance(tx.getTransactionId(), tx.getVisibilityUpperBound(), expiration, type, retainClientId ? clientId : null); } // appending to WAL out of global lock for concurrent performance // we should still be able to arrive at the same state even if log entries are out of order appendToLog(TransactionEdit.createStarted(tx.getTransactionId(), tx.getVisibilityUpperBound(), expiration, type)); } finally { this.logReadLock.unlock(); } return tx; }
public void abort(Transaction tx) { // guard against changes to the transaction log while processing txMetricsCollector.rate("abort"); Stopwatch timer = new Stopwatch().start(); this.logReadLock.lock(); try { synchronized (this) { ensureAvailable(); doAbort(tx.getTransactionId(), tx.getCheckpointWritePointers(), tx.getType()); } appendToLog(TransactionEdit.createAborted(tx.getTransactionId(), tx.getType(), tx.getCheckpointWritePointers())); txMetricsCollector.histogram("abort.latency", (int) timer.elapsedMillis()); } finally { this.logReadLock.unlock(); } }
public Result filter(long txWritePtr) { // This transaction has been rolled back and thus skip the entry if (txWritePtr < 0) { return Result.SKIP; } // This transaction is visible, hence accept the message if (transaction.isVisible(txWritePtr)) { return Result.ACCEPT; } // This transaction is an invalid transaction, so skip the entry and proceed to the next if (Arrays.binarySearch(transaction.getInvalids(), txWritePtr) >= 0) { return Result.SKIP; } // This transaction has not yet been committed, hence hold to ensure ordering return Result.HOLD; } }