public static boolean isValid(String destination) { try { get(destination); return true; } catch (Exception e) { return false; } }
@Override public CompletableFuture<Void> createPartitionedTopicAsync(String destination, int numPartitions) { checkArgument(numPartitions > 1, "Number of partitions should be more than 1"); DestinationName ds = validateTopic(destination); return asyncPutRequest( persistentTopics.path(ds.getNamespace()).path(ds.getEncodedLocalName()).path("partitions"), Entity.entity(numPartitions, MediaType.APPLICATION_JSON)); }
} catch (RestException e) { try { validateAdminAccessOnProperty(pulsar, clientAppId, dn.getProperty()); } catch (RestException authException) { log.warn("Failed to authorize {} on cluster {}", clientAppId, dn.toString()); throw new PulsarClientException(String.format("Authorization failed %s on cluster %s with error %s", clientAppId, dn.toString(), authException.getMessage())); dn.toString(), ex.getMessage(), ex); throw ex; String path = path(PARTITIONED_TOPIC_PATH_ZNODE, dn.getProperty(), dn.getCluster(), dn.getNamespacePortion(), "persistent", dn.getEncodedLocalName()); fetchPartitionedTopicMetadataAsync(pulsar, path).thenAccept(metadata -> { if (log.isDebugEnabled()) {
private void put(DestinationName destinationName, PendingBookieOpsStats bookieOpsStats) { String namespace = destinationName.getNamespace(); if (!nsBookieClientStatsMap.containsKey(namespace)) { Map<String, PendingBookieOpsStats> destBookieClientStatsMap = Maps.newTreeMap(); destBookieClientStatsMap.put(destinationName.toString(), bookieOpsStats); nsBookieClientStatsMap.put(namespace, destBookieClientStatsMap); } else { nsBookieClientStatsMap.get(namespace).put(destinationName.toString(), bookieOpsStats); } } }
private boolean checkCluster(DestinationName destination) { if (destination.isGlobal() || conf.getClusterName().equals(destination.getCluster())) { return true; } else { if (log.isDebugEnabled()) { log.debug("Destination [{}] does not belong to local cluster [{}]", destination.toString(), conf.getClusterName()); } return false; } }
AtomicInteger completed = new AtomicInteger(); for (int partitionIndex = 0; partitionIndex < numPartitions; partitionIndex++) { String partitionName = DestinationName.get(topic).getPartition(partitionIndex).toString(); ProducerImpl producer = new ProducerImpl(client, partitionName, null, conf, new CompletableFuture<Producer>(), partitionIndex);
String path = path(PARTITIONED_TOPIC_PATH_ZNODE, dn.getProperty(), dn.getCluster(), dn.getNamespacePortion(), domain(), dn.getEncodedLocalName()); CompletableFuture<Void> result = new CompletableFuture<>(); fetchPartitionedTopicMetadataAsync(pulsar(), path).thenAccept(partitionMetadata -> { final String ledgerName = dn.getPartition(1).getPersistenceNamingEncoding(); ((ManagedLedgerFactoryImpl) pulsar().getManagedLedgerFactory()).getMetaStore().getCursors(ledgerName, new MetaStoreCallback<List<String>>() { log.warn("[{}] Failed to get partition metadata for {}", clientAppId(), dn.toString()); result.completeExceptionally(ex); return null;
/** * * @return Backlog quota for topic */ @Override public BacklogQuota getBacklogQuota() { DestinationName destination = DestinationName.get(this.getName()); String namespace = destination.getNamespace(); String policyPath = AdminResource.path("policies", namespace); BacklogQuota backlogQuota = brokerService.getBacklogQuotaManager().getBacklogQuota(namespace, policyPath); return backlogQuota; }
@QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { destination = decode(destination); DestinationName dn = DestinationName.get(domain(), property, cluster, namespace, destination); validateAdminAccessOnProperty(dn.getProperty()); PartitionedTopicMetadata partitionMetadata = getPartitionedTopicMetadata(property, cluster, namespace, destination, authoritative); try { for (int i = 0; i < numPartitions; i++) { DestinationName dn_partition = dn.getPartition(i); pulsar().getAdminClient().persistentTopics().deleteAsync(dn_partition.toString()) .whenComplete((r, ex) -> { if (ex != null) { dn.getEncodedLocalName()); try { globalZk().delete(path, -1);
public PartitionedTopicMetadata getPartitionedTopicMetadata(String property, String cluster, String namespace, String destination, boolean authoritative) { DestinationName dn = DestinationName.get(domain(), property, cluster, namespace, destination); validateClusterOwnership(dn.getCluster()); try { checkConnect(dn); } catch (WebApplicationException e) { validateAdminAccessOnProperty(dn.getProperty()); } catch (Exception e) { // unknown error marked as internal server error log.warn("Unexpected error while authorizing lookup. destination={}, role={}. Error: {}", destination, clientAppId(), e.getMessage(), e); throw new RestException(e); } String path = path(PARTITIONED_TOPIC_PATH_ZNODE, property, cluster, namespace, domain(), dn.getEncodedLocalName()); PartitionedTopicMetadata partitionMetadata = fetchPartitionedTopicMetadata(pulsar(), path); if (log.isDebugEnabled()) { log.debug("[{}] Total number of partitions for topic {} is {}", clientAppId(), dn, partitionMetadata.partitions); } return partitionMetadata; }
@Override public Map<String, Set<AuthAction>> getPermissions(String destination) throws PulsarAdminException { try { DestinationName ds = DestinationName.get(destination); return request(persistentTopics.path(ds.getNamespace()).path(ds.getLocalName()).path("permissions")).get( new GenericType<Map<String, Set<AuthAction>>>() { }); } catch (Exception e) { throw getApiException(e); } }
@Suspended AsyncResponse asyncResponse) { dest = Codec.decode(dest); DestinationName topic = DestinationName.get("persistent", property, cluster, namespace, dest); validateClusterOwnership(topic.getCluster()); checkConnect(topic); validateReplicationSettingsOnNamespace(pulsar(), topic.getNamespaceObject()); } catch (WebApplicationException we) { : result.getLookupData().getHttpUrl(); redirect = new URI(String.format("%s%s%s?authoritative=%s", redirectUrl, "/lookup/v2/destination/", topic.getLookupName(), newAuthoritative)); } catch (URISyntaxException e) { log.error("Error in preparing redirect url for {}: {}", topic, e.getMessage(), e);
@PUT @Path("/{property}/{cluster}/{namespace}/{destination}/partitions") @ApiOperation(value = "Create a partitioned topic.", notes = "It needs to be called before creating a producer on a partitioned topic.") @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 409, message = "Partitioned topic already exist") }) public void createPartitionedTopic(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, @PathParam("destination") @Encoded String destination, int numPartitions, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { destination = decode(destination); DestinationName dn = DestinationName.get(domain(), property, cluster, namespace, destination); validateAdminAccessOnProperty(dn.getProperty()); if (numPartitions <= 1) { throw new RestException(Status.NOT_ACCEPTABLE, "Number of partitions should be more than 1"); } try { String path = path(PARTITIONED_TOPIC_PATH_ZNODE, property, cluster, namespace, domain(), dn.getEncodedLocalName()); byte[] data = jsonMapper().writeValueAsBytes(new PartitionedTopicMetadata(numPartitions)); zkCreateOptimistic(path, data); // we wait for the data to be synced in all quorums and the observers Thread.sleep(PARTITIONED_TOPIC_WAIT_SYNC_TIME_MS); log.info("[{}] Successfully created partitioned topic {}", clientAppId(), dn); } catch (KeeperException.NodeExistsException e) { log.warn("[{}] Failed to create already existing partitioned topic {}", clientAppId(), dn); throw new RestException(Status.CONFLICT, "Partitioned topic already exist"); } catch (Exception e) { log.error("[{}] Failed to create partitioned topic {}", clientAppId(), dn, e); throw new RestException(e); } }
@Override public CompletableFuture<Void> checkReplication() { DestinationName name = DestinationName.get(topic); if (!name.isGlobal()) { return CompletableFuture.completedFuture(null); try { policies = brokerService.pulsar().getConfigurationCache().policiesCache() .get(AdminResource.path("policies", name.getNamespace())) .orElseThrow(() -> new KeeperException.NoNodeException()); } catch (Exception e) {
@GET @Path("{property}/{cluster}/{namespace}/{destination}/internal-info") @ApiOperation(value = "Get the internal stats for the topic.") @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Topic does not exist") }) public void getManagedLedgerInfo(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, @PathParam("destination") @Encoded String destination, @Suspended AsyncResponse asyncResponse) { destination = decode(destination); DestinationName dn = DestinationName.get(domain(), property, cluster, namespace, destination); validateAdminAccessOnProperty(dn.getProperty()); String managedLedger = dn.getPersistenceNamingEncoding(); pulsar().getManagedLedgerFactory().asyncGetManagedLedgerInfo(managedLedger, new ManagedLedgerInfoCallback() { @Override public void getInfoComplete(ManagedLedgerInfo info, Object ctx) { asyncResponse.resume((StreamingOutput) output -> { jsonMapper().writer().writeValue(output, info); }); } @Override public void getInfoFailed(ManagedLedgerException exception, Object ctx) { asyncResponse.resume(exception); } }, null); }
int numPartitions) { destination = decode(destination); DestinationName dn = DestinationName.get(domain(), property, cluster, namespace, destination); validateAdminAccessOnProperty(dn.getProperty()); if (dn.isGlobal()) { log.error("[{}] Update partitioned-topic is forbidden on global namespace {}", clientAppId(), dn); throw new RestException(Status.FORBIDDEN, "Update forbidden on global namespace");
final String cluster = fqdn.getCluster(); checkAuthorization(pulsarService, fqdn, clientAppId); } catch (RestException authException) { log.warn("Failed to authorized {} on cluster {}", clientAppId, fqdn.toString()); validationFuture.complete( newLookupResponse(ServerError.AuthorizationError, authException.getMessage(), requestId)); return; } catch (Exception e) { log.warn("Unknown error while authorizing {} on cluster {}", clientAppId, fqdn.toString()); validationFuture.completeExceptionally(e); return; validateReplicationSettingsOnNamespaceAsync(pulsarService, fqdn.getNamespaceObject()) .thenAccept(success -> { log.debug("[{}] Lookup result {}", fqdn.toString(), lookupResult); log.warn("Failed to lookup {} for topic {} with error {}", clientAppId, fqdn.toString(), e.getMessage(), e); lookupfuture.complete( log.warn("Failed to lookup {} for topic {} with error {}", clientAppId, fqdn.toString(), ex.getMessage(), ex); lookupfuture.complete(newLookupResponse(ServerError.ServiceNotReady, ex.getMessage(), requestId));
private void createPersistentTopic(final String topic, CompletableFuture<Topic> topicFuture) { DestinationName destinationName = DestinationName.get(topic); if (!pulsar.getNamespaceService().isServiceUnitActive(destinationName)) { managedLedgerFactory.asyncOpen(destinationName.getPersistenceNamingEncoding(), config, new OpenLedgerCallback() { @Override