aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-process/src
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2014-09-22 22:56:07 +0200
committerSimon Brandhof <simon.brandhof@sonarsource.com>2014-09-22 22:56:07 +0200
commitf00cda378e649a87b2b1693db5aaaec37461a481 (patch)
treeeca8da0483f5e877cac3ed31d13e8af0f4703b8e /server/sonar-process/src
parent92c30ccd4cd311dc602c0e1a08fc97c09970a4f6 (diff)
downloadsonarqube-f00cda378e649a87b2b1693db5aaaec37461a481.tar.gz
sonarqube-f00cda378e649a87b2b1693db5aaaec37461a481.zip
SONAR-4898 add sonar.enableStopCommand property for internal use
Diffstat (limited to 'server/sonar-process/src')
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java20
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java13
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/StopWatcher.java30
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/Stoppable.java26
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/StopperThread.java2
-rw-r--r--server/sonar-process/src/test/java/org/sonar/process/ProcessCommandsTest.java42
6 files changed, 64 insertions, 69 deletions
diff --git a/server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java b/server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java
index 259af6b1eeb..417d62cb5bf 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java
@@ -57,22 +57,19 @@ public class ProcessCommands {
this.stopFile = stopFile;
}
- /**
- * Executed by monitor - delete shared files before starting child process
- */
- public void prepareMonitor() {
+ public void prepare() {
deleteFile(readyFile);
deleteFile(stopFile);
}
- public void finalizeProcess() {
+ public void endWatch() {
// do not fail if files can't be deleted
FileUtils.deleteQuietly(readyFile);
FileUtils.deleteQuietly(stopFile);
}
- public boolean wasReadyAfter(long launchedAt) {
- return isCreatedAfter(readyFile, launchedAt);
+ public boolean isReady() {
+ return readyFile.exists();
}
/**
@@ -89,8 +86,8 @@ public class ProcessCommands {
createFile(stopFile);
}
- public boolean askedForStopAfter(long launchedAt) {
- return isCreatedAfter(stopFile, launchedAt);
+ public boolean askedForStop() {
+ return stopFile.exists();
}
File getReadyFile() {
@@ -117,9 +114,4 @@ public class ProcessCommands {
}
}
}
-
- private boolean isCreatedAfter(File file, long launchedAt) {
- // File#lastModified() can have second precision on some OS
- return file.exists() && file.lastModified() / 1000 >= launchedAt / 1000;
- }
}
diff --git a/server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java b/server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java
index f4d6e7f90f7..870f1aea067 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java
@@ -21,7 +21,7 @@ package org.sonar.process;
import org.slf4j.LoggerFactory;
-public class ProcessEntryPoint {
+public class ProcessEntryPoint implements Stoppable {
public static final String PROPERTY_PROCESS_KEY = "process.key";
public static final String PROPERTY_TERMINATION_TIMEOUT = "process.terminationTimeout";
@@ -32,7 +32,6 @@ public class ProcessEntryPoint {
private final ProcessCommands commands;
private final SystemExit exit;
private volatile Monitored monitored;
- private volatile long launchedAt;
private volatile StopperThread stopperThread;
private final StopWatcher stopWatcher;
@@ -49,7 +48,6 @@ public class ProcessEntryPoint {
this.props = props;
this.exit = exit;
this.commands = commands;
- this.launchedAt = System.currentTimeMillis();
this.stopWatcher = new StopWatcher(commands, this);
}
@@ -68,6 +66,7 @@ public class ProcessEntryPoint {
if (!lifecycle.tryToMoveTo(Lifecycle.State.STARTING)) {
throw new IllegalStateException("Already started");
}
+ commands.prepare();
monitored = mp;
try {
@@ -116,10 +115,12 @@ public class ProcessEntryPoint {
exit.exit(0);
}
- void stopAsync() {
+ @Override
+ public void stopAsync() {
if (lifecycle.tryToMoveTo(Lifecycle.State.STOPPING)) {
stopperThread = new StopperThread(monitored, commands, Long.parseLong(props.nonNullValue(PROPERTY_TERMINATION_TIMEOUT)));
stopperThread.start();
+ stopWatcher.stopWatching();
}
}
@@ -131,10 +132,6 @@ public class ProcessEntryPoint {
return shutdownHook;
}
- long getLaunchedAt() {
- return launchedAt;
- }
-
public static ProcessEntryPoint createForArguments(String[] args) {
Props props = ConfigurationUtils.loadPropsFromCommandLineArgs(args);
ProcessCommands commands = new ProcessCommands(
diff --git a/server/sonar-process/src/main/java/org/sonar/process/StopWatcher.java b/server/sonar-process/src/main/java/org/sonar/process/StopWatcher.java
index 090b0052423..b7b4ffa15d8 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/StopWatcher.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/StopWatcher.java
@@ -23,31 +23,35 @@ import org.slf4j.LoggerFactory;
public class StopWatcher extends Thread {
- private final ProcessEntryPoint process;
+ private final Stoppable stoppable;
private final ProcessCommands commands;
private boolean watching = true;
- public StopWatcher(ProcessCommands commands, ProcessEntryPoint process) {
+ public StopWatcher(ProcessCommands commands, Stoppable stoppable) {
super("Stop Watcher");
this.commands = commands;
- this.process = process;
+ this.stoppable = stoppable;
}
@Override
public void run() {
- while (watching) {
- if (commands.askedForStopAfter(process.getLaunchedAt())) {
- LoggerFactory.getLogger(getClass()).info("Stopping process");
- process.stopAsync();
- watching = false;
- } else {
- try {
- Thread.sleep(500L);
- } catch (InterruptedException ignored) {
+ commands.prepare();
+ try {
+ while (watching) {
+ if (commands.askedForStop()) {
+ LoggerFactory.getLogger(getClass()).info("Stopping process");
+ stoppable.stopAsync();
watching = false;
+ } else {
+ try {
+ Thread.sleep(500L);
+ } catch (InterruptedException ignored) {
+ watching = false;
+ }
}
}
-
+ } finally {
+ commands.endWatch();
}
}
diff --git a/server/sonar-process/src/main/java/org/sonar/process/Stoppable.java b/server/sonar-process/src/main/java/org/sonar/process/Stoppable.java
new file mode 100644
index 00000000000..afd464a67a1
--- /dev/null
+++ b/server/sonar-process/src/main/java/org/sonar/process/Stoppable.java
@@ -0,0 +1,26 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.process;
+
+public interface Stoppable {
+
+ void stopAsync();
+
+}
diff --git a/server/sonar-process/src/main/java/org/sonar/process/StopperThread.java b/server/sonar-process/src/main/java/org/sonar/process/StopperThread.java
index 317cd6f62c3..764d551a93c 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/StopperThread.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/StopperThread.java
@@ -57,6 +57,6 @@ class StopperThread extends Thread {
LoggerFactory.getLogger(getClass()).error(String.format("Can not stop in %dms", terminationTimeout), e);
}
executor.shutdownNow();
- commands.finalizeProcess();
+ commands.endWatch();
}
}
diff --git a/server/sonar-process/src/test/java/org/sonar/process/ProcessCommandsTest.java b/server/sonar-process/src/test/java/org/sonar/process/ProcessCommandsTest.java
index 49c8f024c69..e81a537e2ee 100644
--- a/server/sonar-process/src/test/java/org/sonar/process/ProcessCommandsTest.java
+++ b/server/sonar-process/src/test/java/org/sonar/process/ProcessCommandsTest.java
@@ -40,11 +40,11 @@ public class ProcessCommandsTest {
public void delete_files_on_monitor_startup() throws Exception {
File dir = temp.newFolder();
assertThat(dir).exists();
- FileUtils.touch(new File(dir, "WEB.ready"));
- FileUtils.touch(new File(dir, "WEB.stop"));
+ FileUtils.touch(new File(dir, "web.ready"));
+ FileUtils.touch(new File(dir, "web.stop"));
- ProcessCommands commands = new ProcessCommands(dir, "WEB");
- commands.prepareMonitor();
+ ProcessCommands commands = new ProcessCommands(dir, "web");
+ commands.prepare();
assertThat(commands.getReadyFile()).doesNotExist();
assertThat(commands.getStopFile()).doesNotExist();
@@ -58,7 +58,7 @@ public class ProcessCommandsTest {
ProcessCommands commands = new ProcessCommands(readyFile, temp.newFile());
try {
- commands.prepareMonitor();
+ commands.prepare();
fail();
} catch (MessageException e) {
// ok
@@ -70,39 +70,15 @@ public class ProcessCommandsTest {
File readyFile = temp.newFile();
ProcessCommands commands = new ProcessCommands(readyFile, temp.newFile());
- commands.prepareMonitor();
+ commands.prepare();
+ assertThat(commands.isReady()).isFalse();
assertThat(readyFile).doesNotExist();
commands.setReady();
+ assertThat(commands.isReady()).isTrue();
assertThat(readyFile).exists();
- commands.finalizeProcess();
+ commands.endWatch();
assertThat(readyFile).doesNotExist();
}
-
- @Test
- public void was_ready_after_date() throws Exception {
- File readyFile = mock(File.class);
- ProcessCommands commands = new ProcessCommands(readyFile, temp.newFile());
-
- // does not exist
- when(readyFile.exists()).thenReturn(false);
- when(readyFile.lastModified()).thenReturn(123456L);
- assertThat(commands.wasReadyAfter(122000L)).isFalse();
-
- // readyFile created before
- when(readyFile.exists()).thenReturn(true);
- when(readyFile.lastModified()).thenReturn(123456L);
- assertThat(commands.wasReadyAfter(124000L)).isFalse();
-
- // readyFile created after
- when(readyFile.exists()).thenReturn(true);
- when(readyFile.lastModified()).thenReturn(123456L);
- assertThat(commands.wasReadyAfter(123123L)).isTrue();
-
- // readyFile created after, but can be truncated to second on some OS
- when(readyFile.exists()).thenReturn(true);
- when(readyFile.lastModified()).thenReturn(123000L);
- assertThat(commands.wasReadyAfter(123456L)).isTrue();
- }
}