From 8b081463c681d37ecaeca137141d997d53823a5b Mon Sep 17 00:00:00 2001 From: Evgenij Ryazanov Date: Mon, 7 Aug 2023 21:38:07 +0800 Subject: [PATCH 1/2] Add possibility to enable virtual worker threads in TCP, Web, and PG servers on Java 21+ --- h2/pom.xml | 4 ++ .../precompiled/org/h2/util/Utils21.class | Bin 0 -> 808 bytes h2/src/java21/src/org/h2/util/Utils21.java | 36 ++++++++++++++++ h2/src/java21/src/org/h2/util/package.html | 14 ++++++ h2/src/main/org/h2/server/TcpServer.java | 15 ++++++- h2/src/main/org/h2/server/pg/PgServer.java | 15 ++++++- h2/src/main/org/h2/server/web/WebServer.java | 3 ++ h2/src/main/org/h2/server/web/WebThread.java | 4 +- h2/src/main/org/h2/tools/Console.java | 6 +++ h2/src/main/org/h2/tools/Server.java | 12 ++++++ h2/src/main/org/h2/util/Utils21.java | 40 ++++++++++++++++++ h2/src/main/org/h2/value/Value.java | 2 +- h2/src/tools/org/h2/build/Build.java | 4 ++ h2/src/tools/org/h2/build/doc/dictionary.txt | 2 +- 14 files changed, 150 insertions(+), 7 deletions(-) create mode 100644 h2/src/java21/precompiled/org/h2/util/Utils21.class create mode 100644 h2/src/java21/src/org/h2/util/Utils21.java create mode 100644 h2/src/java21/src/org/h2/util/package.html create mode 100644 h2/src/main/org/h2/util/Utils21.java diff --git a/h2/pom.xml b/h2/pom.xml index 55324f29c8..59be36c917 100644 --- a/h2/pom.xml +++ b/h2/pom.xml @@ -232,6 +232,10 @@ src/java10/precompiled META-INF/versions/10 + + src/java21/precompiled + META-INF/versions/21 + diff --git a/h2/src/java21/precompiled/org/h2/util/Utils21.class b/h2/src/java21/precompiled/org/h2/util/Utils21.class new file mode 100644 index 0000000000000000000000000000000000000000..65e131486e5abe6aaadcdb9beb9de50e9daa587b GIT binary patch literal 808 zcmah{*>2N76g@X_?ASGJNf*l2LP(3#2doy}QX!=aB9cX=G|6i8^ce3kdsUNs~K9b!X z!s?*Y?e*K8;J1C?M-4S#*O{V55_WX9KRj-ahi#s zHHRup1D1_B*o6B3O9*BbCaH*1IVLzxp-VRlLop0wt66Yfv~F3L$AW=H8@Ev-EM7G_ z9-hllO3?TG&`)0y%1(1&VHqn1R&CtD+O_lxJpM&ABSF}5{_S`JS;h(F$DH~MM>~kd zlCa?Up?s6QAIi9=I1p-HG!nr;#J;j~roje?w` zbrNOqNWSt_Cp#DOnHmb4oiLQ~K_HSuCI+?$Ygf~{t|Y<8HRXX^s)`+6oO#|M!acP* z{3^r5UD#6(@PgySUh4~J`v;5?KCxB8eLnSRWE~Iqt@1ew53xRtvvfJabG}uqvi%LW zK2L+H*kTaiF*MW*02OTD5&NqgnE`A}%K_s%mcD`%1Qq(%7^u#^5}u&Jx3V{RC!Xpi J!)(IQ&A%l}v1$MS literal 0 HcmV?d00001 diff --git a/h2/src/java21/src/org/h2/util/Utils21.java b/h2/src/java21/src/org/h2/util/Utils21.java new file mode 100644 index 0000000000..cd0401b658 --- /dev/null +++ b/h2/src/java21/src/org/h2/util/Utils21.java @@ -0,0 +1,36 @@ +/* + * Copyright 2004-2023 H2 Group. Multiple-Licensed under the MPL 2.0, + * and the EPL 1.0 (https://h2database.com/html/license.html). + * Initial Developer: H2 Group + */ +package org.h2.util; + +import java.lang.Thread.Builder.OfVirtual; + +/** + * Utilities with specialized implementations for Java 21 and later versions. + * + * This class contains basic implementations for older versions of Java and it + * is overridden in multi-release JARs. + */ +public final class Utils21 { + + private static final OfVirtual VIRTUAL_THREAD_BUILDER = Thread.ofVirtual(); + + /** + * Creates a new virtual thread (on Java 21+) for the specified task. Use + * {@link Thread#start()} to schedule the thread to execute. On older + * versions of Java a platform daemon thread is created instead. + * + * @param task + * the object to run + * @return a new thread + */ + public static Thread newVirtualThread(Runnable task) { + return VIRTUAL_THREAD_BUILDER.unstarted(task); + } + + private Utils21() { + } + +} diff --git a/h2/src/java21/src/org/h2/util/package.html b/h2/src/java21/src/org/h2/util/package.html new file mode 100644 index 0000000000..07363d4a39 --- /dev/null +++ b/h2/src/java21/src/org/h2/util/package.html @@ -0,0 +1,14 @@ + + + + +Javadoc package documentation +

+ +Internal utility classes reimplemented for Java 21 and later versions. + +

\ No newline at end of file diff --git a/h2/src/main/org/h2/server/TcpServer.java b/h2/src/main/org/h2/server/TcpServer.java index 49d580123d..ca7b3a64fb 100644 --- a/h2/src/main/org/h2/server/TcpServer.java +++ b/h2/src/main/org/h2/server/TcpServer.java @@ -26,7 +26,9 @@ import org.h2.util.NetUtils; import org.h2.util.StringUtils; import org.h2.util.Tool; +import org.h2.util.Utils; import org.h2.util.Utils10; +import org.h2.util.Utils21; /** * The TCP server implements the native H2 database server protocol. @@ -62,6 +64,7 @@ public class TcpServer implements Service { private boolean allowOthers; private boolean isDaemon; private boolean ifExists = true; + private boolean virtualThreads; private JdbcConnection managementDb; private PreparedStatement managementDbAdd; private PreparedStatement managementDbRemove; @@ -182,6 +185,8 @@ public void init(String... args) { allowOthers = true; } else if (Tool.isOption(a, "-tcpDaemon")) { isDaemon = true; + } else if (Tool.isOption(a, "-tcpVirtualThreads")) { + virtualThreads = Utils.parseBoolean(args[++i], virtualThreads, true); } else if (Tool.isOption(a, "-ifExists")) { ifExists = true; } else if (Tool.isOption(a, "-ifNotExists")) { @@ -256,8 +261,14 @@ public void listen() { int id = nextThreadId++; TcpServerThread c = new TcpServerThread(s, this, id); running.add(c); - Thread thread = new Thread(c, threadName + " thread-" + id); - thread.setDaemon(isDaemon); + Thread thread; + if (virtualThreads) { + thread = Utils21.newVirtualThread(c); + } else { + thread = new Thread(c); + thread.setDaemon(isDaemon); + } + thread.setName(threadName + " thread-" + id); c.setThread(thread); thread.start(); } diff --git a/h2/src/main/org/h2/server/pg/PgServer.java b/h2/src/main/org/h2/server/pg/PgServer.java index 1135c9f3a5..a479d2316c 100644 --- a/h2/src/main/org/h2/server/pg/PgServer.java +++ b/h2/src/main/org/h2/server/pg/PgServer.java @@ -19,7 +19,9 @@ import org.h2.server.Service; import org.h2.util.NetUtils; import org.h2.util.Tool; +import org.h2.util.Utils; import org.h2.util.Utils10; +import org.h2.util.Utils21; import org.h2.value.TypeInfo; import org.h2.value.Value; @@ -79,6 +81,7 @@ public class PgServer implements Service { private boolean allowOthers; private boolean isDaemon; private boolean ifExists = true; + private boolean virtualThreads; private String key, keyDatabase; @Override @@ -97,6 +100,8 @@ public void init(String... args) { allowOthers = true; } else if (Tool.isOption(a, "-pgDaemon")) { isDaemon = true; + } else if (Tool.isOption(a, "-pgVirtualThreads")) { + virtualThreads = Utils.parseBoolean(args[++i], virtualThreads, true); } else if (Tool.isOption(a, "-ifExists")) { ifExists = true; } else if (Tool.isOption(a, "-ifNotExists")) { @@ -197,8 +202,14 @@ public void listen() { running.add(c); int id = pid.incrementAndGet(); c.setProcessId(id); - Thread thread = new Thread(c, threadName + " thread-" + id); - thread.setDaemon(isDaemon); + Thread thread; + if (virtualThreads) { + thread = Utils21.newVirtualThread(c); + } else { + thread = new Thread(c); + thread.setDaemon(isDaemon); + } + thread.setName(threadName + " thread-" + id); c.setThread(thread); thread.start(); } diff --git a/h2/src/main/org/h2/server/web/WebServer.java b/h2/src/main/org/h2/server/web/WebServer.java index a134634a46..32d7664574 100644 --- a/h2/src/main/org/h2/server/web/WebServer.java +++ b/h2/src/main/org/h2/server/web/WebServer.java @@ -177,6 +177,7 @@ public class WebServer implements Service { private ShutdownHandler shutdownHandler; private Thread listenerThread; private boolean ifExists = true; + boolean virtualThreads; private String key; private boolean allowSecureCreation; private boolean trace; @@ -336,6 +337,8 @@ public void init(String... args) { setExternalNames(args[++i]); } else if (Tool.isOption(a, "-webDaemon")) { isDaemon = true; + } else if (Tool.isOption(a, "-webVirtualThreads")) { + virtualThreads = Utils.parseBoolean(args[++i], virtualThreads, true); } else if (Tool.isOption(a, "-baseDir")) { String baseDir = args[++i]; SysProperties.setBaseDir(baseDir); diff --git a/h2/src/main/org/h2/server/web/WebThread.java b/h2/src/main/org/h2/server/web/WebThread.java index cdcaf98c50..fa871c7fcb 100644 --- a/h2/src/main/org/h2/server/web/WebThread.java +++ b/h2/src/main/org/h2/server/web/WebThread.java @@ -25,6 +25,7 @@ import org.h2.util.NetworkConnectionInfo; import org.h2.util.StringUtils; import org.h2.util.Utils; +import org.h2.util.Utils21; /** * For each connection to a session, an object of this class is created. @@ -47,7 +48,8 @@ class WebThread extends WebApp implements Runnable { WebThread(Socket socket, WebServer server) { super(server); this.socket = socket; - thread = new Thread(this, "H2 Console thread"); + thread = server.virtualThreads ? Utils21.newVirtualThread(this) : new Thread(this); + thread.setName("H2 Console thread"); } /** diff --git a/h2/src/main/org/h2/tools/Console.java b/h2/src/main/org/h2/tools/Console.java index 86f025c849..6395728185 100644 --- a/h2/src/main/org/h2/tools/Console.java +++ b/h2/src/main/org/h2/tools/Console.java @@ -117,6 +117,8 @@ public void runTool(String... args) throws SQLException { i++; } else if ("-webDaemon".equals(arg)) { // no parameters + } else if ("-webVirtualThreads".equals(arg)) { + i++; } else if ("-webSSL".equals(arg)) { // no parameters } else if ("-webPort".equals(arg)) { @@ -140,6 +142,8 @@ public void runTool(String... args) throws SQLException { // no parameters } else if ("-tcpDaemon".equals(arg)) { // no parameters + } else if ("-tcpVirtualThreads".equals(arg)) { + i++; } else if ("-tcpSSL".equals(arg)) { // no parameters } else if ("-tcpPort".equals(arg)) { @@ -163,6 +167,8 @@ public void runTool(String... args) throws SQLException { // no parameters } else if ("-pgDaemon".equals(arg)) { // no parameters + } else if ("-pgVirtualThreads".equals(arg)) { + i++; } else if ("-pgPort".equals(arg)) { i++; } else { diff --git a/h2/src/main/org/h2/tools/Server.java b/h2/src/main/org/h2/tools/Server.java index be6076fa38..9d453d0fc2 100644 --- a/h2/src/main/org/h2/tools/Server.java +++ b/h2/src/main/org/h2/tools/Server.java @@ -71,6 +71,8 @@ public Server(Service service, String... args) throws SQLException { * used together with -webAllowOthers * [-webDaemon] * Use a daemon thread + * [-webVirtualThreads <true|false>] + * Use virtual threads (on Java 21+ only) * [-webPort <port>] * The port (default: 8082) * [-webSSL] @@ -89,6 +91,8 @@ public Server(Service service, String... args) throws SQLException { * Allow other computers to connect - see below * [-tcpDaemon] * Use a daemon thread + * [-tcpVirtualThreads <true|false>] + * Use virtual threads (on Java 21+ only) * [-tcpPort <port>] * The port (default: 9092) * [-tcpSSL] @@ -105,6 +109,8 @@ public Server(Service service, String... args) throws SQLException { * Allow other computers to connect - see below * [-pgDaemon] * Use a daemon thread + * [-pgVirtualThreads <true|false>] + * Use virtual threads (on Java 21+ only) * [-pgPort <port>] * The port (default: 5435) * [-properties "<dir>"] @@ -148,6 +154,8 @@ private void verifyArgs(String... args) throws SQLException { i++; } else if ("-webDaemon".equals(arg)) { // no parameters + } else if ("-webVirtualThreads".equals(arg)) { + i++; } else if ("-webSSL".equals(arg)) { // no parameters } else if ("-webPort".equals(arg)) { @@ -169,6 +177,8 @@ private void verifyArgs(String... args) throws SQLException { // no parameters } else if ("-tcpDaemon".equals(arg)) { // no parameters + } else if ("-tcpVirtualThreads".equals(arg)) { + i++; } else if ("-tcpSSL".equals(arg)) { // no parameters } else if ("-tcpPort".equals(arg)) { @@ -189,6 +199,8 @@ private void verifyArgs(String... args) throws SQLException { // no parameters } else if ("-pgDaemon".equals(arg)) { // no parameters + } else if ("-pgVirtualThreads".equals(arg)) { + i++; } else if ("-pgPort".equals(arg)) { i++; } else { diff --git a/h2/src/main/org/h2/util/Utils21.java b/h2/src/main/org/h2/util/Utils21.java new file mode 100644 index 0000000000..7adca6142b --- /dev/null +++ b/h2/src/main/org/h2/util/Utils21.java @@ -0,0 +1,40 @@ +/* + * Copyright 2004-2023 H2 Group. Multiple-Licensed under the MPL 2.0, + * and the EPL 1.0 (https://h2database.com/html/license.html). + * Initial Developer: H2 Group + */ +package org.h2.util; + +/** + * Utilities with specialized implementations for Java 21 and later versions. + * + * This class contains basic implementations for older versions of Java and it + * is overridden in multi-release JARs. + */ +public final class Utils21 { + + /* + * Signatures of methods should match with + * h2/src/java21/src/org/h2/util/Utils21.java and precompiled + * h2/src/java21/precompiled/org/h2/util/Utils21.class. + */ + + /** + * Creates a new virtual thread (on Java 21+) for the specified task. Use + * {@link Thread#start()} to schedule the thread to execute. On older + * versions of Java a platform daemon thread is created instead. + * + * @param task + * the object to run + * @return a new thread + */ + public static Thread newVirtualThread(Runnable task) { + Thread thread = new Thread(task); + thread.setDaemon(true); + return thread; + } + + private Utils21() { + } + +} diff --git a/h2/src/main/org/h2/value/Value.java b/h2/src/main/org/h2/value/Value.java index 7a8e12bbc0..5047a31b55 100644 --- a/h2/src/main/org/h2/value/Value.java +++ b/h2/src/main/org/h2/value/Value.java @@ -2711,7 +2711,7 @@ public boolean containsNull() { * Scans this and specified values until a first NULL occurrence and returns * a value where NULL appears earlier, or {@code null} if these two values * have first NULL on the same position. - * + * * @param v * a value of the same data type as this value, must be neither * equal to nor smaller than nor greater than this value diff --git a/h2/src/tools/org/h2/build/Build.java b/h2/src/tools/org/h2/build/Build.java index a55d5fbe40..05d8d333ad 100644 --- a/h2/src/tools/org/h2/build/Build.java +++ b/h2/src/tools/org/h2/build/Build.java @@ -557,6 +557,7 @@ private FileList excludeTestMetaInfFiles(FileList files) { private void addVersions() { copy("temp/META-INF/versions/9", files("src/java9/precompiled"), "src/java9/precompiled"); copy("temp/META-INF/versions/10", files("src/java10/precompiled"), "src/java10/precompiled"); + copy("temp/META-INF/versions/21", files("src/java21/precompiled"), "src/java21/precompiled"); } /** @@ -922,6 +923,9 @@ private void test(boolean ci) { cp = "src/java9/precompiled" + File.pathSeparator + cp; if (version >= 10) { cp = "src/java10/precompiled" + File.pathSeparator + cp; + if (version >= 21) { + cp = "src/java21/precompiled" + File.pathSeparator + cp; + } } } int ret; diff --git a/h2/src/tools/org/h2/build/doc/dictionary.txt b/h2/src/tools/org/h2/build/doc/dictionary.txt index 11554ccb57..60478ced41 100644 --- a/h2/src/tools/org/h2/build/doc/dictionary.txt +++ b/h2/src/tools/org/h2/build/doc/dictionary.txt @@ -855,4 +855,4 @@ duplicating unnested hardening sticky massacred bck clo cur hwm materializedview udca vol connectionpooldatasource xadatasource ampm sssssff sstzh tzs yyyysssss newsequentialid solidus openjdk furthermore ssff secons nashorn fractions btrim underscores ffl decomposed decomposition subfield infinities retryable salted establish -hatchet fis loom birthdate penrosed eve graalvm roberto polyglot truffle scriptengine +hatchet fis loom birthdate penrosed eve graalvm roberto polyglot truffle scriptengine unstarted From fd022b0d1660512d17963b1da60144ca5cbe53f4 Mon Sep 17 00:00:00 2001 From: Evgenij Ryazanov Date: Mon, 7 Aug 2023 21:58:41 +0800 Subject: [PATCH 2/2] Update changelog --- h2/src/docsrc/html/changelog.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/h2/src/docsrc/html/changelog.html b/h2/src/docsrc/html/changelog.html index abac9db9ee..0a64f6e012 100644 --- a/h2/src/docsrc/html/changelog.html +++ b/h2/src/docsrc/html/changelog.html @@ -21,6 +21,10 @@

Change Log

Next Version (unreleased)

    +
  • RP #3865: Add possibility to enable virtual worker threads in TCP, Web, and PG servers on Java 21+ +
  • +
  • PR #3864: Improve performance of TCP client driver when it is used from virtual threads +
  • Issue #2665: Parser shouldn't suggest compatibility syntax elements on parsing error
  • Issue #3089: GREATEST and LEAST aren't fully compliant with the SQL Standard