You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2016/06/03 18:10:57 UTC
[09/10] logging-log4j2 git commit: Add final modifier to method
parameters.
Add final modifier to method parameters.
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/7a5dcd43
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/7a5dcd43
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/7a5dcd43
Branch: refs/heads/master
Commit: 7a5dcd43d559971caf3f00c55586f372ca4d9046
Parents: fe22ab8
Author: ggregory <gg...@apache.org>
Authored: Fri Jun 3 10:05:18 2016 -0700
Committer: ggregory <gg...@apache.org>
Committed: Fri Jun 3 10:05:18 2016 -0700
----------------------------------------------------------------------
.../org/apache/logging/log4j/core/Logger.java | 2 +-
.../logging/log4j/core/LoggerContext.java | 4 +-
.../log4j/core/appender/AbstractManager.java | 8 +-
.../log4j/core/appender/AsyncAppender.java | 2 +-
.../log4j/core/appender/ConsoleAppender.java | 2 +-
.../core/appender/CountingNoOpAppender.java | 4 +-
.../core/appender/OutputStreamManager.java | 4 +-
.../log4j/core/appender/SocketAppender.java | 2 +-
.../appender/rolling/CronTriggeringPolicy.java | 6 +-
.../rolling/DefaultRolloverStrategy.java | 6 +-
.../log4j/core/appender/rolling/FileSize.java | 180 ++---
.../core/appender/rolling/action/Duration.java | 514 +++++++-------
.../core/appender/rolling/action/IfAll.java | 232 +++----
.../core/appender/routing/IdlePurgePolicy.java | 8 +-
.../core/appender/routing/RoutingAppender.java | 4 +-
.../logging/log4j/core/async/AsyncLogger.java | 4 +-
.../core/async/AsyncLoggerConfigDisruptor.java | 2 +-
.../log4j/core/async/AsyncLoggerContext.java | 4 +-
.../log4j/core/async/AsyncLoggerDisruptor.java | 472 ++++++-------
.../log4j/core/async/RingBufferLogEvent.java | 10 +-
.../core/config/AbstractConfiguration.java | 8 +-
.../AwaitCompletionReliabilityStrategy.java | 350 +++++-----
...AwaitUnconditionallyReliabilityStrategy.java | 246 +++----
.../log4j/core/config/ConfigurationFactory.java | 2 +-
.../core/config/ConfigurationScheduler.java | 16 +-
.../core/config/ConfiguratonFileWatcher.java | 4 +-
.../logging/log4j/core/config/Configurator.java | 688 +++++++++----------
.../core/config/DefaultReliabilityStrategy.java | 214 +++---
.../core/config/LockingReliabilityStrategy.java | 270 ++++----
.../impl/DefaultConfigurationBuilder.java | 20 +-
.../impl/DefaultLoggerComponentBuilder.java | 4 +-
.../impl/DefaultScriptFileComponentBuilder.java | 8 +-
.../composite/CompositeConfiguration.java | 6 +-
.../config/composite/DefaultMergeStrategy.java | 16 +-
.../properties/PropertiesConfiguration.java | 2 +-
.../PropertiesConfigurationBuilder.java | 2 +-
.../log4j/core/config/xml/XmlConfiguration.java | 2 +-
.../core/filter/DynamicThresholdFilter.java | 2 +-
.../logging/log4j/core/impl/Log4jLogEvent.java | 32 +-
.../log4j/core/impl/MutableLogEvent.java | 30 +-
.../log4j/core/layout/AbstractStringLayout.java | 2 +-
.../logging/log4j/core/layout/GelfLayout.java | 4 +-
.../log4j/core/layout/JacksonFactory.java | 4 +-
.../core/layout/MarkerPatternSelector.java | 2 +-
.../core/layout/ScriptPatternSelector.java | 4 +-
.../log4j/core/layout/TextEncoderHelper.java | 2 +-
.../logging/log4j/core/net/SmtpManager.java | 4 +-
.../log4j/core/net/TcpSocketManager.java | 2 +-
.../pattern/EqualsReplacementConverter.java | 2 +-
.../log4j/core/pattern/NameAbbreviator.java | 4 +-
.../logging/log4j/core/script/Script.java | 2 +-
.../logging/log4j/core/script/ScriptFile.java | 2 +-
.../log4j/core/script/ScriptManager.java | 2 +-
.../logging/log4j/core/script/ScriptRef.java | 4 +-
.../logging/log4j/core/util/CronExpression.java | 48 +-
.../logging/log4j/core/util/DummyNanoClock.java | 96 +--
.../core/util/ExtensionLanguageMapping.java | 6 +-
.../logging/log4j/core/util/FileUtils.java | 2 +-
.../logging/log4j/core/util/JsonUtils.java | 6 +-
.../logging/log4j/core/util/StringEncoder.java | 6 +-
.../logging/log4j/core/util/WatchManager.java | 10 +-
.../core/util/datetime/FixedDateFormat.java | 686 +++++++++---------
.../core/GcFreeAsynchronousLoggingTest.java | 2 +-
.../log4j/core/GcFreeLoggingTestUtil.java | 4 +-
.../core/GcFreeMixedSyncAyncLoggingTest.java | 2 +-
.../core/GcFreeSynchronousLoggingTest.java | 2 +-
.../AsyncAppenderQueueFullPolicyTest.java | 2 +-
.../appender/mom/kafka/KafkaAppenderTest.java | 292 ++++----
.../RollingAppenderCustomDeleteActionTest.java | 2 +-
...lingAppenderDeleteAccumulatedCount1Test.java | 4 +-
...lingAppenderDeleteAccumulatedCount2Test.java | 4 +-
.../RollingAppenderDeleteMaxDepthTest.java | 4 +-
.../RollingAppenderDeleteNestedTest.java | 4 +-
...ollingAppenderNoUnconditionalDeleteTest.java | 2 +-
.../rolling/action/CountingCondition.java | 124 ++--
.../rolling/action/DeleteActionTest.java | 238 +++----
.../rolling/action/DeletingVisitorTest.java | 270 ++++----
.../appender/rolling/action/FixedCondition.java | 88 +--
.../action/PathSortByModificationTimeTest.java | 186 ++---
.../routing/RoutingAppenderWithPurgingTest.java | 2 +-
.../core/async/perftest/PerfTestDriver.java | 4 +-
.../core/async/perftest/ResponseTimeTest.java | 18 +-
.../core/async/perftest/SimplePerfTest.java | 2 +-
.../core/config/CompositeConfigurationTest.java | 2 +-
.../log4j/core/config/ConfiguratorTest.java | 94 +--
.../builder/ConfigurationAssemblerTest.java | 2 +-
.../builder/CustomConfigurationFactory.java | 4 +-
.../core/filter/AbstractFilterableTest.java | 4 +-
.../log4j/core/impl/Log4jLogEventTest.java | 6 +-
.../log4j/core/impl/ThrowableProxyTest.java | 2 +-
.../core/layout/CsvLogEventLayoutTest.java | 2 +-
.../core/layout/CsvParameterLayoutTest.java | 2 +-
.../log4j/core/layout/GelfLayoutTest.java | 2 +-
.../log4j/core/layout/PatternLayoutTest.java | 2 +-
.../log4j/core/layout/PatternSelectorTest.java | 130 ++--
.../core/layout/SpyByteBufferDestination.java | 2 +-
.../core/pattern/DatePatternConverterTest.java | 2 +-
...qualsIgnoreCaseReplacementConverterTest.java | 2 +-
.../log4j/core/pattern/PatternParserTest.java | 2 +-
...riablesNotEmptyReplacementConverterTest.java | 2 +-
.../log4j/core/util/WatchManagerTest.java | 4 +-
.../logging/log4j/junit/LoggerContextRule.java | 4 +-
.../test/appender/EncodingListAppender.java | 4 +-
.../logging/log4j/jul/AbstractLoggerTest.java | 4 +-
104 files changed, 2913 insertions(+), 2913 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/Logger.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/Logger.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/Logger.java
index d08dd8a..99f4207 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/Logger.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/Logger.java
@@ -632,7 +632,7 @@ public class Logger extends AbstractLogger implements Supplier<LoggerConfig> {
private final String name;
private final MessageFactory messageFactory;
- public LoggerProxy(String name, MessageFactory messageFactory) {
+ public LoggerProxy(final String name, final MessageFactory messageFactory) {
this.name = name;
this.messageFactory = messageFactory;
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
index 82a6de8..fea1975 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
@@ -424,7 +424,7 @@ public class LoggerContext extends AbstractLifeCycle implements org.apache.loggi
* @return True if the Logger exists, false otherwise.
*/
@Override
- public boolean hasLogger(final String name, MessageFactory messageFactory) {
+ public boolean hasLogger(final String name, final MessageFactory messageFactory) {
return loggerRegistry.hasLogger(name, messageFactory);
}
@@ -435,7 +435,7 @@ public class LoggerContext extends AbstractLifeCycle implements org.apache.loggi
* @return True if the Logger exists, false otherwise.
*/
@Override
- public boolean hasLogger(final String name, Class<? extends MessageFactory> messageFactoryClass) {
+ public boolean hasLogger(final String name, final Class<? extends MessageFactory> messageFactoryClass) {
return loggerRegistry.hasLogger(name, messageFactoryClass);
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java
index 45f5141..fd15f17 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java
@@ -150,21 +150,21 @@ public abstract class AbstractManager {
return new HashMap<>();
}
- protected void log(Level level, String message, Throwable throwable) {
+ protected void log(final Level level, final String message, final Throwable throwable) {
Message m = LOGGER.getMessageFactory().newMessage("{} {} {}: {}",
getClass().getSimpleName(), getName(), message, throwable);
LOGGER.log(level, m, throwable);
}
- protected void logDebug(String message, Throwable throwable) {
+ protected void logDebug(final String message, final Throwable throwable) {
log(Level.DEBUG, message, throwable);
}
- protected void logError(String message, Throwable throwable) {
+ protected void logError(final String message, final Throwable throwable) {
log(Level.ERROR, message, throwable);
}
- protected void logWarn(String message, Throwable throwable) {
+ protected void logWarn(final String message, final Throwable throwable) {
log(Level.WARN, message, throwable);
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java
index 83afd92..0abb07e 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java
@@ -141,7 +141,7 @@ public final class AsyncAppender extends AbstractAppender {
* @param logEvent The LogEvent.
*/
@Override
- public void append(LogEvent logEvent) {
+ public void append(final LogEvent logEvent) {
if (!isStarted()) {
throw new IllegalStateException("AsyncAppender " + getName() + " is not active");
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
index 4e1e87c..0eb05d8 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
@@ -69,7 +69,7 @@ public final class ConsoleAppender extends AbstractOutputStreamAppender<OutputSt
}
private ConsoleAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
- final OutputStreamManager manager, final boolean ignoreExceptions, Target target) {
+ final OutputStreamManager manager, final boolean ignoreExceptions, final Target target) {
super(name, layout, filter, ignoreExceptions, true, manager);
this.target = target;
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/CountingNoOpAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/CountingNoOpAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/CountingNoOpAppender.java
index 8164aea..38775eb 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/CountingNoOpAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/CountingNoOpAppender.java
@@ -33,7 +33,7 @@ public class CountingNoOpAppender extends AbstractAppender {
private final AtomicLong total = new AtomicLong();
- public CountingNoOpAppender(String name, Layout<?> layout) {
+ public CountingNoOpAppender(final String name, final Layout<?> layout) {
super(name, null, layout);
}
@@ -42,7 +42,7 @@ public class CountingNoOpAppender extends AbstractAppender {
}
@Override
- public void append(LogEvent event) {
+ public void append(final LogEvent event) {
total.incrementAndGet();
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/OutputStreamManager.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/OutputStreamManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/OutputStreamManager.java
index 20ef401..5e3ae5d 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/OutputStreamManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/OutputStreamManager.java
@@ -143,7 +143,7 @@ public class OutputStreamManager extends AbstractManager implements ByteBufferDe
* @param immediateFlush If true, flushes after writing.
* @throws AppenderLoggingException if an error occurs.
*/
- protected void write(final byte[] bytes, boolean immediateFlush) {
+ protected void write(final byte[] bytes, final boolean immediateFlush) {
write(bytes, 0, bytes.length, immediateFlush);
}
@@ -168,7 +168,7 @@ public class OutputStreamManager extends AbstractManager implements ByteBufferDe
* @param immediateFlush flushes immediately after writing.
* @throws AppenderLoggingException if an error occurs.
*/
- protected synchronized void write(final byte[] bytes, final int offset, final int length, boolean immediateFlush) {
+ protected synchronized void write(final byte[] bytes, final int offset, final int length, final boolean immediateFlush) {
if (immediateFlush && byteBuffer.position() == 0) {
writeToDestination(bytes, offset, length);
flushDestination();
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java
index 1a542db..c49ed46 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java
@@ -199,7 +199,7 @@ public class SocketAppender extends AbstractOutputStreamAppender<AbstractSocketM
final String name,
final String immediateFlush,
final String ignore,
- Layout<? extends Serializable> layout,
+ final Layout<? extends Serializable> layout,
final Filter filter,
final String advertise,
final Configuration config) {
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/CronTriggeringPolicy.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/CronTriggeringPolicy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/CronTriggeringPolicy.java
index b45d6e0..b4d1b1b 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/CronTriggeringPolicy.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/CronTriggeringPolicy.java
@@ -44,7 +44,7 @@ public final class CronTriggeringPolicy implements TriggeringPolicy {
private final Configuration configuration;
private final boolean checkOnStartup;
- private CronTriggeringPolicy(CronExpression schedule, boolean checkOnStartup, Configuration configuration) {
+ private CronTriggeringPolicy(final CronExpression schedule, final boolean checkOnStartup, final Configuration configuration) {
this.cronExpression = schedule;
this.configuration = configuration;
this.checkOnStartup = checkOnStartup;
@@ -89,7 +89,7 @@ public final class CronTriggeringPolicy implements TriggeringPolicy {
*/
@PluginFactory
public static CronTriggeringPolicy createPolicy(
- @PluginConfiguration Configuration configuration,
+ @PluginConfiguration final Configuration configuration,
@PluginAttribute("evaluateOnStartup") final String evaluateOnStartup,
@PluginAttribute("schedule") final String schedule) {
CronExpression cronExpression;
@@ -107,7 +107,7 @@ public final class CronTriggeringPolicy implements TriggeringPolicy {
return new CronTriggeringPolicy(cronExpression, checkOnStartup, configuration);
}
- private static CronExpression getSchedule(String expression) {
+ private static CronExpression getSchedule(final String expression) {
try {
return new CronExpression(expression);
} catch (ParseException pe) {
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java
index 547cc3e..6097586 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java
@@ -131,7 +131,7 @@ public class DefaultRolloverStrategy implements RolloverStrategy {
}
};
- static FileExtensions lookup(String fileExtension) {
+ static FileExtensions lookup(final String fileExtension) {
for (FileExtensions ext : values()) {
if (ext.isExtensionFor(fileExtension)) {
return ext;
@@ -162,11 +162,11 @@ public class DefaultRolloverStrategy implements RolloverStrategy {
return extension.length();
}
- File source(String fileName) {
+ File source(final String fileName) {
return new File(fileName);
}
- File target(String fileName) {
+ File target(final String fileName) {
return new File(fileName);
}
};
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/FileSize.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/FileSize.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/FileSize.java
index e134b1f..08e6b9e 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/FileSize.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/FileSize.java
@@ -1,90 +1,90 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-
-package org.apache.logging.log4j.core.appender.rolling;
-
-import java.text.NumberFormat;
-import java.text.ParseException;
-import java.util.Locale;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.status.StatusLogger;
-
-/**
- * FileSize utility class.
- */
-public final class FileSize {
- private static final Logger LOGGER = StatusLogger.getLogger();
-
- private static final long KB = 1024;
- private static final long MB = KB * KB;
- private static final long GB = KB * MB;
-
- /**
- * Pattern for string parsing.
- */
- private static final Pattern VALUE_PATTERN =
- Pattern.compile("([0-9]+([\\.,][0-9]+)?)\\s*(|K|M|G)B?", Pattern.CASE_INSENSITIVE);
-
- private FileSize() {
- }
-
- /**
- * Converts a string to a number of bytes. Strings consist of a floating point value followed by
- * K, M, or G for kilobytes, megabytes, gigabytes, respectively. The
- * abbreviations KB, MB, and GB are also accepted. Matching is case insensitive.
- *
- * @param string The string to convert
- * @return The Bytes value for the string
- */
- public static long parse(final String string, long defaultValue) {
- final Matcher matcher = VALUE_PATTERN.matcher(string);
-
- // Valid input?
- if (matcher.matches()) {
- try {
- // Get double precision value
- final long value = NumberFormat.getNumberInstance(Locale.getDefault()).parse(
- matcher.group(1)).longValue();
-
- // Get units specified
- final String units = matcher.group(3);
-
- if (units.isEmpty()) {
- return value;
- } else if (units.equalsIgnoreCase("K")) {
- return value * KB;
- } else if (units.equalsIgnoreCase("M")) {
- return value * MB;
- } else if (units.equalsIgnoreCase("G")) {
- return value * GB;
- } else {
- LOGGER.error("FileSize units not recognized: " + string);
- return defaultValue;
- }
- } catch (final ParseException e) {
- LOGGER.error("FileSize unable to parse numeric part: " + string, e);
- return defaultValue;
- }
- }
- LOGGER.error("FileSize unable to parse bytes: " + string);
- return defaultValue;
- }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.core.appender.rolling;
+
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.status.StatusLogger;
+
+/**
+ * FileSize utility class.
+ */
+public final class FileSize {
+ private static final Logger LOGGER = StatusLogger.getLogger();
+
+ private static final long KB = 1024;
+ private static final long MB = KB * KB;
+ private static final long GB = KB * MB;
+
+ /**
+ * Pattern for string parsing.
+ */
+ private static final Pattern VALUE_PATTERN =
+ Pattern.compile("([0-9]+([\\.,][0-9]+)?)\\s*(|K|M|G)B?", Pattern.CASE_INSENSITIVE);
+
+ private FileSize() {
+ }
+
+ /**
+ * Converts a string to a number of bytes. Strings consist of a floating point value followed by
+ * K, M, or G for kilobytes, megabytes, gigabytes, respectively. The
+ * abbreviations KB, MB, and GB are also accepted. Matching is case insensitive.
+ *
+ * @param string The string to convert
+ * @return The Bytes value for the string
+ */
+ public static long parse(final String string, final long defaultValue) {
+ final Matcher matcher = VALUE_PATTERN.matcher(string);
+
+ // Valid input?
+ if (matcher.matches()) {
+ try {
+ // Get double precision value
+ final long value = NumberFormat.getNumberInstance(Locale.getDefault()).parse(
+ matcher.group(1)).longValue();
+
+ // Get units specified
+ final String units = matcher.group(3);
+
+ if (units.isEmpty()) {
+ return value;
+ } else if (units.equalsIgnoreCase("K")) {
+ return value * KB;
+ } else if (units.equalsIgnoreCase("M")) {
+ return value * MB;
+ } else if (units.equalsIgnoreCase("G")) {
+ return value * GB;
+ } else {
+ LOGGER.error("FileSize units not recognized: " + string);
+ return defaultValue;
+ }
+ } catch (final ParseException e) {
+ LOGGER.error("FileSize unable to parse numeric part: " + string, e);
+ return defaultValue;
+ }
+ }
+ LOGGER.error("FileSize unable to parse bytes: " + string);
+ return defaultValue;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/Duration.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/Duration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/Duration.java
index 8508f03..a5103f7 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/Duration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/Duration.java
@@ -1,257 +1,257 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-
-package org.apache.logging.log4j.core.appender.rolling.action;
-
-import java.io.Serializable;
-import java.util.Objects;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Simplified implementation of the <a href="https://en.wikipedia.org/wiki/ISO_8601#Durations">ISO-8601 Durations</a>
- * standard. The supported format is {@code PnDTnHnMnS}, with 'P' and 'T' optional. Days are considered to be exactly 24
- * hours.
- * <p>
- * Similarly to the {@code java.time.Duration} class, this class does not support year or month sections in the format.
- * This implementation does not support fractions or negative values.
- *
- * @see #parse(CharSequence)
- */
-public class Duration implements Serializable, Comparable<Duration> {
- private static final long serialVersionUID = -3756810052716342061L;
-
- /**
- * Constant for a duration of zero.
- */
- public static final Duration ZERO = new Duration(0);
-
- /**
- * Hours per day.
- */
- private static final int HOURS_PER_DAY = 24;
- /**
- * Minutes per hour.
- */
- private static final int MINUTES_PER_HOUR = 60;
- /**
- * Seconds per minute.
- */
- private static final int SECONDS_PER_MINUTE = 60;
- /**
- * Seconds per hour.
- */
- private static final int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;
- /**
- * Seconds per day.
- */
- private static final int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;
-
- /**
- * The pattern for parsing.
- */
- private static final Pattern PATTERN = Pattern.compile("P?(?:([0-9]+)D)?"
- + "(T?(?:([0-9]+)H)?(?:([0-9]+)M)?(?:([0-9]+)?S)?)?", Pattern.CASE_INSENSITIVE);
-
- /**
- * The number of seconds in the duration.
- */
- private final long seconds;
-
- /**
- * Constructs an instance of {@code Duration} using seconds.
- *
- * @param seconds the length of the duration in seconds, positive or negative
- */
- private Duration(long seconds) {
- super();
- this.seconds = seconds;
- }
-
- /**
- * Obtains a {@code Duration} from a text string such as {@code PnDTnHnMnS}.
- * <p>
- * This will parse a textual representation of a duration, including the string produced by {@code toString()}. The
- * formats accepted are based on the ISO-8601 duration format {@code PnDTnHnMnS} with days considered to be exactly
- * 24 hours.
- * <p>
- * This implementation does not support negative numbers or fractions (so the smallest non-zero value a Duration can
- * have is one second).
- * <p>
- * The string optionally starts with the ASCII letter "P" in upper or lower case. There are then four sections, each
- * consisting of a number and a suffix. The sections have suffixes in ASCII of "D", "H", "M" and "S" for days,
- * hours, minutes and seconds, accepted in upper or lower case. The suffixes must occur in order. The ASCII letter
- * "T" may occur before the first occurrence, if any, of an hour, minute or second section. At least one of the four
- * sections must be present, and if "T" is present there must be at least one section after the "T". The number part
- * of each section must consist of one or more ASCII digits. The number may not be prefixed by the ASCII negative or
- * positive symbol. The number of days, hours, minutes and seconds must parse to a {@code long}.
- * <p>
- * Examples:
- *
- * <pre>
- * "PT20S" -- parses as "20 seconds"
- * "PT15M" -- parses as "15 minutes" (where a minute is 60 seconds)
- * "PT10H" -- parses as "10 hours" (where an hour is 3600 seconds)
- * "P2D" -- parses as "2 days" (where a day is 24 hours or 86400 seconds)
- * "P2DT3H4M" -- parses as "2 days, 3 hours and 4 minutes"
- * </pre>
- *
- * @param text the text to parse, not null
- * @return the parsed duration, not null
- * @throws IllegalArgumentException if the text cannot be parsed to a duration
- */
- public static Duration parse(CharSequence text) {
- Objects.requireNonNull(text, "text");
- Matcher matcher = PATTERN.matcher(text);
- if (matcher.matches()) {
- // check for letter T but no time sections
- if ("T".equals(matcher.group(2)) == false) {
- String dayMatch = matcher.group(1);
- String hourMatch = matcher.group(3);
- String minuteMatch = matcher.group(4);
- String secondMatch = matcher.group(5);
- if (dayMatch != null || hourMatch != null || minuteMatch != null || secondMatch != null) {
- long daysAsSecs = parseNumber(text, dayMatch, SECONDS_PER_DAY, "days");
- long hoursAsSecs = parseNumber(text, hourMatch, SECONDS_PER_HOUR, "hours");
- long minsAsSecs = parseNumber(text, minuteMatch, SECONDS_PER_MINUTE, "minutes");
- long seconds = parseNumber(text, secondMatch, 1, "seconds");
- try {
- return create(daysAsSecs, hoursAsSecs, minsAsSecs, seconds);
- } catch (ArithmeticException ex) {
- throw new IllegalArgumentException("Text cannot be parsed to a Duration (overflow) " + text, ex);
- }
- }
- }
- }
- throw new IllegalArgumentException("Text cannot be parsed to a Duration: " + text);
- }
-
- private static long parseNumber(final CharSequence text, final String parsed, final int multiplier,
- final String errorText) {
- // regex limits to [0-9]+
- if (parsed == null) {
- return 0;
- }
- try {
- final long val = Long.parseLong(parsed);
- return val * multiplier;
- } catch (final Exception ex) {
- throw new IllegalArgumentException("Text cannot be parsed to a Duration: " + errorText + " (in " + text
- + ")", ex);
- }
- }
-
- private static Duration create(final long daysAsSecs, final long hoursAsSecs, final long minsAsSecs, final long secs) {
- return create(daysAsSecs + hoursAsSecs + minsAsSecs + secs);
- }
-
- /**
- * Obtains an instance of {@code Duration} using seconds.
- *
- * @param seconds the length of the duration in seconds, positive only
- */
- private static Duration create(final long seconds) {
- if ((seconds) == 0) {
- return ZERO;
- }
- return new Duration(seconds);
- }
-
- /**
- * Converts this duration to the total length in milliseconds.
- *
- * @return the total length of the duration in milliseconds
- */
- public long toMillis() {
- return seconds * 1000L;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
- if (!(obj instanceof Duration)) {
- return false;
- }
- Duration other = (Duration) obj;
- return other.seconds == this.seconds;
- }
-
- @Override
- public int hashCode() {
- return (int) (seconds ^ (seconds >>> 32));
- }
-
- /**
- * A string representation of this duration using ISO-8601 seconds based representation, such as {@code PT8H6M12S}.
- * <p>
- * The format of the returned string will be {@code PnDTnHnMnS}, where n is the relevant days, hours, minutes or
- * seconds part of the duration. If a section has a zero value, it is omitted. The hours, minutes and seconds are
- * all positive.
- * <p>
- * Examples:
- *
- * <pre>
- * "20 seconds" -- "PT20S
- * "15 minutes" (15 * 60 seconds) -- "PT15M"
- * "10 hours" (10 * 3600 seconds) -- "PT10H"
- * "2 days" (2 * 86400 seconds) -- "P2D"
- * </pre>
- *
- * @return an ISO-8601 representation of this duration, not null
- */
- @Override
- public String toString() {
- if (this == ZERO) {
- return "PT0S";
- }
- final long days = seconds / SECONDS_PER_DAY;
- final long hours = (seconds % SECONDS_PER_DAY) / SECONDS_PER_HOUR;
- final int minutes = (int) ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
- final int secs = (int) (seconds % SECONDS_PER_MINUTE);
- final StringBuilder buf = new StringBuilder(24);
- buf.append("P");
- if (days != 0) {
- buf.append(days).append('D');
- }
- if ((hours | minutes | secs) != 0) {
- buf.append('T');
- }
- if (hours != 0) {
- buf.append(hours).append('H');
- }
- if (minutes != 0) {
- buf.append(minutes).append('M');
- }
- if (secs == 0 && buf.length() > 0) {
- return buf.toString();
- }
- buf.append(secs).append('S');
- return buf.toString();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Comparable#compareTo(java.lang.Object)
- */
- @Override
- public int compareTo(Duration other) {
- return Long.signum(toMillis() - other.toMillis());
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.core.appender.rolling.action;
+
+import java.io.Serializable;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Simplified implementation of the <a href="https://en.wikipedia.org/wiki/ISO_8601#Durations">ISO-8601 Durations</a>
+ * standard. The supported format is {@code PnDTnHnMnS}, with 'P' and 'T' optional. Days are considered to be exactly 24
+ * hours.
+ * <p>
+ * Similarly to the {@code java.time.Duration} class, this class does not support year or month sections in the format.
+ * This implementation does not support fractions or negative values.
+ *
+ * @see #parse(CharSequence)
+ */
+public class Duration implements Serializable, Comparable<Duration> {
+ private static final long serialVersionUID = -3756810052716342061L;
+
+ /**
+ * Constant for a duration of zero.
+ */
+ public static final Duration ZERO = new Duration(0);
+
+ /**
+ * Hours per day.
+ */
+ private static final int HOURS_PER_DAY = 24;
+ /**
+ * Minutes per hour.
+ */
+ private static final int MINUTES_PER_HOUR = 60;
+ /**
+ * Seconds per minute.
+ */
+ private static final int SECONDS_PER_MINUTE = 60;
+ /**
+ * Seconds per hour.
+ */
+ private static final int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;
+ /**
+ * Seconds per day.
+ */
+ private static final int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;
+
+ /**
+ * The pattern for parsing.
+ */
+ private static final Pattern PATTERN = Pattern.compile("P?(?:([0-9]+)D)?"
+ + "(T?(?:([0-9]+)H)?(?:([0-9]+)M)?(?:([0-9]+)?S)?)?", Pattern.CASE_INSENSITIVE);
+
+ /**
+ * The number of seconds in the duration.
+ */
+ private final long seconds;
+
+ /**
+ * Constructs an instance of {@code Duration} using seconds.
+ *
+ * @param seconds the length of the duration in seconds, positive or negative
+ */
+ private Duration(final long seconds) {
+ super();
+ this.seconds = seconds;
+ }
+
+ /**
+ * Obtains a {@code Duration} from a text string such as {@code PnDTnHnMnS}.
+ * <p>
+ * This will parse a textual representation of a duration, including the string produced by {@code toString()}. The
+ * formats accepted are based on the ISO-8601 duration format {@code PnDTnHnMnS} with days considered to be exactly
+ * 24 hours.
+ * <p>
+ * This implementation does not support negative numbers or fractions (so the smallest non-zero value a Duration can
+ * have is one second).
+ * <p>
+ * The string optionally starts with the ASCII letter "P" in upper or lower case. There are then four sections, each
+ * consisting of a number and a suffix. The sections have suffixes in ASCII of "D", "H", "M" and "S" for days,
+ * hours, minutes and seconds, accepted in upper or lower case. The suffixes must occur in order. The ASCII letter
+ * "T" may occur before the first occurrence, if any, of an hour, minute or second section. At least one of the four
+ * sections must be present, and if "T" is present there must be at least one section after the "T". The number part
+ * of each section must consist of one or more ASCII digits. The number may not be prefixed by the ASCII negative or
+ * positive symbol. The number of days, hours, minutes and seconds must parse to a {@code long}.
+ * <p>
+ * Examples:
+ *
+ * <pre>
+ * "PT20S" -- parses as "20 seconds"
+ * "PT15M" -- parses as "15 minutes" (where a minute is 60 seconds)
+ * "PT10H" -- parses as "10 hours" (where an hour is 3600 seconds)
+ * "P2D" -- parses as "2 days" (where a day is 24 hours or 86400 seconds)
+ * "P2DT3H4M" -- parses as "2 days, 3 hours and 4 minutes"
+ * </pre>
+ *
+ * @param text the text to parse, not null
+ * @return the parsed duration, not null
+ * @throws IllegalArgumentException if the text cannot be parsed to a duration
+ */
+ public static Duration parse(final CharSequence text) {
+ Objects.requireNonNull(text, "text");
+ Matcher matcher = PATTERN.matcher(text);
+ if (matcher.matches()) {
+ // check for letter T but no time sections
+ if ("T".equals(matcher.group(2)) == false) {
+ String dayMatch = matcher.group(1);
+ String hourMatch = matcher.group(3);
+ String minuteMatch = matcher.group(4);
+ String secondMatch = matcher.group(5);
+ if (dayMatch != null || hourMatch != null || minuteMatch != null || secondMatch != null) {
+ long daysAsSecs = parseNumber(text, dayMatch, SECONDS_PER_DAY, "days");
+ long hoursAsSecs = parseNumber(text, hourMatch, SECONDS_PER_HOUR, "hours");
+ long minsAsSecs = parseNumber(text, minuteMatch, SECONDS_PER_MINUTE, "minutes");
+ long seconds = parseNumber(text, secondMatch, 1, "seconds");
+ try {
+ return create(daysAsSecs, hoursAsSecs, minsAsSecs, seconds);
+ } catch (ArithmeticException ex) {
+ throw new IllegalArgumentException("Text cannot be parsed to a Duration (overflow) " + text, ex);
+ }
+ }
+ }
+ }
+ throw new IllegalArgumentException("Text cannot be parsed to a Duration: " + text);
+ }
+
+ private static long parseNumber(final CharSequence text, final String parsed, final int multiplier,
+ final String errorText) {
+ // regex limits to [0-9]+
+ if (parsed == null) {
+ return 0;
+ }
+ try {
+ final long val = Long.parseLong(parsed);
+ return val * multiplier;
+ } catch (final Exception ex) {
+ throw new IllegalArgumentException("Text cannot be parsed to a Duration: " + errorText + " (in " + text
+ + ")", ex);
+ }
+ }
+
+ private static Duration create(final long daysAsSecs, final long hoursAsSecs, final long minsAsSecs, final long secs) {
+ return create(daysAsSecs + hoursAsSecs + minsAsSecs + secs);
+ }
+
+ /**
+ * Obtains an instance of {@code Duration} using seconds.
+ *
+ * @param seconds the length of the duration in seconds, positive only
+ */
+ private static Duration create(final long seconds) {
+ if ((seconds) == 0) {
+ return ZERO;
+ }
+ return new Duration(seconds);
+ }
+
+ /**
+ * Converts this duration to the total length in milliseconds.
+ *
+ * @return the total length of the duration in milliseconds
+ */
+ public long toMillis() {
+ return seconds * 1000L;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof Duration)) {
+ return false;
+ }
+ Duration other = (Duration) obj;
+ return other.seconds == this.seconds;
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) (seconds ^ (seconds >>> 32));
+ }
+
+ /**
+ * A string representation of this duration using ISO-8601 seconds based representation, such as {@code PT8H6M12S}.
+ * <p>
+ * The format of the returned string will be {@code PnDTnHnMnS}, where n is the relevant days, hours, minutes or
+ * seconds part of the duration. If a section has a zero value, it is omitted. The hours, minutes and seconds are
+ * all positive.
+ * <p>
+ * Examples:
+ *
+ * <pre>
+ * "20 seconds" -- "PT20S
+ * "15 minutes" (15 * 60 seconds) -- "PT15M"
+ * "10 hours" (10 * 3600 seconds) -- "PT10H"
+ * "2 days" (2 * 86400 seconds) -- "P2D"
+ * </pre>
+ *
+ * @return an ISO-8601 representation of this duration, not null
+ */
+ @Override
+ public String toString() {
+ if (this == ZERO) {
+ return "PT0S";
+ }
+ final long days = seconds / SECONDS_PER_DAY;
+ final long hours = (seconds % SECONDS_PER_DAY) / SECONDS_PER_HOUR;
+ final int minutes = (int) ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
+ final int secs = (int) (seconds % SECONDS_PER_MINUTE);
+ final StringBuilder buf = new StringBuilder(24);
+ buf.append("P");
+ if (days != 0) {
+ buf.append(days).append('D');
+ }
+ if ((hours | minutes | secs) != 0) {
+ buf.append('T');
+ }
+ if (hours != 0) {
+ buf.append(hours).append('H');
+ }
+ if (minutes != 0) {
+ buf.append(minutes).append('M');
+ }
+ if (secs == 0 && buf.length() > 0) {
+ return buf.toString();
+ }
+ buf.append(secs).append('S');
+ return buf.toString();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ @Override
+ public int compareTo(final Duration other) {
+ return Long.signum(toMillis() - other.toMillis());
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/IfAll.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/IfAll.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/IfAll.java
index 627a082..9591804 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/IfAll.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/IfAll.java
@@ -1,116 +1,116 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.appender.rolling.action;
-
-import java.nio.file.Path;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.Arrays;
-import java.util.Objects;
-
-import org.apache.logging.log4j.core.config.plugins.Plugin;
-import org.apache.logging.log4j.core.config.plugins.PluginElement;
-import org.apache.logging.log4j.core.config.plugins.PluginFactory;
-
-/**
- * Composite {@code PathCondition} that only accepts objects that are accepted by <em>all</em> component conditions.
- * Corresponds to logical "AND".
- */
-@Plugin(name = "IfAll", category = "Core", printObject = true)
-public final class IfAll implements PathCondition {
-
- private final PathCondition[] components;
-
- private IfAll(final PathCondition... filters) {
- this.components = Objects.requireNonNull(filters, "filters");
- }
-
- public PathCondition[] getDeleteFilters() {
- return components;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.apache.logging.log4j.core.appender.rolling.action.PathCondition#accept(java.nio.file.Path,
- * java.nio.file.Path, java.nio.file.attribute.BasicFileAttributes)
- */
- @Override
- public boolean accept(final Path baseDir, final Path relativePath, final BasicFileAttributes attrs) {
- if (components == null || components.length == 0) {
- return false; // unconditional delete not supported
- }
- return accept(components, baseDir, relativePath, attrs);
- }
-
- /**
- * Returns {@code true} if all the specified conditions accept the specified path, {@code false} otherwise.
- *
- * @param list the array of conditions to evaluate
- * @param baseDir the directory from where to start scanning for deletion candidate files
- * @param relativePath the candidate for deletion. This path is relative to the baseDir.
- * @param attrs attributes of the candidate path
- * @return {@code true} if all the specified conditions accept the specified path, {@code false} otherwise
- * @throws NullPointerException if any of the parameters is {@code null}
- */
- public static boolean accept(final PathCondition[] list, final Path baseDir, final Path relativePath,
- final BasicFileAttributes attrs) {
- for (final PathCondition component : list) {
- if (!component.accept(baseDir, relativePath, attrs)) {
- return false;
- }
- }
- return true;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.apache.logging.log4j.core.appender.rolling.action.PathCondition#beforeFileTreeWalk()
- */
- @Override
- public void beforeFileTreeWalk() {
- beforeFileTreeWalk(components);
- }
-
- /**
- * Calls {@link #beforeFileTreeWalk()} on all of the specified nested conditions.
- *
- * @param nestedConditions the conditions to call {@link #beforeFileTreeWalk()} on
- */
- public static void beforeFileTreeWalk(PathCondition[] nestedConditions) {
- for (PathCondition condition : nestedConditions) {
- condition.beforeFileTreeWalk();
- }
- }
-
- /**
- * Create a Composite PathCondition whose components all need to accept before this condition accepts.
- *
- * @param components The component filters.
- * @return A Composite PathCondition.
- */
- @PluginFactory
- public static IfAll createAndCondition( //
- @PluginElement("PathConditions") final PathCondition... components) {
- return new IfAll(components);
- }
-
- @Override
- public String toString() {
- return "IfAll" + Arrays.toString(components);
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.rolling.action;
+
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Arrays;
+import java.util.Objects;
+
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+
+/**
+ * Composite {@code PathCondition} that only accepts objects that are accepted by <em>all</em> component conditions.
+ * Corresponds to logical "AND".
+ */
+@Plugin(name = "IfAll", category = "Core", printObject = true)
+public final class IfAll implements PathCondition {
+
+ private final PathCondition[] components;
+
+ private IfAll(final PathCondition... filters) {
+ this.components = Objects.requireNonNull(filters, "filters");
+ }
+
+ public PathCondition[] getDeleteFilters() {
+ return components;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.logging.log4j.core.appender.rolling.action.PathCondition#accept(java.nio.file.Path,
+ * java.nio.file.Path, java.nio.file.attribute.BasicFileAttributes)
+ */
+ @Override
+ public boolean accept(final Path baseDir, final Path relativePath, final BasicFileAttributes attrs) {
+ if (components == null || components.length == 0) {
+ return false; // unconditional delete not supported
+ }
+ return accept(components, baseDir, relativePath, attrs);
+ }
+
+ /**
+ * Returns {@code true} if all the specified conditions accept the specified path, {@code false} otherwise.
+ *
+ * @param list the array of conditions to evaluate
+ * @param baseDir the directory from where to start scanning for deletion candidate files
+ * @param relativePath the candidate for deletion. This path is relative to the baseDir.
+ * @param attrs attributes of the candidate path
+ * @return {@code true} if all the specified conditions accept the specified path, {@code false} otherwise
+ * @throws NullPointerException if any of the parameters is {@code null}
+ */
+ public static boolean accept(final PathCondition[] list, final Path baseDir, final Path relativePath,
+ final BasicFileAttributes attrs) {
+ for (final PathCondition component : list) {
+ if (!component.accept(baseDir, relativePath, attrs)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.logging.log4j.core.appender.rolling.action.PathCondition#beforeFileTreeWalk()
+ */
+ @Override
+ public void beforeFileTreeWalk() {
+ beforeFileTreeWalk(components);
+ }
+
+ /**
+ * Calls {@link #beforeFileTreeWalk()} on all of the specified nested conditions.
+ *
+ * @param nestedConditions the conditions to call {@link #beforeFileTreeWalk()} on
+ */
+ public static void beforeFileTreeWalk(final PathCondition[] nestedConditions) {
+ for (PathCondition condition : nestedConditions) {
+ condition.beforeFileTreeWalk();
+ }
+ }
+
+ /**
+ * Create a Composite PathCondition whose components all need to accept before this condition accepts.
+ *
+ * @param components The component filters.
+ * @return A Composite PathCondition.
+ */
+ @PluginFactory
+ public static IfAll createAndCondition( //
+ @PluginElement("PathConditions") final PathCondition... components) {
+ return new IfAll(components);
+ }
+
+ @Override
+ public String toString() {
+ return "IfAll" + Arrays.toString(components);
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/IdlePurgePolicy.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/IdlePurgePolicy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/IdlePurgePolicy.java
index 953f1bc..e9e7469 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/IdlePurgePolicy.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/IdlePurgePolicy.java
@@ -48,13 +48,13 @@ public class IdlePurgePolicy extends AbstractLifeCycle implements PurgePolicy, R
private final ConfigurationScheduler scheduler;
private volatile ScheduledFuture<?> future = null;
- public IdlePurgePolicy(long timeToLive, ConfigurationScheduler scheduler) {
+ public IdlePurgePolicy(final long timeToLive, final ConfigurationScheduler scheduler) {
this.timeToLive = timeToLive;
this.scheduler = scheduler;
}
@Override
- public void initialize(RoutingAppender routingAppender) {
+ public void initialize(final RoutingAppender routingAppender) {
this.routingAppender = routingAppender;
}
@@ -80,7 +80,7 @@ public class IdlePurgePolicy extends AbstractLifeCycle implements PurgePolicy, R
}
@Override
- public void update(String key, LogEvent event) {
+ public void update(final String key, final LogEvent event) {
long now = System.currentTimeMillis();
appendersUsage.put(key, now);
if (future == null) {
@@ -123,7 +123,7 @@ public class IdlePurgePolicy extends AbstractLifeCycle implements PurgePolicy, R
public static PurgePolicy createPurgePolicy(
@PluginAttribute("timeToLive") final String timeToLive,
@PluginAttribute("timeUnit") final String timeUnit,
- @PluginConfiguration Configuration configuration) {
+ @PluginConfiguration final Configuration configuration) {
if (timeToLive == null) {
LOGGER.error("A timeToLive value is required");
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java
index a6b5df0..02f2d33 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java
@@ -55,7 +55,7 @@ public final class RoutingAppender extends AbstractAppender {
private final PurgePolicy purgePolicy;
private RoutingAppender(final String name, final Filter filter, final boolean ignoreExceptions, final Routes routes,
- final RewritePolicy rewritePolicy, final Configuration config, PurgePolicy purgePolicy) {
+ final RewritePolicy rewritePolicy, final Configuration config, final PurgePolicy purgePolicy) {
super(name, filter, null, ignoreExceptions);
this.routes = routes;
this.config = config;
@@ -181,7 +181,7 @@ public final class RoutingAppender extends AbstractAppender {
*
* @param key The appender's key
*/
- public void deleteAppender(String key) {
+ public void deleteAppender(final String key) {
LOGGER.debug("Stopping route with key" + key);
AppenderControl control = appenders.remove(key);
control.getAppender().stop();
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
index 4c590c1..df7eb8a 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
@@ -98,7 +98,7 @@ public class AsyncLogger extends Logger implements EventTranslatorVararg<RingBuf
* @see org.apache.logging.log4j.core.Logger#updateConfiguration(org.apache.logging.log4j.core.config.Configuration)
*/
@Override
- protected void updateConfiguration(Configuration newConfig) {
+ protected void updateConfiguration(final Configuration newConfig) {
nanoClock = newConfig.getNanoClock();
includeLocation = newConfig.getLoggerConfig(name).isIncludeLocation();
super.updateConfiguration(newConfig);
@@ -215,7 +215,7 @@ public class AsyncLogger extends Logger implements EventTranslatorVararg<RingBuf
* @param fqcn fully qualified caller name.
* @return the caller location if requested, {@code null} otherwise.
*/
- private StackTraceElement calcLocationIfRequested(String fqcn) {
+ private StackTraceElement calcLocationIfRequested(final String fqcn) {
// location: very expensive operation. LOG4J2-153:
// Only include if "includeLocation=true" is specified,
// exclude if not specified or if "false" was specified.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
index 276d2ed..d0c9eea 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
@@ -66,7 +66,7 @@ public class AsyncLoggerConfigDisruptor implements AsyncLoggerConfigDelegate {
public Log4jEventWrapper() {
}
- public Log4jEventWrapper(MutableLogEvent mutableLogEvent) {
+ public Log4jEventWrapper(final MutableLogEvent mutableLogEvent) {
event = mutableLogEvent;
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerContext.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerContext.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerContext.java
index a256238..a06893c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerContext.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerContext.java
@@ -81,12 +81,12 @@ public class AsyncLoggerContext extends LoggerContext {
* @see org.apache.logging.log4j.core.LoggerContext#start(org.apache.logging.log4j.core.config.Configuration)
*/
@Override
- public void start(Configuration config) {
+ public void start(final Configuration config) {
maybeStartHelper(config);
super.start(config);
}
- private void maybeStartHelper(Configuration config) {
+ private void maybeStartHelper(final Configuration config) {
// If no log4j configuration was found, there are no loggers
// and there is no point in starting the disruptor (which takes up
// significant memory and starts a thread).
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7a5dcd43/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerDisruptor.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerDisruptor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerDisruptor.java
index 628f4ff..a2dcb19 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerDisruptor.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerDisruptor.java
@@ -1,236 +1,236 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-
-package org.apache.logging.log4j.core.async;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
-import org.apache.logging.log4j.status.StatusLogger;
-
-import com.lmax.disruptor.ExceptionHandler;
-import com.lmax.disruptor.RingBuffer;
-import com.lmax.disruptor.WaitStrategy;
-import com.lmax.disruptor.dsl.Disruptor;
-import com.lmax.disruptor.dsl.ProducerType;
-
-/**
- * Helper class for async loggers: AsyncLoggerDisruptor handles the mechanics of working with the LMAX Disruptor, and
- * works with its associated AsyncLoggerContext to synchronize the life cycle of the Disruptor and its thread with the
- * life cycle of the context. The AsyncLoggerDisruptor of the context is shared by all AsyncLogger objects created by
- * that AsyncLoggerContext.
- */
-class AsyncLoggerDisruptor {
- private static final int SLEEP_MILLIS_BETWEEN_DRAIN_ATTEMPTS = 50;
- private static final int MAX_DRAIN_ATTEMPTS_BEFORE_SHUTDOWN = 200;
- private static final StatusLogger LOGGER = StatusLogger.getLogger();
-
- private volatile Disruptor<RingBufferLogEvent> disruptor;
- private ExecutorService executor;
- private String contextName;
-
- private boolean useThreadLocalTranslator = true;
- private long backgroundThreadId;
- private AsyncQueueFullPolicy asyncQueueFullPolicy;
- private int ringBufferSize;
-
- AsyncLoggerDisruptor(String contextName) {
- this.contextName = contextName;
- }
-
- public String getContextName() {
- return contextName;
- }
-
- public void setContextName(String name) {
- contextName = name;
- }
-
- Disruptor<RingBufferLogEvent> getDisruptor() {
- return disruptor;
- }
-
- /**
- * Creates and starts a new Disruptor and associated thread if none currently exists.
- *
- * @see #stop()
- */
- synchronized void start() {
- if (disruptor != null) {
- LOGGER.trace(
- "[{}] AsyncLoggerDisruptor not starting new disruptor for this context, using existing object.",
- contextName);
- return;
- }
- LOGGER.trace("[{}] AsyncLoggerDisruptor creating new disruptor for this context.", contextName);
- ringBufferSize = DisruptorUtil.calculateRingBufferSize("AsyncLogger.RingBufferSize");
- final WaitStrategy waitStrategy = DisruptorUtil.createWaitStrategy("AsyncLogger.WaitStrategy");
- executor = Executors.newSingleThreadExecutor(new DaemonThreadFactory("AsyncLogger[" + contextName + "]"));
- backgroundThreadId = DisruptorUtil.getExecutorThreadId(executor);
- asyncQueueFullPolicy = AsyncQueueFullPolicyFactory.create();
-
- disruptor = new Disruptor<>(RingBufferLogEvent.FACTORY, ringBufferSize, executor, ProducerType.MULTI,
- waitStrategy);
-
- final ExceptionHandler<RingBufferLogEvent> errorHandler = DisruptorUtil.getAsyncLoggerExceptionHandler();
- disruptor.handleExceptionsWith(errorHandler);
-
- final RingBufferLogEventHandler[] handlers = {new RingBufferLogEventHandler()};
- disruptor.handleEventsWith(handlers);
-
- LOGGER.debug("[{}] Starting AsyncLogger disruptor for this context with ringbufferSize={}, waitStrategy={}, "
- + "exceptionHandler={}...", contextName, disruptor.getRingBuffer().getBufferSize(), waitStrategy
- .getClass().getSimpleName(), errorHandler);
- disruptor.start();
-
- LOGGER.trace("[{}] AsyncLoggers use a {} translator", contextName, useThreadLocalTranslator ? "threadlocal"
- : "vararg");
- }
-
- /**
- * Decreases the reference count. If the reference count reached zero, the Disruptor and its associated thread are
- * shut down and their references set to {@code null}.
- */
- synchronized void stop() {
- final Disruptor<RingBufferLogEvent> temp = getDisruptor();
- if (temp == null) {
- LOGGER.trace("[{}] AsyncLoggerDisruptor: disruptor for this context already shut down.", contextName);
- return; // disruptor was already shut down by another thread
- }
- LOGGER.debug("[{}] AsyncLoggerDisruptor: shutting down disruptor for this context.", contextName);
-
- // We must guarantee that publishing to the RingBuffer has stopped before we call disruptor.shutdown().
- disruptor = null; // client code fails with NPE if log after stop. This is by design.
-
- // Calling Disruptor.shutdown() will wait until all enqueued events are fully processed,
- // but this waiting happens in a busy-spin. To avoid (postpone) wasting CPU,
- // we sleep in short chunks, up to 10 seconds, waiting for the ringbuffer to drain.
- for (int i = 0; hasBacklog(temp) && i < MAX_DRAIN_ATTEMPTS_BEFORE_SHUTDOWN; i++) {
- try {
- Thread.sleep(SLEEP_MILLIS_BETWEEN_DRAIN_ATTEMPTS); // give up the CPU for a while
- } catch (final InterruptedException e) { // ignored
- }
- }
- temp.shutdown(); // busy-spins until all events currently in the disruptor have been processed
-
- LOGGER.trace("[{}] AsyncLoggerDisruptor: shutting down disruptor executor.", contextName);
- executor.shutdown(); // finally, kill the processor thread
- executor = null;
-
- if (DiscardingAsyncQueueFullPolicy.getDiscardCount(asyncQueueFullPolicy) > 0) {
- LOGGER.trace("AsyncLoggerDisruptor: {} discarded {} events.", asyncQueueFullPolicy,
- DiscardingAsyncQueueFullPolicy.getDiscardCount(asyncQueueFullPolicy));
- }
- }
-
- /**
- * Returns {@code true} if the specified disruptor still has unprocessed events.
- */
- private static boolean hasBacklog(final Disruptor<?> theDisruptor) {
- final RingBuffer<?> ringBuffer = theDisruptor.getRingBuffer();
- return !ringBuffer.hasAvailableCapacity(ringBuffer.getBufferSize());
- }
-
- /**
- * Creates and returns a new {@code RingBufferAdmin} that instruments the ringbuffer of the {@code AsyncLogger}.
- *
- * @param jmxContextName name of the {@code AsyncLoggerContext}
- * @return a new {@code RingBufferAdmin} that instruments the ringbuffer
- */
- public RingBufferAdmin createRingBufferAdmin(final String jmxContextName) {
- final RingBuffer<RingBufferLogEvent> ring = disruptor == null ? null : disruptor.getRingBuffer();
- return RingBufferAdmin.forAsyncLogger(ring, jmxContextName);
- }
-
- EventRoute getEventRoute(final Level logLevel) {
- final int remainingCapacity = remainingDisruptorCapacity();
- if (remainingCapacity < 0) {
- return EventRoute.DISCARD;
- }
- return asyncQueueFullPolicy.getRoute(backgroundThreadId, logLevel);
- }
-
- private int remainingDisruptorCapacity() {
- final Disruptor<RingBufferLogEvent> temp = disruptor;
- if (hasLog4jBeenShutDown(temp)) {
- return -1;
- }
- return (int) temp.getRingBuffer().remainingCapacity();
- }
- /**
- * Returns {@code true} if the specified disruptor is null.
- */
- private boolean hasLog4jBeenShutDown(final Disruptor<RingBufferLogEvent> aDisruptor) {
- if (aDisruptor == null) { // LOG4J2-639
- LOGGER.warn("Ignoring log event after log4j was shut down");
- return true;
- }
- return false;
- }
-
- public boolean tryPublish(final RingBufferLogEventTranslator translator) {
- // LOG4J2-639: catch NPE if disruptor field was set to null in stop()
- try {
- return disruptor.getRingBuffer().tryPublishEvent(translator);
- } catch (final NullPointerException npe) {
- LOGGER.warn("[{}] Ignoring log event after log4j was shut down.", contextName);
- return false;
- }
- }
-
- void enqueueLogMessageInfo(final RingBufferLogEventTranslator translator) {
- // LOG4J2-639: catch NPE if disruptor field was set to null in stop()
- try {
- // Note: we deliberately access the volatile disruptor field afresh here.
- // Avoiding this and using an older reference 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.publishEvent(translator);
- } catch (final NullPointerException npe) {
- LOGGER.warn("[{}] Ignoring log event after log4j was shut down.", contextName);
- }
- }
-
- /**
- * Returns whether it is allowed to store non-JDK classes in ThreadLocal objects for efficiency.
- *
- * @return whether AsyncLoggers are allowed to use ThreadLocal objects
- * @since 2.5
- * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-1172">LOG4J2-1172</a>
- */
- public boolean isUseThreadLocals() {
- return useThreadLocalTranslator;
- }
-
- /**
- * Signals this AsyncLoggerDisruptor whether it is allowed to store non-JDK classes in ThreadLocal objects for
- * efficiency.
- * <p>
- * This property may be modified after the {@link #start()} method has been called.
- * </p>
- *
- * @param allow whether AsyncLoggers are allowed to use ThreadLocal objects
- * @since 2.5
- * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-1172">LOG4J2-1172</a>
- */
- public void setUseThreadLocals(final boolean allow) {
- useThreadLocalTranslator = allow;
- LOGGER.trace("[{}] AsyncLoggers have been modified to use a {} translator", contextName,
- useThreadLocalTranslator ? "threadlocal" : "vararg");
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.core.async;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
+import org.apache.logging.log4j.status.StatusLogger;
+
+import com.lmax.disruptor.ExceptionHandler;
+import com.lmax.disruptor.RingBuffer;
+import com.lmax.disruptor.WaitStrategy;
+import com.lmax.disruptor.dsl.Disruptor;
+import com.lmax.disruptor.dsl.ProducerType;
+
+/**
+ * Helper class for async loggers: AsyncLoggerDisruptor handles the mechanics of working with the LMAX Disruptor, and
+ * works with its associated AsyncLoggerContext to synchronize the life cycle of the Disruptor and its thread with the
+ * life cycle of the context. The AsyncLoggerDisruptor of the context is shared by all AsyncLogger objects created by
+ * that AsyncLoggerContext.
+ */
+class AsyncLoggerDisruptor {
+ private static final int SLEEP_MILLIS_BETWEEN_DRAIN_ATTEMPTS = 50;
+ private static final int MAX_DRAIN_ATTEMPTS_BEFORE_SHUTDOWN = 200;
+ private static final StatusLogger LOGGER = StatusLogger.getLogger();
+
+ private volatile Disruptor<RingBufferLogEvent> disruptor;
+ private ExecutorService executor;
+ private String contextName;
+
+ private boolean useThreadLocalTranslator = true;
+ private long backgroundThreadId;
+ private AsyncQueueFullPolicy asyncQueueFullPolicy;
+ private int ringBufferSize;
+
+ AsyncLoggerDisruptor(final String contextName) {
+ this.contextName = contextName;
+ }
+
+ public String getContextName() {
+ return contextName;
+ }
+
+ public void setContextName(final String name) {
+ contextName = name;
+ }
+
+ Disruptor<RingBufferLogEvent> getDisruptor() {
+ return disruptor;
+ }
+
+ /**
+ * Creates and starts a new Disruptor and associated thread if none currently exists.
+ *
+ * @see #stop()
+ */
+ synchronized void start() {
+ if (disruptor != null) {
+ LOGGER.trace(
+ "[{}] AsyncLoggerDisruptor not starting new disruptor for this context, using existing object.",
+ contextName);
+ return;
+ }
+ LOGGER.trace("[{}] AsyncLoggerDisruptor creating new disruptor for this context.", contextName);
+ ringBufferSize = DisruptorUtil.calculateRingBufferSize("AsyncLogger.RingBufferSize");
+ final WaitStrategy waitStrategy = DisruptorUtil.createWaitStrategy("AsyncLogger.WaitStrategy");
+ executor = Executors.newSingleThreadExecutor(new DaemonThreadFactory("AsyncLogger[" + contextName + "]"));
+ backgroundThreadId = DisruptorUtil.getExecutorThreadId(executor);
+ asyncQueueFullPolicy = AsyncQueueFullPolicyFactory.create();
+
+ disruptor = new Disruptor<>(RingBufferLogEvent.FACTORY, ringBufferSize, executor, ProducerType.MULTI,
+ waitStrategy);
+
+ final ExceptionHandler<RingBufferLogEvent> errorHandler = DisruptorUtil.getAsyncLoggerExceptionHandler();
+ disruptor.handleExceptionsWith(errorHandler);
+
+ final RingBufferLogEventHandler[] handlers = {new RingBufferLogEventHandler()};
+ disruptor.handleEventsWith(handlers);
+
+ LOGGER.debug("[{}] Starting AsyncLogger disruptor for this context with ringbufferSize={}, waitStrategy={}, "
+ + "exceptionHandler={}...", contextName, disruptor.getRingBuffer().getBufferSize(), waitStrategy
+ .getClass().getSimpleName(), errorHandler);
+ disruptor.start();
+
+ LOGGER.trace("[{}] AsyncLoggers use a {} translator", contextName, useThreadLocalTranslator ? "threadlocal"
+ : "vararg");
+ }
+
+ /**
+ * Decreases the reference count. If the reference count reached zero, the Disruptor and its associated thread are
+ * shut down and their references set to {@code null}.
+ */
+ synchronized void stop() {
+ final Disruptor<RingBufferLogEvent> temp = getDisruptor();
+ if (temp == null) {
+ LOGGER.trace("[{}] AsyncLoggerDisruptor: disruptor for this context already shut down.", contextName);
+ return; // disruptor was already shut down by another thread
+ }
+ LOGGER.debug("[{}] AsyncLoggerDisruptor: shutting down disruptor for this context.", contextName);
+
+ // We must guarantee that publishing to the RingBuffer has stopped before we call disruptor.shutdown().
+ disruptor = null; // client code fails with NPE if log after stop. This is by design.
+
+ // Calling Disruptor.shutdown() will wait until all enqueued events are fully processed,
+ // but this waiting happens in a busy-spin. To avoid (postpone) wasting CPU,
+ // we sleep in short chunks, up to 10 seconds, waiting for the ringbuffer to drain.
+ for (int i = 0; hasBacklog(temp) && i < MAX_DRAIN_ATTEMPTS_BEFORE_SHUTDOWN; i++) {
+ try {
+ Thread.sleep(SLEEP_MILLIS_BETWEEN_DRAIN_ATTEMPTS); // give up the CPU for a while
+ } catch (final InterruptedException e) { // ignored
+ }
+ }
+ temp.shutdown(); // busy-spins until all events currently in the disruptor have been processed
+
+ LOGGER.trace("[{}] AsyncLoggerDisruptor: shutting down disruptor executor.", contextName);
+ executor.shutdown(); // finally, kill the processor thread
+ executor = null;
+
+ if (DiscardingAsyncQueueFullPolicy.getDiscardCount(asyncQueueFullPolicy) > 0) {
+ LOGGER.trace("AsyncLoggerDisruptor: {} discarded {} events.", asyncQueueFullPolicy,
+ DiscardingAsyncQueueFullPolicy.getDiscardCount(asyncQueueFullPolicy));
+ }
+ }
+
+ /**
+ * Returns {@code true} if the specified disruptor still has unprocessed events.
+ */
+ private static boolean hasBacklog(final Disruptor<?> theDisruptor) {
+ final RingBuffer<?> ringBuffer = theDisruptor.getRingBuffer();
+ return !ringBuffer.hasAvailableCapacity(ringBuffer.getBufferSize());
+ }
+
+ /**
+ * Creates and returns a new {@code RingBufferAdmin} that instruments the ringbuffer of the {@code AsyncLogger}.
+ *
+ * @param jmxContextName name of the {@code AsyncLoggerContext}
+ * @return a new {@code RingBufferAdmin} that instruments the ringbuffer
+ */
+ public RingBufferAdmin createRingBufferAdmin(final String jmxContextName) {
+ final RingBuffer<RingBufferLogEvent> ring = disruptor == null ? null : disruptor.getRingBuffer();
+ return RingBufferAdmin.forAsyncLogger(ring, jmxContextName);
+ }
+
+ EventRoute getEventRoute(final Level logLevel) {
+ final int remainingCapacity = remainingDisruptorCapacity();
+ if (remainingCapacity < 0) {
+ return EventRoute.DISCARD;
+ }
+ return asyncQueueFullPolicy.getRoute(backgroundThreadId, logLevel);
+ }
+
+ private int remainingDisruptorCapacity() {
+ final Disruptor<RingBufferLogEvent> temp = disruptor;
+ if (hasLog4jBeenShutDown(temp)) {
+ return -1;
+ }
+ return (int) temp.getRingBuffer().remainingCapacity();
+ }
+ /**
+ * Returns {@code true} if the specified disruptor is null.
+ */
+ private boolean hasLog4jBeenShutDown(final Disruptor<RingBufferLogEvent> aDisruptor) {
+ if (aDisruptor == null) { // LOG4J2-639
+ LOGGER.warn("Ignoring log event after log4j was shut down");
+ return true;
+ }
+ return false;
+ }
+
+ public boolean tryPublish(final RingBufferLogEventTranslator translator) {
+ // LOG4J2-639: catch NPE if disruptor field was set to null in stop()
+ try {
+ return disruptor.getRingBuffer().tryPublishEvent(translator);
+ } catch (final NullPointerException npe) {
+ LOGGER.warn("[{}] Ignoring log event after log4j was shut down.", contextName);
+ return false;
+ }
+ }
+
+ void enqueueLogMessageInfo(final RingBufferLogEventTranslator translator) {
+ // LOG4J2-639: catch NPE if disruptor field was set to null in stop()
+ try {
+ // Note: we deliberately access the volatile disruptor field afresh here.
+ // Avoiding this and using an older reference 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.publishEvent(translator);
+ } catch (final NullPointerException npe) {
+ LOGGER.warn("[{}] Ignoring log event after log4j was shut down.", contextName);
+ }
+ }
+
+ /**
+ * Returns whether it is allowed to store non-JDK classes in ThreadLocal objects for efficiency.
+ *
+ * @return whether AsyncLoggers are allowed to use ThreadLocal objects
+ * @since 2.5
+ * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-1172">LOG4J2-1172</a>
+ */
+ public boolean isUseThreadLocals() {
+ return useThreadLocalTranslator;
+ }
+
+ /**
+ * Signals this AsyncLoggerDisruptor whether it is allowed to store non-JDK classes in ThreadLocal objects for
+ * efficiency.
+ * <p>
+ * This property may be modified after the {@link #start()} method has been called.
+ * </p>
+ *
+ * @param allow whether AsyncLoggers are allowed to use ThreadLocal objects
+ * @since 2.5
+ * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-1172">LOG4J2-1172</a>
+ */
+ public void setUseThreadLocals(final boolean allow) {
+ useThreadLocalTranslator = allow;
+ LOGGER.trace("[{}] AsyncLoggers have been modified to use a {} translator", contextName,
+ useThreadLocalTranslator ? "threadlocal" : "vararg");
+ }
+}