Search in sources :

Example 16 with MarkDeleteCallback

use of org.apache.bookkeeper.mledger.AsyncCallbacks.MarkDeleteCallback in project incubator-pulsar by apache.

the class ManagedCursorImpl method asyncDelete.

@Override
public void asyncDelete(Iterable<Position> positions, AsyncCallbacks.DeleteCallback callback, Object ctx) {
    if (state == State.Closed) {
        callback.deleteFailed(new ManagedLedgerException("Cursor was already closed"), ctx);
        return;
    }
    PositionImpl newMarkDeletePosition = null;
    lock.writeLock().lock();
    try {
        if (log.isDebugEnabled()) {
            log.debug("[{}] [{}] Deleting individual messages at {}. Current status: {} - md-position: {}", ledger.getName(), name, positions, individualDeletedMessages, markDeletePosition);
        }
        for (Position pos : positions) {
            PositionImpl position = (PositionImpl) checkNotNull(pos);
            if (individualDeletedMessages.contains(position) || position.compareTo(markDeletePosition) <= 0) {
                if (log.isDebugEnabled()) {
                    log.debug("[{}] [{}] Position was already deleted {}", ledger.getName(), name, position);
                }
                continue;
            }
            // Add a range (prev, pos] to the set. Adding the previous entry as an open limit to the range will make
            // the RangeSet recognize the "continuity" between adjacent Positions
            PositionImpl previousPosition = ledger.getPreviousPosition(position);
            individualDeletedMessages.add(Range.openClosed(previousPosition, position));
            ++messagesConsumedCounter;
            if (log.isDebugEnabled()) {
                log.debug("[{}] [{}] Individually deleted messages: {}", ledger.getName(), name, individualDeletedMessages);
            }
        }
        if (individualDeletedMessages.isEmpty()) {
            // No changes to individually deleted messages, so nothing to do at this point
            callback.deleteComplete(ctx);
            return;
        }
        // If the lower bound of the range set is the current mark delete position, then we can trigger a new
        // mark-delete to the upper bound of the first range segment
        Range<PositionImpl> range = individualDeletedMessages.asRanges().iterator().next();
        // If the lowerBound is ahead of MarkDelete, verify if there are any entries in-between
        if (range.lowerEndpoint().compareTo(markDeletePosition) <= 0 || ledger.getNumberOfEntries(Range.openClosed(markDeletePosition, range.lowerEndpoint())) <= 0) {
            if (log.isDebugEnabled()) {
                log.debug("[{}] Found a position range to mark delete for cursor {}: {} ", ledger.getName(), name, range);
            }
            newMarkDeletePosition = range.upperEndpoint();
        }
        if (newMarkDeletePosition != null) {
            newMarkDeletePosition = setAcknowledgedPosition(newMarkDeletePosition);
        } else {
            newMarkDeletePosition = markDeletePosition;
        }
    } catch (Exception e) {
        log.warn("[{}] [{}] Error while updating individualDeletedMessages [{}]", ledger.getName(), name, e.getMessage(), e);
        callback.deleteFailed(getManagedLedgerException(e), ctx);
        return;
    } finally {
        lock.writeLock().unlock();
    }
    // Apply rate limiting to mark-delete operations
    if (markDeleteLimiter != null && !markDeleteLimiter.tryAcquire()) {
        lastMarkDeleteEntry = new MarkDeleteEntry(newMarkDeletePosition, Collections.emptyMap(), null, null);
        callback.deleteComplete(ctx);
        return;
    }
    try {
        internalAsyncMarkDelete(newMarkDeletePosition, Collections.emptyMap(), new MarkDeleteCallback() {

            @Override
            public void markDeleteComplete(Object ctx) {
                callback.deleteComplete(ctx);
            }

            @Override
            public void markDeleteFailed(ManagedLedgerException exception, Object ctx) {
                callback.deleteFailed(exception, ctx);
            }
        }, ctx);
    } catch (Exception e) {
        log.warn("[{}] [{}] Error doing asyncDelete [{}]", ledger.getName(), name, e.getMessage(), e);
        if (log.isDebugEnabled()) {
            log.debug("[{}] Consumer {} cursor asyncDelete error, counters: consumed {} mdPos {} rdPos {}", ledger.getName(), name, messagesConsumedCounter, markDeletePosition, readPosition);
        }
        callback.deleteFailed(new ManagedLedgerException(e), ctx);
    }
}
Also used : MarkDeleteCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.MarkDeleteCallback) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) ManagedLedgerException.getManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException.getManagedLedgerException) ManagedLedgerImpl.createManagedLedgerException(org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.createManagedLedgerException) Position(org.apache.bookkeeper.mledger.Position) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) BKException(org.apache.bookkeeper.client.BKException) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) MetaStoreException(org.apache.bookkeeper.mledger.ManagedLedgerException.MetaStoreException) ManagedLedgerException.getManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException.getManagedLedgerException) CursorAlreadyClosedException(org.apache.bookkeeper.mledger.ManagedLedgerException.CursorAlreadyClosedException) ManagedLedgerImpl.createManagedLedgerException(org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.createManagedLedgerException) NoMoreEntriesToReadException(org.apache.bookkeeper.mledger.ManagedLedgerException.NoMoreEntriesToReadException)

