use of io.pravega.controller.store.stream.records.ActiveTxnRecord in project pravega by pravega.
the class PersistentStreamBase method getTransactionData.
@Override
public CompletableFuture<VersionedTransactionData> getTransactionData(UUID txId, OperationContext context) {
Preconditions.checkNotNull(context, "Operation context cannot be null");
int epoch = RecordHelper.getTransactionEpoch(txId);
return getActiveTx(epoch, txId, context).thenApply(data -> {
ActiveTxnRecord activeTxnRecord = data.getObject();
return new VersionedTransactionData(epoch, txId, data.getVersion(), activeTxnRecord.getTxnStatus(), activeTxnRecord.getTxCreationTimestamp(), activeTxnRecord.getMaxExecutionExpiryTime(), activeTxnRecord.getWriterId(), activeTxnRecord.getCommitTime(), activeTxnRecord.getCommitOrder(), activeTxnRecord.getCommitOffsets());
});
}
use of io.pravega.controller.store.stream.records.ActiveTxnRecord in project pravega by pravega.
the class InMemoryStream method getOrderedCommittingTxnInLowestEpoch.
@Override
CompletableFuture<List<VersionedTransactionData>> getOrderedCommittingTxnInLowestEpoch(int limit, OperationContext context) {
List<Long> toPurge = new ArrayList<>();
ConcurrentSkipListSet<VersionedTransactionData> committing = new ConcurrentSkipListSet<>(Comparator.comparingLong(VersionedTransactionData::getCommitOrder));
AtomicInteger smallestEpoch = new AtomicInteger(Integer.MAX_VALUE);
// take smallest epoch and collect transactions from smallest epoch.
transactionCommitOrder.forEach((order, txId) -> {
int epoch = RecordHelper.getTransactionEpoch(txId);
VersionedMetadata<ActiveTxnRecord> record;
synchronized (txnsLock) {
record = activeTxns.containsKey(txId) ? activeTxns.get(txId) : new VersionedMetadata<>(ActiveTxnRecord.EMPTY, null);
}
switch(record.getObject().getTxnStatus()) {
case COMMITTING:
if (record.getObject().getCommitOrder() == order) {
// if entry matches record's position then include it
committing.add(convertToVersionedMetadata(txId, record.getObject(), record.getVersion()));
if (smallestEpoch.get() > epoch) {
smallestEpoch.set(epoch);
}
} else {
toPurge.add(order);
}
break;
case // do nothing
OPEN:
break;
case COMMITTED:
case ABORTING:
case ABORTED:
case UNKNOWN:
// Aborting, aborted, unknown and committed
toPurge.add(order);
break;
}
});
// remove all stale transactions from transactionCommitOrder
toPurge.forEach(transactionCommitOrder::remove);
// take smallest epoch from committing transactions. order transactions in this epoch by
// ordered position
List<VersionedTransactionData> list = committing.stream().filter(x -> RecordHelper.getTransactionEpoch(x.getId()) == smallestEpoch.get()).sorted(Comparator.comparing(VersionedTransactionData::getCommitOrder)).limit(limit).collect(Collectors.toList());
return CompletableFuture.completedFuture(list);
}
use of io.pravega.controller.store.stream.records.ActiveTxnRecord in project pravega by pravega.
the class StreamTestBase method testgetTransactions.
@Test(timeout = 30000L)
public void testgetTransactions() {
PersistentStreamBase streamObj = spy(createStream("txn", "txn", System.currentTimeMillis(), 1, 0));
UUID txnId1 = new UUID(0L, 0L);
UUID txnId2 = new UUID(0L, 1L);
UUID txnId3 = new UUID(0L, 2L);
UUID txnId4 = new UUID(0L, 3L);
List<UUID> txns = Lists.newArrayList(txnId1, txnId2, txnId3, txnId4);
// create 1 2 and 4. dont create 3.
OperationContext context = getContext();
streamObj.createTransaction(txnId1, 1000L, 1000L, context).join();
streamObj.createTransaction(txnId2, 1000L, 1000L, context).join();
streamObj.sealTransaction(txnId2, true, Optional.empty(), "w", 1000L, context).join();
streamObj.createTransaction(txnId4, 1000L, 1000L, context).join();
streamObj.sealTransaction(txnId4, false, Optional.empty(), "w", 1000L, context).join();
List<ActiveTxnRecord> transactions = streamObj.getTransactionRecords(0, txns.stream().map(UUID::toString).collect(Collectors.toList()), context).join();
assertEquals(4, transactions.size());
assertEquals(transactions.get(0).getTxnStatus(), TxnStatus.OPEN);
assertEquals(transactions.get(1).getTxnStatus(), TxnStatus.COMMITTING);
assertEquals(transactions.get(2), ActiveTxnRecord.EMPTY);
assertEquals(transactions.get(3).getTxnStatus(), TxnStatus.ABORTING);
}
use of io.pravega.controller.store.stream.records.ActiveTxnRecord in project pravega by pravega.
the class StreamMetadataTasksTest method sealStreamWithTxnTest.
@Test(timeout = 30000)
public void sealStreamWithTxnTest() throws Exception {
WriterMock requestEventWriter = new WriterMock(streamMetadataTasks, executor);
streamMetadataTasks.setRequestEventWriter(requestEventWriter);
String streamWithTxn = "streamWithTxn";
// region seal a stream with transactions
long start = System.currentTimeMillis();
final ScalingPolicy policy = ScalingPolicy.fixed(2);
final StreamConfiguration config = StreamConfiguration.builder().scalingPolicy(policy).build();
streamStorePartialMock.createStream(SCOPE, streamWithTxn, config, start, null, executor).get();
streamStorePartialMock.setState(SCOPE, streamWithTxn, State.ACTIVE, null, executor).get();
// create txn
VersionedTransactionData openTxn = streamTransactionMetadataTasks.createTxn(SCOPE, streamWithTxn, 10000L, 0L, 1024 * 1024L).get().getKey();
VersionedTransactionData committingTxn = streamTransactionMetadataTasks.createTxn(SCOPE, streamWithTxn, 10000L, 0L, 1024 * 1024L).get().getKey();
VersionedTransactionData abortingTxn = streamTransactionMetadataTasks.createTxn(SCOPE, streamWithTxn, 10000L, 0L, 1024 * 1024L).get().getKey();
// set transaction to committing
streamStorePartialMock.sealTransaction(SCOPE, streamWithTxn, committingTxn.getId(), true, Optional.empty(), "", Long.MIN_VALUE, null, executor).join();
// set transaction to aborting
streamStorePartialMock.sealTransaction(SCOPE, streamWithTxn, abortingTxn.getId(), false, Optional.empty(), "", Long.MIN_VALUE, null, executor).join();
// Mock getActiveTransactions call such that we return committing txn as OPEN txn.
Map<UUID, ActiveTxnRecord> activeTxns = streamStorePartialMock.getActiveTxns(SCOPE, streamWithTxn, null, executor).join();
Map<UUID, ActiveTxnRecord> retVal = activeTxns.entrySet().stream().map(tx -> {
if (!tx.getValue().getTxnStatus().equals(TxnStatus.OPEN) && !tx.getValue().getTxnStatus().equals(TxnStatus.ABORTING)) {
ActiveTxnRecord txRecord = tx.getValue();
return new AbstractMap.SimpleEntry<>(tx.getKey(), new ActiveTxnRecord(txRecord.getTxCreationTimestamp(), txRecord.getLeaseExpiryTime(), txRecord.getMaxExecutionExpiryTime(), TxnStatus.OPEN));
} else {
return tx;
}
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
doReturn(CompletableFuture.completedFuture(retVal)).when(streamStorePartialMock).getActiveTxns(eq(SCOPE), eq(streamWithTxn), any(), any());
List<AbortEvent> abortListBefore = abortWriter.getEventList();
streamMetadataTasks.sealStream(SCOPE, streamWithTxn, 0L);
AssertExtensions.assertFutureThrows("seal stream did not fail processing with correct exception", processEvent(requestEventWriter), e -> Exceptions.unwrap(e) instanceof StoreException.OperationNotAllowedException);
requestEventWriter.eventQueue.take();
reset(streamStorePartialMock);
// verify that the txn status is set to aborting
VersionedTransactionData txnData = streamStorePartialMock.getTransactionData(SCOPE, streamWithTxn, openTxn.getId(), null, executor).join();
assertEquals(txnData.getStatus(), TxnStatus.ABORTING);
assertEquals(requestEventWriter.getEventQueue().size(), 1);
// verify that events are posted for the abort txn.
List<AbortEvent> abortListAfter = abortWriter.getEventList();
assertEquals(abortListAfter.size(), abortListBefore.size() + 2);
assertTrue(abortListAfter.stream().anyMatch(x -> x.getTxid().equals(openTxn.getId())));
assertTrue(abortListAfter.stream().anyMatch(x -> x.getTxid().equals(abortingTxn.getId())));
txnData = streamStorePartialMock.getTransactionData(SCOPE, streamWithTxn, committingTxn.getId(), null, executor).join();
assertEquals(txnData.getStatus(), TxnStatus.COMMITTING);
// Mock getActiveTransactions call such that we return some non existent transaction id so that DataNotFound is simulated.
// returning a random transaction with list of active txns such that when its abort is attempted, Data Not Found Exception gets thrown
retVal = new HashMap<>();
retVal.put(UUID.randomUUID(), new ActiveTxnRecord(1L, 1L, 1L, TxnStatus.OPEN));
doReturn(CompletableFuture.completedFuture(retVal)).when(streamStorePartialMock).getActiveTxns(eq(SCOPE), eq(streamWithTxn), any(), any());
AssertExtensions.assertFutureThrows("seal stream did not fail processing with correct exception", processEvent(requestEventWriter), e -> Exceptions.unwrap(e) instanceof StoreException.OperationNotAllowedException);
reset(streamStorePartialMock);
// Now complete all existing transactions and verify that seal completes
streamStorePartialMock.abortTransaction(SCOPE, streamWithTxn, openTxn.getId(), null, executor).join();
streamStorePartialMock.abortTransaction(SCOPE, streamWithTxn, abortingTxn.getId(), null, executor).join();
((AbstractStreamMetadataStore) streamStorePartialMock).commitTransaction(SCOPE, streamWithTxn, committingTxn.getId(), null, executor).join();
activeTxns = streamStorePartialMock.getActiveTxns(SCOPE, streamWithTxn, null, executor).join();
assertTrue(activeTxns.isEmpty());
assertTrue(Futures.await(processEvent(requestEventWriter)));
// endregion
}
use of io.pravega.controller.store.stream.records.ActiveTxnRecord in project pravega by pravega.
the class PersistentStreamBase method pingTransaction.
@Override
public CompletableFuture<VersionedTransactionData> pingTransaction(final VersionedTransactionData txnData, final long lease, OperationContext context) {
Preconditions.checkNotNull(context, "Operation context cannot be null");
// Update txn record with new lease value and return versioned tx data.
final int epoch = txnData.getEpoch();
final UUID txnId = txnData.getId();
final Version version = txnData.getVersion();
final long creationTime = txnData.getCreationTime();
final long maxExecutionExpiryTime = txnData.getMaxExecutionExpiryTime();
final TxnStatus status = txnData.getStatus();
final String writerId = txnData.getWriterId();
final long commitTime = txnData.getCommitTime();
final long position = txnData.getCommitOrder();
final ImmutableMap<Long, Long> commitOffsets = txnData.getCommitOffsets();
final ActiveTxnRecord newData = new ActiveTxnRecord(creationTime, System.currentTimeMillis() + lease, maxExecutionExpiryTime, status, writerId, commitTime, position, commitOffsets);
final VersionedMetadata<ActiveTxnRecord> data = new VersionedMetadata<>(newData, version);
return updateActiveTx(epoch, txnId, data, context).thenApply(updatedVersion -> new VersionedTransactionData(epoch, txnId, updatedVersion, status, creationTime, maxExecutionExpiryTime, writerId, commitTime, position, commitOffsets));
}
Aggregations