use of com.yahoo.pulsar.broker.service.BrokerServiceException.ServiceUnitNotReadyException 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.broker.service.BrokerServiceException.ServiceUnitNotReadyException in project pulsar by yahoo.
the class BrokerService method createPersistentTopic.
private CompletableFuture<Topic> createPersistentTopic(final String topic) throws RuntimeException {
checkTopicNsOwnership(topic);
final long topicCreateTimeMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
DestinationName destinationName = DestinationName.get(topic);
if (!pulsar.getNamespaceService().isServiceUnitActive(destinationName)) {
// namespace is being unloaded
String msg = String.format("Namespace is being unloaded, cannot add topic %s", topic);
log.warn(msg);
throw new RuntimeException(new ServiceUnitNotReadyException(msg));
}
final CompletableFuture<Topic> topicFuture = new CompletableFuture<>();
getManagedLedgerConfig(destinationName).thenAccept(config -> {
managedLedgerFactory.asyncOpen(destinationName.getPersistenceNamingEncoding(), config, new OpenLedgerCallback() {
@Override
public void openLedgerComplete(ManagedLedger ledger, Object ctx) {
PersistentTopic persistentTopic = new PersistentTopic(topic, ledger, BrokerService.this);
CompletableFuture<Void> replicationFuture = persistentTopic.checkReplication();
replicationFuture.thenRun(() -> {
log.info("Created topic {}", topic);
long topicLoadLatencyMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) - topicCreateTimeMs;
pulsarStats.recordTopicLoadTimeValue(topic, topicLoadLatencyMs);
addTopicToStatsMaps(destinationName, persistentTopic);
topicFuture.complete(persistentTopic);
});
replicationFuture.exceptionally((ex) -> {
log.warn("Replication check failed. Removing topic from topics list {}, {}", topic, ex);
persistentTopic.stopReplProducers().whenComplete((v, exception) -> {
topics.remove(topic, topicFuture);
topicFuture.completeExceptionally(ex);
});
return null;
});
}
@Override
public void openLedgerFailed(ManagedLedgerException exception, Object ctx) {
log.warn("Failed to create topic {}", topic, exception);
topics.remove(topic, topicFuture);
topicFuture.completeExceptionally(new PersistenceException(exception));
}
}, null);
}).exceptionally((exception) -> {
log.warn("[{}] Failed to get topic configuration: {}", topic, exception.getMessage(), exception);
topics.remove(topic, topicFuture);
topicFuture.completeExceptionally(exception);
return null;
});
return topicFuture;
}
use of com.yahoo.pulsar.broker.service.BrokerServiceException.ServiceUnitNotReadyException in project pulsar by yahoo.
the class BrokerService method checkTopicNsOwnership.
void checkTopicNsOwnership(final String topic) throws RuntimeException {
DestinationName destination = DestinationName.get(topic);
boolean ownedByThisInstance;
try {
ownedByThisInstance = pulsar.getNamespaceService().isServiceUnitOwned(destination);
} catch (Exception e) {
log.debug(String.format("Failed to check the ownership of the destination: %s", destination), e);
throw new RuntimeException(new ServerMetadataException(e));
}
if (!ownedByThisInstance) {
String msg = String.format("Namespace not served by this instance. Please redo the lookup. " + "Request is denied: namespace=%s", destination.getNamespace());
log.warn(msg);
throw new RuntimeException(new ServiceUnitNotReadyException(msg));
}
}
use of com.yahoo.pulsar.broker.service.BrokerServiceException.ServiceUnitNotReadyException in project pulsar by yahoo.
the class ServerCnx method handleProducer.
@Override
protected void handleProducer(final CommandProducer cmdProducer) {
checkArgument(state == State.Connected);
CompletableFuture<Boolean> authorizationFuture;
if (service.isAuthorizationEnabled()) {
authorizationFuture = service.getAuthorizationManager().canProduceAsync(DestinationName.get(cmdProducer.getTopic().toString()), authRole);
} else {
authorizationFuture = CompletableFuture.completedFuture(true);
}
// Use producer name provided by client if present
final String producerName = cmdProducer.hasProducerName() ? cmdProducer.getProducerName() : service.generateUniqueProducerName();
final String topicName = cmdProducer.getTopic();
final long producerId = cmdProducer.getProducerId();
final long requestId = cmdProducer.getRequestId();
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()));
return null;
} else {
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).thenAccept((Topic 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;
}
disableTcpNoDelayIfNeeded(topicName, producerName);
Producer producer = new Producer(topic, ServerCnx.this, producerId, producerName, authRole);
try {
topic.addProducer(producer);
if (isActive()) {
if (producerFuture.complete(producer)) {
log.info("[{}] Created new producer: {}", remoteAddress, producer);
ctx.writeAndFlush(Commands.newProducerSuccess(requestId, producerName));
return;
} else {
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)) {
log.error("[{}] Failed to create topic {}", remoteAddress, topicName, exception);
}
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;
});
}
Aggregations