Example 17 with MarkDeleteCallback

use of org.apache.bookkeeper.mledger.AsyncCallbacks.MarkDeleteCallback in project incubator-pulsar by apache.

the class ManagedCursorImpl method markDelete.

@Override
public void markDelete(Position position, Map<String, Long> properties) throws InterruptedException, ManagedLedgerException {
    checkNotNull(position);
    checkArgument(position instanceof PositionImpl);
    class Result {

        ManagedLedgerException exception = null;
    }
    final Result result = new Result();
    final CountDownLatch counter = new CountDownLatch(1);
    asyncMarkDelete(position, properties, new MarkDeleteCallback() {

        @Override
        public void markDeleteComplete(Object ctx) {
            counter.countDown();
        }

        @Override
        public void markDeleteFailed(ManagedLedgerException exception, Object ctx) {
            result.exception = exception;
            counter.countDown();
        }
    }, null);
    if (!counter.await(ManagedLedgerImpl.AsyncOperationTimeoutSeconds, TimeUnit.SECONDS)) {
        throw new ManagedLedgerException("Timeout during mark-delete operation");
    }
    if (result.exception != null) {
        throw result.exception;
    }
}
Also used : MarkDeleteCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.MarkDeleteCallback) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) ManagedLedgerException.getManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException.getManagedLedgerException) ManagedLedgerImpl.createManagedLedgerException(org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.createManagedLedgerException) CountDownLatch(java.util.concurrent.CountDownLatch)

Example 18 with MarkDeleteCallback

use of org.apache.bookkeeper.mledger.AsyncCallbacks.MarkDeleteCallback in project incubator-pulsar by apache.

the class ManagedCursorImpl method internalResetCursor.

protected void internalResetCursor(PositionImpl position, AsyncCallbacks.ResetCursorCallback resetCursorCallback) {
    if (position.equals(PositionImpl.earliest)) {
        position = ledger.getFirstPosition();
    } else if (position.equals(PositionImpl.latest)) {
        position = ledger.getLastPosition().getNext();
    }
    log.info("[{}] Initiate reset position to {} on cursor {}", ledger.getName(), position, name);
    synchronized (pendingMarkDeleteOps) {
        if (!RESET_CURSOR_IN_PROGRESS_UPDATER.compareAndSet(this, FALSE, TRUE)) {
            log.error("[{}] reset requested - position [{}], previous reset in progress - cursor {}", ledger.getName(), position, name);
            resetCursorCallback.resetFailed(new ManagedLedgerException.ConcurrentFindCursorPositionException("reset already in progress"), position);
        }
    }
    final AsyncCallbacks.ResetCursorCallback callback = resetCursorCallback;
    final PositionImpl newPosition = position;
    VoidCallback finalCallback = new VoidCallback() {

        @Override
        public void operationComplete() {
            // modify mark delete and read position since we are able to persist new position for cursor
            lock.writeLock().lock();
            try {
                PositionImpl newMarkDeletePosition = ledger.getPreviousPosition(newPosition);
                if (markDeletePosition.compareTo(newMarkDeletePosition) >= 0) {
                    messagesConsumedCounter -= getNumberOfEntries(Range.closedOpen(newMarkDeletePosition, markDeletePosition));
                } else {
                    messagesConsumedCounter += getNumberOfEntries(Range.closedOpen(markDeletePosition, newMarkDeletePosition));
                }
                markDeletePosition = newMarkDeletePosition;
                lastMarkDeleteEntry = new MarkDeleteEntry(newMarkDeletePosition, Collections.emptyMap(), null, null);
                individualDeletedMessages.clear();
                PositionImpl oldReadPosition = readPosition;
                if (oldReadPosition.compareTo(newPosition) >= 0) {
                    log.info("[{}] reset position to {} before current read position {} on cursor {}", ledger.getName(), newPosition, oldReadPosition, name);
                } else {
                    log.info("[{}] reset position to {} skipping from current read position {} on cursor {}", ledger.getName(), newPosition, oldReadPosition, name);
                }
                readPosition = newPosition;
            } finally {
                lock.writeLock().unlock();
            }
            synchronized (pendingMarkDeleteOps) {
                pendingMarkDeleteOps.clear();
                if (!RESET_CURSOR_IN_PROGRESS_UPDATER.compareAndSet(ManagedCursorImpl.this, TRUE, FALSE)) {
                    log.error("[{}] expected reset position [{}], but another reset in progress on cursor {}", ledger.getName(), newPosition, name);
                }
            }
            callback.resetComplete(newPosition);
        }

        @Override
        public void operationFailed(ManagedLedgerException exception) {
            synchronized (pendingMarkDeleteOps) {
                if (!RESET_CURSOR_IN_PROGRESS_UPDATER.compareAndSet(ManagedCursorImpl.this, TRUE, FALSE)) {
                    log.error("[{}] expected reset position [{}], but another reset in progress on cursor {}", ledger.getName(), newPosition, name);
                }
            }
            callback.resetFailed(new ManagedLedgerException.InvalidCursorPositionException("unable to persist position for cursor reset " + newPosition.toString()), newPosition);
        }
    };
    internalAsyncMarkDelete(newPosition, Collections.emptyMap(), new MarkDeleteCallback() {

        @Override
        public void markDeleteComplete(Object ctx) {
            finalCallback.operationComplete();
        }

        @Override
        public void markDeleteFailed(ManagedLedgerException exception, Object ctx) {
            finalCallback.operationFailed(exception);
        }
    }, null);
}
Also used : MarkDeleteCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.MarkDeleteCallback) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) ManagedLedgerException.getManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException.getManagedLedgerException) ManagedLedgerImpl.createManagedLedgerException(org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.createManagedLedgerException) AsyncCallbacks(org.apache.bookkeeper.mledger.AsyncCallbacks)

