use of io.pravega.controller.store.VersionedMetadata in project pravega by pravega.
the class PersistentStreamBase method rollingTxnCreateDuplicateEpochs.
@Override
public CompletableFuture<Void> rollingTxnCreateDuplicateEpochs(Map<Long, Long> sealedTxnEpochSegments, long time, VersionedMetadata<CommittingTransactionsRecord> record, OperationContext context) {
Preconditions.checkNotNull(context, "Operation context cannot be null");
Preconditions.checkArgument(record.getObject().isRollingTxnRecord());
CommittingTransactionsRecord committingTxnRecord = record.getObject();
return getActiveEpoch(true, context).thenCompose(activeEpochRecord -> getEpochRecord(committingTxnRecord.getEpoch(), context).thenCompose(transactionEpochRecord -> {
if (activeEpochRecord.getEpoch() > committingTxnRecord.getCurrentEpoch()) {
log.debug(context.getRequestId(), "Duplicate Epochs {} already created. Ignore.", committingTxnRecord.getNewActiveEpoch());
return CompletableFuture.completedFuture(null);
}
long timeStamp = Math.max(activeEpochRecord.getCreationTime() + 1, time);
ImmutableList.Builder<StreamSegmentRecord> duplicateTxnSegmentsBuilder = ImmutableList.builder();
transactionEpochRecord.getSegments().stream().forEach(x -> duplicateTxnSegmentsBuilder.add(newSegmentRecord(computeSegmentId(getSegmentNumber(x.segmentId()), committingTxnRecord.getNewTxnEpoch()), timeStamp, x.getKeyStart(), x.getKeyEnd())));
ImmutableList.Builder<StreamSegmentRecord> duplicateActiveSegmentsBuilder = ImmutableList.builder();
activeEpochRecord.getSegments().stream().forEach(x -> duplicateActiveSegmentsBuilder.add(newSegmentRecord(computeSegmentId(getSegmentNumber(x.segmentId()), committingTxnRecord.getNewActiveEpoch()), timeStamp + 1, x.getKeyStart(), x.getKeyEnd())));
CompletableFuture<EpochRecord> txnEpochFuture = getSplitMergeCountsTillEpoch(activeEpochRecord, context).thenCompose(txnSplitMergeCount -> {
ImmutableList<StreamSegmentRecord> duplicateTxnEpochSegments = duplicateTxnSegmentsBuilder.build();
EpochRecord duplicateTxnEpoch = new EpochRecord(committingTxnRecord.getNewTxnEpoch(), transactionEpochRecord.getReferenceEpoch(), duplicateTxnEpochSegments, timeStamp, getNewEpochSplitCount(txnSplitMergeCount.getKey(), activeEpochRecord.getSegments(), duplicateTxnEpochSegments), getNewEpochMergeCount(txnSplitMergeCount.getValue(), activeEpochRecord.getSegments(), duplicateTxnEpochSegments));
return CompletableFuture.completedFuture(duplicateTxnEpoch);
});
CompletableFuture<EpochRecord> activeEpochFuture = txnEpochFuture.thenCompose(previousEpoch -> getSplitMergeCountsTillEpoch(previousEpoch, context).thenCompose(prevSplitMergeCounts -> {
ImmutableList<StreamSegmentRecord> activeEpochSegments = duplicateActiveSegmentsBuilder.build();
EpochRecord duplicateActiveEpoch = new EpochRecord(committingTxnRecord.getNewActiveEpoch(), activeEpochRecord.getReferenceEpoch(), activeEpochSegments, timeStamp + 1, getNewEpochSplitCount(prevSplitMergeCounts.getKey(), previousEpoch.getSegments(), activeEpochSegments), getNewEpochMergeCount(prevSplitMergeCounts.getValue(), previousEpoch.getSegments(), activeEpochSegments));
return CompletableFuture.completedFuture(duplicateActiveEpoch);
}));
return CompletableFuture.allOf(txnEpochFuture, activeEpochFuture).thenCompose(v -> {
EpochRecord duplicateTxnEpoch = txnEpochFuture.join();
EpochRecord duplicateActiveEpoch = activeEpochFuture.join();
HistoryTimeSeriesRecord timeSeriesRecordTxnEpoch = new HistoryTimeSeriesRecord(duplicateTxnEpoch.getEpoch(), duplicateTxnEpoch.getReferenceEpoch(), ImmutableList.of(), ImmutableList.of(), timeStamp);
HistoryTimeSeriesRecord timeSeriesRecordActiveEpoch = new HistoryTimeSeriesRecord(duplicateActiveEpoch.getEpoch(), duplicateActiveEpoch.getReferenceEpoch(), ImmutableList.of(), ImmutableList.of(), timeStamp + 1);
return createEpochRecord(duplicateTxnEpoch, context).thenCompose(x -> updateHistoryTimeSeries(timeSeriesRecordTxnEpoch, context)).thenCompose(x -> createEpochRecord(duplicateActiveEpoch, context)).thenCompose(x -> updateHistoryTimeSeries(timeSeriesRecordActiveEpoch, context)).thenCompose(x -> createSegmentSealedEpochRecords(activeEpochRecord.getSegments().stream().map(StreamSegmentRecord::segmentId).collect(Collectors.toList()), duplicateTxnEpoch.getEpoch(), context)).thenCompose(x -> createSegmentSealedEpochRecords(duplicateTxnEpoch.getSegments().stream().map(StreamSegmentRecord::segmentId).collect(Collectors.toList()), duplicateActiveEpoch.getEpoch(), context));
}).thenCompose(r -> updateSealedSegmentSizes(sealedTxnEpochSegments, context));
}));
}
use of io.pravega.controller.store.VersionedMetadata in project pravega by pravega.
the class PersistentStreamBase method sealActiveTxn.
/**
* Seal a transaction in OPEN/COMMITTING_TXN/ABORTING state. This method does CAS on the transaction VersionedMetadata node if
* the transaction is in OPEN state, optionally checking version of transaction VersionedMetadata node, if required.
*
* @param epoch transaction epoch.
* @param txId transaction identifier.
* @param commit boolean indicating whether to commit or abort the transaction.
* @param version optional expected version of transaction node to validate before updating it.
* @param writerId writer Id
* @param timestamp commit timestamp supplied by writer
* @return a pair containing transaction status and its epoch.
*/
private CompletableFuture<SimpleEntry<TxnStatus, Integer>> sealActiveTxn(final int epoch, final UUID txId, final boolean commit, final Optional<Version> version, final String writerId, final long timestamp, OperationContext context) {
return getActiveTx(epoch, txId, context).thenCompose(data -> {
ActiveTxnRecord txnRecord = data.getObject();
Version dataVersion = version.orElseGet(data::getVersion);
TxnStatus status = txnRecord.getTxnStatus();
switch(status) {
case OPEN:
return sealActiveTx(epoch, txId, commit, txnRecord, dataVersion, writerId, timestamp, context).thenApply(y -> new SimpleEntry<>(commit ? TxnStatus.COMMITTING : TxnStatus.ABORTING, epoch));
case COMMITTING:
case COMMITTED:
if (commit) {
return CompletableFuture.completedFuture(new SimpleEntry<>(status, epoch));
} else {
throw StoreException.create(StoreException.Type.ILLEGAL_STATE, "Stream: " + getName() + " Transaction: " + txId.toString() + " State: " + status.name());
}
case ABORTING:
case ABORTED:
if (commit) {
throw StoreException.create(StoreException.Type.ILLEGAL_STATE, "Stream: " + getName() + " Transaction: " + txId.toString() + " State: " + status.name());
} else {
return CompletableFuture.completedFuture(new SimpleEntry<>(status, epoch));
}
default:
throw StoreException.create(StoreException.Type.DATA_NOT_FOUND, "Stream: " + getName() + " Transaction: " + txId.toString());
}
});
}
use of io.pravega.controller.store.VersionedMetadata in project pravega by pravega.
the class PersistentStreamBase method startUpdateConfiguration.
/**
* Update configuration at configurationPath.
*
* @param newConfiguration new stream configuration.
* @return future of operation.
*/
@Override
public CompletableFuture<Void> startUpdateConfiguration(final StreamConfiguration newConfiguration, OperationContext context) {
return getVersionedConfigurationRecord(context).thenCompose(configRecord -> {
Preconditions.checkArgument(!configRecord.getObject().isUpdating());
StreamConfiguration oldCfg = configRecord.getObject().getStreamConfiguration();
// Check for tags that needs to be removed.
Set<String> currentTags = new HashSet<>(oldCfg.getTags());
currentTags.removeAll(newConfiguration.getTags());
// Create a StreamConfigurationRecord with the newer Configuration.
StreamConfigurationRecord update;
if (StreamConfiguration.isTagOnlyChange(oldCfg, newConfiguration)) {
update = StreamConfigurationRecord.updateTag(scope, name, newConfiguration, currentTags);
} else {
update = StreamConfigurationRecord.update(scope, name, newConfiguration, currentTags);
}
// Update this in the metadata Stoe.
return Futures.toVoid(setConfigurationData(new VersionedMetadata<>(update, configRecord.getVersion()), context));
});
}
use of io.pravega.controller.store.VersionedMetadata in project pravega by pravega.
the class PersistentStreamBase method scaleOldSegmentsSealed.
@Override
public CompletableFuture<Void> scaleOldSegmentsSealed(Map<Long, Long> sealedSegmentSizes, VersionedMetadata<EpochTransitionRecord> record, OperationContext context) {
Preconditions.checkNotNull(context, "Operation context cannot be null");
EpochTransitionRecord epochTransition = record.getObject();
return Futures.toVoid(clearMarkers(epochTransition.getSegmentsToSeal(), context).thenCompose(x -> updateSealedSegmentSizes(sealedSegmentSizes, context)).thenCompose(x -> updateCurrentEpochRecord(epochTransition.getNewEpoch(), context)));
}
use of io.pravega.controller.store.VersionedMetadata in project pravega by pravega.
the class AbstractReaderGroup method startUpdateConfiguration.
@Override
public CompletableFuture<Void> startUpdateConfiguration(ReaderGroupConfig configuration, OperationContext context) {
return getVersionedConfigurationRecord(context).thenCompose(configRecord -> {
Preconditions.checkArgument(!configRecord.getObject().isUpdating());
Preconditions.checkArgument(configRecord.getObject().getGeneration() == configuration.getGeneration());
ReaderGroupConfigRecord update = ReaderGroupConfigRecord.update(configuration, configuration.getGeneration() + 1, true);
return Futures.toVoid(setConfigurationData(new VersionedMetadata<>(update, configRecord.getVersion()), context));
});
}
Aggregations