From af7b227ccecbeab2167d6a1d16cd520871419d14 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Thu, 7 Jan 2016 12:26:08 +0100 Subject: [PATCH] SONAR-7168 add restart request support to ProcessCommands --- .../sonar/process/DefaultProcessCommands.java | 19 ++++++- .../org/sonar/process/ProcessCommands.java | 16 ++++++ .../org/sonar/process/ProcessEntryPoint.java | 4 ++ .../process/DefaultProcessCommandsTest.java | 53 +++++++++++++++++-- 4 files changed, 86 insertions(+), 6 deletions(-) diff --git a/server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java b/server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java index 72d6ca70560..3ceab37472e 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java +++ b/server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java @@ -56,17 +56,19 @@ public class DefaultProcessCommands implements ProcessCommands { * */ final MappedByteBuffer mappedByteBuffer; private final RandomAccessFile sharedMemory; - private static final int BYTE_LENGTH_FOR_ONE_PROCESS = 1 + 1 + 8; + private static final int BYTE_LENGTH_FOR_ONE_PROCESS = 1 + 1 + 1 + 8; // With this shared memory we can handle up to MAX_PROCESSES processes private static final int MAX_SHARED_MEMORY = BYTE_LENGTH_FOR_ONE_PROCESS * MAX_PROCESSES; public static final byte STOP = (byte) 0xFF; + public static final byte RESTART = (byte) 0xAA; public static final byte READY = (byte) 0x01; public static final byte EMPTY = (byte) 0x00; @@ -135,6 +137,21 @@ public class DefaultProcessCommands implements ProcessCommands { return mappedByteBuffer.get(offset() + 1) == STOP; } + @Override + public void askForRestart() { + mappedByteBuffer.put(offset() + 3, RESTART); + } + + @Override + public boolean askedForRestart() { + return mappedByteBuffer.get(offset() + 3) == RESTART; + } + + @Override + public void acknowledgeAskForRestart() { + mappedByteBuffer.put(offset() + 3, EMPTY); + } + @Override public void endWatch() { IOUtils.closeQuietly(sharedMemory); 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 d6b0ef06018..789a4b8cefc 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 @@ -24,6 +24,7 @@ package org.sonar.process; * * *

@@ -57,5 +58,20 @@ public interface ProcessCommands { boolean askedForStop(); + /** + * To be executed by child process to ask for restart of all child processes + */ + void askForRestart(); + + /** + * Can be called by child or monitor process to know whether child process asked for restart + */ + boolean askedForRestart(); + + /** + * To be executed by monitor process to acknowledge restart request from child process. + */ + void acknowledgeAskForRestart(); + void endWatch(); } 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 55aab7166b7..95a979b4309 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 @@ -52,6 +52,10 @@ public class ProcessEntryPoint implements Stoppable { this.stopWatcher = new StopWatcher(commands, this); } + public ProcessCommands getCommands() { + return commands; + } + public Props getProps() { return props; } diff --git a/server/sonar-process/src/test/java/org/sonar/process/DefaultProcessCommandsTest.java b/server/sonar-process/src/test/java/org/sonar/process/DefaultProcessCommandsTest.java index 763a22ad7d3..ee5f2f21243 100644 --- a/server/sonar-process/src/test/java/org/sonar/process/DefaultProcessCommandsTest.java +++ b/server/sonar-process/src/test/java/org/sonar/process/DefaultProcessCommandsTest.java @@ -31,6 +31,8 @@ import static org.junit.Assert.fail; public class DefaultProcessCommandsTest { + private static final int PROCESS_NUMBER = 1; + @Rule public TemporaryFolder temp = new TemporaryFolder(); @@ -40,7 +42,7 @@ public class DefaultProcessCommandsTest { FileUtils.deleteQuietly(dir); try { - new DefaultProcessCommands(dir, 1); + new DefaultProcessCommands(dir, PROCESS_NUMBER); fail(); } catch (IllegalArgumentException e) { assertThat(e).hasMessage("Not a valid directory: " + dir.getAbsolutePath()); @@ -51,7 +53,7 @@ public class DefaultProcessCommandsTest { public void child_process_update_the_mapped_memory() throws Exception { File dir = temp.newFolder(); - DefaultProcessCommands commands = new DefaultProcessCommands(dir, 1); + DefaultProcessCommands commands = new DefaultProcessCommands(dir, PROCESS_NUMBER); assertThat(commands.isReady()).isFalse(); assertThat(commands.mappedByteBuffer.get(commands.offset())).isEqualTo(DefaultProcessCommands.EMPTY); assertThat(commands.mappedByteBuffer.getLong(2 + commands.offset())).isEqualTo(0L); @@ -69,13 +71,54 @@ public class DefaultProcessCommandsTest { public void ask_for_stop() throws Exception { File dir = temp.newFolder(); - DefaultProcessCommands commands = new DefaultProcessCommands(dir, 1); - assertThat(commands.mappedByteBuffer.get(commands.offset() + 1)).isNotEqualTo(DefaultProcessCommands.STOP); + DefaultProcessCommands commands = new DefaultProcessCommands(dir, PROCESS_NUMBER); + assertThat(commands.mappedByteBuffer.get(commands.offset() + PROCESS_NUMBER)).isNotEqualTo(DefaultProcessCommands.STOP); assertThat(commands.askedForStop()).isFalse(); commands.askForStop(); assertThat(commands.askedForStop()).isTrue(); - assertThat(commands.mappedByteBuffer.get(commands.offset() + 1)).isEqualTo(DefaultProcessCommands.STOP); + assertThat(commands.mappedByteBuffer.get(commands.offset() + PROCESS_NUMBER)).isEqualTo(DefaultProcessCommands.STOP); + } + + @Test + public void ask_for_restart() throws Exception { + File dir = temp.newFolder(); + + DefaultProcessCommands commands = new DefaultProcessCommands(dir, PROCESS_NUMBER); + assertThat(commands.mappedByteBuffer.get(commands.offset() + 3)).isNotEqualTo(DefaultProcessCommands.RESTART); + assertThat(commands.askedForRestart()).isFalse(); + + commands.askForRestart(); + assertThat(commands.askedForRestart()).isTrue(); + assertThat(commands.mappedByteBuffer.get(commands.offset() + 3)).isEqualTo(DefaultProcessCommands.RESTART); + } + + @Test + public void acknowledgeAskForRestart_has_no_effect_when_no_restart_asked() throws Exception { + File dir = temp.newFolder(); + + DefaultProcessCommands commands = new DefaultProcessCommands(dir, PROCESS_NUMBER); + assertThat(commands.mappedByteBuffer.get(commands.offset() + 3)).isNotEqualTo(DefaultProcessCommands.RESTART); + assertThat(commands.askedForRestart()).isFalse(); + + commands.acknowledgeAskForRestart(); + assertThat(commands.mappedByteBuffer.get(commands.offset() + 3)).isNotEqualTo(DefaultProcessCommands.RESTART); + assertThat(commands.askedForRestart()).isFalse(); + } + + @Test + public void acknowledgeAskForRestart_resets_askForRestart_has_no_effect_when_no_restart_asked() throws Exception { + File dir = temp.newFolder(); + + DefaultProcessCommands commands = new DefaultProcessCommands(dir, PROCESS_NUMBER); + + commands.askForRestart(); + assertThat(commands.askedForRestart()).isTrue(); + assertThat(commands.mappedByteBuffer.get(commands.offset() + 3)).isEqualTo(DefaultProcessCommands.RESTART); + + commands.acknowledgeAskForRestart(); + assertThat(commands.mappedByteBuffer.get(commands.offset() + 3)).isNotEqualTo(DefaultProcessCommands.RESTART); + assertThat(commands.askedForRestart()).isFalse(); } @Test -- 2.39.5