-
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][broker] Duplicate ByteBuffer when Caching Backlogged Consumers #17105
[fix][broker] Duplicate ByteBuffer when Caching Backlogged Consumers #17105
Conversation
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.
Nice catch!
Small suggestion: Could we make the The advantage is that we make this method more fault-tolerant and don't need create another |
@mattisonchao - I didn't do it this way because the write path for tail read caching does not need the duplicate I am going to merge this as is so that it does not hold up the 2.11 release at all. We can definitely continue this discussion, especially because we have the PIP on improved caching getting implemented right now. |
…17105) Fixes #16979 ### Motivation #12258 introduced caching for backlogged consumers. When caching the entry, it is important to duplicate the `ByteBuffer` so that the reader index is not shared. The current code has a race condition where the `ByteBuffer` reference in the cache is shared with the dispatcher. When another consumer reads from the cache, the cache calls `duplicate()` on the shared `ByteBuffer`, which copies the current reader index, which might not be 0 if the original dispatcher read data from the `ByteBuffer`. Note: it seems like the caching `insert` method creates (or recycles) more `EntryImpl` instances than is really necessary. Changing that is outside this PR's scope, so I am going to leave it as is. ### Modifications * Create a new `Entry` before inserting it into the cache. * Add a new test to the `EntryCacheTest`. The test fails before this change and passes after it. * Update the `EntryCacheTest` mocking so that it returns unique entries when mocking reads from the bookkeeper. Before, all returned `LedgerEntry` objects had ledgerId 0 and entryId 0, which messed with the caching for the new test. ### Verifying this change This change includes a test that failed before the PR and passes after it. ### Documentation - [x] `doc-not-needed` (cherry picked from commit 76f4195)
…pache#17105) Fixes apache#16979 ### Motivation apache#12258 introduced caching for backlogged consumers. When caching the entry, it is important to duplicate the `ByteBuffer` so that the reader index is not shared. The current code has a race condition where the `ByteBuffer` reference in the cache is shared with the dispatcher. When another consumer reads from the cache, the cache calls `duplicate()` on the shared `ByteBuffer`, which copies the current reader index, which might not be 0 if the original dispatcher read data from the `ByteBuffer`. Note: it seems like the caching `insert` method creates (or recycles) more `EntryImpl` instances than is really necessary. Changing that is outside this PR's scope, so I am going to leave it as is. ### Modifications * Create a new `Entry` before inserting it into the cache. * Add a new test to the `EntryCacheTest`. The test fails before this change and passes after it. * Update the `EntryCacheTest` mocking so that it returns unique entries when mocking reads from the bookkeeper. Before, all returned `LedgerEntry` objects had ledgerId 0 and entryId 0, which messed with the caching for the new test. ### Verifying this change This change includes a test that failed before the PR and passes after it. ### Documentation - [x] `doc-not-needed` (cherry picked from commit 76f4195)
…pache#17105) Fixes apache#16979 ### Motivation apache#12258 introduced caching for backlogged consumers. When caching the entry, it is important to duplicate the `ByteBuffer` so that the reader index is not shared. The current code has a race condition where the `ByteBuffer` reference in the cache is shared with the dispatcher. When another consumer reads from the cache, the cache calls `duplicate()` on the shared `ByteBuffer`, which copies the current reader index, which might not be 0 if the original dispatcher read data from the `ByteBuffer`. Note: it seems like the caching `insert` method creates (or recycles) more `EntryImpl` instances than is really necessary. Changing that is outside this PR's scope, so I am going to leave it as is. ### Modifications * Create a new `Entry` before inserting it into the cache. * Add a new test to the `EntryCacheTest`. The test fails before this change and passes after it. * Update the `EntryCacheTest` mocking so that it returns unique entries when mocking reads from the bookkeeper. Before, all returned `LedgerEntry` objects had ledgerId 0 and entryId 0, which messed with the caching for the new test. ### Verifying this change This change includes a test that failed before the PR and passes after it. ### Documentation - [x] `doc-not-needed`
…pache#17105) Fixes apache#16979 ### Motivation apache#12258 introduced caching for backlogged consumers. When caching the entry, it is important to duplicate the `ByteBuffer` so that the reader index is not shared. The current code has a race condition where the `ByteBuffer` reference in the cache is shared with the dispatcher. When another consumer reads from the cache, the cache calls `duplicate()` on the shared `ByteBuffer`, which copies the current reader index, which might not be 0 if the original dispatcher read data from the `ByteBuffer`. Note: it seems like the caching `insert` method creates (or recycles) more `EntryImpl` instances than is really necessary. Changing that is outside this PR's scope, so I am going to leave it as is. ### Modifications * Create a new `Entry` before inserting it into the cache. * Add a new test to the `EntryCacheTest`. The test fails before this change and passes after it. * Update the `EntryCacheTest` mocking so that it returns unique entries when mocking reads from the bookkeeper. Before, all returned `LedgerEntry` objects had ledgerId 0 and entryId 0, which messed with the caching for the new test. ### Verifying this change This change includes a test that failed before the PR and passes after it. ### Documentation - [x] `doc-not-needed` (cherry picked from commit 76f4195)
Fixes #16979
Motivation
#12258 introduced caching for backlogged consumers. When caching the entry, it is important to duplicate the
ByteBuffer
so that the reader index is not shared. The current code has a race condition where theByteBuffer
reference in the cache is shared with the dispatcher. When another consumer reads from the cache, the cache callsduplicate()
on the sharedByteBuffer
, which copies the current reader index, which might not be 0 if the original dispatcher read data from theByteBuffer
.Note: it seems like the caching
insert
method creates (or recycles) moreEntryImpl
instances than is really necessary. Changing that is outside this PR's scope, so I am going to leave it as is.Modifications
Entry
before inserting it into the cache.EntryCacheTest
. The test fails before this change and passes after it.EntryCacheTest
mocking so that it returns unique entries when mocking reads from the bookkeeper. Before, all returnedLedgerEntry
objects had ledgerId 0 and entryId 0, which messed with the caching for the new test.Verifying this change
This change includes a test that failed before the PR and passes after it.
Documentation
doc-not-needed