Repository: logging-log4j2
Updated Branches:
  refs/heads/master 4c587de33 -> 7060cc307


LOG4J2-2253 Added ParameterVisitableMessage.forEachParameter

This method allows us to iterate over parameters in a
ParameterVisitableMessage without array creation.


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

Branch: refs/heads/master
Commit: 41648dfa16a7176860e3af30b483e85775c48b9d
Parents: ae7f125
Author: Carter Kozak <c4kof...@gmail.com>
Authored: Wed Feb 14 14:48:00 2018 -0500
Committer: rpopma <rpo...@apache.org>
Committed: Mon Feb 26 19:03:43 2018 +0900

----------------------------------------------------------------------
 .../log4j/message/ParameterConsumer.java        | 26 +++++++++++++++++
 .../message/ParameterVisitableMessage.java      | 30 ++++++++++++++++++++
 .../log4j/message/ReusableObjectMessage.java    |  7 ++++-
 .../message/ReusableParameterizedMessage.java   | 10 ++++++-
 .../log4j/message/ReusableSimpleMessage.java    |  6 +++-
 .../ReusableParameterizedMessageTest.java       | 22 ++++++++++++++
 .../log4j/core/async/RingBufferLogEvent.java    | 17 +++++++----
 .../log4j/core/impl/MutableLogEvent.java        | 11 ++++++-
 .../core/async/RingBufferLogEventTest.java      | 12 ++++++++
 9 files changed, 131 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/41648dfa/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterConsumer.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterConsumer.java
 
