use of io.pravega.controller.store.stream.OperationContext in project pravega by pravega.
the class StreamMetadataTasks method generateStreamCut.
/**
* Generate a new stream cut.
*
* @param scope scope.
* @param stream stream name.
* @param contextOpt optional context
* @param delegationToken token to be sent to segmentstore.
* @param previous previous stream cut record
* @return streamCut.
*/
public CompletableFuture<StreamCutRecord> generateStreamCut(final String scope, final String stream, final StreamCutRecord previous, final OperationContext contextOpt, String delegationToken) {
final OperationContext context = contextOpt != null ? contextOpt : streamMetadataStore.createStreamContext(scope, stream, ControllerService.nextRequestId());
return streamMetadataStore.getActiveSegments(scope, stream, context, executor).thenCompose(activeSegments -> Futures.allOfWithResults(activeSegments.stream().parallel().collect(Collectors.toMap(x -> x, x -> getSegmentOffset(scope, stream, x.segmentId(), delegationToken, context.getRequestId()))))).thenCompose(map -> {
final long generationTime = retentionClock.get().get();
ImmutableMap.Builder<Long, Long> builder = ImmutableMap.builder();
map.forEach((key, value) -> builder.put(key.segmentId(), value));
ImmutableMap<Long, Long> streamCutMap = builder.build();
return streamMetadataStore.getSizeTillStreamCut(scope, stream, streamCutMap, Optional.ofNullable(previous), context, executor).thenApply(sizeTill -> new StreamCutRecord(generationTime, sizeTill, streamCutMap));
});
}
use of io.pravega.controller.store.stream.OperationContext in project pravega by pravega.
the class StreamMetadataTasks method updateReaderGroup.
/**
* Update Reader Group Configuration.
*
* @param scope Reader Group scope.
* @param rgName Reader Group name.
* @param config New Reader Group config.
* @param requestId request id.
* @return updation status.
*/
public CompletableFuture<UpdateReaderGroupResponse> updateReaderGroup(final String scope, final String rgName, final ReaderGroupConfig config, long requestId) {
final OperationContext context = streamMetadataStore.createRGContext(scope, rgName, requestId);
return RetryHelper.withRetriesAsync(() -> {
// 1. check if Reader Group exists...
return streamMetadataStore.checkReaderGroupExists(scope, rgName, context, executor).thenCompose(exists -> {
if (!exists) {
UpdateReaderGroupResponse response = UpdateReaderGroupResponse.newBuilder().setStatus(UpdateReaderGroupResponse.Status.RG_NOT_FOUND).setGeneration(config.getGeneration()).build();
return CompletableFuture.completedFuture(response);
}
// 2. check for generation && ID match with existing config
return streamMetadataStore.getReaderGroupConfigRecord(scope, rgName, context, executor).thenCompose(rgConfigRecord -> {
if (rgConfigRecord.getObject().getGeneration() != config.getGeneration()) {
UpdateReaderGroupResponse response = UpdateReaderGroupResponse.newBuilder().setStatus(UpdateReaderGroupResponse.Status.INVALID_CONFIG).setGeneration(config.getGeneration()).build();
return CompletableFuture.completedFuture(response);
}
if (!rgConfigRecord.getObject().isUpdating()) {
return streamMetadataStore.getReaderGroupId(scope, rgName, context, executor).thenCompose(rgId -> {
if (!config.getReaderGroupId().equals(rgId)) {
UpdateReaderGroupResponse response = UpdateReaderGroupResponse.newBuilder().setStatus(UpdateReaderGroupResponse.Status.INVALID_CONFIG).setGeneration(config.getGeneration()).build();
return CompletableFuture.completedFuture(response);
}
ImmutableSet<String> removeStreams = getStreamsToBeUnsubscribed(rgConfigRecord.getObject(), config);
boolean isTransition = isTransitionToOrFromSubscriber(rgConfigRecord.getObject(), config);
UpdateReaderGroupEvent event = new UpdateReaderGroupEvent(scope, rgName, requestId, rgId, rgConfigRecord.getObject().getGeneration() + 1, isTransition, removeStreams);
// 3. Create Reader Group Metadata and submit event
return eventHelperFuture.thenCompose(eventHelper -> eventHelper.addIndexAndSubmitTask(event, () -> streamMetadataStore.startRGConfigUpdate(scope, rgName, config, context, executor)).thenCompose(x -> eventHelper.checkDone(() -> isRGUpdated(scope, rgName, executor, context)).thenCompose(y -> streamMetadataStore.getReaderGroupConfigRecord(scope, rgName, context, executor).thenApply(configRecord -> {
UpdateReaderGroupResponse response = UpdateReaderGroupResponse.newBuilder().setStatus(UpdateReaderGroupResponse.Status.SUCCESS).setGeneration(configRecord.getObject().getGeneration()).build();
return response;
}))));
});
} else {
log.error(requestId, "Reader group config update failed as another update was in progress.");
UpdateReaderGroupResponse response = UpdateReaderGroupResponse.newBuilder().setStatus(UpdateReaderGroupResponse.Status.FAILURE).setGeneration(config.getGeneration()).build();
return CompletableFuture.completedFuture(response);
}
});
});
}, e -> Exceptions.unwrap(e) instanceof RetryableException, READER_GROUP_OPERATION_MAX_RETRIES, executor);
}
use of io.pravega.controller.store.stream.OperationContext in project pravega by pravega.
the class StreamMetadataTasks method createReaderGroupInternal.
public CompletableFuture<CreateReaderGroupResponse> createReaderGroupInternal(final String scope, final String rgName, final ReaderGroupConfig config, final long createTimestamp, long requestId) {
Preconditions.checkNotNull(scope, "ReaderGroup scope is null");
Preconditions.checkNotNull(rgName, "ReaderGroup name is null");
Preconditions.checkNotNull(config, "ReaderGroup config is null");
Preconditions.checkArgument(createTimestamp >= 0);
try {
NameUtils.validateReaderGroupName(rgName);
} catch (IllegalArgumentException | NullPointerException e) {
return CompletableFuture.completedFuture(CreateReaderGroupResponse.newBuilder().setStatus(CreateReaderGroupResponse.Status.INVALID_RG_NAME).build());
}
OperationContext context = streamMetadataStore.createRGContext(scope, rgName, requestId);
return RetryHelper.withRetriesAsync(() -> {
// 1. check if scope with this name exists...
return streamMetadataStore.checkScopeExists(scope, context, executor).thenCompose(exists -> {
if (!exists) {
return CompletableFuture.completedFuture(CreateReaderGroupResponse.newBuilder().setStatus(CreateReaderGroupResponse.Status.SCOPE_NOT_FOUND).build());
}
// 2. check state of the ReaderGroup
return isRGCreationComplete(scope, rgName, context).thenCompose(complete -> {
if (!complete) {
return validateReaderGroupId(config).thenCompose(conf -> streamMetadataStore.addReaderGroupToScope(scope, rgName, conf.getReaderGroupId(), context, executor).thenCompose(x -> createReaderGroupTasks(scope, rgName, conf, createTimestamp, context)).thenCompose(status -> {
if (CreateReaderGroupResponse.Status.SUCCESS.equals(status)) {
return buildCreateSuccessResponse(scope, rgName, context);
} else {
return CompletableFuture.completedFuture(CreateReaderGroupResponse.newBuilder().setStatus(status).build());
}
}));
}
return buildCreateSuccessResponse(scope, rgName, context);
});
});
}, e -> Exceptions.unwrap(e) instanceof RetryableException, 10, executor);
}
use of io.pravega.controller.store.stream.OperationContext in project pravega by pravega.
the class StreamMetadataTasks method retention.
/**
* Method to check retention policy and generate new periodic cuts and/or truncate stream at an existing stream cut.
*
* @param scope scope
* @param stream stream
* @param policy retention policy
* @param recordingTime time of recording
* @param contextOpt operation context
* @param delegationToken token to be sent to segmentstore to authorize this operation.
* @return future.
*/
public CompletableFuture<Void> retention(final String scope, final String stream, final RetentionPolicy policy, final long recordingTime, final OperationContext contextOpt, final String delegationToken) {
Preconditions.checkNotNull(policy);
final OperationContext context = contextOpt != null ? contextOpt : streamMetadataStore.createStreamContext(scope, stream, ControllerService.nextRequestId());
return streamMetadataStore.getRetentionSet(scope, stream, context, executor).thenCompose(retentionSet -> {
StreamCutReferenceRecord latestCut = retentionSet.getLatest();
return generateStreamCutIfRequired(scope, stream, latestCut, recordingTime, context, delegationToken).thenCompose(newRecord -> truncate(scope, stream, policy, context, retentionSet, newRecord));
}).thenAccept(x -> StreamMetrics.reportRetentionEvent(scope, stream));
}
use of io.pravega.controller.store.stream.OperationContext in project pravega by pravega.
the class StreamMetadataTasks method createReaderGroupTasks.
public CompletableFuture<CreateReaderGroupResponse.Status> createReaderGroupTasks(final String scope, final String readerGroup, final ReaderGroupConfig config, final long createTimestamp, final OperationContext context) {
Preconditions.checkNotNull(context, "operation context not null");
return streamMetadataStore.createReaderGroup(scope, readerGroup, config, createTimestamp, context, executor).thenCompose(v -> {
if (!ReaderGroupConfig.StreamDataRetention.NONE.equals(config.getRetentionType())) {
String scopedRGName = NameUtils.getScopedReaderGroupName(scope, readerGroup);
// update Stream metadata tables, only if RG is a Subscriber
Iterator<String> streamIter = config.getStartingStreamCuts().keySet().stream().map(Stream::getScopedName).iterator();
return Futures.loop(streamIter::hasNext, () -> {
Stream stream = Stream.of(streamIter.next());
return streamMetadataStore.addSubscriber(stream.getScope(), stream.getStreamName(), scopedRGName, config.getGeneration(), context, executor);
}, executor);
}
return CompletableFuture.completedFuture(null);
}).thenCompose(x -> createRGStream(scope, NameUtils.getStreamForReaderGroup(readerGroup), StreamConfiguration.builder().scalingPolicy(ScalingPolicy.fixed(1)).rolloverSizeBytes(READER_GROUP_SEGMENT_ROLLOVER_SIZE_BYTES).build(), System.currentTimeMillis(), 10, getRequestId(context)).thenCompose(createStatus -> {
if (createStatus.equals(Controller.CreateStreamStatus.Status.STREAM_EXISTS) || createStatus.equals(Controller.CreateStreamStatus.Status.SUCCESS)) {
return streamMetadataStore.getVersionedReaderGroupState(scope, readerGroup, true, context, executor).thenCompose(newstate -> streamMetadataStore.updateReaderGroupVersionedState(scope, readerGroup, ReaderGroupState.ACTIVE, newstate, context, executor)).thenApply(v1 -> CreateReaderGroupResponse.Status.SUCCESS);
}
return Futures.failedFuture(new IllegalStateException(String.format("Error creating StateSynchronizer Stream for Reader Group %s: %s", readerGroup, createStatus.toString())));
})).exceptionally(ex -> {
log.warn(getRequestId(context), "Error creating StateSynchronizer Stream:{} for Reader Group: {}. Exception: {} ", NameUtils.getStreamForReaderGroup(readerGroup), readerGroup, ex.getMessage());
Throwable cause = Exceptions.unwrap(ex);
throw new CompletionException(cause);
});
}
Aggregations