use of io.pravega.controller.store.stream.OperationContext in project pravega by pravega.
the class StreamMetadataTasks method checkScale.
/**
* Helper method to check if scale operation against an epoch completed or not.
*
* @param scope scope.
* @param stream stream name.
* @param epoch stream epoch.
* @param requestId request id.
* @return returns the newly created segments.
*/
public CompletableFuture<ScaleStatusResponse> checkScale(String scope, String stream, int epoch, long requestId) {
OperationContext context = streamMetadataStore.createStreamContext(scope, stream, requestId);
CompletableFuture<EpochRecord> activeEpochFuture = streamMetadataStore.getActiveEpoch(scope, stream, context, true, executor);
CompletableFuture<State> stateFuture = streamMetadataStore.getState(scope, stream, true, context, executor);
CompletableFuture<EpochTransitionRecord> etrFuture = streamMetadataStore.getEpochTransition(scope, stream, context, executor).thenApply(VersionedMetadata::getObject);
return CompletableFuture.allOf(stateFuture, activeEpochFuture, etrFuture).handle((r, ex) -> {
ScaleStatusResponse.Builder response = ScaleStatusResponse.newBuilder();
if (ex != null) {
Throwable e = Exceptions.unwrap(ex);
if (e instanceof StoreException.DataNotFoundException) {
response.setStatus(ScaleStatusResponse.ScaleStatus.INVALID_INPUT);
} else {
response.setStatus(ScaleStatusResponse.ScaleStatus.INTERNAL_ERROR);
}
} else {
EpochRecord activeEpoch = activeEpochFuture.join();
State state = stateFuture.join();
EpochTransitionRecord etr = etrFuture.join();
if (epoch > activeEpoch.getEpoch()) {
response.setStatus(ScaleStatusResponse.ScaleStatus.INVALID_INPUT);
} else if (activeEpoch.getEpoch() == epoch || activeEpoch.getReferenceEpoch() == epoch) {
response.setStatus(ScaleStatusResponse.ScaleStatus.IN_PROGRESS);
} else {
// has not completed.
if (epoch + 1 == activeEpoch.getReferenceEpoch() && state.equals(State.SCALING) && (etr.equals(EpochTransitionRecord.EMPTY) || etr.getNewEpoch() == activeEpoch.getEpoch())) {
response.setStatus(ScaleStatusResponse.ScaleStatus.IN_PROGRESS);
} else {
response.setStatus(ScaleStatusResponse.ScaleStatus.SUCCESS);
}
}
}
return response.build();
});
}
use of io.pravega.controller.store.stream.OperationContext in project pravega by pravega.
the class StreamMetadataTasks method createMarkStream.
/**
* Method to create mark stream linked to the base stream. Mark Stream is a special single segmented dedicated
* internal stream where watermarks for the said stream are stored.
* @param scope scope for base stream
* @param baseStream name of base stream
* @param timestamp timestamp
* @param requestId request id for stream creation.
* @return Completable future which is completed successfully when the internal mark stream is created
*/
private CompletableFuture<Void> createMarkStream(String scope, String baseStream, long timestamp, long requestId) {
String markStream = NameUtils.getMarkStreamForStream(baseStream);
StreamConfiguration config = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.fixed(1)).build();
OperationContext context = streamMetadataStore.createStreamContext(scope, markStream, requestId);
return this.streamMetadataStore.createStream(scope, markStream, config, timestamp, context, executor).thenCompose(response -> {
final long segmentId = NameUtils.computeSegmentId(response.getStartingSegmentNumber(), 0);
return notifyNewSegment(scope, markStream, segmentId, response.getConfiguration().getScalingPolicy(), this.retrieveDelegationToken(), requestId, config.getRolloverSizeBytes());
}).thenCompose(v -> {
return streamMetadataStore.getVersionedState(scope, markStream, context, executor).thenCompose(state -> Futures.toVoid(streamMetadataStore.updateVersionedState(scope, markStream, State.ACTIVE, state, context, executor)));
});
}
use of io.pravega.controller.store.stream.OperationContext in project pravega by pravega.
the class StreamMetadataTasks method listSubscribers.
/**
* Get list of subscribers for a Stream.
* Subscribers are ReaderGroups reading from a Stream such that their reads impact data retention in the Stream.
* @param scope scope.
* @param stream stream name.
* @param requestId request id
* @return update status.
*/
public CompletableFuture<SubscribersResponse> listSubscribers(String scope, String stream, long requestId) {
final OperationContext context = streamMetadataStore.createStreamContext(scope, stream, requestId);
return streamMetadataStore.checkStreamExists(scope, stream, context, executor).thenCompose(exists -> {
if (!exists) {
return CompletableFuture.completedFuture(SubscribersResponse.newBuilder().setStatus(SubscribersResponse.Status.STREAM_NOT_FOUND).build());
}
// 2. get subscribers
return streamMetadataStore.listSubscribers(scope, stream, context, executor).thenApply(result -> SubscribersResponse.newBuilder().setStatus(SubscribersResponse.Status.SUCCESS).addAllSubscribers(result).build()).exceptionally(ex -> {
log.error(requestId, "Exception trying to get list of subscribers for Stream {}. Cause {}", NameUtils.getScopedStreamName(scope, stream), ex);
Throwable cause = Exceptions.unwrap(ex);
if (cause instanceof TimeoutException) {
throw new CompletionException(cause);
} else {
return SubscribersResponse.newBuilder().setStatus(SubscribersResponse.Status.FAILURE).build();
}
});
});
}
use of io.pravega.controller.store.stream.OperationContext in project pravega by pravega.
the class StreamMetadataTasks method manualScale.
/**
* Helper method to perform scale operation against an scale request.
* This method posts a request in the request stream and then starts the scale operation while
* tracking it's progress. Eventually, after scale completion, it sends a response to the caller.
*
* @param scope scope.
* @param stream stream name.
* @param segmentsToSeal segments to be sealed.
* @param newRanges key ranges for new segments.
* @param scaleTimestamp scaling time stamp.
* @param requestId request id
* @return returns the newly created segments.
*/
public CompletableFuture<ScaleResponse> manualScale(String scope, String stream, List<Long> segmentsToSeal, List<Map.Entry<Double, Double>> newRanges, long scaleTimestamp, long requestId) {
final OperationContext context = streamMetadataStore.createStreamContext(scope, stream, requestId);
ScaleOpEvent event = new ScaleOpEvent(scope, stream, segmentsToSeal, newRanges, true, scaleTimestamp, requestId);
return eventHelperFuture.thenCompose(eventHelper -> eventHelper.addIndexAndSubmitTask(event, () -> streamMetadataStore.submitScale(scope, stream, segmentsToSeal, new ArrayList<>(newRanges), scaleTimestamp, null, context, executor)).handle((startScaleResponse, e) -> {
ScaleResponse.Builder response = ScaleResponse.newBuilder();
if (e != null) {
Throwable cause = Exceptions.unwrap(e);
if (cause instanceof EpochTransitionOperationExceptions.PreConditionFailureException) {
response.setStatus(ScaleResponse.ScaleStreamStatus.PRECONDITION_FAILED);
} else {
log.error(requestId, "Scale for stream {}/{} failed with exception {}", scope, stream, cause);
response.setStatus(ScaleResponse.ScaleStreamStatus.FAILURE);
}
} else {
log.info(requestId, "scale for stream {}/{} started successfully", scope, stream);
response.setStatus(ScaleResponse.ScaleStreamStatus.STARTED);
response.addAllSegments(startScaleResponse.getObject().getNewSegmentsWithRange().entrySet().stream().map(segment -> convert(scope, stream, segment)).collect(Collectors.toList()));
response.setEpoch(startScaleResponse.getObject().getActiveEpoch());
}
return response.build();
}));
}
use of io.pravega.controller.store.stream.OperationContext in project pravega by pravega.
the class StreamMetadataTasks method createRGStream.
/**
* Method to create a State Synchronizer Stream for a Reader Group.
*
* @param scope scope.
* @param stream State Synchronizer stream name.
* @param config stream configuration.
* @param createTimestamp creation timestamp.
* @param numOfRetries number of retries for LockFailedException
* @param requestId requestId
* @return CompletableFuture which when completed will have creation status for the stream.
*/
public CompletableFuture<CreateStreamStatus.Status> createRGStream(String scope, String stream, StreamConfiguration config, long createTimestamp, int numOfRetries, long requestId) {
Preconditions.checkNotNull(config, "streamConfig");
Preconditions.checkArgument(createTimestamp >= 0);
NameUtils.validateStreamName(stream);
OperationContext context = streamMetadataStore.createStreamContext(scope, stream, requestId);
return Futures.exceptionallyExpecting(streamMetadataStore.getState(scope, stream, true, context, executor), e -> Exceptions.unwrap(e) instanceof StoreException.DataNotFoundException, State.UNKNOWN).thenCompose(state -> {
if (state.equals(State.UNKNOWN) || state.equals(State.CREATING)) {
log.debug(requestId, "Creating StateSynchronizer Stream {}", stream);
return createStreamRetryOnLockFailure(scope, stream, config, createTimestamp, numOfRetries, requestId);
} else {
return CompletableFuture.completedFuture(CreateStreamStatus.Status.STREAM_EXISTS);
}
});
}
Aggregations