Search in sources :

Example 1 with NoMoreEntriesToReadException

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
    }
}
Also used : NoMoreEntriesToReadException(org.apache.bookkeeper.mledger.ManagedLedgerException.NoMoreEntriesToReadException) Entry(org.apache.bookkeeper.mledger.Entry) Position(org.apache.bookkeeper.mledger.Position) ManagedLedger(org.apache.bookkeeper.mledger.ManagedLedger) ManagedCursor(org.apache.bookkeeper.mledger.ManagedCursor) Test(org.testng.annotations.Test)

Example 2 with NoMoreEntriesToReadException

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
    }
}
Also used : NoMoreEntriesToReadException(org.apache.bookkeeper.mledger.ManagedLedgerException.NoMoreEntriesToReadException) Entry(org.apache.bookkeeper.mledger.Entry) Position(org.apache.bookkeeper.mledger.Position) ManagedLedger(org.apache.bookkeeper.mledger.ManagedLedger) ManagedCursor(org.apache.bookkeeper.mledger.ManagedCursor) Test(org.testng.annotations.Test)

Example 3 with NoMoreEntriesToReadException

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);
    }
}
Also used : NoMoreEntriesToReadException(org.apache.bookkeeper.mledger.ManagedLedgerException.NoMoreEntriesToReadException) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) ManagedLedgerException.getManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException.getManagedLedgerException) ManagedLedgerImpl.createManagedLedgerException(org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.createManagedLedgerException) CursorAlreadyClosedException(org.apache.bookkeeper.mledger.ManagedLedgerException.CursorAlreadyClosedException)

Example 4 with NoMoreEntriesToReadException

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);
}
Also used : NoMoreEntriesToReadException(org.apache.bookkeeper.mledger.ManagedLedgerException.NoMoreEntriesToReadException) TooManyRequestsException(org.apache.bookkeeper.mledger.ManagedLedgerException.TooManyRequestsException) Consumer(org.apache.pulsar.broker.service.Consumer) AbstractDispatcherSingleActiveConsumer(org.apache.pulsar.broker.service.AbstractDispatcherSingleActiveConsumer)

Example 5 with NoMoreEntriesToReadException

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);
}
Also used : NoMoreEntriesToReadException(org.apache.bookkeeper.mledger.ManagedLedgerException.NoMoreEntriesToReadException) TooManyRequestsException(org.apache.bookkeeper.mledger.ManagedLedgerException.TooManyRequestsException) Consumer(org.apache.pulsar.broker.service.Consumer) PositionImpl(org.apache.bookkeeper.mledger.impl.PositionImpl)

Aggregations

NoMoreEntriesToReadException (org.apache.bookkeeper.mledger.ManagedLedgerException.NoMoreEntriesToReadException)5 Entry (org.apache.bookkeeper.mledger.Entry)2 ManagedCursor (org.apache.bookkeeper.mledger.ManagedCursor)2 ManagedLedger (org.apache.bookkeeper.mledger.ManagedLedger)2 TooManyRequestsException (org.apache.bookkeeper.mledger.ManagedLedgerException.TooManyRequestsException)2 Position (org.apache.bookkeeper.mledger.Position)2 Consumer (org.apache.pulsar.broker.service.Consumer)2 Test (org.testng.annotations.Test)2 ManagedLedgerException (org.apache.bookkeeper.mledger.ManagedLedgerException)1 CursorAlreadyClosedException (org.apache.bookkeeper.mledger.ManagedLedgerException.CursorAlreadyClosedException)1 ManagedLedgerException.getManagedLedgerException (org.apache.bookkeeper.mledger.ManagedLedgerException.getManagedLedgerException)1 ManagedLedgerImpl.createManagedLedgerException (org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.createManagedLedgerException)1 PositionImpl (org.apache.bookkeeper.mledger.impl.PositionImpl)1 AbstractDispatcherSingleActiveConsumer (org.apache.pulsar.broker.service.AbstractDispatcherSingleActiveConsumer)1