You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2015/08/16 07:09:50 UTC
logging-log4j2 git commit: refactor: break up larger methods to
clarify intention and facilitate JVM inlining
Repository: logging-log4j2
Updated Branches:
refs/heads/master ad0eaf476 -> b2ef74c7e
refactor: break up larger methods to clarify intention and facilitate
JVM inlining
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/b2ef74c7
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/b2ef74c7
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/b2ef74c7
Branch: refs/heads/master
Commit: b2ef74c7edd50a0eb8f2f7f2e572c39597695e4f
Parents: ad0eaf4
Author: rpopma <rp...@apache.org>
Authored: Sun Aug 16 14:09:55 2015 +0900
Committer: rpopma <rp...@apache.org>
Committed: Sun Aug 16 14:09:55 2015 +0900
----------------------------------------------------------------------
.../core/async/AsyncLoggerConfigHelper.java | 96 ++++++++++++++------
1 file changed, 66 insertions(+), 30 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b2ef74c7/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigHelper.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigHelper.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigHelper.java
index c4fe1d2..a81d8fa 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigHelper.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigHelper.java
@@ -218,9 +218,15 @@ class AsyncLoggerConfigHelper {
event.loggerConfig.asyncCallAppenders(event.event);
event.clear();
- // notify the BatchEventProcessor that the sequence has progressed.
- // Without this callback the sequence would not be progressed
- // until the batch has completely finished.
+ notifyIntermediateProgress(sequence);
+ }
+
+ /**
+ * Notify the BatchEventProcessor that the sequence has progressed.
+ * Without this callback the sequence would not be progressed
+ * until the batch has completely finished.
+ */
+ private void notifyIntermediateProgress(final long sequence) {
if (++counter > NOTIFY_PROGRESS_THRESHOLD) {
sequenceCallback.set(sequence);
counter = 0;
@@ -312,43 +318,73 @@ class AsyncLoggerConfigHelper {
* calling thread needs to process the event itself
*/
public boolean callAppendersFromAnotherThread(final LogEvent event) {
- // TODO refactor to reduce size to <= 35 bytecodes to allow JVM to inline it
final Disruptor<Log4jEventWrapper> temp = disruptor;
- if (temp == null) { // LOG4J2-639
+ if (!hasLog4jBeenShutDown(temp)) {
+
+ // LOG4J2-471: prevent deadlock when RingBuffer is full and object
+ // being logged calls Logger.log() from its toString() method
+ if (isCalledFromAppenderThreadAndBufferFull(temp)) {
+ // bypass RingBuffer and invoke Appender directly
+ return false;
+ }
+ enqueueEvent(event);
+ }
+ return true;
+ }
+
+ /**
+ * Returns {@code true} if the specified disruptor is null.
+ */
+ private boolean hasLog4jBeenShutDown(final Disruptor<Log4jEventWrapper> aDisruptor) {
+ if (aDisruptor == null) { // LOG4J2-639
LOGGER.fatal("Ignoring log event after log4j was shut down");
return true;
}
+ return false;
+ }
- // LOG4J2-471: prevent deadlock when RingBuffer is full and object
- // being logged calls Logger.log() from its toString() method
- if (isAppenderThread.get() == Boolean.TRUE //
- && temp.getRingBuffer().remainingCapacity() == 0) {
-
- // bypass RingBuffer and invoke Appender directly
- return false;
- }
+ private void enqueueEvent(final LogEvent event) {
// LOG4J2-639: catch NPE if disruptor field was set to null after our check above
try {
- LogEvent logEvent = event;
- if (event instanceof RingBufferLogEvent) {
- // Deal with special case where both types of Async Loggers are used together:
- // RingBufferLogEvents are created by the all-loggers-async type, but
- // this event is also consumed by the some-loggers-async type (this class).
- // The original event will be re-used and modified in an application thread later,
- // so take a snapshot of it, which can be safely processed in the
- // some-loggers-async background thread.
- logEvent = ((RingBufferLogEvent) event).createMemento();
- }
- logEvent.getMessage().getFormattedMessage(); // LOG4J2-763: ask message to freeze parameters
-
- // Note: do NOT use the temp variable above!
- // That could result in adding a log event to the disruptor after it was shut down,
- // which could cause the publishEvent method to hang and never return.
- disruptor.getRingBuffer().publishEvent(translator, logEvent, asyncLoggerConfig);
+ final LogEvent logEvent = prepareEvent(event);
+ enqueue(logEvent);
} catch (final NullPointerException npe) {
LOGGER.fatal("Ignoring log event after log4j was shut down.");
}
- return true;
+ }
+
+ private LogEvent prepareEvent(final LogEvent event) {
+ final LogEvent logEvent = ensureImmutable(event);
+ logEvent.getMessage().getFormattedMessage(); // LOG4J2-763: ask message to freeze parameters
+ return logEvent;
+ }
+
+ private void enqueue(LogEvent logEvent) {
+ // Note: do NOT use the temp variable above!
+ // That could result in adding a log event to the disruptor after it was shut down,
+ // which could cause the publishEvent method to hang and never return.
+ disruptor.getRingBuffer().publishEvent(translator, logEvent, asyncLoggerConfig);
+ }
+
+ private LogEvent ensureImmutable(final LogEvent event) {
+ LogEvent result = event;
+ if (event instanceof RingBufferLogEvent) {
+ // Deal with special case where both types of Async Loggers are used together:
+ // RingBufferLogEvents are created by the all-loggers-async type, but
+ // this event is also consumed by the some-loggers-async type (this class).
+ // The original event will be re-used and modified in an application thread later,
+ // so take a snapshot of it, which can be safely processed in the
+ // some-loggers-async background thread.
+ result = ((RingBufferLogEvent) event).createMemento();
+ }
+ return result;
+ }
+
+ /**
+ * Returns true if the specified ringbuffer is full and the Logger.log() call was made from the appender thread.
+ */
+ private boolean isCalledFromAppenderThreadAndBufferFull(Disruptor<Log4jEventWrapper> disruptor) {
+ return isAppenderThread.get() == Boolean.TRUE && disruptor.getRingBuffer().remainingCapacity() == 0;
}
/**