private boolean hasConflicts(Transaction tx, Set<ChangeId> changeIds) { if (changeIds.isEmpty()) { return false; } for (Map.Entry<Long, Set<ChangeId>> changeSet : committedChangeSets.entrySet()) { // If commit time is greater than tx read-pointer, // basically not visible but committed means "tx committed after given tx was started" if (changeSet.getKey() > tx.getTransactionId()) { if (overlap(changeSet.getValue(), changeIds)) { return true; } } } return false; }
private boolean hasConflicts(Transaction tx, Set<ChangeId> changeIds) { if (changeIds.isEmpty()) { return false; } for (Map.Entry<Long, Set<ChangeId>> changeSet : committedChangeSets.entrySet()) { // If commit time is greater than tx read-pointer, // basically not visible but committed means "tx committed after given tx was started" if (changeSet.getKey() > tx.getTransactionId()) { if (overlap(changeSet.getValue(), changeIds)) { return true; } } } return false; }
@Override public Collection<byte[]> getTxChanges() { if (tx == null) { throw new IllegalStateException("Transaction has not started yet"); } return Collections.singleton(Bytes.concat(fenceId, Longs.toByteArray(tx.getTransactionId()))); }
@Override public Collection<byte[]> getTxChanges() { if (tx == null) { throw new IllegalStateException("Transaction has not started yet"); } return Collections.singleton(Bytes.concat(fenceId, Longs.toByteArray(tx.getTransactionId()))); }
private void postCommit() throws TransactionFailureException { TransactionFailureException cause = null; for (TransactionAware txAware : txAwares) { try { txAware.postTxCommit(); } catch (Throwable e) { String message = String.format("Unable to perform post-commit in transaction-aware '%s' for transaction %d. ", txAware.getTransactionAwareName(), currentTx.getTransactionId()); LOG.warn(message, e); cause = new TransactionFailureException(message, e); } } if (cause != null) { throw cause; } } }
private void commit() throws TransactionFailureException { boolean commitSuccess = false; try { commitSuccess = txClient.commit(currentTx); } catch (TransactionNotInProgressException e) { String message = String.format("Transaction %d is not in progress.", currentTx.getTransactionId()); LOG.warn(message, e); abort(new TransactionFailureException(message, e)); // abort will throw that exception } catch (Throwable e) { String message = String.format("Exception from commit for transaction %d.", currentTx.getTransactionId()); LOG.warn(message, e); abort(new TransactionFailureException(message, e)); // abort will throw that exception } if (!commitSuccess) { String message = String.format("Conflict detected for transaction %d.", currentTx.getTransactionId()); abort(new TransactionConflictException(message)); // abort will throw } }
private void postCommit() throws TransactionFailureException { TransactionFailureException cause = null; for (TransactionAware txAware : txAwares) { try { txAware.postTxCommit(); } catch (Throwable e) { String message = String.format("Unable to perform post-commit in transaction-aware '%s' for transaction %d. ", txAware.getTransactionAwareName(), currentTx.getTransactionId()); LOG.warn(message, e); cause = new TransactionFailureException(message, e); } } if (cause != null) { throw cause; } } }
private Transaction startTx(long expiration, TransactionType type) { Transaction tx = null; 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); } // 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; }
private Transaction startTx(long expiration, TransactionType type) { Transaction tx = null; 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); } // 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 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(); } }
/** * 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()); }
/** * 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()); }
@Test public void testGetInvalidTxSize() throws Exception { Transaction tx1 = txClient.startShort(); txClient.startLong(); txClient.invalidate(tx1.getTransactionId()); ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream err = new ByteArrayOutputStream(); TransactionAdmin txAdmin = new TransactionAdmin(new PrintStream(out), new PrintStream(err)); int status = txAdmin.doMain(new String[]{"--get-invalid-tx-size"}, conf); Assert.assertEquals(0, status); //noinspection ConstantConditions Assert.assertTrue(out.toString("UTF-8").contains("Invalid list size: 1\n")); } }
@Test public void testTruncateInvalidTx() throws Exception { Transaction tx1 = txClient.startLong(); Transaction tx2 = txClient.startShort(); txClient.invalidate(tx1.getTransactionId()); txClient.invalidate(tx2.getTransactionId()); Assert.assertEquals(2, txClient.getInvalidSize()); TransactionAdmin txAdmin = new TransactionAdmin(new PrintStream(System.out), new PrintStream(System.err)); int status = txAdmin.doMain(new String[]{"--truncate-invalid-tx", String.valueOf(tx2.getTransactionId())}, conf); Assert.assertEquals(0, status); Assert.assertEquals(1, txClient.getInvalidSize()); }
@Test public void testTruncateInvalidTx() throws Exception { // Start few transactions and invalidate all of them TransactionSystemClient client = getClient(); Transaction tx1 = client.startLong(); Transaction tx2 = client.startShort(); Transaction tx3 = client.startLong(); client.invalidate(tx1.getTransactionId()); client.invalidate(tx2.getTransactionId()); client.invalidate(tx3.getTransactionId()); // Remove tx2 and tx3 from invalid list Assert.assertTrue(client.truncateInvalidTx(ImmutableSet.of(tx2.getTransactionId(), tx3.getTransactionId()))); Transaction tx = client.startShort(); // Only tx1 should be in invalid list now Assert.assertArrayEquals(new long[] {tx1.getTransactionId()}, tx.getInvalids()); client.abort(tx); }
@Test public void testGetInvalidSize() throws Exception { // Start few transactions and invalidate all of them TransactionSystemClient client = getClient(); Transaction tx1 = client.startLong(); Transaction tx2 = client.startShort(); Transaction tx3 = client.startLong(); Assert.assertEquals(0, client.getInvalidSize()); client.invalidate(tx1.getTransactionId()); client.invalidate(tx2.getTransactionId()); client.invalidate(tx3.getTransactionId()); Assert.assertEquals(3, client.getInvalidSize()); }
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())); }
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())); }
@Test public void testInvalidateTx() throws Exception { TransactionSystemClient client = getClient(); // Invalidate an in-progress tx Transaction tx1 = client.startShort(); client.canCommit(tx1, asList(C1, C2)); Assert.assertTrue(client.invalidate(tx1.getTransactionId())); // Cannot invalidate a committed tx Transaction tx2 = client.startShort(); client.canCommit(tx2, asList(C3, C4)); client.commit(tx2); Assert.assertFalse(client.invalidate(tx2.getTransactionId())); }