b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterConsumer.java
new file mode 100644
index 0000000..ff8c148
--- /dev/null
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterConsumer.java
@@ -0,0 +1,26 @@
+package org.apache.logging.log4j.message;
+
+/**
+ * An operation that accepts two input arguments and returns no result.
+ *
+ * <p>
+ * The third parameter lets callers pass in a stateful object to be modified 
with the key-value pairs,
+ * so the ParameterConsumer implementation itself can be stateless and 
potentially reusable.
+ * </p>
+ *
+ * @param <S> state data
+ * @see ReusableMessage
+ * @since 2.11
+ */
+public interface ParameterConsumer<S> {
+
+    /**
+     * Performs an operation given the specified arguments.
+     *
+     * @param parameter the parameter
+     * @param parameterIndex Index of the parameter
+     * @param state
+     */
+    void accept(Object parameter, short parameterIndex, S state);
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/41648dfa/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterVisitableMessage.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterVisitableMessage.java
 
b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterVisitableMessage.java
new file mode 100644
index 0000000..5cb6228
--- /dev/null
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterVisitableMessage.java
@@ -0,0 +1,30 @@
+package org.apache.logging.log4j.message;
+
+import org.apache.logging.log4j.util.PerformanceSensitive;
+
+/**
+ * Allows message parameters to be iterated over without any allocation
+ * or memory copies.
+ *
+ * @since 2.11
+ */
+@PerformanceSensitive("allocation")
+public interface ParameterVisitableMessage extends Message {
+
+    /**
+     * Performs the given action for each parameter until all values
+     * have been processed or the action throws an exception.
+     * <p>
+     * The second parameter lets callers pass in a stateful object to be 
modified with the key-value pairs,
+     * so the TriConsumer implementation itself can be stateless and 
potentially reusable.
+     * </p>
+     *
+     * @param action The action to be performed for each key-value pair in 
this collection
+     * @param state the object to be passed as the third parameter to each 
invocation on the
+     *          specified ParameterConsumer.
+     * @param <S> type of the third parameter
+     * @since 2.11
+     */
+    <S> void forEachParameter(ParameterConsumer<S> action, S state);
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/41648dfa/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java
 
b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java
index c4ffa22..603381f 100644
--- 
a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java
@@ -24,7 +24,7 @@ import org.apache.logging.log4j.util.StringBuilders;
  * @since 2.6
  */
 @PerformanceSensitive("allocation")
-public class ReusableObjectMessage implements ReusableMessage {
+public class ReusableObjectMessage implements ReusableMessage, 
ParameterVisitableMessage {
     private static final long serialVersionUID = 6922476812535519960L;
 
     private transient Object obj;
@@ -113,6 +113,11 @@ public class ReusableObjectMessage implements 
ReusableMessage {
     }
 
     @Override
+    public <S> void forEachParameter(ParameterConsumer<S> action, S state) {
+        action.accept(obj, (short) 0, state);
+    }
+
+    @Override
     public Message memento() {
         return new ObjectMessage(obj);
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/41648dfa/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
 
b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
index daf2994..55a079c 100644
--- 
a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
@@ -30,7 +30,7 @@ import org.apache.logging.log4j.util.StringBuilders;
  * @since 2.6
  */
 @PerformanceSensitive("allocation")
-public class ReusableParameterizedMessage implements ReusableMessage {
+public class ReusableParameterizedMessage implements ReusableMessage, 
ParameterVisitableMessage {
 
     private static final int MIN_BUILDER_SIZE = 512;
     private static final int MAX_PARMS = 10;
@@ -105,6 +105,14 @@ public class ReusableParameterizedMessage implements 
ReusableMessage {
     }
 
     @Override
+    public <S> void forEachParameter(ParameterConsumer<S> action, S state) {
+        Object[] parameters = getParams();
+        for (short i = 0; i < argCount; i++) {
+            action.accept(parameters[i], i, state);
+        }
+    }
+
+    @Override
     public Message memento() {
         return new ParameterizedMessage(messagePattern, getTrimmedParams());
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/41648dfa/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java
 
b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java
index 905b694..03c290a 100644
--- 
a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java
@@ -23,7 +23,7 @@ import org.apache.logging.log4j.util.PerformanceSensitive;
  * @since 2.6
  */
 @PerformanceSensitive("allocation")
-public class ReusableSimpleMessage implements ReusableMessage, CharSequence {
+public class ReusableSimpleMessage implements ReusableMessage, CharSequence, 
ParameterVisitableMessage {
     private static final long serialVersionUID = -9199974506498249809L;
     private static Object[] EMPTY_PARAMS = new Object[0];
     private CharSequence charSequence;
@@ -81,6 +81,10 @@ public class ReusableSimpleMessage implements 
ReusableMessage, CharSequence {
     }
 
     @Override
+    public <S> void forEachParameter(ParameterConsumer<S> action, S state) {
+    }
+
+    @Override
     public Message memento() {
         return new SimpleMessage(charSequence);
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/41648dfa/log4j-api/src/test/java/org/apache/logging/log4j/message/ReusableParameterizedMessageTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/test/java/org/apache/logging/log4j/message/ReusableParameterizedMessageTest.java
 
b/log4j-api/src/test/java/org/apache/logging/log4j/message/ReusableParameterizedMessageTest.java
index b25735c..38f157d 100644
--- 
a/log4j-api/src/test/java/org/apache/logging/log4j/message/ReusableParameterizedMessageTest.java
+++ 
b/log4j-api/src/test/java/org/apache/logging/log4j/message/ReusableParameterizedMessageTest.java
@@ -19,6 +19,9 @@ package org.apache.logging.log4j.message;
 import org.apache.logging.log4j.junit.Mutable;
 import org.junit.Test;
 
+import java.util.LinkedList;
+import java.util.List;
+
 import static org.junit.Assert.*;
 
 /**
@@ -144,4 +147,23 @@ public class ReusableParameterizedMessageTest {
         msg.set(testMsg, "msgs", EXCEPTION2);
         assertSame(EXCEPTION2, msg.getThrowable());
     }
+
+    @Test
+    public void testParameterConsumer() {
+        final String testMsg = "Test message {}";
+        final ReusableParameterizedMessage msg = new 
ReusableParameterizedMessage();
+        final Throwable EXCEPTION1 = new IllegalAccessError("#1");
+        msg.set(testMsg, "msg", EXCEPTION1);
+        List<Object> expected = new LinkedList<>();
+        expected.add("msg");
+        expected.add(EXCEPTION1);
+        final List<Object> actual = new LinkedList<>();
+        msg.forEachParameter(new ParameterConsumer<Void>() {
+            @Override
+            public void accept(Object parameter, short parameterIndex, Void 
state) {
+                actual.add(parameter);
+            }
+        }, null);
+        assertEquals(expected, actual);
+    }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/41648dfa/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
index 0a2964d..4fee2ef 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
@@ -32,11 +32,7 @@ import org.apache.logging.log4j.core.time.NanoClock;
 import org.apache.logging.log4j.core.util.*;
 import org.apache.logging.log4j.core.time.Instant;
 import org.apache.logging.log4j.core.time.MutableInstant;
-import org.apache.logging.log4j.message.Message;
-import org.apache.logging.log4j.message.ParameterizedMessage;
-import org.apache.logging.log4j.message.ReusableMessage;
-import org.apache.logging.log4j.message.SimpleMessage;
-import org.apache.logging.log4j.message.TimestampMessage;
+import org.apache.logging.log4j.message.*;
 import org.apache.logging.log4j.util.ReadOnlyStringMap;
 import org.apache.logging.log4j.util.StringBuilders;
 import org.apache.logging.log4j.util.StringMap;
@@ -48,7 +44,7 @@ import com.lmax.disruptor.EventFactory;
  * When the Disruptor is started, the RingBuffer is populated with event 
objects. These objects are then re-used during
  * the life of the RingBuffer.
  */
-public class RingBufferLogEvent implements LogEvent, ReusableMessage, 
CharSequence {
+public class RingBufferLogEvent implements LogEvent, ReusableMessage, 
CharSequence, ParameterVisitableMessage {
 
     /** The {@code EventFactory} for {@code RingBufferLogEvent}s. */
     public static final Factory FACTORY = new Factory();
@@ -284,6 +280,15 @@ public class RingBufferLogEvent implements LogEvent, 
ReusableMessage, CharSequen
     }
 
     @Override
+    public <S> void forEachParameter(ParameterConsumer<S> action, S state) {
+        if (parameters != null) {
+            for (short i = 0; i < parameterCount; i++) {
+                action.accept(parameters[i], i, state);
+            }
+        }
+    }
+
+    @Override
     public Message memento() {
         if (message != null) {
             return message;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/41648dfa/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
index b427c4a..b5993fe 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
@@ -42,7 +42,7 @@ import org.apache.logging.log4j.util.Strings;
  * Mutable implementation of the {@code LogEvent} interface.
  * @since 2.6
  */
-public class MutableLogEvent implements LogEvent, ReusableMessage {
+public class MutableLogEvent implements LogEvent, ReusableMessage, 
ParameterVisitableMessage {
     private static final Message EMPTY = new SimpleMessage(Strings.EMPTY);
 
     private int threadPriority;
@@ -254,6 +254,15 @@ public class MutableLogEvent implements LogEvent, 
ReusableMessage {
         return parameters == null ? null : Arrays.copyOf(parameters, 
parameterCount);
     }
 
+    @Override
+    public <S> void forEachParameter(ParameterConsumer<S> action, S state) {
+        if (parameters != null) {
+            for (short i = 0; i < parameterCount; i++) {
+                action.accept(parameters[i], i, state);
+            }
+        }
+    }
+
     /**
      * @see ReusableMessage#getThrowable()
      */

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/41648dfa/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java
index cc50b42..fdc03d4 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java
@@ -32,6 +32,7 @@ import org.apache.logging.log4j.categories.AsyncLoggers;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.time.internal.DummyNanoClock;
 import org.apache.logging.log4j.core.time.internal.FixedPreciseClock;
+import org.apache.logging.log4j.message.ParameterConsumer;
 import org.apache.logging.log4j.util.FilteredObjectInputStream;
 import org.apache.logging.log4j.util.StringMap;
 import org.apache.logging.log4j.core.impl.ThrowableProxy;
@@ -189,4 +190,15 @@ public class RingBufferLogEventTest {
             fail("the messageText field was not set");
         }
     }
+
+    @Test
+    public void testForEachParameterNothingSet() {
+        final RingBufferLogEvent evt = new RingBufferLogEvent();
+        evt.forEachParameter(new ParameterConsumer<Void>() {
+            @Override
+            public void accept(Object parameter, short parameterIndex, Void 
state) {
+                fail("Should not have been called");
+            }
+        }, null);
+    }
 }

Reply via email to