Search in sources :

Example 1 with InitialPosition

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

the class ManagedLedgerImpl method asyncOpenCursor.

@Override
public synchronized void asyncOpenCursor(final String cursorName, final InitialPosition initialPosition, final OpenCursorCallback callback, final Object ctx) {
    try {
        checkManagedLedgerIsOpen();
        checkFenced();
    } catch (ManagedLedgerException e) {
        callback.openCursorFailed(e, ctx);
        return;
    }
    if (uninitializedCursors.containsKey(cursorName)) {
        uninitializedCursors.get(cursorName).thenAccept(cursor -> {
            callback.openCursorComplete(cursor, ctx);
        }).exceptionally(ex -> {
            callback.openCursorFailed((ManagedLedgerException) ex, ctx);
            return null;
        });
        return;
    }
    ManagedCursor cachedCursor = cursors.get(cursorName);
    if (cachedCursor != null) {
        if (log.isDebugEnabled()) {
            log.debug("[{}] Cursor was already created {}", name, cachedCursor);
        }
        callback.openCursorComplete(cachedCursor, ctx);
        return;
    }
    // Create a new one and persist it
    if (log.isDebugEnabled()) {
        log.debug("[{}] Creating new cursor: {}", name, cursorName);
    }
    final ManagedCursorImpl cursor = new ManagedCursorImpl(bookKeeper, config, this, cursorName);
    CompletableFuture<ManagedCursor> cursorFuture = new CompletableFuture<>();
    uninitializedCursors.put(cursorName, cursorFuture);
    cursor.initialize(getLastPosition(), new VoidCallback() {

        @Override
        public void operationComplete() {
            log.info("[{}] Opened new cursor: {}", name, cursor);
            cursor.setActive();
            // Update the ack position (ignoring entries that were written while the cursor was being created)
            cursor.initializeCursorPosition(initialPosition == InitialPosition.Latest ? getLastPositionAndCounter() : getFirstPositionAndCounter());
            synchronized (this) {
                cursors.add(cursor);
                uninitializedCursors.remove(cursorName).complete(cursor);
            }
            callback.openCursorComplete(cursor, ctx);
        }

        @Override
        public void operationFailed(ManagedLedgerException exception) {
            log.warn("[{}] Failed to open cursor: {}", name, cursor);
            synchronized (this) {
                uninitializedCursors.remove(cursorName).completeExceptionally(exception);
            }
            callback.openCursorFailed(exception, ctx);
        }
    });
}
Also used : OpenCallback(org.apache.bookkeeper.client.AsyncCallback.OpenCallback) CloseCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.CloseCallback) LoggerFactory(org.slf4j.LoggerFactory) Random(java.util.Random) MetaStoreCallback(org.apache.bookkeeper.mledger.impl.MetaStore.MetaStoreCallback) Pair(org.apache.bookkeeper.mledger.util.Pair) Unpooled(io.netty.buffer.Unpooled) GrowableArrayBlockingQueue(org.apache.pulsar.common.util.collections.GrowableArrayBlockingQueue) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) OpenCursorCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.OpenCursorCallback) ManagedCursor(org.apache.bookkeeper.mledger.ManagedCursor) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ManagedLedger(org.apache.bookkeeper.mledger.ManagedLedger) ManagedLedgerConfig(org.apache.bookkeeper.mledger.ManagedLedgerConfig) Map(java.util.Map) ManagedLedgerMXBean(org.apache.bookkeeper.mledger.ManagedLedgerMXBean) DeleteCursorCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.DeleteCursorCallback) LedgerHandle(org.apache.bookkeeper.client.LedgerHandle) ManagedLedgerInfo(org.apache.bookkeeper.mledger.proto.MLDataFormats.ManagedLedgerInfo) Commands(org.apache.pulsar.common.api.Commands) LedgerInfo(org.apache.bookkeeper.mledger.proto.MLDataFormats.ManagedLedgerInfo.LedgerInfo) OrderedScheduler(org.apache.bookkeeper.common.util.OrderedScheduler) ManagedLedgerAlreadyClosedException(org.apache.bookkeeper.mledger.ManagedLedgerException.ManagedLedgerAlreadyClosedException) NestedPositionInfo(org.apache.bookkeeper.mledger.proto.MLDataFormats.NestedPositionInfo) AtomicReferenceFieldUpdater(java.util.concurrent.atomic.AtomicReferenceFieldUpdater) Range(com.google.common.collect.Range) Futures(org.apache.bookkeeper.mledger.util.Futures) Math.min(java.lang.Math.min) Position(org.apache.bookkeeper.mledger.Position) NavigableMap(java.util.NavigableMap) BookKeeper(org.apache.bookkeeper.client.BookKeeper) BKException(org.apache.bookkeeper.client.BKException) AddEntryCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.AddEntryCallback) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) Queues(com.google.common.collect.Queues) ManagedLedgerFencedException(org.apache.bookkeeper.mledger.ManagedLedgerException.ManagedLedgerFencedException) NonRecoverableLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException.NonRecoverableLedgerException) BoundType(com.google.common.collect.BoundType) Stat(org.apache.bookkeeper.mledger.impl.MetaStore.Stat) ManagedLedgerTerminatedException(org.apache.bookkeeper.mledger.ManagedLedgerException.ManagedLedgerTerminatedException) Queue(java.util.Queue) BadVersionException(org.apache.bookkeeper.mledger.ManagedLedgerException.BadVersionException) ConcurrentLinkedQueue(java.util.concurrent.ConcurrentLinkedQueue) CreateCallback(org.apache.bookkeeper.client.AsyncCallback.CreateCallback) DeleteLedgerCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.DeleteLedgerCallback) Entry(org.apache.bookkeeper.mledger.Entry) CompletableFuture(java.util.concurrent.CompletableFuture) ReadEntryCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.ReadEntryCallback) AtomicReference(java.util.concurrent.atomic.AtomicReference) RateLimiter(com.google.common.util.concurrent.RateLimiter) TerminateCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.TerminateCallback) SafeRun.safeRun(org.apache.bookkeeper.mledger.util.SafeRun.safeRun) MetaStoreException(org.apache.bookkeeper.mledger.ManagedLedgerException.MetaStoreException) Lists(com.google.common.collect.Lists) ByteBuf(io.netty.buffer.ByteBuf) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) MessageMetadata(org.apache.pulsar.common.api.proto.PulsarApi.MessageMetadata) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) AtomicLongFieldUpdater(java.util.concurrent.atomic.AtomicLongFieldUpdater) Maps(com.google.common.collect.Maps) TooManyRequestsException(org.apache.bookkeeper.mledger.ManagedLedgerException.TooManyRequestsException) TimeUnit(java.util.concurrent.TimeUnit) ConcurrentSkipListMap(java.util.concurrent.ConcurrentSkipListMap) ConcurrentLongHashMap(org.apache.pulsar.common.util.collections.ConcurrentLongHashMap) CallbackMutex(org.apache.bookkeeper.mledger.util.CallbackMutex) VoidCallback(org.apache.bookkeeper.mledger.impl.ManagedCursorImpl.VoidCallback) InitialPosition(org.apache.pulsar.common.api.proto.PulsarApi.CommandSubscribe.InitialPosition) Collections(java.util.Collections) VoidCallback(org.apache.bookkeeper.mledger.impl.ManagedCursorImpl.VoidCallback) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) CompletableFuture(java.util.concurrent.CompletableFuture) ManagedCursor(org.apache.bookkeeper.mledger.ManagedCursor)

