You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2016/04/03 18:12:50 UTC

[1/3] logging-log4j2 git commit: LOG4J2-1343, LOG4J2-1344 added OutputStreamByteBufferDestinationAdapter

Repository: logging-log4j2
Updated Branches:
  refs/heads/LOG4J2-1344-gc-free-fileappender [created] a0ffd098e


LOG4J2-1343, LOG4J2-1344 added OutputStreamByteBufferDestinationAdapter


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

Branch: refs/heads/LOG4J2-1344-gc-free-fileappender
Commit: b7d783380d2d6445d33ff68471e7955ef96a3200
Parents: b77edb7
Author: rpopma <rp...@apache.org>
Authored: Mon Apr 4 00:10:55 2016 +0900
Committer: rpopma <rp...@apache.org>
Committed: Mon Apr 4 00:10:55 2016 +0900

----------------------------------------------------------------------
 .../apache/logging/log4j/core/util/Assert.java  |  7 ++
 ...utputStreamByteBufferDestinationAdapter.java | 80 ++++++++++++++++++++
 2 files changed, 87 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b7d78338/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Assert.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Assert.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Assert.java
index c7704e2..ff5b1e3 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Assert.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Assert.java
@@ -25,6 +25,13 @@ public final class Assert {
     private Assert() {
     }
 
+    public static int valueIsAtLeast(final int value, final int minValue) {
+        if (value < minValue) {
+            throw new IllegalArgumentException("Value should be at least " + minValue + " but was " + value);
+        }
+        return value;
+    }
+
     /**
      * Throws a {@code NullPointerException} if the specified parameter is
      * {@code null}, otherwise returns the specified parameter.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b7d78338/log4j-core/src/main/java/org/apache/logging/log4j/core/util/OutputStreamByteBufferDestinationAdapter.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/OutputStreamByteBufferDestinationAdapter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/OutputStreamByteBufferDestinationAdapter.java
new file mode 100644
index 0000000..c48582a
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/OutputStreamByteBufferDestinationAdapter.java
@@ -0,0 +1,80 @@
+/*
+ * 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.util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.Objects;
+
+import org.apache.logging.log4j.core.layout.ByteBufferDestination;
+import org.apache.logging.log4j.core.util.Assert;
+
+/**
+ * Adapts an OutputStream to the ByteBufferDestination interface.
+ *
+ * @see ByteBufferDestination
+ */
+public class OutputStreamByteBufferDestinationAdapter implements ByteBufferDestination {
+    private static final int DEFAULT_BUFFER_SIZE = 4 * 1024;
+    private final OutputStream out;
+    private final int bufferSize;
+    private ByteBuffer byteBuffer;
+
+    public OutputStreamByteBufferDestinationAdapter(final OutputStream out) {
+        this(out, DEFAULT_BUFFER_SIZE);
+    }
+
+    public OutputStreamByteBufferDestinationAdapter(final OutputStream out, final int bufferSize) {
+        this.out = Objects.requireNonNull(out);
+        this.bufferSize = Assert.valueIsAtLeast(bufferSize, 16);
+    }
+
+    @Override
+    public ByteBuffer getByteBuffer() {
+        if (byteBuffer == null) {
+            byteBuffer = ByteBuffer.wrap(new byte[bufferSize]);
+        }
+        return byteBuffer;
+    }
+
+    /**
+     * Writes any data in the specified {@code ByteBuffer} to the wrapped {@code OutputStream}, returning the specified
+     * {@code ByteBuffer}.
+     *
+     * @param buf the buffer to drain
+     * @return the specified ByteBuffer
+     */
+    @Override
+    public ByteBuffer drain(final ByteBuffer buf) {
+        buf.flip();
+        try {
+            out.write(buf.array(), 0, buf.limit());
+        } catch (final IOException ex) {
+            throw new IllegalStateException("Could not write " + buf.limit() + " bytes to " + out, ex);
+        }
+        buf.clear();
+        return buf;
+    }
+
+    /**
+     * Writes any data remaining in the {@code ByteBuffer} to the {@code OutputStream}.
+     */
+    public void drain() {
+        drain(getByteBuffer());
+    }
+}


[3/3] logging-log4j2 git commit: LOG4J2-1344 initial gc-free version (draft)

Posted by rp...@apache.org.
LOG4J2-1344 initial gc-free version (draft)


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

Branch: refs/heads/LOG4J2-1344-gc-free-fileappender
Commit: a0ffd098ec5b985d70263df8ab6cfab5a77a5be4
Parents: 7aa4dc5
Author: rpopma <rp...@apache.org>
Authored: Mon Apr 4 01:12:42 2016 +0900
Committer: rpopma <rp...@apache.org>
Committed: Mon Apr 4 01:12:42 2016 +0900

----------------------------------------------------------------------
 .../log4j/core/appender/FileManager.java        | 21 +++++++++----
 .../appender/rolling/RollingFileManager.java    | 31 ++++++++++++++++----
 2 files changed, 41 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/a0ffd098/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FileManager.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FileManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FileManager.java
index 4de34ad..998695f 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FileManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FileManager.java
@@ -29,6 +29,9 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.layout.ByteBufferDestination;
+import org.apache.logging.log4j.core.util.Constants;
+import org.apache.logging.log4j.core.util.OutputStreamByteBufferDestinationAdapter;
 
 
 /**
@@ -45,8 +48,8 @@ public class FileManager extends OutputStreamManager {
 
     protected FileManager(final String fileName, final OutputStream os, final boolean append, final boolean locking,
             final String advertiseURI, final Layout<? extends Serializable> layout, final int bufferSize,
-            final boolean writeHeader) {
-        super(os, fileName, layout, writeHeader);
+            final boolean writeHeader, final ByteBufferDestination destination) {
+        super(os, fileName, layout, writeHeader, destination);
         this.isAppend = append;
         this.isLocking = locking;
         this.advertiseURI = advertiseURI;
@@ -126,7 +129,7 @@ public class FileManager extends OutputStreamManager {
     public boolean isLocking() {
         return isLocking;
     }
-    
+
     /**
      * Returns the buffer size to use if the appender was configured with BufferedIO=true, otherwise returns a negative
      * number.
@@ -202,13 +205,21 @@ public class FileManager extends OutputStreamManager {
             try {
                 os = new FileOutputStream(name, data.append);
                 int bufferSize = data.bufferSize;
+
+                ByteBufferDestination destination = null;
+
+                // if Constants.ENABLE_THREADLOCALS is true, we use ByteBufferDestination to buffer the data
                 if (data.bufferedIO) {
-                    os = new BufferedOutputStream(os, bufferSize);
+                    if (Constants.ENABLE_THREADLOCALS) {
+                        destination = new OutputStreamByteBufferDestinationAdapter(os, bufferSize);
+                    } else {
+                        os = new BufferedOutputStream(os, bufferSize);
+                    }
                 } else {
                     bufferSize = -1; // signals to RollingFileManager not to use BufferedOutputStream
                 }
                 return new FileManager(name, os, data.append, data.locking, data.advertiseURI, data.layout, bufferSize,
-                        writeHeader);
+                        writeHeader, destination);
             } catch (final FileNotFoundException ex) {
                 LOGGER.error("FileManager (" + name + ") " + ex, ex);
             }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/a0ffd098/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
index 81104e8..314093f 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
@@ -32,7 +32,10 @@ import org.apache.logging.log4j.core.appender.FileManager;
 import org.apache.logging.log4j.core.appender.ManagerFactory;
 import org.apache.logging.log4j.core.appender.rolling.action.AbstractAction;
 import org.apache.logging.log4j.core.appender.rolling.action.Action;
+import org.apache.logging.log4j.core.layout.ByteBufferDestination;
+import org.apache.logging.log4j.core.util.Constants;
 import org.apache.logging.log4j.core.util.Log4jThread;
+import org.apache.logging.log4j.core.util.OutputStreamByteBufferDestinationAdapter;
 
 /**
  * The Rolling File Manager.
@@ -57,8 +60,9 @@ public class RollingFileManager extends FileManager {
     protected RollingFileManager(final String fileName, final String pattern, final OutputStream os,
             final boolean append, final long size, final long time, final TriggeringPolicy triggeringPolicy,
             final RolloverStrategy rolloverStrategy, final String advertiseURI,
-            final Layout<? extends Serializable> layout, final int bufferSize, final boolean writeHeader) {
-        super(fileName, os, append, false, advertiseURI, layout, bufferSize, writeHeader);
+            final Layout<? extends Serializable> layout, final int bufferSize, final boolean writeHeader,
+            final ByteBufferDestination destination) {
+        super(fileName, os, append, false, advertiseURI, layout, bufferSize, writeHeader, destination);
         this.size = size;
         this.initialTime = time;
         this.triggeringPolicy = triggeringPolicy;
@@ -134,9 +138,16 @@ public class RollingFileManager extends FileManager {
 
     protected void createFileAfterRollover() throws IOException  {
         final OutputStream os = new FileOutputStream(getFileName(), isAppend());
-        if (getBufferSize() > 0) { // negative buffer size means no buffering
-            setOutputStream(new BufferedOutputStream(os, getBufferSize()));
+
+        if (getBufferSize() > 0) {
+            if (Constants.ENABLE_THREADLOCALS) {
+                byteBufferDestination.setOutputStream(os);
+                setOutputStream(os);
+            } else {
+                setOutputStream(new BufferedOutputStream(os, getBufferSize()));
+            }
         } else {
+            // Negative buffer size means no buffering.
             setOutputStream(os);
         }
     }
@@ -398,18 +409,26 @@ public class RollingFileManager extends FileManager {
             }
             final long size = data.append ? file.length() : 0;
 
+            ByteBufferDestination destination = null;
             OutputStream os;
             try {
                 os = new FileOutputStream(name, data.append);
                 int bufferSize = data.bufferSize;
+
+                // if Constants.ENABLE_THREADLOCALS is true,
+                // we use ByteBufferDestination to buffer the data
                 if (data.bufferedIO) {
-                    os = new BufferedOutputStream(os, bufferSize);
+                    if (Constants.ENABLE_THREADLOCALS) {
+                        destination = new OutputStreamByteBufferDestinationAdapter(os, bufferSize);
+                    } else {
+                        os = new BufferedOutputStream(os, bufferSize);
+                    }
                 } else {
                     bufferSize = -1; // negative buffer size signals bufferedIO was configured false
                 }
                 final long time = file.lastModified(); // LOG4J2-531 create file first so time has valid value
                 return new RollingFileManager(name, data.pattern, os, data.append, size, time, data.policy,
-                    data.strategy, data.advertiseURI, data.layout, bufferSize, writeHeader);
+                    data.strategy, data.advertiseURI, data.layout, bufferSize, writeHeader, destination);
             } catch (final FileNotFoundException ex) {
                 LOGGER.error("FileManager (" + name + ") " + ex, ex);
             }


[2/3] logging-log4j2 git commit: LOG4J2-1343 initial gc-free version

Posted by rp...@apache.org.
LOG4J2-1343 initial gc-free version


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

Branch: refs/heads/LOG4J2-1344-gc-free-fileappender
Commit: 7aa4dc5ae2b35309f2b84f2d17e4cb909848acc9
Parents: b7d7833
Author: rpopma <rp...@apache.org>
Authored: Mon Apr 4 01:12:02 2016 +0900
Committer: rpopma <rp...@apache.org>
Committed: Mon Apr 4 01:12:02 2016 +0900

----------------------------------------------------------------------
 .../appender/AbstractOutputStreamAppender.java  | 21 +++++++++++++++-----
 .../core/appender/OutputStreamManager.java      | 18 +++++++++++++++++
 2 files changed, 34 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7aa4dc5a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractOutputStreamAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractOutputStreamAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractOutputStreamAppender.java
index 7ed06d6..3b44efd 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractOutputStreamAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractOutputStreamAppender.java
@@ -20,10 +20,12 @@ import java.io.Serializable;
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.layout.ByteBufferDestination;
+import org.apache.logging.log4j.core.util.Constants;
 
 /**
  * Appends log events as bytes to a byte output stream. The stream encoding is defined in the layout.
- * 
+ *
  * @param <M> The kind of {@link OutputStreamManager} under management
  */
 public abstract class AbstractOutputStreamAppender<M extends OutputStreamManager> extends AbstractAppender {
@@ -41,7 +43,7 @@ public abstract class AbstractOutputStreamAppender<M extends OutputStreamManager
     /**
      * Instantiates a WriterAppender and set the output destination to a new {@link java.io.OutputStreamWriter}
      * initialized with <code>os</code> as its {@link java.io.OutputStream}.
-     * 
+     *
      * @param name The name of the Appender.
      * @param layout The layout to format the message.
      * @param manager The OutputStreamManager.
@@ -55,7 +57,7 @@ public abstract class AbstractOutputStreamAppender<M extends OutputStreamManager
 
     /**
      * Gets the immediate flush setting.
-     * 
+     *
      * @return immediate flush.
      */
     public boolean getImmediateFlush() {
@@ -64,7 +66,7 @@ public abstract class AbstractOutputStreamAppender<M extends OutputStreamManager
 
     /**
      * Gets the manager.
-     * 
+     *
      * @return the manager.
      */
     public M getManager() {
@@ -93,12 +95,21 @@ public abstract class AbstractOutputStreamAppender<M extends OutputStreamManager
      * <p>
      * Most subclasses of <code>AbstractOutputStreamAppender</code> will need to override this method.
      * </p>
-     * 
+     *
      * @param event The LogEvent.
      */
     @Override
     public void append(final LogEvent event) {
         try {
+            if (Constants.ENABLE_THREADLOCALS) {
+                final ByteBufferDestination destination = manager.getByteBufferDestination();
+                getLayout().encode(event, destination);
+                if (this.immediateFlush || event.isEndOfBatch()) {
+                    destination.drain(destination.getByteBuffer()); // write buffer to outputStream
+                    manager.flush();
+                }
+                return;
+            }
             final byte[] bytes = getLayout().toByteArray(event);
             if (bytes != null && bytes.length > 0) {
                 manager.write(bytes, this.immediateFlush || event.isEndOfBatch());

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7aa4dc5a/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 cb1813e..433c2e0 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
@@ -18,8 +18,11 @@ package org.apache.logging.log4j.core.appender;
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.util.Objects;
 
 import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.layout.ByteBufferDestination;
+import org.apache.logging.log4j.core.util.OutputStreamByteBufferDestinationAdapter;
 
 /**
  * Manages an OutputStream so that it can be shared by multiple Appenders and will
@@ -29,9 +32,15 @@ public class OutputStreamManager extends AbstractManager {
 
     private volatile OutputStream os;
     protected final Layout<?> layout;
+    protected final ByteBufferDestination byteBufferDestination;
 
     protected OutputStreamManager(final OutputStream os, final String streamName, final Layout<?> layout,
             final boolean writeHeader) {
+        this(os, streamName, layout, writeHeader, new OutputStreamByteBufferDestinationAdapter(os));
+    }
+
+    protected OutputStreamManager(final OutputStream os, final String streamName, final Layout<?> layout,
+            final boolean writeHeader, final ByteBufferDestination byteBufferDestination) {
         super(streamName);
         this.os = os;
         this.layout = layout;
@@ -45,6 +54,7 @@ public class OutputStreamManager extends AbstractManager {
                 }
             }
         }
+        this.byteBufferDestination = Objects.requireNonNull(byteBufferDestination, "byteBufferDestination");
     }
 
     /**
@@ -61,6 +71,10 @@ public class OutputStreamManager extends AbstractManager {
         return AbstractManager.getManager(name, factory, data);
     }
 
+    public ByteBufferDestination getByteBufferDestination() {
+        return byteBufferDestination;
+    }
+
     /**
      * Default hook to write footer during close.
      */
@@ -74,6 +88,10 @@ public class OutputStreamManager extends AbstractManager {
      * Writes the footer.
      */
     protected void writeFooter() {
+        // ensure all buffered data is written to the stream before writing footer
+        final ByteBufferDestination destination = getByteBufferDestination();
+        destination.drain(destination.getByteBuffer());
+
         if (layout == null) {
             return;
         }