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/12 18:33:42 UTC
[02/17] logging-log4j2 git commit: LOG4J2-1343 OutputStreamManager
now implements ByteBufferDestination
LOG4J2-1343 OutputStreamManager now implements ByteBufferDestination
- subclasses must pass a ByteBuffer to the constructor
- all write() operations get added to the buffer first before being flushed to the destination
- added separate methods for flushBuffer(), flushDestination() and writeToDestination(), subclasses may override
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/f29d6fd1
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/f29d6fd1
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/f29d6fd1
Branch: refs/heads/master
Commit: f29d6fd1e3ff852b7fa9fdf1a3b2bc2087591b31
Parents: 7c3aa06
Author: rpopma <rp...@apache.org>
Authored: Tue Apr 12 02:29:37 2016 +0900
Committer: rpopma <rp...@apache.org>
Committed: Tue Apr 12 02:29:37 2016 +0900
----------------------------------------------------------------------
.../core/appender/OutputStreamManager.java | 178 ++++++++++++-------
1 file changed, 112 insertions(+), 66 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f29d6fd1/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 aff8573..7379804 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
@@ -19,23 +19,38 @@ package org.apache.logging.log4j.core.appender;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+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.Constants;
/**
* Manages an OutputStream so that it can be shared by multiple Appenders and will
* allow appenders to reconfigure without requiring a new stream.
*/
-public class OutputStreamManager extends AbstractManager {
+public class OutputStreamManager extends AbstractManager implements ByteBufferDestination {
+ protected static final int DEFAULT_BUFFER_SIZE = 8 * 1024;
private volatile OutputStream os;
protected final Layout<?> layout;
- private ByteBufferDestination byteBufferDestination;
+ protected ByteBuffer byteBuffer;
protected OutputStreamManager(final OutputStream os, final String streamName, final Layout<?> layout,
final boolean writeHeader) {
+ this(os, streamName, layout, writeHeader, ByteBuffer.wrap(new byte[DEFAULT_BUFFER_SIZE]));
+ }
+
+ /**
+ *
+ * @param os
+ * @param streamName
+ * @param layout
+ * @param writeHeader
+ * @param byteBuffer
+ * @since 2.6
+ */
+ protected OutputStreamManager(final OutputStream os, final String streamName, final Layout<?> layout,
+ final boolean writeHeader, final ByteBuffer byteBuffer) {
super(streamName);
this.os = os;
this.layout = layout;
@@ -49,6 +64,7 @@ public class OutputStreamManager extends AbstractManager {
}
}
}
+ this.byteBuffer = Objects.requireNonNull(byteBuffer, "byteBuffer");
}
/**
@@ -114,6 +130,25 @@ public class OutputStreamManager extends AbstractManager {
}
/**
+ * Some output streams synchronize writes while others do not.
+ * @param bytes The serialized Log event.
+ * @throws AppenderLoggingException if an error occurs.
+ */
+ protected void write(final byte[] bytes) {
+ write(bytes, 0, bytes.length, false);
+ }
+
+ /**
+ * Some output streams synchronize writes while others do not.
+ * @param bytes The serialized Log event.
+ * @param immediateFlush If true, flushes after writing.
+ * @throws AppenderLoggingException if an error occurs.
+ */
+ protected void write(final byte[] bytes, boolean immediateFlush) {
+ write(bytes, 0, bytes.length, immediateFlush);
+ }
+
+ /**
* Some output streams synchronize writes while others do not. Synchronizing here insures that
* log events won't be intertwined.
* @param bytes The serialized Log event.
@@ -122,7 +157,6 @@ public class OutputStreamManager extends AbstractManager {
* @throws AppenderLoggingException if an error occurs.
*/
protected void write(final byte[] bytes, final int offset, final int length) {
- flushBuffer();
write(bytes, offset, length, false);
}
@@ -137,11 +171,32 @@ public class OutputStreamManager extends AbstractManager {
*/
protected synchronized void write(final byte[] bytes, final int offset, final int length, boolean immediateFlush) {
// System.out.println("write " + count);
+ if (length >= byteBuffer.capacity()) {
+ // if request length exceeds buffer capacity, flush the buffer and write the data directly
+ flush();
+ writeToDestination(bytes, offset, length);
+ } else {
+ if (length > byteBuffer.remaining()) {
+ flush();
+ }
+ byteBuffer.put(bytes, offset, length);
+ }
+ if (immediateFlush) {
+ flush();
+ }
+ }
+
+ /**
+ * Writes the specified section of the specified byte array to the stream.
+ *
+ * @param bytes the array containing data
+ * @param offset from where to write
+ * @param length how many bytes to write
+ * @since 2.6
+ */
+ protected synchronized void writeToDestination(final byte[] bytes, final int offset, final int length) {
try {
os.write(bytes, offset, length);
- if (immediateFlush) {
- os.flush();
- }
} catch (final IOException ex) {
final String msg = "Error writing to stream " + getName();
throw new AppenderLoggingException(msg, ex);
@@ -149,24 +204,40 @@ public class OutputStreamManager extends AbstractManager {
}
/**
- * Some output streams synchronize writes while others do not.
- * @param bytes The serialized Log event.
- * @throws AppenderLoggingException if an error occurs.
+ * Calls {@code flush()} on the underlying output stream.
+ * @since 2.6
*/
- protected void write(final byte[] bytes) {
- flushBuffer();
- write(bytes, 0, bytes.length, false);
+ protected synchronized void flushDestination() {
+ try {
+ os.flush();
+ } catch (final IOException ex) {
+ final String msg = "Error flushing stream " + getName();
+ throw new AppenderLoggingException(msg, ex);
+ }
}
/**
- * Some output streams synchronize writes while others do not.
- * @param bytes The serialized Log event.
- * @param immediateFlush If true, flushes after writing.
- * @throws AppenderLoggingException if an error occurs.
+ * Drains the ByteBufferDestination's buffer into the destination. By default this calls
+ * {@link OutputStreamManager#write(byte[], int, int, boolean)} with the buffer contents.
+ * The underlying stream is not {@linkplain OutputStream#flush() flushed}.
+ *
+ * @see #flushDestination()
+ * @since 2.6
*/
- protected void write(final byte[] bytes, boolean immediateFlush) {
- flushBuffer();
- write(bytes, 0, bytes.length, immediateFlush);
+ protected synchronized void flushBuffer(final ByteBuffer buf) {
+ buf.flip();
+ if (buf.limit() > 0) {
+ writeToDestination(buf.array(), 0, buf.limit());
+ }
+ buf.clear();
+ }
+
+ /**
+ * Flushes any buffers.
+ */
+ public synchronized void flush() {
+ flushBuffer(byteBuffer);
+ flushDestination();
}
protected synchronized void close() {
@@ -183,60 +254,35 @@ public class OutputStreamManager extends AbstractManager {
}
/**
- * Flushes any buffers.
+ * Returns this {@code ByteBufferDestination}'s buffer.
+ * @return the buffer
+ * @since 2.6
*/
- public synchronized void flush() {
- try {
- flushBuffer();
- os.flush();
- } catch (final IOException ex) {
- final String msg = "Error flushing stream " + getName();
- throw new AppenderLoggingException(msg, ex);
- }
+ @Override
+ public ByteBuffer getByteBuffer() {
+ return byteBuffer;
}
/**
* Drains the ByteBufferDestination's buffer into the destination. By default this calls
- * {@link OutputStreamManager#write(byte[], int, int, boolean)} with the buffer contents and the Appender's
- * {@link AbstractOutputStreamAppender#immediateFlush} value.
+ * {@link #flushBuffer(ByteBuffer)} with the specified buffer. Subclasses may override.
* <p>
- * This method has no effect if the garbage-free Layout encode mechanism is not enabled.
+ * Do not call this method lightly! For some subclasses this is a very expensive operation. For example,
+ * {@link MemoryMappedFileManager} will assume this method was called because the end of the mapped region
+ * was reached during a text encoding operation and will {@linkplain MemoryMappedFileManager#remap() remap} its
+ * buffer.
+ * </p><p>
+ * To just flush the buffered contents to the underlying stream, call
+ * {@link #flushBuffer(ByteBuffer)} directly instead.
* </p>
- */
- protected void flushBuffer() {
- if (Constants.ENABLE_DIRECT_ENCODERS) {
- final ByteBufferDestination destination = getByteBufferDestination();
- synchronized (destination) {
- destination.drain(destination.getByteBuffer());
- }
- }
- }
-
- /**
- * Subclasses that do buffered IO should override.
- * @return this implementation always returns {@code false}
- */
- protected boolean isBufferedIO() {
- return false;
- }
-
- public ByteBufferDestination getByteBufferDestination() {
- return byteBufferDestination;
- }
-
- public void setByteBufferDestination(final ByteBufferDestination byteBufferDestination) {
- this.byteBufferDestination = byteBufferDestination;
- }
-
- /**
- * When the garbage-free Layout.encode mechanism is used, this method is called to create a ByteBufferDestination
- * for this OutputStreamManager.
*
- * @param immediateFlush the value to pass to the {@link #write(byte[], int, int, boolean)} method when the
- * ByteBufferDestination is {@link ByteBufferDestination#drain(ByteBuffer) drained}
- * @return a new ByteBufferDestination that drains into this OutputStreamManager
+ * @param buf the buffer whose contents to write the the destination
+ * @return the specified buffer
+ * @since 2.6
*/
- protected ByteBufferDestination createByteBufferDestination(final boolean immediateFlush) {
- return new OutputStreamManagerDestination(immediateFlush, this);
+ @Override
+ public ByteBuffer drain(final ByteBuffer buf) {
+ flushBuffer(buf);
+ return buf;
}
}