This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch api-queue
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 4fd515f7833d4c3e37a728106d34c8e34b5c0fa7
Author: Volkan Yazıcı <[email protected]>
AuthorDate: Tue Dec 12 12:45:09 2023 +0100

    Move JCTools-based queues in the API to a new module
---
 {log4j-api => log4j-api-queue-jctools}/pom.xml     | 41 +++++++------
 .../log4j/api/queue/JCToolsQueueFactory.java       | 37 +++++++++++
 log4j-api/pom.xml                                  | 11 +---
 .../logging/log4j/internal/QueueFactories.java     | 71 +++++++++-------------
 .../logging/log4j/internal/RecyclerFactories.java  |  4 +-
 .../apache/logging/log4j/status/StatusLogger.java  |  2 +-
 pom.xml                                            |  7 +++
 7 files changed, 99 insertions(+), 74 deletions(-)

diff --git a/log4j-api/pom.xml b/log4j-api-queue-jctools/pom.xml
similarity index 64%
copy from log4j-api/pom.xml
copy to log4j-api-queue-jctools/pom.xml
index 2ea9e66998..18dd10d906 100644
--- a/log4j-api/pom.xml
+++ b/log4j-api-queue-jctools/pom.xml
@@ -15,44 +15,45 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
   <modelVersion>4.0.0</modelVersion>
+
   <parent>
     <groupId>org.apache.logging.log4j</groupId>
     <artifactId>log4j</artifactId>
     <version>${revision}</version>
     <relativePath>../log4j-parent</relativePath>
   </parent>
-  <artifactId>log4j-api</artifactId>
-  <packaging>jar</packaging>
-  <name>Apache Log4j API</name>
-  <description>The Apache Log4j API</description>
+
+  <artifactId>log4j-api-queue-jctools</artifactId>
+  <name>Apache Log4j API queue provider (JCTools)</name>
+  <description>Provides JCTools-based queue implementations for the Apache 
Log4j API.</description>
+
   <properties>
-    <maven.javadoc.skip>false</maven.javadoc.skip>
+
+    <log4jParentDir>${basedir}/..</log4jParentDir>
 
     <!--
       ~ OSGi and JPMS options
       -->
-    <bnd-module-name>org.apache.logging.log4j</bnd-module-name>
-    <bnd-extra-package-options>
-      <!-- No JSR 305 at runtime -->
-      !javax.annotation.*,
-      <!-- Optional dependencies -->
-      org.jctools.*;resolution:=optional
-    </bnd-extra-package-options>
-    <bnd-extra-module-options>
-      <!-- No JSR 305 at runtime -->
-      jsr305;ignore=true,
-      <!-- Used in StringBuilders through reflection -->
-      java.sql;static=true
-    </bnd-extra-module-options>
+    
<bnd-module-name>org.apache.logging.log4j.api.queue.jctools</bnd-module-name>
+    <Fragment-Host>org.apache.logging.log4j.core</Fragment-Host>
 
   </properties>
+
   <dependencies>
+
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+    </dependency>
+
     <dependency>
       <groupId>org.jctools</groupId>
       <artifactId>jctools-core</artifactId>
-      <optional>true</optional>
     </dependency>
+
   </dependencies>
+
 </project>
diff --git 
a/log4j-api-queue-jctools/src/main/java/org/apache/logging/log4j/api/queue/JCToolsQueueFactory.java
 
b/log4j-api-queue-jctools/src/main/java/org/apache/logging/log4j/api/queue/JCToolsQueueFactory.java
new file mode 100644
index 0000000000..57a39e31f8
--- /dev/null
+++ 
b/log4j-api-queue-jctools/src/main/java/org/apache/logging/log4j/api/queue/JCToolsQueueFactory.java
@@ -0,0 +1,37 @@
+/*
+ * 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.api.queue;
+
+import aQute.bnd.annotation.spi.ServiceProvider;
+import java.util.Queue;
+import org.apache.logging.log4j.spi.QueueFactory;
+import org.jctools.queues.MpmcArrayQueue;
+
+/**
+ * A multi-producer-multi-consumer, thread-safe {@link QueueFactory} 
implementation based on <a 
href="https://jctools.github.io/JCTools/";>JCTools</a>.
+ */
+@ServiceProvider(QueueFactory.class)
+public final class JCToolsQueueFactory implements QueueFactory {
+
+    @Override
+    public <E> Queue<E> create(final int capacity) {
+        if (capacity < 1) {
+            throw new IllegalArgumentException("invalid capacity: " + 
capacity);
+        }
+        return new MpmcArrayQueue<>(capacity);
+    }
+}
diff --git a/log4j-api/pom.xml b/log4j-api/pom.xml
index 2ea9e66998..bb22c40e74 100644
--- a/log4j-api/pom.xml
+++ b/log4j-api/pom.xml
@@ -36,9 +36,7 @@
     <bnd-module-name>org.apache.logging.log4j</bnd-module-name>
     <bnd-extra-package-options>
       <!-- No JSR 305 at runtime -->
-      !javax.annotation.*,
-      <!-- Optional dependencies -->
-      org.jctools.*;resolution:=optional
+      !javax.annotation.*
     </bnd-extra-package-options>
     <bnd-extra-module-options>
       <!-- No JSR 305 at runtime -->
@@ -48,11 +46,4 @@
     </bnd-extra-module-options>
 
   </properties>
-  <dependencies>
-    <dependency>
-      <groupId>org.jctools</groupId>
-      <artifactId>jctools-core</artifactId>
-      <optional>true</optional>
-    </dependency>
-  </dependencies>
 </project>
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/internal/QueueFactories.java 
b/log4j-api/src/main/java/org/apache/logging/log4j/internal/QueueFactories.java
index 3d0313057b..b0275c4506 100644
--- 
a/log4j-api/src/main/java/org/apache/logging/log4j/internal/QueueFactories.java
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/internal/QueueFactories.java
@@ -16,67 +16,56 @@
  */
 package org.apache.logging.log4j.internal;
 
+import static org.apache.logging.log4j.util.LowLevelLogUtil.log;
+
+import aQute.bnd.annotation.spi.ServiceConsumer;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
+import java.util.List;
 import java.util.Queue;
+import java.util.ServiceLoader;
 import java.util.concurrent.ArrayBlockingQueue;
-import java.util.function.Supplier;
 import org.apache.logging.log4j.spi.QueueFactory;
 import org.apache.logging.log4j.util.Cast;
 import org.apache.logging.log4j.util.InternalApi;
 import org.apache.logging.log4j.util.LoaderUtil;
-import org.jctools.queues.MpmcArrayQueue;
+import org.apache.logging.log4j.util.ServiceLoaderUtil;
 
 /**
- * Provides {@link QueueFactory} instances for different use cases.
- * <p>
- * Implementations provided by <a 
href="https://jctools.github.io/JCTools/";>JCTools</a> will be preferred, if 
available at runtime.
- * Otherwise, {@link ArrayBlockingQueue} will be used.
- * </p>
+ * Provides the default {@link QueueFactory} instance.
  *
  * @since 3.0.0
  */
 @InternalApi
-public enum QueueFactories implements QueueFactory {
+@ServiceConsumer(QueueFactory.class)
+public final class QueueFactories {
 
     /**
-     * Provides a bounded queue for multi-producer/multi-consumer usage.
+     * The default {@link QueueFactory} instance.
      */
-    MPMC(() -> MpmcArrayQueue::new);
-
-    private final QueueFactory queueFactory;
-
-    QueueFactories(final Supplier<QueueFactory> queueFactoryProvider) {
-        this.queueFactory = getOrReplaceQueueFactory(queueFactoryProvider);
-    }
-
-    private static QueueFactory getOrReplaceQueueFactory(final 
Supplier<QueueFactory> queueFactoryProvider) {
-        try {
-            final QueueFactory queueFactory = queueFactoryProvider.get();
-            // Test with a large enough capacity to avoid any 
`IllegalArgumentExceptions` from trivial queues
-            queueFactory.create(16);
-            return queueFactory;
-        } catch (final LinkageError ignored) {
-            return ArrayBlockingQueueFactory.INSTANCE;
+    public static final QueueFactory INSTANCE = findInstance();
+
+    private static QueueFactory findInstance() {
+        final ServiceLoader<QueueFactory> serviceLoader =
+                ServiceLoader.load(QueueFactory.class, 
QueueFactory.class.getClassLoader());
+        final List<QueueFactory> factories =
+                ServiceLoaderUtil.safeStream(serviceLoader).toList();
+        if (factories.isEmpty()) {
+            return ArrayBlockingQueue::new;
+        } else {
+            final int factoryCount = factories.size();
+            if (factoryCount > 1) {
+                log("Log4j was expecting a single `QueueFactory` provider, 
found:");
+                for (int factoryIndex = 0; factoryIndex < factoryCount; 
factoryIndex++) {
+                    log((factoryIndex + 1) + ". `" + 
factories.get(factoryIndex) + "`");
+                }
+                log("Log4j will use the first `QueueFactory` provider as the 
default.");
+            }
+            return factories.get(0);
         }
     }
 
-    @Override
-    public <E> Queue<E> create(final int capacity) {
-        return queueFactory.create(capacity);
-    }
-
-    private static final class ArrayBlockingQueueFactory implements 
QueueFactory {
-
-        private static final ArrayBlockingQueueFactory INSTANCE = new 
ArrayBlockingQueueFactory();
-
-        private ArrayBlockingQueueFactory() {}
-
-        @Override
-        public <E> Queue<E> create(final int capacity) {
-            return new ArrayBlockingQueue<>(capacity);
-        }
-    }
+    private QueueFactories() {}
 
     /**
      * Creates a {@link QueueFactory} using the provided supplier.
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/internal/RecyclerFactories.java
 
b/log4j-api/src/main/java/org/apache/logging/log4j/internal/RecyclerFactories.java
index aea850f199..c7ec83a87a 100644
--- 
a/log4j-api/src/main/java/org/apache/logging/log4j/internal/RecyclerFactories.java
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/internal/RecyclerFactories.java
@@ -42,7 +42,7 @@ public final class RecyclerFactories {
      */
     public static final RecyclerFactory INSTANCE = isThreadLocalsEnabled()
             ? new ThreadLocalRecyclerFactory(CAPACITY)
-            : new QueueingRecyclerFactory(QueueFactories.MPMC, CAPACITY);
+            : new QueueingRecyclerFactory(QueueFactories.INSTANCE, CAPACITY);
 
     private RecyclerFactories() {}
 
@@ -146,7 +146,7 @@ public final class RecyclerFactories {
 
         // Execute the read spec
         final QueueFactory queueFactory =
-                supplierPath != null ? QueueFactories.ofSupplier(supplierPath) 
: QueueFactories.MPMC;
+                supplierPath != null ? QueueFactories.ofSupplier(supplierPath) 
: QueueFactories.INSTANCE;
         return new QueueingRecyclerFactory(queueFactory, capacity);
     }
 
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java 
b/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
index 7f0247ccef..d5134593ef 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
@@ -97,7 +97,7 @@ public final class StatusLogger extends AbstractLogger {
         this.logger = logger;
         this.configuration = configuration;
         this.listenersLevel = configuration.getDefaultLevel().intLevel();
-        messages = QueueFactories.MPMC.create(configuration.getMaxEntries());
+        messages = 
QueueFactories.INSTANCE.create(configuration.getMaxEntries());
     }
 
     /**
diff --git a/pom.xml b/pom.xml
index 3dcdfa03ce..8862927529 100644
--- a/pom.xml
+++ b/pom.xml
@@ -234,6 +234,7 @@
          Note that modules here must have a corresponding entry in 
`dependencyManagement > dependencies` block below! -->
     <module>log4j-1.2-api</module>
     <module>log4j-api</module>
+    <module>log4j-api-queue-jctools</module>
     <module>log4j-api-test</module>
     <module>log4j-appserver</module>
     <module>log4j-core</module>
@@ -356,6 +357,12 @@
         <version>${project.version}</version>
       </dependency>
 
+      <dependency>
+        <groupId>org.apache.logging.log4j</groupId>
+        <artifactId>log4j-api-queue-jctools</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+
       <dependency>
         <groupId>org.apache.logging.log4j</groupId>
         <artifactId>log4j-api-test</artifactId>

Reply via email to