From 01c756fb8b64dd47ee3b18c9d59f771cedd3ac40 Mon Sep 17 00:00:00 2001 From: Martin Vahlensieck Date: Tue, 4 Jun 2024 12:50:48 +0200 Subject: [PATCH] Add option to notify systemd on startup Because this loads a native library, it requires Java 21 with preview features enables. --- build.gradle | 12 +++-- .../client/PolyphenyControlConnector.java | 14 ------ .../control/main/ControlCommand.java | 48 ++++++++++++++++++- 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/build.gradle b/build.gradle index 2a97721..9348a79 100644 --- a/build.gradle +++ b/build.gradle @@ -58,13 +58,17 @@ sourceSets { } } +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } +} + tasks.withType(JavaCompile).configureEach { options.encoding = "UTF-8" - sourceCompatibility = "11" - targetCompatibility = "11" + options.compilerArgs += "--enable-preview" } - configurations { webjars } @@ -175,7 +179,7 @@ artifacts { task extractWebjars(type: Copy) { - configurations.webjars.each {jar -> + configurations.webjars.each { jar -> from zipTree(jar) into "$buildDir/webjars" duplicatesStrategy = DuplicatesStrategy.EXCLUDE diff --git a/control-connector/src/main/java/org/polypheny/control/client/PolyphenyControlConnector.java b/control-connector/src/main/java/org/polypheny/control/client/PolyphenyControlConnector.java index 5b0e599..8cefa10 100644 --- a/control-connector/src/main/java/org/polypheny/control/client/PolyphenyControlConnector.java +++ b/control-connector/src/main/java/org/polypheny/control/client/PolyphenyControlConnector.java @@ -174,11 +174,6 @@ String getStatus() { } - public int checkForAnyRunningPolyphenyInstances() { - return Integer.parseInt( executeGet( "/control/checkAnyRunningPolyphenyInstances" ) ); - } - - private String executeGet( String command ) { HttpResponse httpResponse; try { @@ -191,15 +186,6 @@ private String executeGet( String command ) { } - private void executePost( String command, String data ) { - try { - Unirest.post( controlUrl + command ).body( data ).asString(); - } catch ( UnirestException e ) { - log.error( "Exception while sending request", e ); - } - } - - private class WebSocket extends WebSocketClient { private final Gson gson = new Gson(); diff --git a/src/main/java/org/polypheny/control/main/ControlCommand.java b/src/main/java/org/polypheny/control/main/ControlCommand.java index 2cc5455..30cd757 100644 --- a/src/main/java/org/polypheny/control/main/ControlCommand.java +++ b/src/main/java/org/polypheny/control/main/ControlCommand.java @@ -20,6 +20,13 @@ import com.github.rvesse.airline.annotations.Command; import com.github.rvesse.airline.annotations.Option; import com.typesafe.config.Config; +import java.lang.foreign.Arena; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.Linker; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.ValueLayout; +import java.lang.invoke.MethodHandle; import java.util.HashMap; import org.polypheny.control.authentication.AuthenticationFileManager; import org.polypheny.control.control.ConfigManager; @@ -31,7 +38,10 @@ public class ControlCommand extends AbstractCommand { @Option(name = { "-p", "--port" }, description = "Overwrite port of the Polypheny Control dashboard and API.") - private final int port = -1; + private int port = -1; + + @Option(name = { "--notify" }, description = "Notify systemd when server is listening.") + private boolean notify = false; @Option(name = { "-x", "--suppress-warning" }, description = "Suppress the auth warnings on startup.") protected boolean suppressWarning = false; @@ -63,6 +73,16 @@ public int _run_() { server = new Server( control, ConfigManager.getConfig().getInt( "pcrtl.control.port" ) ); } + if ( notify ) { + try { + notifySystemd(); + } catch ( Throwable t ) { + server.shutdown(); + System.err.println( "Failed to notify systemd: " + t.getMessage() ); + return 1; + } + } + Runtime.getRuntime().addShutdownHook( new Thread( () -> running = false ) ); while ( running ) { @@ -80,6 +100,32 @@ public int _run_() { } + @SuppressWarnings("preview") + private static void notifySystemd() { + // When adding another architecture, ensure that the sizes of the types below are correct. + if ( !System.getProperty( "os.arch" ).equals( "amd64" ) ) { + throw new RuntimeException( "Unexpected OS architecture" ); + } + try ( Arena a = Arena.ofConfined() ) { + Linker l = Linker.nativeLinker(); + SymbolLookup systemd = SymbolLookup.libraryLookup( "libsystemd.so.0", a ); + MethodHandle sd_notify = l.downcallHandle( + systemd.find( "sd_notify" ).orElseThrow(), + FunctionDescriptor.ofVoid( ValueLayout.JAVA_INT, ValueLayout.ADDRESS ) + ); + MemorySegment m = a.allocateUtf8String( "READY=1" ); + sd_notify.invokeExact( 0, m ); + } catch ( IllegalArgumentException e ) { + if ( e.getMessage().contains( "Cannot open library" ) ) { + throw new RuntimeException( "libsystemd is required for --notify" ); + } + throw e; + } catch ( Throwable e ) { + throw new RuntimeException( e ); + } + } + + private static void warnNoUserAccounts() { System.out.println( "WARNING: No Users Exist. Polypheny-Control executes and manages Polypheny-DB." ); System.out.println( "WARNING: For security reasons it is advisable to create at least one user." );