use of org.apache.bookkeeper.mledger.ManagedLedgerException.NoMoreEntriesToReadException in project incubator-pulsar by apache.
the class ManagedLedgerTerminationTest method terminateWithCursorReadOrWait.
@Test(timeOut = 20000)
public void terminateWithCursorReadOrWait() throws Exception {
ManagedLedger ledger = factory.open("my_test_ledger");
ManagedCursor c1 = ledger.openCursor("c1");
Position p0 = ledger.addEntry("entry-0".getBytes());
Position p1 = ledger.addEntry("entry-1".getBytes());
assertEquals(ledger.isTerminated(), false);
Position lastPosition = ledger.terminate();
assertEquals(ledger.isTerminated(), true);
assertEquals(lastPosition, p1);
List<Entry> entries = c1.readEntries(10);
assertEquals(entries.size(), 2);
assertEquals(entries.get(0).getPosition(), p0);
assertEquals(entries.get(1).getPosition(), p1);
entries.forEach(Entry::release);
// Normal read will just return no entries
assertEquals(c1.readEntries(10), Collections.emptyList());
// Read or wait will fail
try {
c1.readEntriesOrWait(10);
fail("Should have thrown exception");
} catch (NoMoreEntriesToReadException e) {
// Expected
}
}
use of org.apache.bookkeeper.mledger.ManagedLedgerException.NoMoreEntriesToReadException in project incubator-pulsar by apache.
the class ManagedLedgerTerminationTest method terminateWithNonDurableCursor.
@Test(timeOut = 20000)
public void terminateWithNonDurableCursor() throws Exception {
ManagedLedger ledger = factory.open("my_test_ledger");
Position p0 = ledger.addEntry("entry-0".getBytes());
Position p1 = ledger.addEntry("entry-1".getBytes());
assertEquals(ledger.isTerminated(), false);
Position lastPosition = ledger.terminate();
assertEquals(ledger.isTerminated(), true);
assertEquals(lastPosition, p1);
ManagedCursor c1 = ledger.newNonDurableCursor(PositionImpl.earliest);
List<Entry> entries = c1.readEntries(10);
assertEquals(entries.size(), 2);
assertEquals(entries.get(0).getPosition(), p0);
assertEquals(entries.get(1).getPosition(), p1);
entries.forEach(Entry::release);
// Normal read will just return no entries
assertEquals(c1.readEntries(10), Collections.emptyList());
// Read or wait will fail
try {
c1.readEntriesOrWait(10);
fail("Should have thrown exception");
} catch (NoMoreEntriesToReadException e) {
// Expected
}
}
use of org.apache.bookkeeper.mledger.ManagedLedgerException.NoMoreEntriesToReadException in project incubator-pulsar by apache.
the class ManagedCursorImpl method asyncReadEntriesOrWait.
@Override
public void asyncReadEntriesOrWait(int numberOfEntriesToRead, ReadEntriesCallback callback, Object ctx) {
checkArgument(numberOfEntriesToRead > 0);
if (STATE_UPDATER.get(this) == State.Closed) {
callback.readEntriesFailed(new CursorAlreadyClosedException("Cursor was already closed"), ctx);
return;
}
if (hasMoreEntries()) {
// If we have available entries, we can read them immediately
if (log.isDebugEnabled()) {
log.debug("[{}] [{}] Read entries immediately", ledger.getName(), name);
}
asyncReadEntries(numberOfEntriesToRead, callback, ctx);
} else {
OpReadEntry op = OpReadEntry.create(this, PositionImpl.get(readPosition), numberOfEntriesToRead, callback, ctx);
if (!WAITING_READ_OP_UPDATER.compareAndSet(this, null, op)) {
callback.readEntriesFailed(new ManagedLedgerException("We can only have a single waiting callback"), ctx);
return;
}
if (log.isDebugEnabled()) {
log.debug("[{}] [{}] Deferring retry of read at position {}", ledger.getName(), name, op.readPosition);
}
// Check again for new entries again in 10ms, then if still no entries are available register to be notified
ledger.getScheduledExecutor().schedule(safeRun(() -> {
if (log.isDebugEnabled()) {
log.debug("[{}] [{}] Re-trying the read at position {}", ledger.getName(), name, op.readPosition);
}
if (!hasMoreEntries()) {
if (log.isDebugEnabled()) {
log.debug("[{}] [{}] Still no entries available. Register for notification", ledger.getName(), name);
}
// Let the managed ledger know we want to be notified whenever a new entry is published
ledger.waitingCursors.add(this);
} else {
if (log.isDebugEnabled()) {
log.debug("[{}] [{}] Skip notification registering since we do have entries available", ledger.getName(), name);
}
}
// checked and the time we've asked to be notified by managed ledger
if (hasMoreEntries()) {
if (log.isDebugEnabled()) {
log.debug("[{}] [{}] Found more entries", ledger.getName(), name);
}
// Try to cancel the notification request
if (WAITING_READ_OP_UPDATER.compareAndSet(this, op, null)) {
if (log.isDebugEnabled()) {
log.debug("[{}] [{}] Cancelled notification and scheduled read at {}", ledger.getName(), name, op.readPosition);
}
PENDING_READ_OPS_UPDATER.incrementAndGet(this);
ledger.asyncReadEntries(op);
} else {
if (log.isDebugEnabled()) {
log.debug("[{}] [{}] notification was already cancelled", ledger.getName(), name);
}
}
} else if (ledger.isTerminated()) {
// At this point we registered for notification and still there were no more available
// entries.
// If the managed ledger was indeed terminated, we need to notify the cursor
callback.readEntriesFailed(new NoMoreEntriesToReadException("Topic was terminated"), ctx);
}
}), 10, TimeUnit.MILLISECONDS);
}
}
use of org.apache.bookkeeper.mledger.ManagedLedgerException.NoMoreEntriesToReadException in project incubator-pulsar by apache.
the class PersistentDispatcherSingleActiveConsumer method readEntriesFailed.
@Override
public synchronized void readEntriesFailed(ManagedLedgerException exception, Object ctx) {
havePendingRead = false;
Consumer c = (Consumer) ctx;
long waitTimeMillis = readFailureBackoff.next();
if (exception instanceof NoMoreEntriesToReadException) {
if (cursor.getNumberOfEntriesInBacklog() == 0) {
// Topic has been terminated and there are no more entries to read
// Notify the consumer only if all the messages were already acknowledged
consumers.forEach(Consumer::reachedEndOfTopic);
}
} else if (!(exception instanceof TooManyRequestsException)) {
log.error("[{}-{}] Error reading entries at {} : {} - Retrying to read in {} seconds", name, c, cursor.getReadPosition(), exception.getMessage(), waitTimeMillis / 1000.0);
} else {
if (log.isDebugEnabled()) {
log.debug("[{}-{}] Got throttled by bookies while reading at {} : {} - Retrying to read in {} seconds", name, c, cursor.getReadPosition(), exception.getMessage(), waitTimeMillis / 1000.0);
}
}
checkNotNull(c);
// Reduce read batch size to avoid flooding bookies with retries
readBatchSize = 1;
topic.getBrokerService().executor().schedule(() -> {
synchronized (PersistentDispatcherSingleActiveConsumer.this) {
Consumer currentConsumer = ACTIVE_CONSUMER_UPDATER.get(this);
// we should retry the read if we have an active consumer and there is no pending read
if (currentConsumer != null && !havePendingRead) {
if (log.isDebugEnabled()) {
log.debug("[{}-{}] Retrying read operation", name, c);
}
readMoreEntries(currentConsumer);
} else {
log.info("[{}-{}] Skipping read retry: Current Consumer {}, havePendingRead {}", name, c, currentConsumer, havePendingRead);
}
}
}, waitTimeMillis, TimeUnit.MILLISECONDS);
}
use of org.apache.bookkeeper.mledger.ManagedLedgerException.NoMoreEntriesToReadException in project incubator-pulsar by apache.
the class PersistentDispatcherMultipleConsumers method readEntriesFailed.
@Override
public synchronized void readEntriesFailed(ManagedLedgerException exception, Object ctx) {
ReadType readType = (ReadType) ctx;
long waitTimeMillis = readFailureBackoff.next();
if (exception instanceof NoMoreEntriesToReadException) {
if (cursor.getNumberOfEntriesInBacklog() == 0) {
// Topic has been terminated and there are no more entries to read
// Notify the consumer only if all the messages were already acknowledged
consumerList.forEach(Consumer::reachedEndOfTopic);
}
} else if (!(exception instanceof TooManyRequestsException)) {
log.error("[{}] Error reading entries at {} : {}, Read Type {} - Retrying to read in {} seconds", name, cursor.getReadPosition(), exception.getMessage(), readType, waitTimeMillis / 1000.0);
} else {
if (log.isDebugEnabled()) {
log.debug("[{}] Error reading entries at {} : {}, Read Type {} - Retrying to read in {} seconds", name, cursor.getReadPosition(), exception.getMessage(), readType, waitTimeMillis / 1000.0);
}
}
if (shouldRewindBeforeReadingOrReplaying) {
shouldRewindBeforeReadingOrReplaying = false;
cursor.rewind();
}
if (readType == ReadType.Normal) {
havePendingRead = false;
} else {
havePendingReplayRead = false;
if (exception instanceof ManagedLedgerException.InvalidReplayPositionException) {
PositionImpl markDeletePosition = (PositionImpl) cursor.getMarkDeletedPosition();
messagesToReplay.removeIf((ledgerId, entryId) -> {
return ComparisonChain.start().compare(ledgerId, markDeletePosition.getLedgerId()).compare(entryId, markDeletePosition.getEntryId()).result() <= 0;
});
}
}
readBatchSize = 1;
topic.getBrokerService().executor().schedule(() -> {
synchronized (PersistentDispatcherMultipleConsumers.this) {
if (!havePendingRead) {
log.info("[{}] Retrying read operation", name);
readMoreEntries();
} else {
log.info("[{}] Skipping read retry: havePendingRead {}", name, havePendingRead, exception);
}
}
}, waitTimeMillis, TimeUnit.MILLISECONDS);
}
Aggregations