Example 19 with MarkDeleteCallback

use of org.apache.bookkeeper.mledger.AsyncCallbacks.MarkDeleteCallback in project incubator-pulsar by apache.

the class NonDurableCursorTest method asyncMarkDeleteBlocking.

@Test(timeOut = 20000)
public void asyncMarkDeleteBlocking() throws Exception {
    ManagedLedgerConfig config = new ManagedLedgerConfig();
    config.setMaxEntriesPerLedger(10);
    config.setMetadataMaxEntriesPerLedger(5);
    ManagedLedger ledger = factory.open("my_test_ledger", config);
    final ManagedCursor c1 = ledger.openCursor("c1");
    final AtomicReference<Position> lastPosition = new AtomicReference<Position>();
    final int N = 100;
    final CountDownLatch latch = new CountDownLatch(N);
    for (int i = 0; i < N; i++) {
        ledger.asyncAddEntry("entry".getBytes(Encoding), new AddEntryCallback() {

            @Override
            public void addFailed(ManagedLedgerException exception, Object ctx) {
            }

            @Override
            public void addComplete(Position position, Object ctx) {
                lastPosition.set(position);
                c1.asyncMarkDelete(position, new MarkDeleteCallback() {

                    @Override
                    public void markDeleteFailed(ManagedLedgerException exception, Object ctx) {
                    }

                    @Override
                    public void markDeleteComplete(Object ctx) {
                        latch.countDown();
                    }
                }, null);
            }
        }, null);
    }
    latch.await();
    assertEquals(c1.getNumberOfEntries(), 0);
    // Reopen
    ManagedLedgerFactory factory2 = new ManagedLedgerFactoryImpl(bkc, bkc.getZkHandle());
    ledger = factory2.open("my_test_ledger");
    ManagedCursor c2 = ledger.openCursor("c1");
    assertEquals(c2.getMarkDeletedPosition(), lastPosition.get());
    factory2.shutdown();
}
Also used : Position(org.apache.bookkeeper.mledger.Position) ManagedLedger(org.apache.bookkeeper.mledger.ManagedLedger) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) ManagedCursor(org.apache.bookkeeper.mledger.ManagedCursor) MarkDeleteCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.MarkDeleteCallback) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) ManagedLedgerFactory(org.apache.bookkeeper.mledger.ManagedLedgerFactory) ManagedLedgerConfig(org.apache.bookkeeper.mledger.ManagedLedgerConfig) AddEntryCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.AddEntryCallback) Test(org.testng.annotations.Test)

Aggregations

MarkDeleteCallback (org.apache.bookkeeper.mledger.AsyncCallbacks.MarkDeleteCallback)19 ManagedLedgerException (org.apache.bookkeeper.mledger.ManagedLedgerException)19 CountDownLatch (java.util.concurrent.CountDownLatch)11 ManagedCursor (org.apache.bookkeeper.mledger.ManagedCursor)10 ManagedLedger (org.apache.bookkeeper.mledger.ManagedLedger)10 Position (org.apache.bookkeeper.mledger.Position)10 Test (org.testng.annotations.Test)9 ManagedLedgerConfig (org.apache.bookkeeper.mledger.ManagedLedgerConfig)8 AddEntryCallback (org.apache.bookkeeper.mledger.AsyncCallbacks.AddEntryCallback)6 ManagedLedgerFactory (org.apache.bookkeeper.mledger.ManagedLedgerFactory)5 ManagedLedgerException.getManagedLedgerException (org.apache.bookkeeper.mledger.ManagedLedgerException.getManagedLedgerException)4 ManagedLedgerImpl.createManagedLedgerException (org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.createManagedLedgerException)4 AtomicReference (java.util.concurrent.atomic.AtomicReference)3 OpenCursorCallback (org.apache.bookkeeper.mledger.AsyncCallbacks.OpenCursorCallback)3 OpenLedgerCallback (org.apache.bookkeeper.mledger.AsyncCallbacks.OpenLedgerCallback)3 InvalidProtocolBufferException (com.google.protobuf.InvalidProtocolBufferException)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 CompletableFuture (java.util.concurrent.CompletableFuture)2 BKException (org.apache.bookkeeper.client.BKException)2