From c6c9ddc67473ec3efde0f8e7e1e8bb0e87beeb5b Mon Sep 17 00:00:00 2001
From: "Michael A. McMahon"
Date: Tue, 29 Aug 2023 12:35:12 -0700
Subject: [PATCH 1/3] Check for common FJP having zero threads
---
.../java/oracle/r2dbc/OracleR2dbcOptions.java | 8 ++++---
.../impl/OracleConnectionFactoryImpl.java | 24 ++++++++++++++++++-
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/src/main/java/oracle/r2dbc/OracleR2dbcOptions.java b/src/main/java/oracle/r2dbc/OracleR2dbcOptions.java
index 682bf08..a6363c5 100644
--- a/src/main/java/oracle/r2dbc/OracleR2dbcOptions.java
+++ b/src/main/java/oracle/r2dbc/OracleR2dbcOptions.java
@@ -56,9 +56,11 @@ private OracleR2dbcOptions() {}
* ...
* .build();
*
- * If this option is not configured, then Oracle R2DBC will use
- * {@code ForkJoinPool}'s
- * {@linkplain ForkJoinPool#commonPool() common pool} by default.
+ * If this option is not configured, then Oracle R2DBC will
+ * use the {@linkplain ForkJoinPool#commonPool() common ForkJoinPool} by
+ * default. However, if the common {@code ForkJoinPool} has a maximum pool
+ * size that is potentially zero, then a single-threaded {@code Executor} will
+ * be used by default.
*/
public static final Option EXECUTOR;
diff --git a/src/main/java/oracle/r2dbc/impl/OracleConnectionFactoryImpl.java b/src/main/java/oracle/r2dbc/impl/OracleConnectionFactoryImpl.java
index 9019153..1b29eb7 100755
--- a/src/main/java/oracle/r2dbc/impl/OracleConnectionFactoryImpl.java
+++ b/src/main/java/oracle/r2dbc/impl/OracleConnectionFactoryImpl.java
@@ -102,6 +102,27 @@
*/
final class OracleConnectionFactoryImpl implements ConnectionFactory {
+ /**
+ *
+ * The default executor when {@link OracleR2dbcOptions#EXECUTOR} is not
+ * configured. It will use the common {@code ForkJoinPool}, unless it has
+ * a maximum pool size of 0. See:
+ * https://github.com/oracle/oracle-r2dbc/issues/129
+ *
+ * As of JDK 11, it appears that ForkJoinPool does not expose a
+ * maximum pool size. {@link ForkJoinPool#getCommonPoolParallelism()} and
+ * {@link ForkJoinPool#getParallelism()} will return 1 when the maximum pool
+ * size is 0. For this reason, the conditional below will check for a
+ * parallelism that is greater than 1, rather than 0. It is noted that
+ * {@code CompletableFuture} uses the same logic when initializing its
+ * USE_COMMON_POOL field.
+ *
+ */
+ private static final Executor DEFAULT_EXECUTOR =
+ ForkJoinPool.getCommonPoolParallelism() > 1
+ ? ForkJoinPool.commonPool()
+ : new ForkJoinPool(1);
+
/** JDBC data source that this factory uses to open connections */
private final DataSource dataSource;
@@ -200,7 +221,7 @@ final class OracleConnectionFactoryImpl implements ConnectionFactory {
Object executor = options.getValue(OracleR2dbcOptions.EXECUTOR);
if (executor == null) {
- this.executor = ForkJoinPool.commonPool();
+ this.executor = DEFAULT_EXECUTOR;
}
else if (executor instanceof Executor) {
this.executor = (Executor) executor;
@@ -267,4 +288,5 @@ public Publisher create() {
public ConnectionFactoryMetadata getMetadata() {
return () -> "Oracle Database";
}
+
}
From 53e5f71a2531315fef34c94d035f76d443e80cd5 Mon Sep 17 00:00:00 2001
From: "Michael A. McMahon"
Date: Tue, 29 Aug 2023 13:48:00 -0700
Subject: [PATCH 2/3] Reduce concurrency of concurrent tests.
---
src/test/java/oracle/r2dbc/impl/OracleStatementImplTest.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/test/java/oracle/r2dbc/impl/OracleStatementImplTest.java b/src/test/java/oracle/r2dbc/impl/OracleStatementImplTest.java
index eac9a04..59045cf 100644
--- a/src/test/java/oracle/r2dbc/impl/OracleStatementImplTest.java
+++ b/src/test/java/oracle/r2dbc/impl/OracleStatementImplTest.java
@@ -3222,7 +3222,7 @@ private void verifyConcurrentFetch(Connection connection) {
// Create many statements and execute them in parallel.
@SuppressWarnings({"unchecked","rawtypes"})
Publisher[] publishers =
- new Publisher[Runtime.getRuntime().availableProcessors() * 4];
+ new Publisher[Runtime.getRuntime().availableProcessors() * 2];
for (int i = 0; i < publishers.length; i++) {
From c801c10847f16f88fc09836e9ac7d1ef6358b292 Mon Sep 17 00:00:00 2001
From: Michael-A-McMahon
Date: Wed, 25 Oct 2023 12:09:29 -0700
Subject: [PATCH 3/3] Only check for 0 parallelism property
---
.../r2dbc/impl/OracleConnectionFactoryImpl.java | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/src/main/java/oracle/r2dbc/impl/OracleConnectionFactoryImpl.java b/src/main/java/oracle/r2dbc/impl/OracleConnectionFactoryImpl.java
index 1b29eb7..08b2a5a 100755
--- a/src/main/java/oracle/r2dbc/impl/OracleConnectionFactoryImpl.java
+++ b/src/main/java/oracle/r2dbc/impl/OracleConnectionFactoryImpl.java
@@ -108,20 +108,13 @@ final class OracleConnectionFactoryImpl implements ConnectionFactory {
* configured. It will use the common {@code ForkJoinPool}, unless it has
* a maximum pool size of 0. See:
* https://github.com/oracle/oracle-r2dbc/issues/129
- *
- * As of JDK 11, it appears that ForkJoinPool does not expose a
- * maximum pool size. {@link ForkJoinPool#getCommonPoolParallelism()} and
- * {@link ForkJoinPool#getParallelism()} will return 1 when the maximum pool
- * size is 0. For this reason, the conditional below will check for a
- * parallelism that is greater than 1, rather than 0. It is noted that
- * {@code CompletableFuture} uses the same logic when initializing its
- * USE_COMMON_POOL field.
*
*/
private static final Executor DEFAULT_EXECUTOR =
- ForkJoinPool.getCommonPoolParallelism() > 1
- ? ForkJoinPool.commonPool()
- : new ForkJoinPool(1);
+ "0".equals(System.getProperty(
+ "java.util.concurrent.ForkJoinPool.common.parallelism"))
+ ? new ForkJoinPool(1)
+ : ForkJoinPool.commonPool();
/** JDBC data source that this factory uses to open connections */
private final DataSource dataSource;