use of io.pravega.controller.store.Version in project pravega by pravega.
the class PersistentStreamBase method startCommittingTransactions.
@Override
public CompletableFuture<Map.Entry<VersionedMetadata<CommittingTransactionsRecord>, List<VersionedTransactionData>>> startCommittingTransactions(int limit, OperationContext context) {
Preconditions.checkNotNull(context, "Operation context cannot be null");
return getVersionedCommitTransactionsRecord(context).thenCompose(versioned -> {
if (versioned.getObject().equals(CommittingTransactionsRecord.EMPTY)) {
return getOrderedCommittingTxnInLowestEpoch(limit, context).thenCompose(list -> {
if (list.isEmpty()) {
List<VersionedTransactionData> emptyTransactionData = new LinkedList<>();
return CompletableFuture.completedFuture(new SimpleEntry<>(versioned, emptyTransactionData));
} else {
ImmutableList.Builder<UUID> txIdList = ImmutableList.builder();
list.forEach(x -> {
txIdList.add(x.getId());
});
List<Long> positions = list.stream().map(VersionedTransactionData::getCommitOrder).collect(Collectors.toList());
int epoch = RecordHelper.getTransactionEpoch(list.get(0).getId());
CommittingTransactionsRecord record = new CommittingTransactionsRecord(epoch, txIdList.build());
return updateCommittingTxnRecord(new VersionedMetadata<>(record, versioned.getVersion()), context).thenCompose(version -> removeTxnsFromCommitOrder(positions, context).thenApply(v -> new SimpleEntry<>(new VersionedMetadata<>(record, version), list)));
}
});
} else {
List<String> transactionsToCommit = versioned.getObject().getTransactionsToCommit().stream().map(UUID::toString).collect(Collectors.toList());
return getVersionedTransactionRecords(versioned.getObject().getEpoch(), transactionsToCommit, context).thenApply(x -> new SimpleEntry<>(versioned, x));
}
});
}
use of io.pravega.controller.store.Version in project pravega by pravega.
the class PersistentStreamBase method submitScale.
/**
* This method attempts to start a new scale workflow. For this it first computes epoch transition and stores it
* in the metadastore.
* This method can be called by manual scale or during the processing of auto-scale event. Which means there could be
* concurrent calls to this method.
*
* @param segmentsToSeal segments that will be sealed at the end of this scale operation.
* @param newRanges key ranges of new segments to be created
* @param scaleTimestamp scaling timestamp
* @return : list of newly created segments with current epoch
*/
@Override
public CompletableFuture<VersionedMetadata<EpochTransitionRecord>> submitScale(final List<Long> segmentsToSeal, final List<Map.Entry<Double, Double>> newRanges, final long scaleTimestamp, final VersionedMetadata<EpochTransitionRecord> existing, OperationContext context) {
Preconditions.checkNotNull(context, "Operation context cannot be null");
return verifyNotSealed(context).thenCompose(v -> {
if (existing == null) {
return getEpochTransition(context);
} else {
return CompletableFuture.completedFuture(existing);
}
}).thenCompose(record -> getActiveEpochRecord(true, context).thenCompose(currentEpoch -> getConfiguration(context).thenCompose(config -> {
if (!record.getObject().equals(EpochTransitionRecord.EMPTY)) {
// and new ranges are identical). else throw scale conflict exception
if (!RecordHelper.verifyRecordMatchesInput(segmentsToSeal, newRanges, false, record.getObject())) {
log.debug(context.getRequestId(), "scale conflict, another scale operation is ongoing");
throw new EpochTransitionOperationExceptions.ConflictException();
}
return CompletableFuture.completedFuture(record);
} else {
// check input is valid and satisfies preconditions
if (!RecordHelper.canScaleFor(segmentsToSeal, currentEpoch)) {
return updateEpochTransitionNode(new VersionedMetadata<>(EpochTransitionRecord.EMPTY, record.getVersion()), context).thenApply(x -> {
log.warn(context.getRequestId(), "scale precondition failed {}", segmentsToSeal);
throw new EpochTransitionOperationExceptions.PreConditionFailureException();
});
}
if (!RecordHelper.validateInputRange(segmentsToSeal, newRanges, currentEpoch)) {
log.error(context.getRequestId(), "scale input invalid {} {}", segmentsToSeal, newRanges);
throw new EpochTransitionOperationExceptions.InputInvalidException();
}
int numberOfSegmentsPostScale = currentEpoch.getSegments().size() - segmentsToSeal.size() + newRanges.size();
if (numberOfSegmentsPostScale < config.getScalingPolicy().getMinNumSegments()) {
log.warn(context.getRequestId(), "Scale cannot be performed as Min Segment Count will not hold {} {}", segmentsToSeal, newRanges);
throw new EpochTransitionOperationExceptions.PreConditionFailureException();
}
EpochTransitionRecord epochTransition = RecordHelper.computeEpochTransition(currentEpoch, segmentsToSeal, newRanges, scaleTimestamp);
return updateEpochTransitionNode(new VersionedMetadata<>(epochTransition, record.getVersion()), context).thenApply(version -> {
log.info(context.getRequestId(), "scale for stream {}/{} accepted. Segments to seal = {}", scope, name, epochTransition.getSegmentsToSeal());
return new VersionedMetadata<>(epochTransition, version);
});
}
})));
}
use of io.pravega.controller.store.Version 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