Example 2 with InitialPosition

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

the class PersistentTopic method subscribe.

@Override
public CompletableFuture<Consumer> subscribe(final ServerCnx cnx, String subscriptionName, long consumerId, SubType subType, int priorityLevel, String consumerName, boolean isDurable, MessageId startMessageId, Map<String, String> metadata, boolean readCompacted, InitialPosition initialPosition) {
    final CompletableFuture<Consumer> future = new CompletableFuture<>();
    if (readCompacted && !(subType == SubType.Failover || subType == SubType.Exclusive)) {
        future.completeExceptionally(new NotAllowedException("readCompacted only allowed on failover or exclusive subscriptions"));
        return future;
    }
    if (isBlank(subscriptionName)) {
        if (log.isDebugEnabled()) {
            log.debug("[{}] Empty subscription name", topic);
        }
        future.completeExceptionally(new NamingException("Empty subscription name"));
        return future;
    }
    if (hasBatchMessagePublished && !cnx.isBatchMessageCompatibleVersion()) {
        if (log.isDebugEnabled()) {
            log.debug("[{}] Consumer doesn't support batch-message {}", topic, subscriptionName);
        }
        future.completeExceptionally(new UnsupportedVersionException("Consumer doesn't support batch-message"));
        return future;
    }
    if (subscriptionName.startsWith(replicatorPrefix) || subscriptionName.equals(DEDUPLICATION_CURSOR_NAME)) {
        log.warn("[{}] Failed to create subscription for {}", topic, subscriptionName);
        future.completeExceptionally(new NamingException("Subscription with reserved subscription name attempted"));
        return future;
    }
    lock.readLock().lock();
    try {
        if (isFenced) {
            log.warn("[{}] Attempting to subscribe to a fenced topic", topic);
            future.completeExceptionally(new TopicFencedException("Topic is temporarily unavailable"));
            return future;
        }
        USAGE_COUNT_UPDATER.incrementAndGet(this);
        if (log.isDebugEnabled()) {
            log.debug("[{}] [{}] [{}] Added consumer -- count: {}", topic, subscriptionName, consumerName, USAGE_COUNT_UPDATER.get(this));
        }
    } finally {
        lock.readLock().unlock();
    }
    CompletableFuture<? extends Subscription> subscriptionFuture = // 
    isDurable ? // 
    getDurableSubscription(subscriptionName, initialPosition) : getNonDurableSubscription(subscriptionName, startMessageId);
    int maxUnackedMessages = isDurable ? brokerService.pulsar().getConfiguration().getMaxUnackedMessagesPerConsumer() : 0;
    subscriptionFuture.thenAccept(subscription -> {
        try {
            Consumer consumer = new Consumer(subscription, subType, topic, consumerId, priorityLevel, consumerName, maxUnackedMessages, cnx, cnx.getRole(), metadata, readCompacted, initialPosition);
            subscription.addConsumer(consumer);
            if (!cnx.isActive()) {
                consumer.close();
                if (log.isDebugEnabled()) {
                    log.debug("[{}] [{}] [{}] Subscribe failed -- count: {}", topic, subscriptionName, consumer.consumerName(), USAGE_COUNT_UPDATER.get(PersistentTopic.this));
                }
                future.completeExceptionally(new BrokerServiceException("Connection was closed while the opening the cursor "));
            } else {
                log.info("[{}][{}] Created new subscription for {}", topic, subscriptionName, consumerId);
                future.complete(consumer);
            }
        } catch (BrokerServiceException e) {
            if (e instanceof ConsumerBusyException) {
                log.warn("[{}][{}] Consumer {} {} already connected", topic, subscriptionName, consumerId, consumerName);
            } else if (e instanceof SubscriptionBusyException) {
                log.warn("[{}][{}] {}", topic, subscriptionName, e.getMessage());
            }
            USAGE_COUNT_UPDATER.decrementAndGet(PersistentTopic.this);
            future.completeExceptionally(e);
        }
    }).exceptionally(ex -> {
        log.warn("[{}] Failed to create subscription for {}: ", topic, subscriptionName, ex.getMessage());
        USAGE_COUNT_UPDATER.decrementAndGet(PersistentTopic.this);
        future.completeExceptionally(new PersistenceException(ex));
        return null;
    });
    return future;
}
Also used : SubscriptionStats(org.apache.pulsar.common.policies.data.SubscriptionStats) NamingException(org.apache.pulsar.broker.service.BrokerServiceException.NamingException) Topic(org.apache.pulsar.broker.service.Topic) LedgerInfo(org.apache.pulsar.common.policies.data.PersistentTopicInternalStats.LedgerInfo) PersistentTopicStats(org.apache.pulsar.common.policies.data.PersistentTopicStats) AdminResource(org.apache.pulsar.broker.admin.AdminResource) NotAllowedException(org.apache.pulsar.broker.service.BrokerServiceException.NotAllowedException) SchemaVersion(org.apache.pulsar.common.schema.SchemaVersion) CloseCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.CloseCallback) UnsupportedVersionException(org.apache.pulsar.broker.service.BrokerServiceException.UnsupportedVersionException) LoggerFactory(org.slf4j.LoggerFactory) ObjectObjectHashMap(com.carrotsearch.hppc.ObjectObjectHashMap) ProducerBusyException(org.apache.pulsar.broker.service.BrokerServiceException.ProducerBusyException) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) OpenCursorCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.OpenCursorCallback) MessageImpl(org.apache.pulsar.client.impl.MessageImpl) ManagedCursor(org.apache.bookkeeper.mledger.ManagedCursor) ManagedLedger(org.apache.bookkeeper.mledger.ManagedLedger) Map(java.util.Map) DeleteCursorCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.DeleteCursorCallback) StatsOutputStream(org.apache.pulsar.utils.StatsOutputStream) PositionImpl(org.apache.bookkeeper.mledger.impl.PositionImpl) ReplicationMetrics(org.apache.pulsar.broker.stats.ReplicationMetrics) ManagedLedgerAlreadyClosedException(org.apache.bookkeeper.mledger.ManagedLedgerException.ManagedLedgerAlreadyClosedException) Set(java.util.Set) Position(org.apache.bookkeeper.mledger.Position) BrokerService(org.apache.pulsar.broker.service.BrokerService) ReplicatorStats(org.apache.pulsar.common.policies.data.ReplicatorStats) IndividualDeletedEntries(org.apache.bookkeeper.mledger.ManagedCursor.IndividualDeletedEntries) NamespaceStats(org.apache.pulsar.broker.stats.NamespaceStats) Sets(com.google.common.collect.Sets) AddEntryCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.AddEntryCallback) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) SubscriptionBusyException(org.apache.pulsar.broker.service.BrokerServiceException.SubscriptionBusyException) MessageIdImpl(org.apache.pulsar.client.impl.MessageIdImpl) ManagedCursorImpl(org.apache.bookkeeper.mledger.impl.ManagedCursorImpl) ServerCnx(org.apache.pulsar.broker.service.ServerCnx) List(java.util.List) FutureUtil(org.apache.pulsar.common.util.FutureUtil) ConcurrentOpenHashSet(org.apache.pulsar.common.util.collections.ConcurrentOpenHashSet) BatchMessageIdImpl(org.apache.pulsar.client.impl.BatchMessageIdImpl) ConcurrentOpenHashMap(org.apache.pulsar.common.util.collections.ConcurrentOpenHashMap) ManagedLedgerFencedException(org.apache.bookkeeper.mledger.ManagedLedgerException.ManagedLedgerFencedException) TopicTerminatedException(org.apache.pulsar.broker.service.BrokerServiceException.TopicTerminatedException) SchemaData(org.apache.pulsar.common.schema.SchemaData) Optional(java.util.Optional) ManagedLedgerTerminatedException(org.apache.bookkeeper.mledger.ManagedLedgerException.ManagedLedgerTerminatedException) PersistentTopicInternalStats(org.apache.pulsar.common.policies.data.PersistentTopicInternalStats) NamespaceBundleStats(org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats) AsyncCallbacks(org.apache.bookkeeper.mledger.AsyncCallbacks) PublisherStats(org.apache.pulsar.common.policies.data.PublisherStats) Subscription(org.apache.pulsar.broker.service.Subscription) TopicName(org.apache.pulsar.common.naming.TopicName) CursorStats(org.apache.pulsar.common.policies.data.PersistentTopicInternalStats.CursorStats) Entry(org.apache.bookkeeper.mledger.Entry) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) BacklogQuota(org.apache.pulsar.common.policies.data.BacklogQuota) CompletableFuture(java.util.concurrent.CompletableFuture) ReentrantReadWriteLock(java.util.concurrent.locks.ReentrantReadWriteLock) Consumer(org.apache.pulsar.broker.service.Consumer) TerminateCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.TerminateCallback) TopicClosedException(org.apache.pulsar.broker.service.BrokerServiceException.TopicClosedException) ServerMetadataException(org.apache.pulsar.broker.service.BrokerServiceException.ServerMetadataException) DateFormatter(org.apache.pulsar.common.util.DateFormatter) Lists(com.google.common.collect.Lists) ByteBuf(io.netty.buffer.ByteBuf) CompactedTopicImpl(org.apache.pulsar.compaction.CompactedTopicImpl) FastThreadLocal(io.netty.util.concurrent.FastThreadLocal) ClusterReplicationMetrics(org.apache.pulsar.broker.stats.ClusterReplicationMetrics) ManagedLedgerImpl(org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl) Logger(org.slf4j.Logger) SubType(org.apache.pulsar.common.api.proto.PulsarApi.CommandSubscribe.SubType) KeeperException(org.apache.zookeeper.KeeperException) CompactedTopic(org.apache.pulsar.compaction.CompactedTopic) BrokerServiceException(org.apache.pulsar.broker.service.BrokerServiceException) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) MoreObjects(com.google.common.base.MoreObjects) AtomicLongFieldUpdater(java.util.concurrent.atomic.AtomicLongFieldUpdater) PersistenceException(org.apache.pulsar.broker.service.BrokerServiceException.PersistenceException) Producer(org.apache.pulsar.broker.service.Producer) TopicFencedException(org.apache.pulsar.broker.service.BrokerServiceException.TopicFencedException) Maps(com.google.common.collect.Maps) TimeUnit(java.util.concurrent.TimeUnit) Policies(org.apache.pulsar.common.policies.data.Policies) TopicBusyException(org.apache.pulsar.broker.service.BrokerServiceException.TopicBusyException) MessageId(org.apache.pulsar.client.api.MessageId) Compactor(org.apache.pulsar.compaction.Compactor) StringUtils.isBlank(org.apache.commons.lang3.StringUtils.isBlank) POLICIES(org.apache.pulsar.broker.cache.ConfigurationCacheService.POLICIES) Codec(org.apache.pulsar.common.util.Codec) ConsumerBusyException(org.apache.pulsar.broker.service.BrokerServiceException.ConsumerBusyException) Replicator(org.apache.pulsar.broker.service.Replicator) ConsumerStats(org.apache.pulsar.common.policies.data.ConsumerStats) InitialPosition(org.apache.pulsar.common.api.proto.PulsarApi.CommandSubscribe.InitialPosition) Collections(java.util.Collections) TopicFencedException(org.apache.pulsar.broker.service.BrokerServiceException.TopicFencedException) NotAllowedException(org.apache.pulsar.broker.service.BrokerServiceException.NotAllowedException) BrokerServiceException(org.apache.pulsar.broker.service.BrokerServiceException) CompletableFuture(java.util.concurrent.CompletableFuture) ConsumerBusyException(org.apache.pulsar.broker.service.BrokerServiceException.ConsumerBusyException) Consumer(org.apache.pulsar.broker.service.Consumer) PersistenceException(org.apache.pulsar.broker.service.BrokerServiceException.PersistenceException) NamingException(org.apache.pulsar.broker.service.BrokerServiceException.NamingException) SubscriptionBusyException(org.apache.pulsar.broker.service.BrokerServiceException.SubscriptionBusyException) UnsupportedVersionException(org.apache.pulsar.broker.service.BrokerServiceException.UnsupportedVersionException)

