/** * Creates a new instance in the {@link State#INPROGRESS} state. */ public static TransactionEdit createStarted(long writePointer, long visibilityUpperBound, long expirationDate, TransactionType type) { return new TransactionEdit(writePointer, visibilityUpperBound, State.INPROGRESS, expirationDate, null, 0L, false, type, null, 0L, 0L, null); }
@Test public void testSerialization() throws Exception { assertSerializedEdit(TransactionEdit.createAborted(1L, TransactionType.SHORT, new long[0])); assertSerializedEdit(TransactionEdit.createAborted(1L, TransactionType.SHORT, new long[]{ 2L, 3L })); assertSerializedEdit(TransactionEdit.createAborted(1L, TransactionType.LONG, new long[0])); assertSerializedEdit(TransactionEdit.createAborted(1L, TransactionType.LONG, new long[]{ 2L, 3L })); assertSerializedEdit(TransactionEdit.createCheckpoint(2L, 1L)); assertSerializedEdit(TransactionEdit.createCommitted(1L, Sets.<ChangeId>newHashSet(), 2L, false)); assertSerializedEdit(TransactionEdit.createCommitted(1L, Sets.<ChangeId>newHashSet(), 2L, true)); assertSerializedEdit(TransactionEdit.createCommitted(1L, Sets.newHashSet(new ChangeId(new byte[]{'a', 'b', 'c'})), 2L, false)); assertSerializedEdit(TransactionEdit.createCommitted(1L, Sets.newHashSet(new ChangeId(new byte[]{ 'a', 'b', 'c' }), new ChangeId(new byte[]{ 'd', 'e', 'f' })), 2L, true)); assertSerializedEdit(TransactionEdit.createCommitting(1L, Sets.<ChangeId>newHashSet())); assertSerializedEdit(TransactionEdit.createCommitting(1L, Sets.newHashSet(new ChangeId(new byte[]{'a', 'b', 'c'})))); assertSerializedEdit(TransactionEdit.createCommitting(1L, Sets.newHashSet(new ChangeId(new byte[]{'a', 'b', 'c'}), new ChangeId(new byte[]{'d', 'e', 'f'})))); assertSerializedEdit(TransactionEdit.createInvalid(1L)); assertSerializedEdit(TransactionEdit.createMoveWatermark(10L)); assertSerializedEdit(TransactionEdit.createStarted(2L, 1L, System.currentTimeMillis() + 1000, TransactionType.SHORT)); assertSerializedEdit(TransactionEdit.createStarted(2L, 1L, System.currentTimeMillis() + 10000, TransactionType.LONG)); assertSerializedEdit(TransactionEdit.createTruncateInvalidTx(Sets.newHashSet(new Long(1)))); assertSerializedEdit(TransactionEdit.createTruncateInvalidTx( Sets.newHashSet(new Long(1), new Long(2), new Long(3)))); assertSerializedEdit(TransactionEdit.createTruncateInvalidTxBefore(System.currentTimeMillis())); }
case INPROGRESS: edits.add( TransactionEdit.createStarted(writePointer, writePointer - 1, System.currentTimeMillis() + 300000L, TransactionType.SHORT)); break; case COMMITTING: edits.add(TransactionEdit.createCommitting(writePointer, generateChangeSet(10))); break; case COMMITTED: edits.add(TransactionEdit.createCommitted(writePointer, generateChangeSet(10), writePointer + 1, random.nextBoolean())); break; case INVALID: edits.add(TransactionEdit.createInvalid(writePointer)); break; case ABORTED: edits.add(TransactionEdit.createAborted(writePointer, TransactionType.SHORT, null)); break; case MOVE_WATERMARK: edits.add(TransactionEdit.createMoveWatermark(writePointer)); break;
private void assertSerializedEdit(TransactionEdit originalEdit) throws IOException { ByteArrayDataOutput out = ByteStreams.newDataOutput(); originalEdit.write(out); TransactionEdit decodedEdit = new TransactionEdit(); DataInput in = ByteStreams.newDataInput(out.toByteArray()); decodedEdit.readFields(in); Assert.assertEquals(originalEdit, decodedEdit); } }
TransactionEdit edit1 = TransactionEdit.createStarted(wp1, wp1 - 10, time1 + 100000, TransactionType.LONG); TransactionEdit edit2 = TransactionEdit.createInvalid(wp1); TransactionEdit edit3 = TransactionEdit.createStarted(wp2, wp2 - 10, time2 + 10000, TransactionType.SHORT); TransactionEdit edit4 = TransactionEdit.createInvalid(wp2); TransactionEdit edit5 = TransactionEdit.createStarted(wp3, wp3 - 10, time3 + 100000, TransactionType.LONG); TransactionEdit edit6 = TransactionEdit.createInvalid(wp3); TransactionEdit edit7 = TransactionEdit.createStarted(wp4, wp4 - 10, time4 + 10000, TransactionType.SHORT); TransactionEdit edit8 = TransactionEdit.createInvalid(wp4); TransactionEdit edit9 = TransactionEdit.createTruncateInvalidTx(ImmutableSet.of(wp1, wp3)); TransactionEdit edit10 = TransactionEdit.createTruncateInvalidTxBefore(time3);
@SuppressWarnings("deprecation") private void verifyDecodingSupportsOlderVersion(TransactionEdit edit, TransactionEditCodecs.TransactionEditCodec olderCodec) throws IOException { // encoding with older version of codec ByteArrayDataOutput out = ByteStreams.newDataOutput(); TransactionEditCodecs.encode(edit, out, olderCodec); // decoding TransactionEdit decodedEdit = new TransactionEdit(); DataInput in = ByteStreams.newDataInput(out.toByteArray()); decodedEdit.readFields(in); Assert.assertEquals(edit, decodedEdit); }
TransactionEdit edit1 = TransactionEdit.createStarted(wp1, wp1 - 10, time1 + 100000, TransactionType.LONG); TransactionEdit edit2 = TransactionEdit.createAborted(wp1, TransactionType.LONG, null); TransactionEdit edit3 = TransactionEdit.createStarted(wp2, wp2 - 10, time2 + 100000, TransactionType.LONG); TransactionEdit edit4 = TransactionEdit.createInvalid(wp2); TransactionEdit edit5 = TransactionEdit.createStarted(wp3, wp3 - 10, time3 + 100000, TransactionType.LONG); TransactionEdit edit6 = TransactionEdit.createInvalid(wp3); TransactionEdit edit7 = TransactionEdit.createAborted(wp3, TransactionType.LONG, null);
@Override public void readFields(DataInput in) throws IOException { this.key.readFields(in); this.edit.readFields(in); } }
@Test public void testV2SerdeCompat() throws Exception { TransactionEditCodecs.TransactionEditCodec olderCodec = new TransactionEditCodecs.TransactionEditCodecV2(); // start tx edit and committed tx edit cover all fields of tx edit // NOTE: transaction type to null as this is expected default for decoding older versions that doesn't store it verifyDecodingSupportsOlderVersion(TransactionEdit.createStarted(2L, 100L, 1000L, null), olderCodec); verifyDecodingSupportsOlderVersion( TransactionEdit.createCommitted(2L, Sets.newHashSet(new ChangeId(COL)), 3L, true), olderCodec); }
@Override public void write(DataOutput out) throws IOException { this.key.write(out); this.edit.write(out); }
committingChangeSets.remove(tx); inProgress.remove(tx); invalidEdits.add(TransactionEdit.createInvalid(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(); } }
/** * Removes the given transaction ids from the invalid list. * @param invalidTxIds transaction ids * @return true if invalid list got changed, false otherwise */ public boolean truncateInvalidTx(Set<Long> invalidTxIds) { // guard against changes to the transaction log while processing txMetricsCollector.rate("truncateInvalidTx"); Stopwatch timer = new Stopwatch().start(); this.logReadLock.lock(); try { boolean success; synchronized (this) { ensureAvailable(); success = doTruncateInvalidTx(invalidTxIds); } appendToLog(TransactionEdit.createTruncateInvalidTx(invalidTxIds)); txMetricsCollector.histogram("truncateInvalidTx.latency", (int) timer.elapsedMillis()); return success; } finally { this.logReadLock.unlock(); } }
addCommittingChangeSet(tx.getTransactionId(), set); appendToLog(TransactionEdit.createCommitting(tx.getTransactionId(), set)); } finally { this.logReadLock.unlock();
appendToLog(TransactionEdit.createCheckpoint(newWritePointer, txId)); } finally { this.logReadLock.unlock();
appendToLog(TransactionEdit.createCommitted(tx.getTransactionId(), changeSet, commitPointer, addToCommitted)); } finally { this.logReadLock.unlock();
@Override public void readFields(DataInput in) throws IOException { this.key.readFields(in); this.edit.readFields(in); } }
@Test public void testV1SerdeCompat() throws Exception { TransactionEditCodecs.TransactionEditCodec olderCodec = new TransactionEditCodecs.TransactionEditCodecV1(); // start tx edit and committed tx edit cover all fields of tx edit // NOTE: set visibilityUpperBound to 0 and transaction type to null as this is expected default // for decoding older versions that doesn't store it verifyDecodingSupportsOlderVersion(TransactionEdit.createStarted(2L, 0L, 1000L, null), olderCodec); verifyDecodingSupportsOlderVersion( TransactionEdit.createCommitted(2L, Sets.newHashSet(new ChangeId(COL)), 3L, true), olderCodec); }
@Override public void write(DataOutput out) throws IOException { this.key.write(out); this.edit.write(out); }