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 2014/09/16 17:18:07 UTC
[3/4] git commit: various improvements and fixes in appender and
manager
various improvements and fixes in appender and manager
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/e751c22a
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/e751c22a
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/e751c22a
Branch: refs/heads/LOG4J2-431
Commit: e751c22af16e7b0c4a96932a9ede8ddf51426eb1
Parents: ebbe63a
Author: rpopma <rp...@apache.org>
Authored: Wed Sep 17 00:15:44 2014 +0900
Committer: rpopma <rp...@apache.org>
Committed: Wed Sep 17 00:15:44 2014 +0900
----------------------------------------------------------------------
.../core/appender/MemoryMappedFileAppender.java | 99 ++++++++++----------
.../core/appender/MemoryMappedFileManager.java | 41 +++++---
2 files changed, 78 insertions(+), 62 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e751c22a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/MemoryMappedFileAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/MemoryMappedFileAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/MemoryMappedFileAppender.java
index f0910b5..785c3da 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/MemoryMappedFileAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/MemoryMappedFileAppender.java
@@ -35,10 +35,10 @@ import org.apache.logging.log4j.core.util.Booleans;
import org.apache.logging.log4j.core.util.Integers;
/**
- * File Appender.
+ * Memory Mapped File Appender.
*/
@Plugin(name = "MemoryMappedFile", category = "Core", elementType = "appender", printObject = true)
-public final class MemoryMappedFileAppender extends AbstractOutputStreamAppender<RandomAccessFileManager> {
+public final class MemoryMappedFileAppender extends AbstractOutputStreamAppender<MemoryMappedFileManager> {
private static final long serialVersionUID = 1L;
@@ -46,13 +46,12 @@ public final class MemoryMappedFileAppender extends AbstractOutputStreamAppender
private Object advertisement;
private final Advertiser advertiser;
- private MemoryMappedFileAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
- final RandomAccessFileManager manager, final String filename, final boolean ignoreExceptions,
- final boolean immediateFlush, final Advertiser advertiser) {
+ private MemoryMappedFileAppender(final String name, final Layout<? extends Serializable> layout,
+ final Filter filter, final MemoryMappedFileManager manager, final String filename,
+ final boolean ignoreExceptions, final boolean immediateFlush, final Advertiser advertiser) {
super(name, layout, filter, ignoreExceptions, immediateFlush, manager);
if (advertiser != null) {
- final Map<String, String> configuration = new HashMap<String, String>(
- layout.getContentFormat());
+ final Map<String, String> configuration = new HashMap<String, String>(layout.getContentFormat());
configuration.putAll(manager.getContentFormat());
configuration.put("contentType", layout.getContentType());
configuration.put("name", name);
@@ -96,82 +95,82 @@ public final class MemoryMappedFileAppender extends AbstractOutputStreamAppender
public String getFileName() {
return this.fileName;
}
-
+
/**
- * Returns the size of the file manager's buffer.
- * @return the buffer size
+ * Returns the length of the memory mapped region.
+ *
+ * @return the length of the memory mapped region
*/
- public int getBufferSize() {
- return getManager().getBufferSize();
+ public int getRegionLength() {
+ return getManager().getRegionLength();
}
- // difference from standard File Appender:
- // locking is not supported and buffering cannot be switched off
/**
- * Create a File Appender.
+ * Create a Memory Mapped File Appender.
*
* @param fileName The name and path of the file.
- * @param append "True" if the file should be appended to, "false" if it
- * should be overwritten. The default is "true".
+ * @param append "True" if the file should be appended to, "false" if it should be overwritten. The default is
+ * "true".
* @param name The name of the Appender.
- * @param immediateFlush "true" if the contents should be flushed on every
- * write, "false" otherwise. The default is "true".
- * @param bufferSizeStr The buffer size, defaults to {@value RandomAccessFileManager#DEFAULT_BUFFER_SIZE}.
- * @param ignore If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise
- * they are propagated to the caller.
- * @param layout The layout to use to format the event. If no layout is
- * provided the default PatternLayout will be used.
+ * @param immediateFlush "true" if the contents should be flushed on every write, "false" otherwise. The default is
+ * "true".
+ * @param regionLengthStr The buffer size, defaults to {@value RandomAccessFileManager#DEFAULT_REGION=LENGTH}.
+ * @param ignore If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise they
+ * are propagated to the caller.
+ * @param layout The layout to use to format the event. If no layout is provided the default PatternLayout will be
+ * used.
* @param filter The filter, if any, to use.
- * @param advertise "true" if the appender configuration should be
- * advertised, "false" otherwise.
- * @param advertiseURI The advertised URI which can be used to retrieve the
- * file contents.
+ * @param advertise "true" if the appender configuration should be advertised, "false" otherwise.
+ * @param advertiseURI The advertised URI which can be used to retrieve the file contents.
* @param config The Configuration.
* @return The FileAppender.
*/
@PluginFactory
public static MemoryMappedFileAppender createAppender(
- @PluginAttribute("fileName") final String fileName,
- @PluginAttribute("append") final String append,
- @PluginAttribute("name") final String name,
- @PluginAttribute("immediateFlush") final String immediateFlush,
- @PluginAttribute("bufferSize") final String bufferSizeStr,
- @PluginAttribute("ignoreExceptions") final String ignore,
- @PluginElement("Layout") Layout<? extends Serializable> layout,
- @PluginElement("Filter") final Filter filter,
- @PluginAttribute("advertise") final String advertise,
- @PluginAttribute("advertiseURI") final String advertiseURI,
+ // @formatter:off
+ @PluginAttribute("fileName") final String fileName, //
+ @PluginAttribute("append") final String append, //
+ @PluginAttribute("name") final String name, //
+ @PluginAttribute("immediateFlush") final String immediateFlush, //
+ @PluginAttribute("regionLength") final String regionLengthStr, //
+ @PluginAttribute("ignoreExceptions") final String ignore, //
+ @PluginElement("Layout") Layout<? extends Serializable> layout, //
+ @PluginElement("Filter") final Filter filter, //
+ @PluginAttribute("advertise") final String advertise, //
+ @PluginAttribute("advertiseURI") final String advertiseURI, //
@PluginConfiguration final Configuration config) {
+ // @formatter:on
final boolean isAppend = Booleans.parseBoolean(append, true);
- final boolean isFlush = Booleans.parseBoolean(immediateFlush, true);
+ final boolean isForce = Booleans.parseBoolean(immediateFlush, true);
final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
final boolean isAdvertise = Boolean.parseBoolean(advertise);
- final int bufferSize = Integers.parseInt(bufferSizeStr, RandomAccessFileManager.DEFAULT_BUFFER_SIZE);
+ final int regionLength = Integers.parseInt(regionLengthStr, MemoryMappedFileManager.DEFAULT_REGION_LENGTH);
+ final int actualRegionLength = Integers.ceilingNextPowerOfTwo(regionLength);
+ if (regionLength != actualRegionLength) {
+ LOGGER.info("MemoryMappedAppender[{}] Rounded up region length from {} to next power of two: {}", name,
+ regionLength, actualRegionLength);
+ }
if (name == null) {
- LOGGER.error("No name provided for FileAppender");
+ LOGGER.error("No name provided for MemoryMappedFileAppender");
return null;
}
if (fileName == null) {
- LOGGER.error("No filename provided for FileAppender with name "
- + name);
+ LOGGER.error("No filename provided for MemoryMappedFileAppender with name " + name);
return null;
}
if (layout == null) {
layout = PatternLayout.createDefaultLayout();
}
- final RandomAccessFileManager manager = RandomAccessFileManager.getFileManager(
- fileName, isAppend, isFlush, bufferSize, advertiseURI, layout
- );
+ final MemoryMappedFileManager manager = MemoryMappedFileManager.getFileManager(fileName, isAppend, isForce,
+ actualRegionLength, advertiseURI, layout);
if (manager == null) {
return null;
}
- return new MemoryMappedFileAppender(
- name, layout, filter, manager, fileName, ignoreExceptions, isFlush,
- isAdvertise ? config.getAdvertiser() : null
- );
+ return new MemoryMappedFileAppender(name, layout, filter, manager, fileName, ignoreExceptions, isForce,
+ isAdvertise ? config.getAdvertiser() : null);
}
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e751c22a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/MemoryMappedFileManager.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/MemoryMappedFileManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/MemoryMappedFileManager.java
index 2a66d03..29f8c54 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/MemoryMappedFileManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/MemoryMappedFileManager.java
@@ -32,6 +32,7 @@ import java.util.HashMap;
import java.util.Map;
import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.util.Assert;
import org.apache.logging.log4j.core.util.Closer;
/**
@@ -39,14 +40,15 @@ import org.apache.logging.log4j.core.util.Closer;
* memory and writes to this memory region.
* <p>
*
+ * @see <a href="http://www.codeproject.com/Tips/683614/Things-to-Know-about-Memory-Mapped-File-in-Java">http://www.codeproject.com/Tips/683614/Things-to-Know-about-Memory-Mapped-File-in-Java</a>
* @see <a href="http://bugs.java.com/view_bug.do?bug_id=6893654">http://bugs.java.com/view_bug.do?bug_id=6893654</a>
* @see <a href="http://bugs.java.com/view_bug.do?bug_id=4724038">http://bugs.java.com/view_bug.do?bug_id=4724038</a>
* @see <a
* href="http://stackoverflow.com/questions/9261316/memory-mapped-mappedbytebuffer-or-direct-bytebuffer-for-db-implementation">http://stackoverflow.com/questions/9261316/memory-mapped-mappedbytebuffer-or-direct-bytebuffer-for-db-implementation</a>
- * @see <a href="http://www.codeproject.com/Tips/683614/Things-to-Know-about-Memory-Mapped-File-in-Java">http://www.codeproject.com/Tips/683614/Things-to-Know-about-Memory-Mapped-File-in-Java</a>
*
*/
public class MemoryMappedFileManager extends OutputStreamManager {
+ static final int DEFAULT_REGION_LENGTH = 32 * 1024 * 1024;
private static final MemoryMappedFileManagerFactory FACTORY = new MemoryMappedFileManagerFactory();
private final boolean isForce;
@@ -55,17 +57,19 @@ public class MemoryMappedFileManager extends OutputStreamManager {
private final RandomAccessFile randomAccessFile;
private final ThreadLocal<Boolean> isEndOfBatch = new ThreadLocal<Boolean>();
private MappedByteBuffer mappedBuffer;
+ private long mappingOffset;
protected MemoryMappedFileManager(final RandomAccessFile file, final String fileName, final OutputStream os,
final boolean force, final long position, final int regionLength, final String advertiseURI,
final Layout<? extends Serializable> layout) throws IOException {
super(os, fileName, layout);
this.isForce = force;
- this.randomAccessFile = file;
+ this.randomAccessFile = Assert.requireNonNull(file, "RandomAccessFile");
this.regionLength = regionLength;
this.advertiseURI = advertiseURI;
this.isEndOfBatch.set(Boolean.FALSE);
this.mappedBuffer = mmap(randomAccessFile.getChannel(), position, regionLength);
+ this.mappingOffset = position;
}
/**
@@ -73,16 +77,16 @@ public class MemoryMappedFileManager extends OutputStreamManager {
*
* @param fileName The name of the file to manage.
* @param append true if the file should be appended to, false if it should be overwritten.
- * @param isFlush true if the contents should be flushed to disk on every write
- * @param bufferSize The buffer size.
+ * @param isForce true if the contents should be flushed to disk on every write
+ * @param regionLength The mapped region length.
* @param advertiseURI the URI to use when advertising the file
* @param layout The layout.
* @return A MemoryMappedFileManager for the File.
*/
public static MemoryMappedFileManager getFileManager(final String fileName, final boolean append,
- final boolean isFlush, final int bufferSize, final String advertiseURI,
+ final boolean isForce, final int regionLength, final String advertiseURI,
final Layout<? extends Serializable> layout) {
- return (MemoryMappedFileManager) getManager(fileName, new FactoryData(append, isFlush, bufferSize,
+ return (MemoryMappedFileManager) getManager(fileName, new FactoryData(append, isForce, regionLength,
advertiseURI, layout), FACTORY);
}
@@ -98,7 +102,11 @@ public class MemoryMappedFileManager extends OutputStreamManager {
protected synchronized void write(final byte[] bytes, int offset, int length) {
super.write(bytes, offset, length); // writes to dummy output stream
- if (length > mappedBuffer.remaining()) {
+ while (length > mappedBuffer.remaining()) {
+ final int chunk = mappedBuffer.remaining();
+ mappedBuffer.put(bytes, offset, chunk);
+ offset += chunk;
+ length -= chunk;
remap();
}
mappedBuffer.put(bytes, offset, length);
@@ -108,13 +116,15 @@ public class MemoryMappedFileManager extends OutputStreamManager {
}
}
- private void remap() {
- final long position = mappedBuffer.position();
+ private synchronized void remap() {
+ final long offset = this.mappingOffset + mappedBuffer.position();
+ final int length = mappedBuffer.remaining() + regionLength;
try {
unsafeUnmap(mappedBuffer);
- final long newLength = randomAccessFile.length() + regionLength;
- randomAccessFile.setLength(newLength);
- mappedBuffer = mmap(randomAccessFile.getChannel(), position, regionLength);
+ final long fileLength = randomAccessFile.length() + regionLength;
+ randomAccessFile.setLength(fileLength);
+ mappedBuffer = mmap(randomAccessFile.getChannel(), offset, length);
+ mappingOffset = offset;
} catch (final Exception ex) {
LOGGER.error("Unable to remap " + getName() + ". " + ex);
}
@@ -127,7 +137,14 @@ public class MemoryMappedFileManager extends OutputStreamManager {
@Override
public synchronized void close() {
+ final long length = mappingOffset + mappedBuffer.position();
+ try {
+ unsafeUnmap(mappedBuffer);
+ } catch (Exception ex) {
+ LOGGER.error("Unable to unmap MappedBuffer " + getName() + ". " + ex);
+ }
try {
+ randomAccessFile.setLength(length);
randomAccessFile.close();
} catch (final IOException ex) {
LOGGER.error("Unable to close MemoryMappedFile " + getName() + ". " + ex);