Search in sources :

Example 1 with ServerError

use of org.apache.pulsar.common.api.proto.PulsarApi.ServerError in project incubator-pulsar by apache.

the class ServerCnx method handlePartitionMetadataRequest.

@Override
protected void handlePartitionMetadataRequest(CommandPartitionedTopicMetadata partitionMetadata) {
    final long requestId = partitionMetadata.getRequestId();
    if (log.isDebugEnabled()) {
        log.debug("[{}] Received PartitionMetadataLookup from {} for {}", partitionMetadata.getTopic(), remoteAddress, requestId);
    }
    TopicName topicName = validateTopicName(partitionMetadata.getTopic(), requestId, partitionMetadata);
    if (topicName == null) {
        return;
    }
    String originalPrincipal = null;
    if (authenticateOriginalAuthData && partitionMetadata.hasOriginalAuthData()) {
        originalPrincipal = validateOriginalPrincipal(partitionMetadata.hasOriginalAuthData() ? partitionMetadata.getOriginalAuthData() : null, partitionMetadata.hasOriginalAuthMethod() ? partitionMetadata.getOriginalAuthMethod() : null, partitionMetadata.hasOriginalPrincipal() ? partitionMetadata.getOriginalPrincipal() : this.originalPrincipal, requestId, partitionMetadata);
        if (originalPrincipal == null) {
            return;
        }
    } else {
        originalPrincipal = partitionMetadata.hasOriginalPrincipal() ? partitionMetadata.getOriginalPrincipal() : this.originalPrincipal;
    }
    final Semaphore lookupSemaphore = service.getLookupRequestSemaphore();
    if (lookupSemaphore.tryAcquire()) {
        if (invalidOriginalPrincipal(originalPrincipal)) {
            final String msg = "Valid Proxy Client role should be provided for getPartitionMetadataRequest ";
            log.warn("[{}] {} with role {} and proxyClientAuthRole {} on topic {}", remoteAddress, msg, authRole, originalPrincipal, topicName);
            ctx.writeAndFlush(Commands.newPartitionMetadataResponse(ServerError.AuthorizationError, msg, requestId));
            lookupSemaphore.release();
            return;
        }
        CompletableFuture<Boolean> isProxyAuthorizedFuture;
        if (service.isAuthorizationEnabled() && originalPrincipal != null) {
            isProxyAuthorizedFuture = service.getAuthorizationService().canLookupAsync(topicName, authRole, authenticationData);
        } else {
            isProxyAuthorizedFuture = CompletableFuture.completedFuture(true);
        }
        String finalOriginalPrincipal = originalPrincipal;
        isProxyAuthorizedFuture.thenApply(isProxyAuthorized -> {
            if (isProxyAuthorized) {
                getPartitionedTopicMetadata(getBrokerService().pulsar(), finalOriginalPrincipal != null ? finalOriginalPrincipal : authRole, authenticationData, topicName).handle((metadata, ex) -> {
                    if (ex == null) {
                        int partitions = metadata.partitions;
                        ctx.writeAndFlush(Commands.newPartitionMetadataResponse(partitions, requestId));
                    } else {
                        if (ex instanceof PulsarClientException) {
                            log.warn("Failed to authorize {} at [{}] on topic {} : {}", getRole(), remoteAddress, topicName, ex.getMessage());
                            ctx.writeAndFlush(Commands.newPartitionMetadataResponse(ServerError.AuthorizationError, ex.getMessage(), requestId));
                        } else {
                            log.warn("Failed to get Partitioned Metadata [{}] {}: {}", remoteAddress, topicName, ex.getMessage(), ex);
                            ServerError error = (ex instanceof RestException) && ((RestException) ex).getResponse().getStatus() < 500 ? ServerError.MetadataError : ServerError.ServiceNotReady;
                            ctx.writeAndFlush(Commands.newPartitionMetadataResponse(error, ex.getMessage(), requestId));
                        }
                    }
                    lookupSemaphore.release();
                    return null;
                });
            } else {
                final String msg = "Proxy Client is not authorized to Get Partition Metadata";
                log.warn("[{}] {} with role {} on topic {}", remoteAddress, msg, authRole, topicName);
                ctx.writeAndFlush(Commands.newPartitionMetadataResponse(ServerError.AuthorizationError, msg, requestId));
                lookupSemaphore.release();
            }
            return null;
        }).exceptionally(ex -> {
            final String msg = "Exception occured while trying to authorize get Partition Metadata";
            log.warn("[{}] {} with role {} on topic {}", remoteAddress, msg, authRole, topicName);
            ctx.writeAndFlush(Commands.newPartitionMetadataResponse(ServerError.AuthorizationError, msg, requestId));
            lookupSemaphore.release();
            return null;
        });
    } else {
        if (log.isDebugEnabled()) {
            log.debug("[{}] Failed Partition-Metadata lookup due to too many lookup-requests {}", remoteAddress, topicName);
        }
        ctx.writeAndFlush(Commands.newPartitionMetadataResponse(ServerError.TooManyRequests, "Failed due to too many pending lookup requests", requestId));
    }
}
Also used : PulsarApi(org.apache.pulsar.common.api.proto.PulsarApi) ServiceUnitNotReadyException(org.apache.pulsar.broker.service.BrokerServiceException.ServiceUnitNotReadyException) CommandUtils(org.apache.pulsar.common.api.CommandUtils) SocketAddress(java.net.SocketAddress) PersistentTopicsBase.getPartitionedTopicMetadata(org.apache.pulsar.broker.admin.impl.PersistentTopicsBase.getPartitionedTopicMetadata) SchemaVersion(org.apache.pulsar.common.schema.SchemaVersion) CommandAck(org.apache.pulsar.common.api.proto.PulsarApi.CommandAck) LoggerFactory(org.slf4j.LoggerFactory) AuthenticationException(javax.naming.AuthenticationException) StringUtils(org.apache.commons.lang3.StringUtils) CommandCloseConsumer(org.apache.pulsar.common.api.proto.PulsarApi.CommandCloseConsumer) CommandGetLastMessageId(org.apache.pulsar.common.api.proto.PulsarApi.CommandGetLastMessageId) CommandSend(org.apache.pulsar.common.api.proto.PulsarApi.CommandSend) ServerError(org.apache.pulsar.common.api.proto.PulsarApi.ServerError) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) PulsarHandler(org.apache.pulsar.common.api.PulsarHandler) Map(java.util.Map) RestException(org.apache.pulsar.broker.web.RestException) NamespaceName(org.apache.pulsar.common.naming.NamespaceName) CommandGetTopicsOfNamespace(org.apache.pulsar.common.api.proto.PulsarApi.CommandGetTopicsOfNamespace) PulsarClientException(org.apache.pulsar.client.api.PulsarClientException) ProtocolVersion.v5(org.apache.pulsar.common.api.proto.PulsarApi.ProtocolVersion.v5) PositionImpl(org.apache.bookkeeper.mledger.impl.PositionImpl) CommandConnect(org.apache.pulsar.common.api.proto.PulsarApi.CommandConnect) Commands(org.apache.pulsar.common.api.Commands) Commands.newLookupErrorResponse(org.apache.pulsar.common.api.Commands.newLookupErrorResponse) CommandSubscribe(org.apache.pulsar.common.api.proto.PulsarApi.CommandSubscribe) Set(java.util.Set) CommandRedeliverUnacknowledgedMessages(org.apache.pulsar.common.api.proto.PulsarApi.CommandRedeliverUnacknowledgedMessages) Position(org.apache.bookkeeper.mledger.Position) CommandCloseProducer(org.apache.pulsar.common.api.proto.PulsarApi.CommandCloseProducer) CommandFlow(org.apache.pulsar.common.api.proto.PulsarApi.CommandFlow) Collectors(java.util.stream.Collectors) AuthenticationDataSource(org.apache.pulsar.broker.authentication.AuthenticationDataSource) MessageIdImpl(org.apache.pulsar.client.impl.MessageIdImpl) List(java.util.List) StringUtils.isNotBlank(org.apache.commons.lang3.StringUtils.isNotBlank) BatchMessageIdImpl(org.apache.pulsar.client.impl.BatchMessageIdImpl) SafeRun(org.apache.bookkeeper.mledger.util.SafeRun) SslHandler(io.netty.handler.ssl.SslHandler) SchemaData(org.apache.pulsar.common.schema.SchemaData) CommandConsumerStatsResponse(org.apache.pulsar.common.api.proto.PulsarApi.CommandConsumerStatsResponse) CommandPartitionedTopicMetadata(org.apache.pulsar.common.api.proto.PulsarApi.CommandPartitionedTopicMetadata) MessageIdData(org.apache.pulsar.common.api.proto.PulsarApi.MessageIdData) ClientCnx(org.apache.pulsar.client.impl.ClientCnx) TopicName(org.apache.pulsar.common.naming.TopicName) ChannelOption(io.netty.channel.ChannelOption) CommandConsumerStats(org.apache.pulsar.common.api.proto.PulsarApi.CommandConsumerStats) GeneratedMessageLite(com.google.protobuf.GeneratedMessageLite) BacklogQuota(org.apache.pulsar.common.policies.data.BacklogQuota) CompletableFuture(java.util.concurrent.CompletableFuture) ProtocolVersion(org.apache.pulsar.common.api.proto.PulsarApi.ProtocolVersion) SchemaType(org.apache.pulsar.common.schema.SchemaType) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) ServerMetadataException(org.apache.pulsar.broker.service.BrokerServiceException.ServerMetadataException) SSLSession(javax.net.ssl.SSLSession) ByteBuf(io.netty.buffer.ByteBuf) MessageMetadata(org.apache.pulsar.common.api.proto.PulsarApi.MessageMetadata) CommandProducer(org.apache.pulsar.common.api.proto.PulsarApi.CommandProducer) CommandSeek(org.apache.pulsar.common.api.proto.PulsarApi.CommandSeek) AuthenticationDataCommand(org.apache.pulsar.broker.authentication.AuthenticationDataCommand) Metadata(org.apache.pulsar.common.naming.Metadata) Logger(org.slf4j.Logger) SubType(org.apache.pulsar.common.api.proto.PulsarApi.CommandSubscribe.SubType) Semaphore(java.util.concurrent.Semaphore) CommandLookupTopic(org.apache.pulsar.common.api.proto.PulsarApi.CommandLookupTopic) TimeUnit(java.util.concurrent.TimeUnit) CommandUnsubscribe(org.apache.pulsar.common.api.proto.PulsarApi.CommandUnsubscribe) ConcurrentLongHashMap(org.apache.pulsar.common.util.collections.ConcurrentLongHashMap) TopicLookup.lookupTopicAsync(org.apache.pulsar.broker.lookup.TopicLookup.lookupTopicAsync) PulsarServerException(org.apache.pulsar.broker.PulsarServerException) ConsumerBusyException(org.apache.pulsar.broker.service.BrokerServiceException.ConsumerBusyException) ChannelHandler(io.netty.channel.ChannelHandler) ConsumerStats(org.apache.pulsar.common.policies.data.ConsumerStats) InitialPosition(org.apache.pulsar.common.api.proto.PulsarApi.CommandSubscribe.InitialPosition) ServerError(org.apache.pulsar.common.api.proto.PulsarApi.ServerError) PulsarClientException(org.apache.pulsar.client.api.PulsarClientException) RestException(org.apache.pulsar.broker.web.RestException) Semaphore(java.util.concurrent.Semaphore) TopicName(org.apache.pulsar.common.naming.TopicName)

