From: Sébastien Lesaint Date: Tue, 21 Feb 2017 11:24:07 +0000 (+0100) Subject: SONAR-8435 add abort exit points to AutoStarter when shutdown while running X-Git-Tag: 6.4-RC1~885 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=d4510ae328cbcc6d9d51ffb391aff121708e5988;p=sonarqube.git SONAR-8435 add abort exit points to AutoStarter when shutdown while running --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/server/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index d74834f8dea..2622ab4d28a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -49,8 +49,8 @@ public class Platform { private static final Platform INSTANCE = new Platform(); - private final Supplier autoStarterSupplier; - private PlatformAutoStarter autoStarter = null; + private final Supplier autoStarterSupplier; + private AutoStarter autoStarter = null; private Properties properties; private ServletContext servletContext; private PlatformLevel level1; @@ -71,7 +71,7 @@ public class Platform { }; } - protected Platform(Supplier autoStarterSupplier) { + protected Platform(Supplier autoStarterSupplier) { this.autoStarterSupplier = autoStarterSupplier; } @@ -110,23 +110,20 @@ public class Platform { LOGGER.info("Database needs migration"); } else { this.autoStarter = autoStarterSupplier.get(); - this.autoStarter.execute(() -> { - try { + this.autoStarter.execute(new AutoStarterRunnable(autoStarter) { + @Override + public void doRun() { if (dbRequiredMigration) { LOGGER.info("Database has been automatically updated"); } - startLevel34Containers(); + runIfNotAborted(Platform.this::startLevel34Containers); - executeStartupTasks(startup); + runIfNotAborted(() -> executeStartupTasks(startup)); // switch current container last to avoid giving access to a partially initialized container - currentLevel = level4; + runIfNotAborted(() -> currentLevel = level4); // stop safemode container if it existed - stopSafeModeContainer(); - } catch (Throwable t) { - autoStarter.failure(t); - } finally { - autoStarter.success(); + runIfNotAborted(Platform.this::stopSafeModeContainer); } }); } @@ -179,7 +176,7 @@ public class Platform { return Status.BOOTING; } - private static boolean isRunning(@Nullable PlatformAutoStarter autoStarter) { + private static boolean isRunning(@Nullable AutoStarter autoStarter) { return autoStarter != null && autoStarter.isRunning(); } @@ -280,10 +277,10 @@ public class Platform { // Do not rename "stop" public void doStop() { try { + stopAutoStarter(); stopSafeModeContainer(); stopLevel234Containers(); stopLevel1Container(); - autoStarter = null; currentLevel = null; dbConnected = false; started = false; @@ -292,6 +289,13 @@ public class Platform { } } + private void stopAutoStarter() { + if (autoStarter != null) { + autoStarter.abort(); + autoStarter = null; + } + } + public void addComponents(Collection components) { level4AddedComponents.addAll(components); } @@ -312,7 +316,7 @@ public class Platform { NO_STARTUP_TASKS, ALL } - public interface PlatformAutoStarter { + public interface AutoStarter { /** * Let the autostarted execute the provided code. */ @@ -332,11 +336,64 @@ public class Platform { * Indicates whether the AutoStarter is running. */ boolean isRunning(); + + /** + * Requests the startcode (ie. the argument of {@link #execute(Runnable)}) aborts its processing (if it supports it). + */ + void abort(); + + /** + * Indicates whether {@link #abort()} was invoked. + *

+ * This method can be used by the start code to check whether it should proceed running or stop. + *

+ */ + boolean isAborting(); + + /** + * Called when abortion is complete. + *

+ * Start code support abortion should call this method once is done processing and if it stopped on abortion. + *

+ */ + void aborted(); } - private static final class AsynchronousAutoStarter implements PlatformAutoStarter { + private abstract static class AutoStarterRunnable implements Runnable { + private final AutoStarter autoStarter; + + AutoStarterRunnable(AutoStarter autoStarter) { + this.autoStarter = autoStarter; + } + + @Override + public void run() { + try { + doRun(); + } catch (Throwable t) { + autoStarter.failure(t); + } finally { + if (autoStarter.isAborting()) { + autoStarter.aborted(); + } else { + autoStarter.success(); + } + } + } + + abstract void doRun(); + + void runIfNotAborted(Runnable r) { + if (!autoStarter.isAborting()) { + r.run(); + } + } + } + + private static final class AsynchronousAutoStarter implements AutoStarter { private final ProcessCommandWrapper processCommandWrapper; private boolean running = true; + private boolean abort = false; private AsynchronousAutoStarter(ProcessCommandWrapper processCommandWrapper) { this.processCommandWrapper = processCommandWrapper; @@ -356,6 +413,13 @@ public class Platform { @Override public void success() { + LOGGER.debug("Background initialization of SonarQube done"); + this.running = false; + } + + @Override + public void aborted() { + LOGGER.debug("Background initialization of SonarQube aborted"); this.running = false; } @@ -363,5 +427,15 @@ public class Platform { public boolean isRunning() { return running; } + + @Override + public void abort() { + this.abort = true; + } + + @Override + public boolean isAborting() { + return this.abort; + } } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ServerTesterPlatform.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ServerTesterPlatform.java index a1fd38d25df..ca2a3f4324e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/ServerTesterPlatform.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/ServerTesterPlatform.java @@ -22,7 +22,7 @@ package org.sonar.server.platform; import java.util.function.Supplier; public class ServerTesterPlatform extends Platform { - public ServerTesterPlatform(Supplier autoStarterFactory) { + public ServerTesterPlatform(Supplier autoStarterFactory) { super(autoStarterFactory); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/tester/ServerTester.java b/server/sonar-server/src/test/java/org/sonar/server/tester/ServerTester.java index 897c601a74a..d7862d6ce0d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/tester/ServerTester.java +++ b/server/sonar-server/src/test/java/org/sonar/server/tester/ServerTester.java @@ -125,7 +125,7 @@ public class ServerTester extends ExternalResource { if (!esIndexes) { properties.put("sonar.internal.es.disableIndexes", true); } - platform = new ServerTesterPlatform(() -> new Platform.PlatformAutoStarter() { + platform = new ServerTesterPlatform(() -> new Platform.AutoStarter() { private boolean running = false; @Override @@ -150,6 +150,21 @@ public class ServerTester extends ExternalResource { public boolean isRunning() { return this.running; } + + @Override + public void abort() { + // do nothing specific + } + + @Override + public boolean isAborting() { + return false; + } + + @Override + public void aborted() { + // do nothing specific + } }); platform.init(properties, servletContext); platform.addComponents(components);