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
use copy-on-write list in InMemoryAppender #8808
Conversation
@@ -94,7 +94,7 @@ public void append(LogEvent logEvent) | |||
|
|||
List<LogEvent> getLogEvents() | |||
{ | |||
return Collections.unmodifiableList(logEvents); | |||
return Collections.synchronizedList(logEvents); |
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.
- It's not copy-on-write (as the title of your PR says), it's
synchronizedList
, but this doesn't solve the problem: see https://github.com/code-review-checklists/java-concurrency#synchronized-collection-iter. However, if you actually useCopyOnWriteArrayList
instead ofArrayList
aslogEvents
, that would help. Don't forget to change the type of the field fromList<LogEvent>
toCopyOnWriteArrayList<LogEvent>
and to add a comment explaining the need for thread safety (in the form of usingCopyOnWriteArrayList
), along the lines of https://github.com/code-review-checklists/java-concurrency#justify-document.
thank you, @leventov |
@@ -78,12 +77,13 @@ public void clearLogEvents() | |||
{ | |||
static final String NAME = InMemoryAppender.class.getName(); | |||
|
|||
private final List<LogEvent> logEvents; | |||
// need copy-on-write collection for thread safety of iteration and modification concurrently outside of a critical section |
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.
This comment doesn't achieve its goal: to help somebody to see why the enclosing class needs to be thread-safe. With the current comment, in order to do that, the reader (developer) should invoke "Find usages" IDE action and analyze these usages carefully. This is time-consuming. In essence, there should be concurrent access documentation, as described in https://github.com/code-review-checklists/java-concurrency#justify-document.
This comment is also misleading because there are no critical sections in this code.
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.
how about:
logEvents has concurrent iteration and modification in CuratorModuleTest::exitsJvmWhenMaxRetriesExceeded(), needs to be thread safe
I am learning from better developers and was thinking about contract of logger and how would it could be solved should it be inmemorylogger be used somewhere else some day. |
@LoriLori Since this class resides in tests, not production, the performance doesn't matter and we shouldn't waste time comparing |
@zhenxiao please merge the master branch into your PR branch to make the CI pass. |
f0595d7
to
1e4c9be
Compare
master merged into this PR. failure seems not related |
@zhenxiao don't rebase your PRs. Your should never do this in Druid. Once you open a PR, you only merge other branches into your PR branch, never rebase it. |
oh, sure. seems tests passed |
Fixes #8759
@leventov