Example 3 with InitialPosition

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

Aggregations

Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)3 ByteBuf (io.netty.buffer.ByteBuf)3 List (java.util.List)3 Map (java.util.Map)3 CompletableFuture (java.util.concurrent.CompletableFuture)3 TimeUnit (java.util.concurrent.TimeUnit)3 Position (org.apache.bookkeeper.mledger.Position)3 Lists (com.google.common.collect.Lists)2 Maps (com.google.common.collect.Maps)2 Collections (java.util.Collections)2 AtomicLongFieldUpdater (java.util.concurrent.atomic.AtomicLongFieldUpdater)2 AddEntryCallback (org.apache.bookkeeper.mledger.AsyncCallbacks.AddEntryCallback)2 CloseCallback (org.apache.bookkeeper.mledger.AsyncCallbacks.CloseCallback)2 DeleteCursorCallback (org.apache.bookkeeper.mledger.AsyncCallbacks.DeleteCursorCallback)2 OpenCursorCallback (org.apache.bookkeeper.mledger.AsyncCallbacks.OpenCursorCallback)2 TerminateCallback (org.apache.bookkeeper.mledger.AsyncCallbacks.TerminateCallback)2 Entry (org.apache.bookkeeper.mledger.Entry)2 ManagedCursor (org.apache.bookkeeper.mledger.ManagedCursor)2 ManagedLedger (org.apache.bookkeeper.mledger.ManagedLedger)2 ManagedLedgerException (org.apache.bookkeeper.mledger.ManagedLedgerException)2