-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix for cursor reset after topic reload #315
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -240,7 +240,6 @@ protected void recoverFromLedger(final ManagedCursorInfo info, final VoidCallbac | |
} | ||
|
||
// Read the last entry in the ledger | ||
cursorLedger = lh; | ||
lh.asyncReadLastEntry((rc1, lh1, seq, ctx1) -> { | ||
if (log.isDebugEnabled()) { | ||
log.debug("readComplete rc={} entryId={}", rc1, lh1.getLastAddConfirmed()); | ||
|
@@ -762,24 +761,17 @@ public void operationFailed(ManagedLedgerException exception) { | |
|
||
}; | ||
|
||
if (cursorLedger == null) { | ||
persistPositionMetaStore(-1, newPosition, new MetaStoreCallback<Void>() { | ||
@Override | ||
public void operationComplete(Void result, Stat stat) { | ||
log.info("[{}] Updated cursor {} with ledger id {} md-position={} rd-position={}", | ||
ledger.getName(), name, -1, markDeletePosition, readPosition); | ||
cursorLedgerStat = stat; | ||
finalCallback.operationComplete(); | ||
} | ||
internalAsyncMarkDelete(newPosition, new MarkDeleteCallback() { | ||
@Override | ||
public void markDeleteComplete(Object ctx) { | ||
finalCallback.operationComplete(); | ||
} | ||
|
||
@Override | ||
public void operationFailed(MetaStoreException e) { | ||
finalCallback.operationFailed(e); | ||
} | ||
}); | ||
} else { | ||
persistPosition(cursorLedger, newPosition, finalCallback); | ||
} | ||
@Override | ||
public void markDeleteFailed(ManagedLedgerException exception, Object ctx) { | ||
finalCallback.operationFailed(exception); | ||
} | ||
}, null); | ||
} | ||
|
||
@Override | ||
|
@@ -1817,21 +1809,10 @@ public void operationFailed(ManagedLedgerException exception) { | |
|
||
private void flushPendingMarkDeletes() { | ||
if (!pendingMarkDeleteOps.isEmpty()) { | ||
if (RESET_CURSOR_IN_PROGRESS_UPDATER.get(this) == TRUE) { | ||
failPendingMarkDeletes(); | ||
} else { | ||
internalFlushPendingMarkDeletes(); | ||
} | ||
internalFlushPendingMarkDeletes(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, that is covered 😉 Take a look at // Trigger the final callback after having (eventually) triggered the switchin-ledger operation. This
// will ensure that no race condition will happen between the next mark-delete and the switching
// operation.
if (mdEntry.callbackGroup != null) {
// Trigger the callback for every request in the group
for (PendingMarkDeleteEntry e : mdEntry.callbackGroup) {
e.callback.markDeleteComplete(e.ctx);
}
} else {
// Only trigger the callback for the current request
mdEntry.callback.markDeleteComplete(mdEntry.ctx);
} So, 1 single write and triggers all the callbacks There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. |
||
} | ||
} | ||
|
||
private void failPendingMarkDeletes() { | ||
for (PendingMarkDeleteEntry e : pendingMarkDeleteOps) { | ||
e.callback.markDeleteFailed(new ManagedLedgerException("reset cursor in progress"), e.ctx); | ||
} | ||
pendingMarkDeleteOps.clear(); | ||
} | ||
|
||
void internalFlushPendingMarkDeletes() { | ||
PendingMarkDeleteEntry lastEntry = pendingMarkDeleteOps.getLast(); | ||
lastEntry.callbackGroup = Lists.newArrayList(pendingMarkDeleteOps); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so, if we don't initialize
cursorLedger
at the time recovery then it will be null initially and at that time internal-stat will not return correct value ofcursorLedgerLastEntry
. So, is there any specific reason to not initialize it at recovery time?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very good point. I removed it because it is confusing to use the same variable to store 2 different kinds of ledger handler (one read-write and the other read-only)
Anyway I think it still make sense for the internal stats. In this case we would see:
and that is appropriate since we are in
NoLedger
state.This below is the code that returns the
-1
: