You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by pk...@apache.org on 2024/05/20 10:17:39 UTC
(logging-log4j2) branch feature/2.x/cleanup-thread-context2 updated: Add inheritability to `StringArrayThreadContextMap`
This is an automated email from the ASF dual-hosted git repository.
pkarwasz pushed a commit to branch feature/2.x/cleanup-thread-context2
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/feature/2.x/cleanup-thread-context2 by this push:
new 80cce5007a Add inheritability to `StringArrayThreadContextMap`
80cce5007a is described below
commit 80cce5007a00bcb6df317071f35b36dbacfd9e5b
Author: Piotr P. Karwasz <pi...@karwasz.org>
AuthorDate: Mon May 20 12:17:32 2024 +0200
Add inheritability to `StringArrayThreadContextMap`
---
.../log4j/core/context/ThreadContextMapTest.java | 4 +-
.../core/impl/ThreadContextDataInjectorTest.java | 2 +-
.../AbstractSortedArrayThreadContextMap.java | 3 +-
.../core/context/StringArrayThreadContextMap.java | 61 ++++++++++++++--------
4 files changed, 46 insertions(+), 24 deletions(-)
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/context/ThreadContextMapTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/context/ThreadContextMapTest.java
index 7f8e0fa5f9..aff6dd63a4 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/context/ThreadContextMapTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/context/ThreadContextMapTest.java
@@ -38,7 +38,9 @@ class ThreadContextMapTest extends AbstractThreadContextMapTest {
props.setProperty("log4j2.isThreadContextMapInheritable", "true");
final PropertiesUtil util = new PropertiesUtil(props);
return Stream.of(
- new CopyOnWriteSortedArrayThreadContextMap(util), new GarbageFreeSortedArrayThreadContextMap(util));
+ new StringArrayThreadContextMap(util),
+ new CopyOnWriteSortedArrayThreadContextMap(util),
+ new GarbageFreeSortedArrayThreadContextMap(util));
}
@ParameterizedTest
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjectorTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjectorTest.java
index efa723bad0..03c3be708f 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjectorTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjectorTest.java
@@ -52,7 +52,7 @@ public class ThreadContextDataInjectorTest {
return asList(new String[][] {
{"org.apache.logging.log4j.core.context.CopyOnWriteSortedArrayThreadContextMap"},
{"org.apache.logging.log4j.core.context.GarbageFreeSortedArrayThreadContextMap"},
- // {"org.apache.logging.log4j.core.context.StringArrayThreadContextMap"}
+ {"org.apache.logging.log4j.core.context.StringArrayThreadContextMap"}
});
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/context/AbstractSortedArrayThreadContextMap.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/context/AbstractSortedArrayThreadContextMap.java
index 508ce701f7..7dcf7d23b1 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/context/AbstractSortedArrayThreadContextMap.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/context/AbstractSortedArrayThreadContextMap.java
@@ -31,6 +31,7 @@ import org.jspecify.annotations.Nullable;
/**
* Commons base class for {@link StringMap}-based implementations of {@code ThreadContextMap}.
+ * @since 2.24.0
*/
public abstract class AbstractSortedArrayThreadContextMap implements ReadOnlyThreadContextMap, ObjectThreadContextMap {
@@ -38,7 +39,7 @@ public abstract class AbstractSortedArrayThreadContextMap implements ReadOnlyThr
* Property name ({@value} ) for selecting {@code InheritableThreadLocal} (value "true") or plain
* {@code ThreadLocal} (value is not "true") in the implementation.
*/
- public static final String INHERITABLE_MAP = "isThreadContextMapInheritable";
+ private static final String INHERITABLE_MAP = "isThreadContextMapInheritable";
/**
* The default initial capacity.
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/context/StringArrayThreadContextMap.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/context/StringArrayThreadContextMap.java
index 0416a00ef3..0fadf2304f 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/context/StringArrayThreadContextMap.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/context/StringArrayThreadContextMap.java
@@ -16,12 +16,14 @@
*/
package org.apache.logging.log4j.core.context;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import org.apache.logging.log4j.core.context.internal.UnmodifiableArrayBackedMap;
import org.apache.logging.log4j.spi.ThreadContextMap;
import org.apache.logging.log4j.util.BiConsumer;
+import org.apache.logging.log4j.util.PropertiesUtil;
import org.apache.logging.log4j.util.ReadOnlyStringMap;
import org.apache.logging.log4j.util.TriConsumer;
import org.jspecify.annotations.NullMarked;
@@ -41,31 +43,48 @@ import org.jspecify.annotations.Nullable;
public class StringArrayThreadContextMap implements ThreadContextMap, ReadOnlyStringMap {
private static final long serialVersionUID = -2635197170958057849L;
- private ThreadLocal<Object @Nullable []> threadLocalMapState;
+ /**
+ * Property name ({@value} ) for selecting {@code InheritableThreadLocal} (value "true") or plain
+ * {@code ThreadLocal} (value is not "true") in the implementation.
+ */
+ private static final String INHERITABLE_MAP = "isThreadContextMapInheritable";
+
+ private ThreadLocal<Object @Nullable []> localMap;
public StringArrayThreadContextMap() {
- threadLocalMapState = new ThreadLocal<>();
+ localMap = new ThreadLocal<>();
+ }
+
+ StringArrayThreadContextMap(final PropertiesUtil properties) {
+ localMap = properties.getBooleanProperty(INHERITABLE_MAP)
+ ? new InheritableThreadLocal<Object @Nullable []>() {
+ @Override
+ protected Object @Nullable [] childValue(final Object @Nullable [] parentValue) {
+ return parentValue != null ? Arrays.copyOf(parentValue, parentValue.length) : null;
+ }
+ }
+ : new ThreadLocal<>();
}
@Override
public void put(final String key, final String value) {
- final Object[] state = threadLocalMapState.get();
+ final Object[] state = localMap.get();
final UnmodifiableArrayBackedMap modifiedMap =
UnmodifiableArrayBackedMap.getInstance(state).copyAndPut(key, value);
- threadLocalMapState.set(modifiedMap.getBackingArray());
+ localMap.set(modifiedMap.getBackingArray());
}
@Override
public void putAll(final Map<String, String> m) {
- final Object[] state = threadLocalMapState.get();
+ final Object[] state = localMap.get();
final UnmodifiableArrayBackedMap modifiedMap =
UnmodifiableArrayBackedMap.getInstance(state).copyAndPutAll(m);
- threadLocalMapState.set(modifiedMap.getBackingArray());
+ localMap.set(modifiedMap.getBackingArray());
}
@Override
public @Nullable String get(final String key) {
- final Object[] state = threadLocalMapState.get();
+ final Object[] state = localMap.get();
if (state == null) {
return null;
}
@@ -74,27 +93,27 @@ public class StringArrayThreadContextMap implements ThreadContextMap, ReadOnlySt
@Override
public void remove(final String key) {
- final Object[] state = threadLocalMapState.get();
+ final Object[] state = localMap.get();
if (state != null) {
final UnmodifiableArrayBackedMap modifiedMap =
UnmodifiableArrayBackedMap.getInstance(state).copyAndRemove(key);
- threadLocalMapState.set(modifiedMap.getBackingArray());
+ localMap.set(modifiedMap.getBackingArray());
}
}
@Override
public void removeAll(final Iterable<String> keys) {
- final Object[] state = threadLocalMapState.get();
+ final Object[] state = localMap.get();
if (state != null) {
final UnmodifiableArrayBackedMap modifiedMap =
UnmodifiableArrayBackedMap.getInstance(state).copyAndRemoveAll(keys);
- threadLocalMapState.set(modifiedMap.getBackingArray());
+ localMap.set(modifiedMap.getBackingArray());
}
}
@Override
public void clear() {
- threadLocalMapState.remove();
+ localMap.remove();
}
@Override
@@ -104,13 +123,13 @@ public class StringArrayThreadContextMap implements ThreadContextMap, ReadOnlySt
@Override
public boolean containsKey(final String key) {
- final Object @Nullable [] state = threadLocalMapState.get();
+ final Object @Nullable [] state = localMap.get();
return (state != null && (UnmodifiableArrayBackedMap.getInstance(state)).containsKey(key));
}
@Override
public <V> void forEach(final BiConsumer<String, ? super V> action) {
- final Object[] state = threadLocalMapState.get();
+ final Object[] state = localMap.get();
if (state == null) {
return;
}
@@ -120,7 +139,7 @@ public class StringArrayThreadContextMap implements ThreadContextMap, ReadOnlySt
@Override
public <V, S> void forEach(final TriConsumer<String, ? super V, S> action, final S state) {
- final Object[] localState = threadLocalMapState.get();
+ final Object[] localState = localMap.get();
if (localState == null) {
return;
}
@@ -136,7 +155,7 @@ public class StringArrayThreadContextMap implements ThreadContextMap, ReadOnlySt
@Override
public Map<String, String> getCopy() {
- final Object[] state = threadLocalMapState.get();
+ final Object[] state = localMap.get();
if (state == null) {
return new HashMap<>(0);
}
@@ -145,7 +164,7 @@ public class StringArrayThreadContextMap implements ThreadContextMap, ReadOnlySt
@Override
public @Nullable Map<String, String> getImmutableMapOrNull() {
- final Object[] state = threadLocalMapState.get();
+ final Object[] state = localMap.get();
return (state == null ? null : UnmodifiableArrayBackedMap.getInstance(state));
}
@@ -156,13 +175,13 @@ public class StringArrayThreadContextMap implements ThreadContextMap, ReadOnlySt
@Override
public int size() {
- final Object[] state = threadLocalMapState.get();
+ final Object[] state = localMap.get();
return UnmodifiableArrayBackedMap.getInstance(state).size();
}
@Override
public String toString() {
- final Object[] state = threadLocalMapState.get();
+ final Object[] state = localMap.get();
return state == null
? "{}"
: UnmodifiableArrayBackedMap.getInstance(state).toString();
@@ -172,7 +191,7 @@ public class StringArrayThreadContextMap implements ThreadContextMap, ReadOnlySt
public int hashCode() {
final int prime = 31;
int result = 1;
- final Object[] state = threadLocalMapState.get();
+ final Object[] state = localMap.get();
result = prime * result
+ ((state == null)
? 0
@@ -192,7 +211,7 @@ public class StringArrayThreadContextMap implements ThreadContextMap, ReadOnlySt
return false;
}
final ThreadContextMap other = (ThreadContextMap) obj;
- final Map<String, String> map = UnmodifiableArrayBackedMap.getInstance(this.threadLocalMapState.get());
+ final Map<String, String> map = UnmodifiableArrayBackedMap.getInstance(this.localMap.get());
final Map<String, String> otherMap = other.getImmutableMapOrNull();
return Objects.equals(map, otherMap);
}