List of usage examples for java.util.concurrent CompletableFuture completeExceptionally
public boolean completeExceptionally(Throwable ex)
From source file:org.apache.pulsar.broker.admin.impl.PersistentTopicsBase.java
private CompletableFuture<Void> updatePartitionedTopic(TopicName topicName, int numPartitions) { final String path = ZkAdminPaths.partitionedTopicPath(topicName); CompletableFuture<Void> updatePartition = new CompletableFuture<>(); createSubscriptions(topicName, numPartitions).thenAccept(res -> { try {//from w ww. j av a 2 s. c o m byte[] data = jsonMapper().writeValueAsBytes(new PartitionedTopicMetadata(numPartitions)); globalZk().setData(path, data, -1, (rc, path1, ctx, stat) -> { if (rc == KeeperException.Code.OK.intValue()) { updatePartition.complete(null); } else { updatePartition.completeExceptionally(KeeperException.create(KeeperException.Code.get(rc), "failed to create update partitions")); } }, null); } catch (Exception e) { updatePartition.completeExceptionally(e); } }).exceptionally(ex -> { updatePartition.completeExceptionally(ex); return null; }); return updatePartition; }
From source file:org.apache.pulsar.broker.admin.impl.PersistentTopicsBase.java
/** * It creates subscriptions for new partitions of existing partitioned-topics * * @param topicName/* ww w.j av a 2 s. c o m*/ * : topic-name: persistent://prop/cluster/ns/topic * @param numPartitions * : number partitions for the topics */ private CompletableFuture<Void> createSubscriptions(TopicName topicName, int numPartitions) { String path = path(PARTITIONED_TOPIC_PATH_ZNODE, topicName.getPersistenceNamingEncoding()); CompletableFuture<Void> result = new CompletableFuture<>(); fetchPartitionedTopicMetadataAsync(pulsar(), path).thenAccept(partitionMetadata -> { if (partitionMetadata.partitions <= 1) { result.completeExceptionally(new RestException(Status.CONFLICT, "Topic is not partitioned topic")); return; } if (partitionMetadata.partitions >= numPartitions) { result.completeExceptionally(new RestException(Status.CONFLICT, "number of partitions must be more than existing " + partitionMetadata.partitions)); return; } PulsarAdmin admin; try { admin = pulsar().getAdminClient(); } catch (PulsarServerException e1) { result.completeExceptionally(e1); return; } admin.topics().getStatsAsync(topicName.getPartition(0).toString()).thenAccept(stats -> { stats.subscriptions.keySet().forEach(subscription -> { List<CompletableFuture<Void>> subscriptionFutures = new ArrayList<>(); for (int i = partitionMetadata.partitions; i < numPartitions; i++) { final String topicNamePartition = topicName.getPartition(i).toString(); subscriptionFutures.add(admin.topics().createSubscriptionAsync(topicNamePartition, subscription, MessageId.latest)); } FutureUtil.waitForAll(subscriptionFutures).thenRun(() -> { log.info("[{}] Successfully created new partitions {}", clientAppId(), topicName); result.complete(null); }).exceptionally(ex -> { log.warn("[{}] Failed to create subscriptions on new partitions for {}", clientAppId(), topicName, ex); result.completeExceptionally(ex); return null; }); }); }).exceptionally(ex -> { if (ex.getCause() instanceof PulsarAdminException.NotFoundException) { // The first partition doesn't exist, so there are currently to subscriptions to recreate result.complete(null); } else { log.warn("[{}] Failed to get list of subscriptions of {}", clientAppId(), topicName.getPartition(0), ex); result.completeExceptionally(ex); } return null; }); }).exceptionally(ex -> { log.warn("[{}] Failed to get partition metadata for {}", clientAppId(), topicName.toString()); result.completeExceptionally(ex); return null; }); return result; }
From source file:org.apache.pulsar.broker.authorization.AuthorizationService.java
/** * Check whether the specified role can perform a lookup for the specified topic. * * For that the caller needs to have producer or consumer permission. * * @param topicName/*from w ww . j a v a2s. co m*/ * @param role * @return * @throws Exception */ public CompletableFuture<Boolean> canLookupAsync(TopicName topicName, String role, AuthenticationDataSource authenticationData) { CompletableFuture<Boolean> finalResult = new CompletableFuture<Boolean>(); canProduceAsync(topicName, role, authenticationData).whenComplete((produceAuthorized, ex) -> { if (ex == null) { if (produceAuthorized) { finalResult.complete(produceAuthorized); return; } } else { if (log.isDebugEnabled()) { log.debug( "Topic [{}] Role [{}] exception occured while trying to check Produce permissions. {}", topicName.toString(), role, ex.getMessage()); } } canConsumeAsync(topicName, role, null, null).whenComplete((consumeAuthorized, e) -> { if (e == null) { if (consumeAuthorized) { finalResult.complete(consumeAuthorized); return; } } else { if (log.isDebugEnabled()) { log.debug( "Topic [{}] Role [{}] exception occured while trying to check Consume permissions. {}", topicName.toString(), role, e.getMessage()); } finalResult.completeExceptionally(e); return; } finalResult.complete(false); }); }); return finalResult; }
From source file:org.apache.pulsar.broker.authorization.PulsarAuthorizationProvider.java
/** * Check if the specified role has permission to receive messages from the specified fully qualified topic * name.//from ww w. jav a 2 s.co m * * @param topicName * the fully qualified topic name associated with the topic. * @param role * the app id used to receive messages from the topic. * @param subscription * the subscription name defined by the client */ @Override public CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String role, AuthenticationDataSource authenticationData, String subscription) { CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>(); try { configCache.policiesCache().getAsync(POLICY_ROOT + topicName.getNamespace()).thenAccept(policies -> { if (!policies.isPresent()) { if (log.isDebugEnabled()) { log.debug("Policies node couldn't be found for topic : {}", topicName); } } else { if (isNotBlank(subscription)) { // validate if role is authorize to access subscription. (skip validatation if authorization // list is empty) Set<String> roles = policies.get().auth_policies.subscription_auth_roles.get(subscription); if (roles != null && !roles.isEmpty() && !roles.contains(role)) { log.warn("[{}] is not authorized to subscribe on {}-{}", role, topicName, subscription); PulsarServerException ex = new PulsarServerException( String.format("%s is not authorized to access subscription %s on topic %s", role, subscription, topicName)); permissionFuture.complete(false); return; } // validate if subscription-auth mode is configured switch (policies.get().subscription_auth_mode) { case Prefix: if (!subscription.startsWith(role)) { PulsarServerException ex = new PulsarServerException(String.format( "Failed to create consumer - The subscription name needs to be prefixed by the authentication role, like %s-xxxx for topic: %s", role, topicName)); permissionFuture.completeExceptionally(ex); return; } break; default: break; } } } // check namespace and topic level consume-permissions checkAuthorization(topicName, role, AuthAction.consume).thenAccept(isAuthorized -> { permissionFuture.complete(isAuthorized); }); }).exceptionally(ex -> { log.warn("Client with Role - {} failed to get permissions for topic - {}. {}", role, topicName, ex.getMessage()); permissionFuture.completeExceptionally(ex); return null; }); } catch (Exception e) { log.warn("Client with Role - {} failed to get permissions for topic - {}. {}", role, topicName, e.getMessage()); permissionFuture.completeExceptionally(e); } return permissionFuture; }
From source file:org.apache.pulsar.broker.authorization.PulsarAuthorizationProvider.java
/** * Check whether the specified role can perform a lookup for the specified topic. * * For that the caller needs to have producer or consumer permission. * * @param topicName//w ww .j av a 2s .c o m * @param role * @return * @throws Exception */ @Override public CompletableFuture<Boolean> canLookupAsync(TopicName topicName, String role, AuthenticationDataSource authenticationData) { CompletableFuture<Boolean> finalResult = new CompletableFuture<Boolean>(); canProduceAsync(topicName, role, authenticationData).whenComplete((produceAuthorized, ex) -> { if (ex == null) { if (produceAuthorized) { finalResult.complete(produceAuthorized); return; } } else { if (log.isDebugEnabled()) { log.debug( "Topic [{}] Role [{}] exception occured while trying to check Produce permissions. {}", topicName.toString(), role, ex.getMessage()); } } canConsumeAsync(topicName, role, authenticationData, null).whenComplete((consumeAuthorized, e) -> { if (e == null) { if (consumeAuthorized) { finalResult.complete(consumeAuthorized); return; } } else { if (log.isDebugEnabled()) { log.debug( "Topic [{}] Role [{}] exception occured while trying to check Consume permissions. {}", topicName.toString(), role, e.getMessage()); } finalResult.completeExceptionally(e); return; } finalResult.complete(false); }); }); return finalResult; }
From source file:org.apache.pulsar.broker.authorization.PulsarAuthorizationProvider.java
@Override public CompletableFuture<Void> grantPermissionAsync(NamespaceName namespaceName, Set<AuthAction> actions, String role, String authDataJson) { CompletableFuture<Void> result = new CompletableFuture<>(); try {//from www . ja va2 s .c om validatePoliciesReadOnlyAccess(); } catch (Exception e) { result.completeExceptionally(e); } ZooKeeper globalZk = configCache.getZooKeeper(); final String policiesPath = String.format("/%s/%s/%s", "admin", POLICIES, namespaceName.toString()); try { Stat nodeStat = new Stat(); byte[] content = globalZk.getData(policiesPath, null, nodeStat); Policies policies = getThreadLocal().readValue(content, Policies.class); policies.auth_policies.namespace_auth.put(role, actions); // Write back the new policies into zookeeper globalZk.setData(policiesPath, getThreadLocal().writeValueAsBytes(policies), nodeStat.getVersion()); configCache.policiesCache().invalidate(policiesPath); log.info("[{}] Successfully granted access for role {}: {} - namespace {}", role, role, actions, namespaceName); result.complete(null); } catch (KeeperException.NoNodeException e) { log.warn("[{}] Failed to set permissions for namespace {}: does not exist", role, namespaceName); result.completeExceptionally(new IllegalArgumentException("Namespace does not exist" + namespaceName)); } catch (KeeperException.BadVersionException e) { log.warn("[{}] Failed to set permissions for namespace {}: concurrent modification", role, namespaceName); result.completeExceptionally(new IllegalStateException( "Concurrent modification on zk path: " + policiesPath + ", " + e.getMessage())); } catch (Exception e) { log.error("[{}] Failed to get permissions for namespace {}", role, namespaceName, e); result.completeExceptionally( new IllegalStateException("Failed to get permissions for namespace " + namespaceName)); } return result; }
From source file:org.apache.pulsar.broker.authorization.PulsarAuthorizationProvider.java
private CompletableFuture<Void> updateSubscriptionPermissionAsync(NamespaceName namespace, String subscriptionName, Set<String> roles, boolean remove) { CompletableFuture<Void> result = new CompletableFuture<>(); try {/*from ww w . j a va2s.c o m*/ validatePoliciesReadOnlyAccess(); } catch (Exception e) { result.completeExceptionally(e); } ZooKeeper globalZk = configCache.getZooKeeper(); final String policiesPath = String.format("/%s/%s/%s", "admin", POLICIES, namespace.toString()); try { Stat nodeStat = new Stat(); byte[] content = globalZk.getData(policiesPath, null, nodeStat); Policies policies = getThreadLocal().readValue(content, Policies.class); if (remove) { if (policies.auth_policies.subscription_auth_roles.get(subscriptionName) != null) { policies.auth_policies.subscription_auth_roles.get(subscriptionName).removeAll(roles); } else { log.info("[{}] Couldn't find role {} while revoking for sub = {}", namespace, subscriptionName, roles); result.completeExceptionally(new IllegalArgumentException("couldn't find subscription")); return result; } } else { policies.auth_policies.subscription_auth_roles.put(subscriptionName, roles); } // Write back the new policies into zookeeper globalZk.setData(policiesPath, getThreadLocal().writeValueAsBytes(policies), nodeStat.getVersion()); configCache.policiesCache().invalidate(policiesPath); log.info("[{}] Successfully granted access for role {} for sub = {}", namespace, subscriptionName, roles); result.complete(null); } catch (KeeperException.NoNodeException e) { log.warn("[{}] Failed to set permissions for namespace {}: does not exist", subscriptionName, namespace); result.completeExceptionally(new IllegalArgumentException("Namespace does not exist" + namespace)); } catch (KeeperException.BadVersionException e) { log.warn("[{}] Failed to set permissions for {} on namespace {}: concurrent modification", subscriptionName, roles, namespace); result.completeExceptionally(new IllegalStateException( "Concurrent modification on zk path: " + policiesPath + ", " + e.getMessage())); } catch (Exception e) { log.error("[{}] Failed to get permissions for role {} on namespace {}", subscriptionName, roles, namespace, e); result.completeExceptionally( new IllegalStateException("Failed to get permissions for namespace " + namespace)); } return result; }
From source file:org.apache.pulsar.broker.authorization.PulsarAuthorizationProvider.java
public CompletableFuture<Boolean> checkPermission(TopicName topicName, String role, AuthAction action) { CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>(); try {//from w w w . ja v a 2 s . co m configCache.policiesCache().getAsync(POLICY_ROOT + topicName.getNamespace()).thenAccept(policies -> { if (!policies.isPresent()) { if (log.isDebugEnabled()) { log.debug("Policies node couldn't be found for topic : {}", topicName); } } else { Map<String, Set<AuthAction>> namespaceRoles = policies.get().auth_policies.namespace_auth; Set<AuthAction> namespaceActions = namespaceRoles.get(role); if (namespaceActions != null && namespaceActions.contains(action)) { // The role has namespace level permission permissionFuture.complete(true); return; } Map<String, Set<AuthAction>> topicRoles = policies.get().auth_policies.destination_auth .get(topicName.toString()); if (topicRoles != null) { // Topic has custom policy Set<AuthAction> topicActions = topicRoles.get(role); if (topicActions != null && topicActions.contains(action)) { // The role has topic level permission permissionFuture.complete(true); return; } } // Using wildcard if (conf.isAuthorizationAllowWildcardsMatching()) { if (checkWildcardPermission(role, action, namespaceRoles)) { // The role has namespace level permission by wildcard match permissionFuture.complete(true); return; } if (topicRoles != null && checkWildcardPermission(role, action, topicRoles)) { // The role has topic level permission by wildcard match permissionFuture.complete(true); return; } } } permissionFuture.complete(false); }).exceptionally(ex -> { log.warn("Client with Role - {} failed to get permissions for topic - {}. {}", role, topicName, ex.getMessage()); permissionFuture.completeExceptionally(ex); return null; }); } catch (Exception e) { log.warn("Client with Role - {} failed to get permissions for topic - {}. {}", role, topicName, e.getMessage()); permissionFuture.completeExceptionally(e); } return permissionFuture; }
From source file:org.apache.pulsar.broker.lookup.TopicLookup.java
/** * * Lookup broker-service address for a given namespace-bundle which contains given topic. * * a. Returns broker-address if namespace-bundle is already owned by any broker * b. If current-broker receives lookup-request and if it's not a leader * then current broker redirects request to leader by returning leader-service address. * c. If current-broker is leader then it finds out least-loaded broker to own namespace bundle and * redirects request by returning least-loaded broker. * d. If current-broker receives request to own the namespace-bundle then it owns a bundle and returns * success(connect) response to client./*from w w w. j a v a 2 s . com*/ * * @param pulsarService * @param topicName * @param authoritative * @param clientAppId * @param requestId * @return */ public static CompletableFuture<ByteBuf> lookupTopicAsync(PulsarService pulsarService, TopicName topicName, boolean authoritative, String clientAppId, AuthenticationDataSource authenticationData, long requestId) { final CompletableFuture<ByteBuf> validationFuture = new CompletableFuture<>(); final CompletableFuture<ByteBuf> lookupfuture = new CompletableFuture<>(); final String cluster = topicName.getCluster(); // (1) validate cluster getClusterDataIfDifferentCluster(pulsarService, cluster, clientAppId).thenAccept(differentClusterData -> { if (differentClusterData != null) { if (log.isDebugEnabled()) { log.debug("[{}] Redirecting the lookup call to {}/{} cluster={}", clientAppId, differentClusterData.getBrokerServiceUrl(), differentClusterData.getBrokerServiceUrlTls(), cluster); } validationFuture.complete(newLookupResponse(differentClusterData.getBrokerServiceUrl(), differentClusterData.getBrokerServiceUrlTls(), true, LookupType.Redirect, requestId, false)); } else { // (2) authorize client try { checkAuthorization(pulsarService, topicName, clientAppId, authenticationData); } catch (RestException authException) { log.warn("Failed to authorized {} on cluster {}", clientAppId, topicName.toString()); validationFuture.complete(newLookupErrorResponse(ServerError.AuthorizationError, authException.getMessage(), requestId)); return; } catch (Exception e) { log.warn("Unknown error while authorizing {} on cluster {}", clientAppId, topicName.toString()); validationFuture.completeExceptionally(e); return; } // (3) validate global namespace checkLocalOrGetPeerReplicationCluster(pulsarService, topicName.getNamespaceObject()) .thenAccept(peerClusterData -> { if (peerClusterData == null) { // (4) all validation passed: initiate lookup validationFuture.complete(null); return; } // if peer-cluster-data is present it means namespace is owned by that peer-cluster and // request should be redirect to the peer-cluster if (StringUtils.isBlank(peerClusterData.getBrokerServiceUrl()) && StringUtils.isBlank(peerClusterData.getBrokerServiceUrl())) { validationFuture.complete(newLookupErrorResponse(ServerError.MetadataError, "Redirected cluster's brokerService url is not configured", requestId)); return; } validationFuture.complete(newLookupResponse(peerClusterData.getBrokerServiceUrl(), peerClusterData.getBrokerServiceUrlTls(), true, LookupType.Redirect, requestId, false)); }).exceptionally(ex -> { validationFuture.complete( newLookupErrorResponse(ServerError.MetadataError, ex.getMessage(), requestId)); return null; }); } }).exceptionally(ex -> { validationFuture.completeExceptionally(ex); return null; }); // Initiate lookup once validation completes validationFuture.thenAccept(validaitonFailureResponse -> { if (validaitonFailureResponse != null) { lookupfuture.complete(validaitonFailureResponse); } else { pulsarService.getNamespaceService().getBrokerServiceUrlAsync(topicName, authoritative) .thenAccept(lookupResult -> { if (log.isDebugEnabled()) { log.debug("[{}] Lookup result {}", topicName.toString(), lookupResult); } if (!lookupResult.isPresent()) { lookupfuture.complete(newLookupErrorResponse(ServerError.ServiceNotReady, "No broker was available to own " + topicName, requestId)); return; } LookupData lookupData = lookupResult.get().getLookupData(); if (lookupResult.get().isRedirect()) { boolean newAuthoritative = isLeaderBroker(pulsarService); lookupfuture.complete( newLookupResponse(lookupData.getBrokerUrl(), lookupData.getBrokerUrlTls(), newAuthoritative, LookupType.Redirect, requestId, false)); } else { // When running in standalone mode we want to redirect the client through the service // url, so that the advertised address configuration is not relevant anymore. boolean redirectThroughServiceUrl = pulsarService.getConfiguration() .isRunningStandalone(); lookupfuture.complete(newLookupResponse(lookupData.getBrokerUrl(), lookupData.getBrokerUrlTls(), true /* authoritative */, LookupType.Connect, requestId, redirectThroughServiceUrl)); } }).exceptionally(ex -> { if (ex instanceof CompletionException && ex.getCause() instanceof IllegalStateException) { log.info("Failed to lookup {} for topic {} with error {}", clientAppId, topicName.toString(), ex.getCause().getMessage()); } else { log.warn("Failed to lookup {} for topic {} with error {}", clientAppId, topicName.toString(), ex.getMessage(), ex); } lookupfuture.complete(newLookupErrorResponse(ServerError.ServiceNotReady, ex.getMessage(), requestId)); return null; }); } }).exceptionally(ex -> { if (ex instanceof CompletionException && ex.getCause() instanceof IllegalStateException) { log.info("Failed to lookup {} for topic {} with error {}", clientAppId, topicName.toString(), ex.getCause().getMessage()); } else { log.warn("Failed to lookup {} for topic {} with error {}", clientAppId, topicName.toString(), ex.getMessage(), ex); } lookupfuture.complete(newLookupErrorResponse(ServerError.ServiceNotReady, ex.getMessage(), requestId)); return null; }); return lookupfuture; }
From source file:org.apache.pulsar.broker.namespace.NamespaceService.java
private void searchForCandidateBroker(NamespaceBundle bundle, CompletableFuture<LookupResult> lookupFuture, boolean authoritative) { String candidateBroker = null; try {/*from w w w. j a v a 2s.co m*/ // check if this is Heartbeat or SLAMonitor namespace candidateBroker = checkHeartbeatNamespace(bundle); if (candidateBroker == null) { String broker = getSLAMonitorBrokerName(bundle); // checking if the broker is up and running if (broker != null && isBrokerActive(broker)) { candidateBroker = broker; } } if (candidateBroker == null) { if (!this.loadManager.get().isCentralized() || pulsar.getLeaderElectionService().isLeader()) { candidateBroker = getLeastLoadedFromLoadManager(bundle); } else { if (authoritative) { // leader broker already assigned the current broker as owner candidateBroker = pulsar.getWebServiceAddress(); } else { // forward to leader broker to make assignment candidateBroker = pulsar.getLeaderElectionService().getCurrentLeader().getServiceUrl(); } } } } catch (Exception e) { LOG.warn("Error when searching for candidate broker to acquire {}: {}", bundle, e.getMessage(), e); lookupFuture.completeExceptionally(e); return; } try { checkNotNull(candidateBroker); if (pulsar.getWebServiceAddress().equals(candidateBroker)) { // Load manager decided that the local broker should try to become the owner ownershipCache.tryAcquiringOwnership(bundle).thenAccept(ownerInfo -> { if (ownerInfo.isDisabled()) { if (LOG.isDebugEnabled()) { LOG.debug("Namespace bundle {} is currently being unloaded", bundle); } lookupFuture.completeExceptionally(new IllegalStateException( String.format("Namespace bundle %s is currently being unloaded", bundle))); } else { // Found owner for the namespace bundle // Schedule the task to pre-load destinations pulsar.loadNamespaceDestinations(bundle); lookupFuture.complete(new LookupResult(ownerInfo)); } }).exceptionally(exception -> { LOG.warn("Failed to acquire ownership for namespace bundle {}: ", bundle, exception.getMessage(), exception); lookupFuture.completeExceptionally(new PulsarServerException( "Failed to acquire ownership for namespace bundle " + bundle, exception)); return null; }); } else { // Load managed decider some other broker should try to acquire ownership if (LOG.isDebugEnabled()) { LOG.debug("Redirecting to broker {} to acquire ownership of bundle {}", candidateBroker, bundle); } // Now setting the redirect url createLookupResult(candidateBroker).thenAccept(lookupResult -> lookupFuture.complete(lookupResult)) .exceptionally(ex -> { lookupFuture.completeExceptionally(ex); return null; }); } } catch (Exception e) { LOG.warn("Error in trying to acquire namespace bundle ownership for {}: {}", bundle, e.getMessage(), e); lookupFuture.completeExceptionally(e); } }