Example 2 with ServerError

use of org.apache.pulsar.common.api.proto.PulsarApi.ServerError in project incubator-pulsar by apache.

the class ServerCnx method handleSubscribe.

@Override
protected void handleSubscribe(final CommandSubscribe subscribe) {
    checkArgument(state == State.Connected);
    final long requestId = subscribe.getRequestId();
    final long consumerId = subscribe.getConsumerId();
    TopicName topicName = validateTopicName(subscribe.getTopic(), requestId, subscribe);
    if (topicName == null) {
        return;
    }
    if (invalidOriginalPrincipal(originalPrincipal)) {
        final String msg = "Valid Proxy Client role should be provided while subscribing ";
        log.warn("[{}] {} with role {} and proxyClientAuthRole {} on topic {}", remoteAddress, msg, authRole, originalPrincipal, topicName);
        ctx.writeAndFlush(Commands.newError(requestId, ServerError.AuthorizationError, msg));
        return;
    }
    final String subscriptionName = subscribe.getSubscription();
    final SubType subType = subscribe.getSubType();
    final String consumerName = subscribe.getConsumerName();
    final boolean isDurable = subscribe.getDurable();
    final MessageIdImpl startMessageId = subscribe.hasStartMessageId() ? new BatchMessageIdImpl(subscribe.getStartMessageId().getLedgerId(), subscribe.getStartMessageId().getEntryId(), subscribe.getStartMessageId().getPartition(), subscribe.getStartMessageId().getBatchIndex()) : null;
    final String subscription = subscribe.getSubscription();
    final int priorityLevel = subscribe.hasPriorityLevel() ? subscribe.getPriorityLevel() : 0;
    final boolean readCompacted = subscribe.getReadCompacted();
    final Map<String, String> metadata = CommandUtils.metadataFromCommand(subscribe);
    final InitialPosition initialPosition = subscribe.getInitialPosition();
    CompletableFuture<Boolean> isProxyAuthorizedFuture;
    if (service.isAuthorizationEnabled() && originalPrincipal != null) {
        isProxyAuthorizedFuture = service.getAuthorizationService().canConsumeAsync(topicName, authRole, authenticationData, subscribe.getSubscription());
    } else {
        isProxyAuthorizedFuture = CompletableFuture.completedFuture(true);
    }
    isProxyAuthorizedFuture.thenApply(isProxyAuthorized -> {
        if (isProxyAuthorized) {
            CompletableFuture<Boolean> authorizationFuture;
            if (service.isAuthorizationEnabled()) {
                authorizationFuture = service.getAuthorizationService().canConsumeAsync(topicName, originalPrincipal != null ? originalPrincipal : authRole, authenticationData, subscription);
            } else {
                authorizationFuture = CompletableFuture.completedFuture(true);
            }
            authorizationFuture.thenApply(isAuthorized -> {
                if (isAuthorized) {
                    if (log.isDebugEnabled()) {
                        log.debug("[{}] Client is authorized to subscribe with role {}", remoteAddress, authRole);
                    }
                    log.info("[{}] Subscribing on topic {} / {}", remoteAddress, topicName, subscriptionName);
                    try {
                        Metadata.validateMetadata(metadata);
                    } catch (IllegalArgumentException iae) {
                        final String msg = iae.getMessage();
                        ctx.writeAndFlush(Commands.newError(requestId, ServerError.MetadataError, msg));
                        return null;
                    }
                    CompletableFuture<Consumer> consumerFuture = new CompletableFuture<>();
                    CompletableFuture<Consumer> existingConsumerFuture = consumers.putIfAbsent(consumerId, consumerFuture);
                    if (existingConsumerFuture != null) {
                        if (existingConsumerFuture.isDone() && !existingConsumerFuture.isCompletedExceptionally()) {
                            Consumer consumer = existingConsumerFuture.getNow(null);
                            log.info("[{}] Consumer with the same id is already created: {}", remoteAddress, consumer);
                            ctx.writeAndFlush(Commands.newSuccess(requestId));
                            return null;
                        } else {
                            // There was an early request to create a consumer with same consumerId. This can happen
                            // when
                            // client timeout is lower the broker timeouts. We need to wait until the previous
                            // consumer
                            // creation request either complete or fails.
                            log.warn("[{}][{}][{}] Consumer is already present on the connection", remoteAddress, topicName, subscriptionName);
                            ServerError error = !existingConsumerFuture.isDone() ? ServerError.ServiceNotReady : getErrorCode(existingConsumerFuture);
                            ctx.writeAndFlush(Commands.newError(requestId, error, "Consumer is already present on the connection"));
                            return null;
                        }
                    }
                    service.getTopic(topicName.toString()).thenCompose(topic -> topic.subscribe(ServerCnx.this, subscriptionName, consumerId, subType, priorityLevel, consumerName, isDurable, startMessageId, metadata, readCompacted, initialPosition)).thenAccept(consumer -> {
                        if (consumerFuture.complete(consumer)) {
                            log.info("[{}] Created subscription on topic {} / {}", remoteAddress, topicName, subscriptionName);
                            ctx.writeAndFlush(Commands.newSuccess(requestId), ctx.voidPromise());
                        } else {
                            // The consumer future was completed before by a close command
                            try {
                                consumer.close();
                                log.info("[{}] Cleared consumer created after timeout on client side {}", remoteAddress, consumer);
                            } catch (BrokerServiceException e) {
                                log.warn("[{}] Error closing consumer created after timeout on client side {}: {}", remoteAddress, consumer, e.getMessage());
                            }
                            consumers.remove(consumerId, consumerFuture);
                        }
                    }).exceptionally(exception -> {
                        if (exception.getCause() instanceof ConsumerBusyException) {
                            if (log.isDebugEnabled()) {
                                log.debug("[{}][{}][{}] Failed to create consumer because exclusive consumer is already connected: {}", remoteAddress, topicName, subscriptionName, exception.getCause().getMessage());
                            }
                        } else {
                            log.warn("[{}][{}][{}] Failed to create consumer: {}", remoteAddress, topicName, subscriptionName, exception.getCause().getMessage(), exception);
                        }
                        // back to client, only if not completed already.
                        if (consumerFuture.completeExceptionally(exception)) {
                            ctx.writeAndFlush(Commands.newError(requestId, BrokerServiceException.getClientErrorCode(exception.getCause()), exception.getCause().getMessage()));
                        }
                        consumers.remove(consumerId, consumerFuture);
                        return null;
                    });
                } else {
                    String msg = "Client is not authorized to subscribe";
                    log.warn("[{}] {} with role {}", remoteAddress, msg, authRole);
                    ctx.writeAndFlush(Commands.newError(requestId, ServerError.AuthorizationError, msg));
                }
                return null;
            }).exceptionally(e -> {
                String msg = String.format("[%s] %s with role %s", remoteAddress, e.getMessage(), authRole);
                log.warn(msg);
                ctx.writeAndFlush(Commands.newError(requestId, ServerError.AuthorizationError, e.getMessage()));
                return null;
            });
        } else {
            final String msg = "Proxy Client is not authorized to subscribe";
            log.warn("[{}] {} with role {} on topic {}", remoteAddress, msg, authRole, topicName);
            ctx.writeAndFlush(Commands.newError(requestId, ServerError.AuthorizationError, msg));
        }
        return null;
    }).exceptionally(ex -> {
        String msg = String.format("[%s] %s with role %s", remoteAddress, ex.getMessage(), authRole);
        if (ex.getCause() instanceof PulsarServerException) {
            log.info(msg);
        } else {
            log.warn(msg);
        }
        ctx.writeAndFlush(Commands.newError(requestId, ServerError.AuthorizationError, ex.getMessage()));
        return null;
    });
}
Also used : PulsarApi(org.apache.pulsar.common.api.proto.PulsarApi) ServiceUnitNotReadyException(org.apache.pulsar.broker.service.BrokerServiceException.ServiceUnitNotReadyException) CommandUtils(org.apache.pulsar.common.api.CommandUtils) SocketAddress(java.net.SocketAddress) PersistentTopicsBase.getPartitionedTopicMetadata(org.apache.pulsar.broker.admin.impl.PersistentTopicsBase.getPartitionedTopicMetadata) SchemaVersion(org.apache.pulsar.common.schema.SchemaVersion) CommandAck(org.apache.pulsar.common.api.proto.PulsarApi.CommandAck) LoggerFactory(org.slf4j.LoggerFactory) AuthenticationException(javax.naming.AuthenticationException) StringUtils(org.apache.commons.lang3.StringUtils) CommandCloseConsumer(org.apache.pulsar.common.api.proto.PulsarApi.CommandCloseConsumer) CommandGetLastMessageId(org.apache.pulsar.common.api.proto.PulsarApi.CommandGetLastMessageId) CommandSend(org.apache.pulsar.common.api.proto.PulsarApi.CommandSend) ServerError(org.apache.pulsar.common.api.proto.PulsarApi.ServerError) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) PulsarHandler(org.apache.pulsar.common.api.PulsarHandler) Map(java.util.Map) RestException(org.apache.pulsar.broker.web.RestException) NamespaceName(org.apache.pulsar.common.naming.NamespaceName) CommandGetTopicsOfNamespace(org.apache.pulsar.common.api.proto.PulsarApi.CommandGetTopicsOfNamespace) PulsarClientException(org.apache.pulsar.client.api.PulsarClientException) ProtocolVersion.v5(org.apache.pulsar.common.api.proto.PulsarApi.ProtocolVersion.v5) PositionImpl(org.apache.bookkeeper.mledger.impl.PositionImpl) CommandConnect(org.apache.pulsar.common.api.proto.PulsarApi.CommandConnect) Commands(org.apache.pulsar.common.api.Commands) Commands.newLookupErrorResponse(org.apache.pulsar.common.api.Commands.newLookupErrorResponse) CommandSubscribe(org.apache.pulsar.common.api.proto.PulsarApi.CommandSubscribe) Set(java.util.Set) CommandRedeliverUnacknowledgedMessages(org.apache.pulsar.common.api.proto.PulsarApi.CommandRedeliverUnacknowledgedMessages) Position(org.apache.bookkeeper.mledger.Position) CommandCloseProducer(org.apache.pulsar.common.api.proto.PulsarApi.CommandCloseProducer) CommandFlow(org.apache.pulsar.common.api.proto.PulsarApi.CommandFlow) Collectors(java.util.stream.Collectors) AuthenticationDataSource(org.apache.pulsar.broker.authentication.AuthenticationDataSource) MessageIdImpl(org.apache.pulsar.client.impl.MessageIdImpl) List(java.util.List) StringUtils.isNotBlank(org.apache.commons.lang3.StringUtils.isNotBlank) BatchMessageIdImpl(org.apache.pulsar.client.impl.BatchMessageIdImpl) SafeRun(org.apache.bookkeeper.mledger.util.SafeRun) SslHandler(io.netty.handler.ssl.SslHandler) SchemaData(org.apache.pulsar.common.schema.SchemaData) CommandConsumerStatsResponse(org.apache.pulsar.common.api.proto.PulsarApi.CommandConsumerStatsResponse) CommandPartitionedTopicMetadata(org.apache.pulsar.common.api.proto.PulsarApi.CommandPartitionedTopicMetadata) MessageIdData(org.apache.pulsar.common.api.proto.PulsarApi.MessageIdData) ClientCnx(org.apache.pulsar.client.impl.ClientCnx) TopicName(org.apache.pulsar.common.naming.TopicName) ChannelOption(io.netty.channel.ChannelOption) CommandConsumerStats(org.apache.pulsar.common.api.proto.PulsarApi.CommandConsumerStats) GeneratedMessageLite(com.google.protobuf.GeneratedMessageLite) BacklogQuota(org.apache.pulsar.common.policies.data.BacklogQuota) CompletableFuture(java.util.concurrent.CompletableFuture) ProtocolVersion(org.apache.pulsar.common.api.proto.PulsarApi.ProtocolVersion) SchemaType(org.apache.pulsar.common.schema.SchemaType) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) ServerMetadataException(org.apache.pulsar.broker.service.BrokerServiceException.ServerMetadataException) SSLSession(javax.net.ssl.SSLSession) ByteBuf(io.netty.buffer.ByteBuf) MessageMetadata(org.apache.pulsar.common.api.proto.PulsarApi.MessageMetadata) CommandProducer(org.apache.pulsar.common.api.proto.PulsarApi.CommandProducer) CommandSeek(org.apache.pulsar.common.api.proto.PulsarApi.CommandSeek) AuthenticationDataCommand(org.apache.pulsar.broker.authentication.AuthenticationDataCommand) Metadata(org.apache.pulsar.common.naming.Metadata) Logger(org.slf4j.Logger) SubType(org.apache.pulsar.common.api.proto.PulsarApi.CommandSubscribe.SubType) Semaphore(java.util.concurrent.Semaphore) CommandLookupTopic(org.apache.pulsar.common.api.proto.PulsarApi.CommandLookupTopic) TimeUnit(java.util.concurrent.TimeUnit) CommandUnsubscribe(org.apache.pulsar.common.api.proto.PulsarApi.CommandUnsubscribe) ConcurrentLongHashMap(org.apache.pulsar.common.util.collections.ConcurrentLongHashMap) TopicLookup.lookupTopicAsync(org.apache.pulsar.broker.lookup.TopicLookup.lookupTopicAsync) PulsarServerException(org.apache.pulsar.broker.PulsarServerException) ConsumerBusyException(org.apache.pulsar.broker.service.BrokerServiceException.ConsumerBusyException) ChannelHandler(io.netty.channel.ChannelHandler) ConsumerStats(org.apache.pulsar.common.policies.data.ConsumerStats) InitialPosition(org.apache.pulsar.common.api.proto.PulsarApi.CommandSubscribe.InitialPosition) PulsarServerException(org.apache.pulsar.broker.PulsarServerException) SubType(org.apache.pulsar.common.api.proto.PulsarApi.CommandSubscribe.SubType) ServerError(org.apache.pulsar.common.api.proto.PulsarApi.ServerError) MessageIdImpl(org.apache.pulsar.client.impl.MessageIdImpl) BatchMessageIdImpl(org.apache.pulsar.client.impl.BatchMessageIdImpl) InitialPosition(org.apache.pulsar.common.api.proto.PulsarApi.CommandSubscribe.InitialPosition) TopicName(org.apache.pulsar.common.naming.TopicName) CompletableFuture(java.util.concurrent.CompletableFuture) ConsumerBusyException(org.apache.pulsar.broker.service.BrokerServiceException.ConsumerBusyException) CommandCloseConsumer(org.apache.pulsar.common.api.proto.PulsarApi.CommandCloseConsumer) BatchMessageIdImpl(org.apache.pulsar.client.impl.BatchMessageIdImpl)

