use of com.yahoo.pulsar.common.naming.NamespaceBundle in project pulsar by yahoo.
the class NamespaceService method splitAndOwnBundle.
/**
* 1. split the given bundle into two bundles 2. assign ownership of both the bundles to current broker 3. update
* policies with newly created bundles into LocalZK 4. disable original bundle and refresh the cache
*
* @param bundle
* @return
* @throws Exception
*/
public CompletableFuture<Void> splitAndOwnBundle(NamespaceBundle bundle) throws Exception {
final CompletableFuture<Void> future = new CompletableFuture<>();
Pair<NamespaceBundles, List<NamespaceBundle>> splittedBundles = bundleFactory.splitBundles(bundle, 2);
if (splittedBundles != null) {
checkNotNull(splittedBundles.getLeft());
checkNotNull(splittedBundles.getRight());
checkArgument(splittedBundles.getRight().size() == 2, "bundle has to be split in two bundles");
NamespaceName nsname = bundle.getNamespaceObject();
try {
// take ownership of newly split bundles
for (NamespaceBundle sBundle : splittedBundles.getRight()) {
checkNotNull(ownershipCache.tryAcquiringOwnership(sBundle));
}
updateNamespaceBundles(nsname, splittedBundles.getLeft(), (rc, path, zkCtx, stat) -> pulsar.getOrderedExecutor().submit(safeRun(() -> {
if (rc == KeeperException.Code.OK.intValue()) {
// disable old bundle
try {
ownershipCache.disableOwnership(bundle);
// invalidate cache as zookeeper has new split
// namespace bundle
bundleFactory.invalidateBundleCache(nsname);
// update bundled_topic cache for load-report-generation
pulsar.getBrokerService().refreshTopicToStatsMaps(bundle);
loadManager.setLoadReportForceUpdateFlag();
future.complete(null);
} catch (Exception e) {
String msg1 = format("failed to disable bundle %s under namespace [%s] with error %s", nsname.toString(), bundle.toString(), e.getMessage());
LOG.warn(msg1, e);
future.completeExceptionally(new ServiceUnitNotReadyException(msg1));
}
} else {
String msg2 = format("failed to update namespace [%s] policies due to %s", nsname.toString(), KeeperException.create(KeeperException.Code.get(rc)).getMessage());
LOG.warn(msg2);
future.completeExceptionally(new ServiceUnitNotReadyException(msg2));
}
})));
} catch (Exception e) {
String msg = format("failed to aquire ownership of split bundle for namespace [%s], %s", nsname.toString(), e.getMessage());
LOG.warn(msg, e);
future.completeExceptionally(new ServiceUnitNotReadyException(msg));
}
} else {
String msg = format("bundle %s not found under namespace", bundle.toString());
future.completeExceptionally(new ServiceUnitNotReadyException(msg));
}
return future;
}
use of com.yahoo.pulsar.common.naming.NamespaceBundle in project pulsar by yahoo.
the class BrokerService method addTopicToStatsMaps.
private void addTopicToStatsMaps(DestinationName topicName, PersistentTopic topic) {
try {
NamespaceBundle namespaceBundle = pulsar.getNamespaceService().getBundle(topicName);
if (namespaceBundle != null) {
synchronized (multiLayerTopicsMap) {
String serviceUnit = namespaceBundle.toString();
//
multiLayerTopicsMap.computeIfAbsent(topicName.getNamespace(), //
k -> new ConcurrentOpenHashMap<>()).computeIfAbsent(serviceUnit, //
k -> new ConcurrentOpenHashMap<>()).put(topicName.toString(), topic);
}
}
invalidateOfflineTopicStatCache(topicName);
} catch (Exception e) {
log.warn("Got exception when retrieving bundle name during create persistent topic", e);
}
}
use of com.yahoo.pulsar.common.naming.NamespaceBundle in project pulsar by yahoo.
the class BrokerService method unloadServiceUnit.
/**
* Unload all the topic served by the broker service under the given service unit
*
* @param serviceUnit
* @return
*/
public CompletableFuture<Integer> unloadServiceUnit(NamespaceBundle serviceUnit) {
CompletableFuture<Integer> result = new CompletableFuture<Integer>();
List<CompletableFuture<Void>> closeFutures = Lists.newArrayList();
topics.forEach((name, topicFuture) -> {
DestinationName topicName = DestinationName.get(name);
if (serviceUnit.includes(topicName)) {
// Topic needs to be unloaded
log.info("[{}] Unloading topic", topicName);
closeFutures.add(topicFuture.thenCompose(Topic::close));
}
});
CompletableFuture<Void> aggregator = FutureUtil.waitForAll(closeFutures);
aggregator.thenAccept(res -> result.complete(closeFutures.size())).exceptionally(ex -> {
result.completeExceptionally(ex);
return null;
});
return result;
}
use of com.yahoo.pulsar.common.naming.NamespaceBundle in project pulsar by yahoo.
the class NamespaceService method findBrokerServiceUrl.
/**
* Main internal method to lookup and setup ownership of service unit to a broker
*
* @param bundle
* @param authoritative
* @param readOnly
* @return
* @throws PulsarServerException
*/
private CompletableFuture<LookupResult> findBrokerServiceUrl(NamespaceBundle bundle, boolean authoritative, boolean readOnly) {
if (LOG.isDebugEnabled()) {
LOG.debug("findBrokerServiceUrl: {} - read-only: {}", bundle, readOnly);
}
CompletableFuture<LookupResult> future = new CompletableFuture<>();
// First check if we or someone else already owns the bundle
ownershipCache.getOwnerAsync(bundle).thenAccept(nsData -> {
if (!nsData.isPresent()) {
if (readOnly) {
future.completeExceptionally(new IllegalStateException(String.format("Can't find owner of ServiceUnit: %s", bundle)));
} else {
pulsar.getExecutor().execute(() -> {
searchForCandidateBroker(bundle, future, authoritative);
});
}
} else if (nsData.get().isDisabled()) {
future.completeExceptionally(new IllegalStateException(String.format("Namespace bundle %s is being unloaded", bundle)));
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Namespace bundle {} already owned by {} ", bundle, nsData);
}
future.complete(new LookupResult(nsData.get()));
}
}).exceptionally(exception -> {
LOG.warn("Failed to check owner for bundle {}: {}", bundle, exception.getMessage(), exception);
future.completeExceptionally(exception);
return null;
});
return future;
}
use of com.yahoo.pulsar.common.naming.NamespaceBundle in project pulsar by yahoo.
the class Namespaces method unsubscribeNamespace.
@POST
@Path("/{property}/{cluster}/{namespace}/unsubscribe/{subscription}")
@ApiOperation(value = "Unsubscribes the given subscription on all destinations on a namespace.")
@ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Namespace does not exist") })
public void unsubscribeNamespace(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, @PathParam("subscription") String subscription, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) {
validateAdminAccessOnProperty(property);
NamespaceName nsName = new NamespaceName(property, cluster, namespace);
try {
NamespaceBundles bundles = pulsar().getNamespaceService().getNamespaceBundleFactory().getBundles(nsName);
Exception exception = null;
for (NamespaceBundle nsBundle : bundles.getBundles()) {
try {
// check if the bundle is owned by any broker, if not then there are no subscriptions
if (pulsar().getNamespaceService().getOwner(nsBundle).isPresent()) {
// TODO: make this admin call asynchronous
pulsar().getAdminClient().namespaces().unsubscribeNamespaceBundle(nsName.toString(), nsBundle.getBundleRange(), subscription);
}
} catch (Exception e) {
if (exception == null) {
exception = e;
}
}
}
if (exception != null) {
if (exception instanceof PulsarAdminException) {
throw new RestException((PulsarAdminException) exception);
} else {
throw new RestException(exception.getCause());
}
}
} catch (WebApplicationException wae) {
throw wae;
} catch (Exception e) {
throw new RestException(e);
}
log.info("[{}] Successfully unsubscribed {} on all the bundles for namespace {}", clientAppId(), subscription, nsName.toString());
}
Aggregations