use of org.apache.bookkeeper.mledger.AsyncCallbacks.OpenLedgerCallback in project incubator-pulsar by apache.
the class BrokerService method createPersistentTopic.
private void createPersistentTopic(final String topic, CompletableFuture<Topic> topicFuture) {
final long topicCreateTimeMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
TopicName topicName = TopicName.get(topic);
if (!pulsar.getNamespaceService().isServiceUnitActive(topicName)) {
// namespace is being unloaded
String msg = String.format("Namespace is being unloaded, cannot add topic %s", topic);
log.warn(msg);
pulsar.getExecutor().submit(() -> topics.remove(topic, topicFuture));
topicFuture.completeExceptionally(new ServiceUnitNotReadyException(msg));
return;
}
getManagedLedgerConfig(topicName).thenAccept(managedLedgerConfig -> {
// Once we have the configuration, we can proceed with the async open operation
managedLedgerFactory.asyncOpen(topicName.getPersistenceNamingEncoding(), managedLedgerConfig, new OpenLedgerCallback() {
@Override
public void openLedgerComplete(ManagedLedger ledger, Object ctx) {
try {
PersistentTopic persistentTopic = new PersistentTopic(topic, ledger, BrokerService.this);
CompletableFuture<Void> replicationFuture = persistentTopic.checkReplication();
replicationFuture.thenCompose(v -> {
// Also check dedup status
return persistentTopic.checkDeduplicationStatus();
}).thenRun(() -> {
log.info("Created topic {} - dedup is {}", topic, persistentTopic.isDeduplicationEnabled() ? "enabled" : "disabled");
long topicLoadLatencyMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) - topicCreateTimeMs;
pulsarStats.recordTopicLoadTimeValue(topic, topicLoadLatencyMs);
addTopicToStatsMaps(topicName, persistentTopic);
topicFuture.complete(persistentTopic);
}).exceptionally((ex) -> {
log.warn("Replication or dedup check failed. Removing topic from topics list {}, {}", topic, ex);
persistentTopic.stopReplProducers().whenComplete((v, exception) -> {
topics.remove(topic, topicFuture);
topicFuture.completeExceptionally(ex);
});
return null;
});
} catch (NamingException e) {
log.warn("Failed to create topic {}-{}", topic, e.getMessage());
pulsar.getExecutor().submit(() -> topics.remove(topic, topicFuture));
topicFuture.completeExceptionally(e);
}
}
@Override
public void openLedgerFailed(ManagedLedgerException exception, Object ctx) {
log.warn("Failed to create topic {}", topic, exception);
pulsar.getExecutor().submit(() -> topics.remove(topic, topicFuture));
topicFuture.completeExceptionally(new PersistenceException(exception));
}
}, null);
}).exceptionally((exception) -> {
log.warn("[{}] Failed to get topic configuration: {}", topic, exception.getMessage(), exception);
// remove topic from topics-map in different thread to avoid possible deadlock if
// createPersistentTopic-thread only tries to handle this future-result
pulsar.getExecutor().submit(() -> topics.remove(topic, topicFuture));
topicFuture.completeExceptionally(exception);
return null;
});
}
use of org.apache.bookkeeper.mledger.AsyncCallbacks.OpenLedgerCallback in project incubator-pulsar by apache.
the class ManagedLedgerWriter method main.
public static void main(String[] args) throws Exception {
final Arguments arguments = new Arguments();
JCommander jc = new JCommander(arguments);
jc.setProgramName("pulsar-perf-producer");
try {
jc.parse(args);
} catch (ParameterException e) {
System.out.println(e.getMessage());
jc.usage();
System.exit(-1);
}
if (arguments.help) {
jc.usage();
System.exit(-1);
}
arguments.testTime = TimeUnit.SECONDS.toMillis(arguments.testTime);
// Dump config variables
ObjectMapper m = new ObjectMapper();
ObjectWriter w = m.writerWithDefaultPrettyPrinter();
log.info("Starting Pulsar managed-ledger perf writer with config: {}", w.writeValueAsString(arguments));
byte[] payloadData = new byte[arguments.msgSize];
ByteBuf payloadBuffer = PooledByteBufAllocator.DEFAULT.directBuffer(arguments.msgSize);
payloadBuffer.writerIndex(arguments.msgSize);
// Now processing command line arguments
String managedLedgerPrefix = "test-" + DigestUtils.sha1Hex(UUID.randomUUID().toString()).substring(0, 5);
ClientConfiguration bkConf = new ClientConfiguration();
bkConf.setUseV2WireProtocol(true);
bkConf.setLedgerManagerFactoryClass(HierarchicalLedgerManagerFactory.class);
bkConf.setAddEntryTimeout(30);
bkConf.setReadEntryTimeout(30);
bkConf.setThrottleValue(0);
bkConf.setNumChannelsPerBookie(arguments.maxConnections);
bkConf.setZkServers(arguments.zookeeperServers);
ManagedLedgerFactoryConfig mlFactoryConf = new ManagedLedgerFactoryConfig();
mlFactoryConf.setMaxCacheSize(0);
ManagedLedgerFactory factory = new ManagedLedgerFactoryImpl(bkConf, mlFactoryConf);
ManagedLedgerConfig mlConf = new ManagedLedgerConfig();
mlConf.setEnsembleSize(arguments.ensembleSize);
mlConf.setWriteQuorumSize(arguments.writeQuorum);
mlConf.setAckQuorumSize(arguments.ackQuorum);
mlConf.setMinimumRolloverTime(10, TimeUnit.MINUTES);
mlConf.setMetadataEnsembleSize(arguments.ensembleSize);
mlConf.setMetadataWriteQuorumSize(arguments.writeQuorum);
mlConf.setMetadataAckQuorumSize(arguments.ackQuorum);
mlConf.setDigestType(arguments.digestType);
mlConf.setMaxSizePerLedgerMb(2048);
List<CompletableFuture<ManagedLedger>> futures = new ArrayList<>();
for (int i = 0; i < arguments.numManagedLedgers; i++) {
String name = String.format("%s-%03d", managedLedgerPrefix, i);
CompletableFuture<ManagedLedger> future = new CompletableFuture<>();
futures.add(future);
factory.asyncOpen(name, mlConf, new OpenLedgerCallback() {
@Override
public void openLedgerComplete(ManagedLedger ledger, Object ctx) {
future.complete(ledger);
}
@Override
public void openLedgerFailed(ManagedLedgerException exception, Object ctx) {
future.completeExceptionally(exception);
}
}, null);
}
List<ManagedLedger> managedLedgers = futures.stream().map(CompletableFuture::join).collect(Collectors.toList());
log.info("Created {} managed ledgers", managedLedgers.size());
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
printAggregatedStats();
}
});
Collections.shuffle(managedLedgers);
AtomicBoolean isDone = new AtomicBoolean();
List<List<ManagedLedger>> managedLedgersPerThread = Lists.partition(managedLedgers, Math.max(1, managedLedgers.size() / arguments.numThreads));
for (int i = 0; i < arguments.numThreads; i++) {
List<ManagedLedger> managedLedgersForThisThread = managedLedgersPerThread.get(i);
int nunManagedLedgersForThisThread = managedLedgersForThisThread.size();
long numMessagesForThisThread = arguments.numMessages / arguments.numThreads;
int maxOutstandingForThisThread = arguments.maxOutstanding;
executor.submit(() -> {
try {
final double msgRate = arguments.msgRate / (double) arguments.numThreads;
final RateLimiter rateLimiter = RateLimiter.create(msgRate);
// Acquire 1 sec worth of messages to have a slower ramp-up
rateLimiter.acquire((int) msgRate);
final long startTime = System.currentTimeMillis();
final Semaphore semaphore = new Semaphore(maxOutstandingForThisThread);
final AddEntryCallback addEntryCallback = new AddEntryCallback() {
@Override
public void addComplete(Position position, Object ctx) {
long sendTime = (Long) (ctx);
messagesSent.increment();
bytesSent.add(payloadData.length);
long latencyMicros = NANOSECONDS.toMicros(System.nanoTime() - sendTime);
recorder.recordValue(latencyMicros);
cumulativeRecorder.recordValue(latencyMicros);
semaphore.release();
}
@Override
public void addFailed(ManagedLedgerException exception, Object ctx) {
log.warn("Write error on message", exception);
System.exit(-1);
}
};
// Send messages on all topics/producers
long totalSent = 0;
while (true) {
for (int j = 0; j < nunManagedLedgersForThisThread; j++) {
if (arguments.testTime > 0) {
if (System.currentTimeMillis() - startTime > arguments.testTime) {
log.info("------------------- DONE -----------------------");
printAggregatedStats();
isDone.set(true);
Thread.sleep(5000);
System.exit(0);
}
}
if (numMessagesForThisThread > 0) {
if (totalSent++ >= numMessagesForThisThread) {
log.info("------------------- DONE -----------------------");
printAggregatedStats();
isDone.set(true);
Thread.sleep(5000);
System.exit(0);
}
}
semaphore.acquire();
rateLimiter.acquire();
final long sendTime = System.nanoTime();
managedLedgersForThisThread.get(j).asyncAddEntry(payloadBuffer, addEntryCallback, sendTime);
}
}
} catch (Throwable t) {
log.error("Got error", t);
}
});
}
// Print report stats
long oldTime = System.nanoTime();
Histogram reportHistogram = null;
while (true) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
break;
}
if (isDone.get()) {
break;
}
long now = System.nanoTime();
double elapsed = (now - oldTime) / 1e9;
double rate = messagesSent.sumThenReset() / elapsed;
double throughput = bytesSent.sumThenReset() / elapsed / 1024 / 1024 * 8;
reportHistogram = recorder.getIntervalHistogram(reportHistogram);
log.info("Throughput produced: {} msg/s --- {} Mbit/s --- Latency: mean: {} ms - med: {} - 95pct: {} - 99pct: {} - 99.9pct: {} - 99.99pct: {} - Max: {}", throughputFormat.format(rate), throughputFormat.format(throughput), dec.format(reportHistogram.getMean() / 1000.0), dec.format(reportHistogram.getValueAtPercentile(50) / 1000.0), dec.format(reportHistogram.getValueAtPercentile(95) / 1000.0), dec.format(reportHistogram.getValueAtPercentile(99) / 1000.0), dec.format(reportHistogram.getValueAtPercentile(99.9) / 1000.0), dec.format(reportHistogram.getValueAtPercentile(99.99) / 1000.0), dec.format(reportHistogram.getMaxValue() / 1000.0));
reportHistogram.reset();
oldTime = now;
}
factory.shutdown();
}
use of org.apache.bookkeeper.mledger.AsyncCallbacks.OpenLedgerCallback in project incubator-pulsar by apache.
the class ManagedLedgerFactoryImpl method open.
@Override
public ManagedLedger open(String name, ManagedLedgerConfig config) throws InterruptedException, ManagedLedgerException {
class Result {
ManagedLedger l = null;
ManagedLedgerException e = null;
}
final Result r = new Result();
final CountDownLatch latch = new CountDownLatch(1);
asyncOpen(name, config, new OpenLedgerCallback() {
@Override
public void openLedgerComplete(ManagedLedger ledger, Object ctx) {
r.l = ledger;
latch.countDown();
}
@Override
public void openLedgerFailed(ManagedLedgerException exception, Object ctx) {
r.e = exception;
latch.countDown();
}
}, null);
latch.await();
if (r.e != null) {
throw r.e;
}
return r.l;
}
use of org.apache.bookkeeper.mledger.AsyncCallbacks.OpenLedgerCallback in project incubator-pulsar by apache.
the class PersistentTopicTest method setupMLAsyncCallbackMocks.
void setupMLAsyncCallbackMocks() {
ledgerMock = mock(ManagedLedger.class);
cursorMock = mock(ManagedCursor.class);
final CompletableFuture<Void> closeFuture = new CompletableFuture<>();
doReturn(new ArrayList<Object>()).when(ledgerMock).getCursors();
doReturn("mockCursor").when(cursorMock).getName();
// doNothing().when(cursorMock).asyncClose(new CloseCallback() {
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
// return closeFuture.get();
return closeFuture.complete(null);
}
}).when(cursorMock).asyncClose(new CloseCallback() {
@Override
public void closeComplete(Object ctx) {
log.info("[{}] Successfully closed cursor ledger", "mockCursor");
closeFuture.complete(null);
}
@Override
public void closeFailed(ManagedLedgerException exception, Object ctx) {
// isFenced.set(false);
log.error("Error closing cursor for subscription", exception);
closeFuture.completeExceptionally(new BrokerServiceException.PersistenceException(exception));
}
}, null);
// call openLedgerComplete with ledgerMock on ML factory asyncOpen
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
((OpenLedgerCallback) invocationOnMock.getArguments()[2]).openLedgerComplete(ledgerMock, null);
return null;
}
}).when(mlFactoryMock).asyncOpen(matches(".*success.*"), any(ManagedLedgerConfig.class), any(OpenLedgerCallback.class), anyObject());
// call openLedgerFailed on ML factory asyncOpen
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
((OpenLedgerCallback) invocationOnMock.getArguments()[2]).openLedgerFailed(new ManagedLedgerException("Managed ledger failure"), null);
return null;
}
}).when(mlFactoryMock).asyncOpen(matches(".*fail.*"), any(ManagedLedgerConfig.class), any(OpenLedgerCallback.class), anyObject());
// call addComplete on ledger asyncAddEntry
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
((AddEntryCallback) invocationOnMock.getArguments()[1]).addComplete(new PositionImpl(1, 1), invocationOnMock.getArguments()[2]);
return null;
}
}).when(ledgerMock).asyncAddEntry(any(ByteBuf.class), any(AddEntryCallback.class), anyObject());
// call openCursorComplete on cursor asyncOpen
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
((OpenCursorCallback) invocationOnMock.getArguments()[2]).openCursorComplete(cursorMock, null);
return null;
}
}).when(ledgerMock).asyncOpenCursor(matches(".*success.*"), any(InitialPosition.class), any(OpenCursorCallback.class), anyObject());
// call deleteLedgerComplete on ledger asyncDelete
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
((DeleteLedgerCallback) invocationOnMock.getArguments()[0]).deleteLedgerComplete(null);
return null;
}
}).when(ledgerMock).asyncDelete(any(DeleteLedgerCallback.class), anyObject());
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
((DeleteCursorCallback) invocationOnMock.getArguments()[1]).deleteCursorComplete(null);
return null;
}
}).when(ledgerMock).asyncDeleteCursor(matches(".*success.*"), any(DeleteCursorCallback.class), anyObject());
doAnswer((invokactionOnMock) -> {
((MarkDeleteCallback) invokactionOnMock.getArguments()[2]).markDeleteComplete(invokactionOnMock.getArguments()[3]);
return null;
}).when(cursorMock).asyncMarkDelete(anyObject(), anyObject(), any(MarkDeleteCallback.class), anyObject());
}
use of org.apache.bookkeeper.mledger.AsyncCallbacks.OpenLedgerCallback in project incubator-pulsar by apache.
the class PersistentTopicTest method testCreateTopicMLFailure.
@Test
public void testCreateTopicMLFailure() throws Exception {
final String jinxedTopicName = "persistent://prop/use/ns-abc/topic3";
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
new Thread(() -> {
((OpenLedgerCallback) invocationOnMock.getArguments()[2]).openLedgerFailed(new ManagedLedgerException("Managed ledger failure"), null);
}).start();
return null;
}
}).when(mlFactoryMock).asyncOpen(anyString(), any(ManagedLedgerConfig.class), any(OpenLedgerCallback.class), anyObject());
CompletableFuture<Topic> future = brokerService.getTopic(jinxedTopicName);
// wait for completion
try {
future.get(1, TimeUnit.SECONDS);
fail("should have failed");
} catch (TimeoutException e) {
fail("Should not time out");
} catch (Exception e) {
// OK
}
}
Aggregations