Example 3 with ServerError

use of org.apache.pulsar.common.api.proto.PulsarApi.ServerError in project incubator-pulsar by apache.

the class ServerCnx method handleProducer.

@Override
protected void handleProducer(final CommandProducer cmdProducer) {
    checkArgument(state == State.Connected);
    final long producerId = cmdProducer.getProducerId();
    final long requestId = cmdProducer.getRequestId();
    // Use producer name provided by client if present
    final String producerName = cmdProducer.hasProducerName() ? cmdProducer.getProducerName() : service.generateUniqueProducerName();
    final boolean isEncrypted = cmdProducer.getEncrypted();
    final Map<String, String> metadata = CommandUtils.metadataFromCommand(cmdProducer);
    TopicName topicName = validateTopicName(cmdProducer.getTopic(), requestId, cmdProducer);
    if (topicName == null) {
        return;
    }
    if (invalidOriginalPrincipal(originalPrincipal)) {
        final String msg = "Valid Proxy Client role should be provided while creating producer ";
        log.warn("[{}] {} with role {} and proxyClientAuthRole {} on topic {}", remoteAddress, msg, authRole, originalPrincipal, topicName);
        ctx.writeAndFlush(Commands.newError(requestId, ServerError.AuthorizationError, msg));
        return;
    }
    CompletableFuture<Boolean> isProxyAuthorizedFuture;
    if (service.isAuthorizationEnabled() && originalPrincipal != null) {
        isProxyAuthorizedFuture = service.getAuthorizationService().canProduceAsync(topicName, authRole, authenticationData);
    } else {
        isProxyAuthorizedFuture = CompletableFuture.completedFuture(true);
    }
    isProxyAuthorizedFuture.thenApply(isProxyAuthorized -> {
        if (isProxyAuthorized) {
            CompletableFuture<Boolean> authorizationFuture;
            if (service.isAuthorizationEnabled()) {
                authorizationFuture = service.getAuthorizationService().canProduceAsync(topicName, originalPrincipal != null ? originalPrincipal : authRole, authenticationData);
            } else {
                authorizationFuture = CompletableFuture.completedFuture(true);
            }
            authorizationFuture.thenApply(isAuthorized -> {
                if (isAuthorized) {
                    if (log.isDebugEnabled()) {
                        log.debug("[{}] Client is authorized to Produce with role {}", remoteAddress, authRole);
                    }
                    CompletableFuture<Producer> producerFuture = new CompletableFuture<>();
                    CompletableFuture<Producer> existingProducerFuture = producers.putIfAbsent(producerId, producerFuture);
                    if (existingProducerFuture != null) {
                        if (existingProducerFuture.isDone() && !existingProducerFuture.isCompletedExceptionally()) {
                            Producer producer = existingProducerFuture.getNow(null);
                            log.info("[{}] Producer with the same id is already created: {}", remoteAddress, producer);
                            ctx.writeAndFlush(Commands.newProducerSuccess(requestId, producer.getProducerName(), producer.getSchemaVersion()));
                            return null;
                        } else {
                            // There was an early request to create a producer with
                            // same producerId. This can happen when
                            // client
                            // timeout is lower the broker timeouts. We need to wait
                            // until the previous producer creation
                            // request
                            // either complete or fails.
                            ServerError error = !existingProducerFuture.isDone() ? ServerError.ServiceNotReady : getErrorCode(existingProducerFuture);
                            log.warn("[{}][{}] Producer is already present on the connection", remoteAddress, topicName);
                            ctx.writeAndFlush(Commands.newError(requestId, error, "Producer is already present on the connection"));
                            return null;
                        }
                    }
                    log.info("[{}][{}] Creating producer. producerId={}", remoteAddress, topicName, producerId);
                    service.getTopic(topicName.toString()).thenAccept((Topic topic) -> {
                        // on topic
                        if (topic.isBacklogQuotaExceeded(producerName)) {
                            IllegalStateException illegalStateException = new IllegalStateException("Cannot create producer on topic with backlog quota exceeded");
                            BacklogQuota.RetentionPolicy retentionPolicy = topic.getBacklogQuota().getPolicy();
                            if (retentionPolicy == BacklogQuota.RetentionPolicy.producer_request_hold) {
                                ctx.writeAndFlush(Commands.newError(requestId, ServerError.ProducerBlockedQuotaExceededError, illegalStateException.getMessage()));
                            } else if (retentionPolicy == BacklogQuota.RetentionPolicy.producer_exception) {
                                ctx.writeAndFlush(Commands.newError(requestId, ServerError.ProducerBlockedQuotaExceededException, illegalStateException.getMessage()));
                            }
                            producerFuture.completeExceptionally(illegalStateException);
                            producers.remove(producerId, producerFuture);
                            return;
                        }
                        // Check whether the producer will publish encrypted messages or not
                        if (topic.isEncryptionRequired() && !isEncrypted) {
                            String msg = String.format("Encryption is required in %s", topicName);
                            log.warn("[{}] {}", remoteAddress, msg);
                            ctx.writeAndFlush(Commands.newError(requestId, ServerError.MetadataError, msg));
                            return;
                        }
                        disableTcpNoDelayIfNeeded(topicName.toString(), producerName);
                        CompletableFuture<SchemaVersion> schemaVersionFuture;
                        if (cmdProducer.hasSchema()) {
                            schemaVersionFuture = topic.addSchema(getSchema(cmdProducer.getSchema()));
                        } else {
                            schemaVersionFuture = CompletableFuture.completedFuture(SchemaVersion.Empty);
                        }
                        schemaVersionFuture.exceptionally(exception -> {
                            ctx.writeAndFlush(Commands.newError(requestId, ServerError.UnknownError, exception.getMessage()));
                            producers.remove(producerId, producerFuture);
                            return null;
                        });
                        schemaVersionFuture.thenAccept(schemaVersion -> {
                            Producer producer = new Producer(topic, ServerCnx.this, producerId, producerName, authRole, isEncrypted, metadata, schemaVersion);
                            try {
                                topic.addProducer(producer);
                                if (isActive()) {
                                    if (producerFuture.complete(producer)) {
                                        log.info("[{}] Created new producer: {}", remoteAddress, producer);
                                        ctx.writeAndFlush(Commands.newProducerSuccess(requestId, producerName, producer.getLastSequenceId(), producer.getSchemaVersion()));
                                        return;
                                    } else {
                                        // The producer's future was completed before by
                                        // a close command
                                        producer.closeNow();
                                        log.info("[{}] Cleared producer created after timeout on client side {}", remoteAddress, producer);
                                    }
                                } else {
                                    producer.closeNow();
                                    log.info("[{}] Cleared producer created after connection was closed: {}", remoteAddress, producer);
                                    producerFuture.completeExceptionally(new IllegalStateException("Producer created after connection was closed"));
                                }
                            } catch (BrokerServiceException ise) {
                                log.error("[{}] Failed to add producer to topic {}: {}", remoteAddress, topicName, ise.getMessage());
                                ctx.writeAndFlush(Commands.newError(requestId, BrokerServiceException.getClientErrorCode(ise), ise.getMessage()));
                                producerFuture.completeExceptionally(ise);
                            }
                            producers.remove(producerId, producerFuture);
                        });
                    }).exceptionally(exception -> {
                        Throwable cause = exception.getCause();
                        if (!(cause instanceof ServiceUnitNotReadyException)) {
                            // Do not print stack traces for expected exceptions
                            log.error("[{}] Failed to create topic {}", remoteAddress, topicName, exception);
                        }
                        // client, only if not completed already.
                        if (producerFuture.completeExceptionally(exception)) {
                            ctx.writeAndFlush(Commands.newError(requestId, BrokerServiceException.getClientErrorCode(cause), cause.getMessage()));
                        }
                        producers.remove(producerId, producerFuture);
                        return null;
                    });
                } else {
                    String msg = "Client is not authorized to Produce";
                    log.warn("[{}] {} with role {}", remoteAddress, msg, authRole);
                    ctx.writeAndFlush(Commands.newError(requestId, ServerError.AuthorizationError, msg));
                }
                return null;
            }).exceptionally(e -> {
                String msg = String.format("[%s] %s with role %s", remoteAddress, e.getMessage(), authRole);
                log.warn(msg);
                ctx.writeAndFlush(Commands.newError(requestId, ServerError.AuthorizationError, e.getMessage()));
                return null;
            });
        } else {
            final String msg = "Proxy Client is not authorized to Produce";
            log.warn("[{}] {} with role {} on topic {}", remoteAddress, msg, authRole, topicName);
            ctx.writeAndFlush(Commands.newError(requestId, ServerError.AuthorizationError, msg));
        }
        return null;
    }).exceptionally(ex -> {
        String msg = String.format("[%s] %s with role %s", remoteAddress, ex.getMessage(), authRole);
        log.warn(msg);
        ctx.writeAndFlush(Commands.newError(requestId, ServerError.AuthorizationError, ex.getMessage()));
        return null;
    });
}
Also used : PulsarApi(org.apache.pulsar.common.api.proto.PulsarApi) ServiceUnitNotReadyException(org.apache.pulsar.broker.service.BrokerServiceException.ServiceUnitNotReadyException) CommandUtils(org.apache.pulsar.common.api.CommandUtils) SocketAddress(java.net.SocketAddress) PersistentTopicsBase.getPartitionedTopicMetadata(org.apache.pulsar.broker.admin.impl.PersistentTopicsBase.getPartitionedTopicMetadata) SchemaVersion(org.apache.pulsar.common.schema.SchemaVersion) CommandAck(org.apache.pulsar.common.api.proto.PulsarApi.CommandAck) LoggerFactory(org.slf4j.LoggerFactory) AuthenticationException(javax.naming.AuthenticationException) StringUtils(org.apache.commons.lang3.StringUtils) CommandCloseConsumer(org.apache.pulsar.common.api.proto.PulsarApi.CommandCloseConsumer) CommandGetLastMessageId(org.apache.pulsar.common.api.proto.PulsarApi.CommandGetLastMessageId) CommandSend(org.apache.pulsar.common.api.proto.PulsarApi.CommandSend) ServerError(org.apache.pulsar.common.api.proto.PulsarApi.ServerError) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) PulsarHandler(org.apache.pulsar.common.api.PulsarHandler) Map(java.util.Map) RestException(org.apache.pulsar.broker.web.RestException) NamespaceName(org.apache.pulsar.common.naming.NamespaceName) CommandGetTopicsOfNamespace(org.apache.pulsar.common.api.proto.PulsarApi.CommandGetTopicsOfNamespace) PulsarClientException(org.apache.pulsar.client.api.PulsarClientException) ProtocolVersion.v5(org.apache.pulsar.common.api.proto.PulsarApi.ProtocolVersion.v5) PositionImpl(org.apache.bookkeeper.mledger.impl.PositionImpl) CommandConnect(org.apache.pulsar.common.api.proto.PulsarApi.CommandConnect) Commands(org.apache.pulsar.common.api.Commands) Commands.newLookupErrorResponse(org.apache.pulsar.common.api.Commands.newLookupErrorResponse) CommandSubscribe(org.apache.pulsar.common.api.proto.PulsarApi.CommandSubscribe) Set(java.util.Set) CommandRedeliverUnacknowledgedMessages(org.apache.pulsar.common.api.proto.PulsarApi.CommandRedeliverUnacknowledgedMessages) Position(org.apache.bookkeeper.mledger.Position) CommandCloseProducer(org.apache.pulsar.common.api.proto.PulsarApi.CommandCloseProducer) CommandFlow(org.apache.pulsar.common.api.proto.PulsarApi.CommandFlow) Collectors(java.util.stream.Collectors) AuthenticationDataSource(org.apache.pulsar.broker.authentication.AuthenticationDataSource) MessageIdImpl(org.apache.pulsar.client.impl.MessageIdImpl) List(java.util.List) StringUtils.isNotBlank(org.apache.commons.lang3.StringUtils.isNotBlank) BatchMessageIdImpl(org.apache.pulsar.client.impl.BatchMessageIdImpl) SafeRun(org.apache.bookkeeper.mledger.util.SafeRun) SslHandler(io.netty.handler.ssl.SslHandler) SchemaData(org.apache.pulsar.common.schema.SchemaData) CommandConsumerStatsResponse(org.apache.pulsar.common.api.proto.PulsarApi.CommandConsumerStatsResponse) CommandPartitionedTopicMetadata(org.apache.pulsar.common.api.proto.PulsarApi.CommandPartitionedTopicMetadata) MessageIdData(org.apache.pulsar.common.api.proto.PulsarApi.MessageIdData) ClientCnx(org.apache.pulsar.client.impl.ClientCnx) TopicName(org.apache.pulsar.common.naming.TopicName) ChannelOption(io.netty.channel.ChannelOption) CommandConsumerStats(org.apache.pulsar.common.api.proto.PulsarApi.CommandConsumerStats) GeneratedMessageLite(com.google.protobuf.GeneratedMessageLite) BacklogQuota(org.apache.pulsar.common.policies.data.BacklogQuota) CompletableFuture(java.util.concurrent.CompletableFuture) ProtocolVersion(org.apache.pulsar.common.api.proto.PulsarApi.ProtocolVersion) SchemaType(org.apache.pulsar.common.schema.SchemaType) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) ServerMetadataException(org.apache.pulsar.broker.service.BrokerServiceException.ServerMetadataException) SSLSession(javax.net.ssl.SSLSession) ByteBuf(io.netty.buffer.ByteBuf) MessageMetadata(org.apache.pulsar.common.api.proto.PulsarApi.MessageMetadata) CommandProducer(org.apache.pulsar.common.api.proto.PulsarApi.CommandProducer) CommandSeek(org.apache.pulsar.common.api.proto.PulsarApi.CommandSeek) AuthenticationDataCommand(org.apache.pulsar.broker.authentication.AuthenticationDataCommand) Metadata(org.apache.pulsar.common.naming.Metadata) Logger(org.slf4j.Logger) SubType(org.apache.pulsar.common.api.proto.PulsarApi.CommandSubscribe.SubType) Semaphore(java.util.concurrent.Semaphore) CommandLookupTopic(org.apache.pulsar.common.api.proto.PulsarApi.CommandLookupTopic) TimeUnit(java.util.concurrent.TimeUnit) CommandUnsubscribe(org.apache.pulsar.common.api.proto.PulsarApi.CommandUnsubscribe) ConcurrentLongHashMap(org.apache.pulsar.common.util.collections.ConcurrentLongHashMap) TopicLookup.lookupTopicAsync(org.apache.pulsar.broker.lookup.TopicLookup.lookupTopicAsync) PulsarServerException(org.apache.pulsar.broker.PulsarServerException) ConsumerBusyException(org.apache.pulsar.broker.service.BrokerServiceException.ConsumerBusyException) ChannelHandler(io.netty.channel.ChannelHandler) ConsumerStats(org.apache.pulsar.common.policies.data.ConsumerStats) InitialPosition(org.apache.pulsar.common.api.proto.PulsarApi.CommandSubscribe.InitialPosition) ServerError(org.apache.pulsar.common.api.proto.PulsarApi.ServerError) TopicName(org.apache.pulsar.common.naming.TopicName) ServiceUnitNotReadyException(org.apache.pulsar.broker.service.BrokerServiceException.ServiceUnitNotReadyException) CompletableFuture(java.util.concurrent.CompletableFuture) CommandCloseProducer(org.apache.pulsar.common.api.proto.PulsarApi.CommandCloseProducer) CommandProducer(org.apache.pulsar.common.api.proto.PulsarApi.CommandProducer) CommandLookupTopic(org.apache.pulsar.common.api.proto.PulsarApi.CommandLookupTopic)

Aggregations

Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)3 GeneratedMessageLite (com.google.protobuf.GeneratedMessageLite)3 ByteBuf (io.netty.buffer.ByteBuf)3 ChannelHandler (io.netty.channel.ChannelHandler)3 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)3 ChannelOption (io.netty.channel.ChannelOption)3 SslHandler (io.netty.handler.ssl.SslHandler)3 SocketAddress (java.net.SocketAddress)3 List (java.util.List)3 Map (java.util.Map)3 Set (java.util.Set)3 CompletableFuture (java.util.concurrent.CompletableFuture)3 Semaphore (java.util.concurrent.Semaphore)3 TimeUnit (java.util.concurrent.TimeUnit)3 Collectors (java.util.stream.Collectors)3 AuthenticationException (javax.naming.AuthenticationException)3 SSLSession (javax.net.ssl.SSLSession)3 Position (org.apache.bookkeeper.mledger.Position)3 PositionImpl (org.apache.bookkeeper.mledger.impl.PositionImpl)3 SafeRun (org.apache.bookkeeper.mledger.util.SafeRun)3