Search in sources :

Example 1 with CommandProducer

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

the class Commands method newProducer.

public static ByteBuf newProducer(String topic, long producerId, long requestId, String producerName, boolean encrypted, Map<String, String> metadata) {
    CommandProducer.Builder producerBuilder = CommandProducer.newBuilder();
    producerBuilder.setTopic(topic);
    producerBuilder.setProducerId(producerId);
    producerBuilder.setRequestId(requestId);
    if (producerName != null) {
        producerBuilder.setProducerName(producerName);
    }
    producerBuilder.setEncrypted(encrypted);
    producerBuilder.addAllMetadata(CommandUtils.toKeyValueList(metadata));
    CommandProducer producer = producerBuilder.build();
    ByteBuf res = serializeWithSize(BaseCommand.newBuilder().setType(Type.PRODUCER).setProducer(producer));
    producerBuilder.recycle();
    producer.recycle();
    return res;
}
Also used : CommandProducer(org.apache.pulsar.common.api.proto.PulsarApi.CommandProducer) ByteBuf(io.netty.buffer.ByteBuf)

Example 2 with CommandProducer

use of org.apache.pulsar.common.api.proto.PulsarApi.CommandProducer 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

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