Skip to content

[Enhancement] Nested read-write lock issue in ManagedCursor #23605

@Denovo1998

Description

@Denovo1998

Search before asking

  • I searched in the issues and found nothing similar.

Motivation

The following are all related to the org.apache.bookkeeper.mledger.impl.ManagedCursorImpl#isMessageDeleted:

@Override
public boolean isMessageDeleted(Position position) {
lock.readLock().lock();
try {
return position.compareTo(markDeletePosition) <= 0
|| individualDeletedMessages.contains(position.getLedgerId(), position.getEntryId());
} finally {
lock.readLock().unlock();
}
}

  1. A write lock has already been acquired, but a read lock has been acquired as well. This doesn't pose a major problem, but it does result in some unnecessary additional overhead.

    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) {
    Position position = requireNonNull(pos);
    if (ledger.getLastConfirmedEntry().compareTo(position) < 0) {
    if (log.isDebugEnabled()) {
    log.debug(
    "[{}] Failed mark delete due to invalid markDelete {} is ahead of last-confirmed-entry {} "
    + "for cursor [{}]", ledger.getName(), position, ledger.getLastConfirmedEntry(), name);
    }
    callback.deleteFailed(new ManagedLedgerException("Invalid mark deleted position"), ctx);
    return;
    }
    if (isMessageDeleted(position)) {

  2. The performance impact of nested read locks can be negligible, but frequent acquisition and release of locks will slightly increase system overhead.

    lock.readLock().lock();
    try {
    positions.stream().filter(this::isMessageDeleted).forEach(alreadyAcknowledgedPositions::add);
    } finally {
    lock.readLock().unlock();
    }

Solution

Add a method that does not require a read lock.

    private boolean isMessageDeletedWithOutReadLock(Position position) {
        return position.compareTo(markDeletePosition) <= 0
                || individualDeletedMessages.contains(position.getLedgerId(), position.getEntryId());
    }

Alternatives

No response

Anything else?

I think the modification at 22246 here is for code reuse, but the nested read-write locks in these two segments may need to be modified.

If such a modification is necessary, please let me know, and I will submit a simple PR.

Are you willing to submit a PR?

  • I'm willing to submit a PR!

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/enhancementThe enhancements for the existing features or docs. e.g. reduce memory usage of the delayed messages

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions