Repository: logging-log4j2
Updated Branches:
  refs/heads/master 8025bb18c -> 6f02c4487


LOG4J2-1121 initial version of ReliabilityStrategy interface and
implementations

Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/1596a6fe
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/1596a6fe
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/1596a6fe

Branch: refs/heads/master
Commit: 1596a6fef1b9b6ea039b6299a24432aeff3abd88
Parents: 01d11a7
Author: rpopma <[email protected]>
Authored: Sun Sep 20 05:23:28 2015 +0900
Committer: rpopma <[email protected]>
Committed: Sun Sep 20 05:23:28 2015 +0900

----------------------------------------------------------------------
 .../AwaitCompletionReliabilityStrategy.java     | 156 +++++++++++++++++++
 .../core/config/DefaultReliabilityStrategy.java | 103 ++++++++++++
 .../log4j/core/config/ReliabilityStrategy.java  |  72 +++++++++
 3 files changed, 331 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1596a6fe/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AwaitCompletionReliabilityStrategy.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AwaitCompletionReliabilityStrategy.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AwaitCompletionReliabilityStrategy.java
new file mode 100644
index 0000000..fc75031
--- /dev/null
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AwaitCompletionReliabilityStrategy.java
@@ -0,0 +1,156 @@
+/*
+ * 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.config;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.util.Supplier;
+
+/**
+ * Object responsible for ensuring log events are delivered to a working 
appender, even during or after a
+ * reconfiguration.
+ */
+public class AwaitCompletionReliabilityStrategy implements ReliabilityStrategy 
{
+    private static final int MAX_RETRIES = 3;
+    private final AtomicInteger counter = new AtomicInteger();
+    private final AtomicBoolean shutdown = new AtomicBoolean(false);
+    private final Lock shutdownLock = new ReentrantLock();
+    private final Condition noLogEvents = shutdownLock.newCondition(); // 
should only be used when shutdown == true
+    private final LoggerConfig loggerConfig;
+
+    public AwaitCompletionReliabilityStrategy(final LoggerConfig loggerConfig) 
{
+        this.loggerConfig = loggerConfig;
+    }
+
+    /* (non-Javadoc)
+     * @see 
org.apache.logging.log4j.core.config.ReliabilityStrategy#log(org.apache.logging.log4j.util.Supplier,
 java.lang.String, java.lang.String, org.apache.logging.log4j.Marker, 
org.apache.logging.log4j.Level, org.apache.logging.log4j.message.Message, 
java.lang.Throwable)
+     */
+    @Override
+    public void log(final Supplier<LoggerConfig> reconfigured, final String 
loggerName, final String fqcn,
+            final Marker marker, final Level level, final Message data, final 
Throwable t) {
+
+        final LoggerConfig config = getActiveLoggerConfig(reconfigured);
+        try {
+            config.log(loggerName, fqcn, marker, level, data, t);
+        } finally {
+            config.getReliabilityStrategy().afterLogEvent();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see 
org.apache.logging.log4j.core.config.ReliabilityStrategy#log(org.apache.logging.log4j.util.Supplier,
 org.apache.logging.log4j.core.LogEvent)
+     */
+    @Override
+    public void log(final Supplier<LoggerConfig> reconfigured, final LogEvent 
event) {
+        final LoggerConfig config = getActiveLoggerConfig(reconfigured);
+        try {
+            config.log(event);
+        } finally {
+            config.getReliabilityStrategy().afterLogEvent();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see 
org.apache.logging.log4j.core.config.ReliabilityStrategy#beforeLogEvent(org.apache.logging.log4j.core.config.LoggerConfig,
 org.apache.logging.log4j.util.Supplier)
+     */
+    @Override
+    public LoggerConfig getActiveLoggerConfig(final Supplier<LoggerConfig> 
next) {
+        LoggerConfig result = this.loggerConfig;
+        if (!beforeLogEvent()) {
+            result = next.get();
+            return result.getReliabilityStrategy().getActiveLoggerConfig(next);
+        }
+        return result;
+    }
+
+    private boolean beforeLogEvent() {
+        return counter.incrementAndGet() > 0;
+    }
+
+    public void afterLogEvent() {
+        if (counter.decrementAndGet() == 0 && shutdown.get()) {
+            signalCompletionIfShutdown();
+        }
+    }
+
+    private void signalCompletionIfShutdown() {
+        final Lock lock = shutdownLock;
+        lock.lock();
+        try {
+            noLogEvents.signalAll();
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see 
org.apache.logging.log4j.core.config.ReliabilityStrategy#beforeStopAppenders()
+     */
+    @Override
+    public void beforeStopAppenders() {
+        waitForCompletion();
+    }
+
+    /**
+     * Waits for all log events to complete before returning.
+     */
+    private void waitForCompletion() {
+        shutdownLock.lock();
+        try {
+            if (shutdown.compareAndSet(false, true)) {
+                int retries = 0;
+                // while (counter.get() > 0) {
+                while (!counter.compareAndSet(0, Integer.MIN_VALUE)) {
+
+                    // counter was non-zero
+                    if (counter.get() < 0) { // this should not happen
+                        return; // but if it does, we are already done
+                    }
+                    // counter greater than zero, wait for afterLogEvent to 
decrease count
+                    try {
+                        noLogEvents.await(retries + 1, TimeUnit.SECONDS);
+                    } catch (final InterruptedException ie) {
+                        if (++retries > MAX_RETRIES) {
+                            break;
+                        }
+                    }
+                }
+            }
+        } finally {
+            shutdownLock.unlock();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see 
org.apache.logging.log4j.core.config.ReliabilityStrategy#beforeStopConfiguration(org.apache.logging.log4j.core.config.Configuration)
+     */
+    @Override
+    public void beforeStopConfiguration(Configuration configuration) {
+        // no action
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1596a6fe/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultReliabilityStrategy.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultReliabilityStrategy.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultReliabilityStrategy.java
new file mode 100644
index 0000000..3ffc127
--- /dev/null
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultReliabilityStrategy.java
@@ -0,0 +1,103 @@
+/*
+ * 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.config;
+
+import java.util.Objects;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.util.Supplier;
+
+/**
+ * Reliability strategy that does nothing.
+ */
+public class DefaultReliabilityStrategy implements ReliabilityStrategy {
+
+    private final LoggerConfig loggerConfig;
+
+    public DefaultReliabilityStrategy(final LoggerConfig loggerConfig) {
+        this.loggerConfig = Objects.requireNonNull(loggerConfig, "loggerConfig 
is null");
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see 
org.apache.logging.log4j.core.config.ReliabilityStrategy#log(org.apache.logging.log4j.util.Supplier,
+     * java.lang.String, java.lang.String, org.apache.logging.log4j.Marker, 
org.apache.logging.log4j.Level,
+     * org.apache.logging.log4j.message.Message, java.lang.Throwable)
+     */
+    @Override
+    public void log(Supplier<LoggerConfig> reconfigured, String loggerName, 
String fqcn, Marker marker, Level level,
+            Message data, Throwable t) {
+        loggerConfig.log(loggerName, fqcn, marker, level, data, t);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see 
org.apache.logging.log4j.core.config.ReliabilityStrategy#log(org.apache.logging.log4j.util.Supplier,
+     * org.apache.logging.log4j.core.LogEvent)
+     */
+    @Override
+    public void log(Supplier<LoggerConfig> reconfigured, LogEvent event) {
+        loggerConfig.log(event);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * 
org.apache.logging.log4j.core.config.ReliabilityStrategy#beforeLogEvent(org.apache.logging.log4j.core.config.
+     * LoggerConfig, org.apache.logging.log4j.util.Supplier)
+     */
+    @Override
+    public LoggerConfig getActiveLoggerConfig(Supplier<LoggerConfig> next) {
+        return this.loggerConfig;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see 
org.apache.logging.log4j.core.config.ReliabilityStrategy#afterLogEvent()
+     */
+    @Override
+    public void afterLogEvent() {
+        // no action
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see 
org.apache.logging.log4j.core.config.ReliabilityStrategy#beforeStopAppenders()
+     */
+    @Override
+    public void beforeStopAppenders() {
+        // no action
+    }
+
+    /* (non-Javadoc)
+     * @see 
org.apache.logging.log4j.core.config.ReliabilityStrategy#beforeStopConfiguration(org.apache.logging.log4j.core.config.Configuration)
+     */
+    @Override
+    public void beforeStopConfiguration(Configuration configuration) {
+        // no action
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1596a6fe/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ReliabilityStrategy.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ReliabilityStrategy.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ReliabilityStrategy.java
new file mode 100644
index 0000000..76d8704
--- /dev/null
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ReliabilityStrategy.java
@@ -0,0 +1,72 @@
+/*
+ * 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.config;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.util.Supplier;
+
+/**
+ * Interface for objects that know how to ensure delivery of log events to the 
appropriate appenders, even during and
+ * after the configuration has been modified while the system is actively used.
+ */
+public interface ReliabilityStrategy {
+
+    /**
+     * Logs an event.
+     *
+     * @param loggerName The name of the Logger.
+     * @param fqcn The fully qualified class name of the caller.
+     * @param marker A Marker or null if none is present.
+     * @param level The event Level.
+     * @param data The Message.
+     * @param t A Throwable or null.
+     */
+    void log(Supplier<LoggerConfig> reconfigured, String loggerName, String 
fqcn, Marker marker,
+            Level level, Message data, Throwable t);
+
+    /**
+     * Logs an event.
+     *
+     * @param event The log event.
+     */
+    void log(Supplier<LoggerConfig> reconfigured, LogEvent event);
+
+    /**
+     * For internal use by the ReliabilityStrategy; returns the LoggerConfig 
to use.
+     * @param next
+     * @return
+     */
+    LoggerConfig getActiveLoggerConfig(Supplier<LoggerConfig> next);
+
+    void afterLogEvent();
+    
+    /**
+     * Called before all appenders are stopped.
+     */
+    void beforeStopAppenders();
+
+    /**
+     * 
+     * @param abstractConfiguration
+     */
+    void beforeStopConfiguration(Configuration configuration);
+
+}
\ No newline at end of file

Reply via email to