aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-process
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2016-03-09 12:01:36 +0100
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>2016-03-21 16:44:03 +0100
commit99d84905d981395e5026f693f7a948f31a40007a (patch)
tree8c66884ba1ec8fe7455aedf21dab043f8ec73bf4 /server/sonar-process
parenteb5e8f7774ee19a58c6796840ec9e71d67bb5a1d (diff)
downloadsonarqube-99d84905d981395e5026f693f7a948f31a40007a.tar.gz
sonarqube-99d84905d981395e5026f693f7a948f31a40007a.zip
SONAR-7435 add operational flag to shared memory IPC
Diffstat (limited to 'server/sonar-process')
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java28
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java10
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java9
-rw-r--r--server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java85
4 files changed, 100 insertions, 32 deletions
diff --git a/server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java b/server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java
index 52f5bcfd9fd..fe11a0e9fa3 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java
@@ -53,6 +53,7 @@ import static org.sonar.process.ProcessCommands.MAX_PROCESSES;
* <li>First byte contains {@link #EMPTY} until process is UP and writes {@link #UP}</li>
* <li>Second byte contains {@link #EMPTY} until any process requests current one to stop by writing value {@link #STOP}</li>
* <li>Third byte contains {@link #EMPTY} until any process requests current one to restart by writing value {@link #RESTART}. Process acknowledges restart by writing back {@link #EMPTY}</li>
+ * <li>Fourth byte will always contain {@link #EMPTY} unless process declares that it is operational by writing {@link #OPERATIONAL}. This does not imply that is done starting.</li>
* <li>The next 8 bytes contains a long (value of {@link System#currentTimeMillis()}) which represents the date of the last ping</li>
* </ul>
* </p>
@@ -61,15 +62,17 @@ public class AllProcessesCommands {
private static final int UP_BYTE_OFFSET = 0;
private static final int STOP_BYTE_OFFSET = 1;
private static final int RESTART_BYTE_OFFSET = 2;
- private static final int PING_BYTE_OFFSET = 3;
+ private static final int OPERATIONAL_BYTE_OFFSET = 3;
+ private static final int PING_BYTE_OFFSET = 4;
- private static final int BYTE_LENGTH_FOR_ONE_PROCESS = 1 + 1 + 1 + 8;
+ private static final int BYTE_LENGTH_FOR_ONE_PROCESS = 1 + 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;
private static final byte STOP = (byte) 0xFF;
private static final byte RESTART = (byte) 0xAA;
+ private static final byte OPERATIONAL = (byte) 0x59;
private static final byte UP = (byte) 0x01;
private static final byte EMPTY = (byte) 0x00;
@@ -118,6 +121,17 @@ public class AllProcessesCommands {
writeByte(processNumber, UP_BYTE_OFFSET, UP);
}
+ boolean isOperational(int processNumber) {
+ return readByte(processNumber, OPERATIONAL_BYTE_OFFSET) == OPERATIONAL;
+ }
+
+ /**
+ * To be executed by child process to declare that it is started and fully operational
+ */
+ void setOperational(int processNumber) {
+ writeByte(processNumber, OPERATIONAL_BYTE_OFFSET, OPERATIONAL);
+ }
+
void ping(int processNumber) {
writeLong(processNumber, PING_BYTE_OFFSET, System.currentTimeMillis());
}
@@ -206,6 +220,16 @@ public class AllProcessesCommands {
}
@Override
+ public boolean isOperational() {
+ return AllProcessesCommands.this.isOperational(processNumber);
+ }
+
+ @Override
+ public void setOperational() {
+ AllProcessesCommands.this.setOperational(processNumber);
+ }
+
+ @Override
public void ping() {
AllProcessesCommands.this.ping(processNumber);
}
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 0ef4413aa75..6d726ee9172 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
@@ -50,6 +50,16 @@ public class DefaultProcessCommands implements ProcessCommands {
}
@Override
+ public boolean isOperational() {
+ return delegate.isOperational();
+ }
+
+ @Override
+ public void setOperational() {
+ delegate.setOperational();
+ }
+
+ @Override
public void ping() {
delegate.ping();
}
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 f52f5b5f5df..1057ad54158 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
@@ -41,6 +41,15 @@ public interface ProcessCommands extends AutoCloseable {
*/
void setUp();
+ boolean isOperational();
+
+ /**
+ * To be executed by child process to declare that it is done starting and fully operational.
+ *
+ * @throws IllegalStateException if {@link #setUp()} has not been called
+ */
+ void setOperational();
+
void ping();
long getLastPing();
diff --git a/server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java b/server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java
index ad92121b824..bda42cf07e7 100644
--- a/server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java
+++ b/server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java
@@ -20,6 +20,7 @@
package org.sonar.process;
import java.io.File;
+import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.junit.Rule;
import org.junit.Test;
@@ -36,6 +37,7 @@ public class AllProcessesCommandsTest {
private static final byte STOP = (byte) 0xFF;
private static final byte RESTART = (byte) 0xAA;
private static final byte UP = (byte) 0x01;
+ private static final byte OPERATIONAL = (byte) 0x59;
private static final byte EMPTY = (byte) 0x00;
@Rule
@@ -57,84 +59,101 @@ public class AllProcessesCommandsTest {
}
@Test
- public void child_process_update_the_mapped_memory() throws Exception {
- File dir = temp.newFolder();
+ public void write_and_read_up() throws IOException {
+ AllProcessesCommands commands = new AllProcessesCommands(temp.newFolder());
+ int offset = 0;
- AllProcessesCommands commands = new AllProcessesCommands(dir);
assertThat(commands.isUp(PROCESS_NUMBER)).isFalse();
- assertThat(commands.mappedByteBuffer.get(commands.offset(PROCESS_NUMBER))).isEqualTo(EMPTY);
- assertThat(commands.mappedByteBuffer.getLong(2 + commands.offset(PROCESS_NUMBER))).isEqualTo(0L);
+ assertThat(readByte(commands, offset)).isEqualTo(EMPTY);
commands.setUp(PROCESS_NUMBER);
assertThat(commands.isUp(PROCESS_NUMBER)).isTrue();
- assertThat(commands.mappedByteBuffer.get(commands.offset(PROCESS_NUMBER))).isEqualTo(UP);
+ assertThat(readByte(commands, offset)).isEqualTo(UP);
+ }
+
+ @Test
+ public void write_and_read_operational() throws IOException {
+ AllProcessesCommands commands = new AllProcessesCommands(temp.newFolder());
+ int offset = 3;
+
+ assertThat(commands.isOperational(PROCESS_NUMBER)).isFalse();
+ assertThat(readByte(commands, offset)).isEqualTo(EMPTY);
+
+ commands.setOperational(PROCESS_NUMBER);
+ assertThat(commands.isOperational(PROCESS_NUMBER)).isTrue();
+ assertThat(readByte(commands, offset)).isEqualTo(OPERATIONAL);
+ }
+
+ @Test
+ public void write_and_read_ping() throws IOException {
+ AllProcessesCommands commands = new AllProcessesCommands(temp.newFolder());
+
+ int offset = 4;
+ assertThat(readLong(commands, offset)).isEqualTo(0L);
long currentTime = System.currentTimeMillis();
commands.ping(PROCESS_NUMBER);
- assertThat(commands.mappedByteBuffer.getLong(3 + commands.offset(PROCESS_NUMBER))).isGreaterThanOrEqualTo(currentTime);
+ assertThat(readLong(commands, offset)).isGreaterThanOrEqualTo(currentTime);
}
@Test
public void ask_for_stop() throws Exception {
- File dir = temp.newFolder();
+ AllProcessesCommands commands = new AllProcessesCommands(temp.newFolder());
+ int offset = 1;
- AllProcessesCommands commands = new AllProcessesCommands(dir);
- assertThat(commands.mappedByteBuffer.get(commands.offset(PROCESS_NUMBER) + 1)).isNotEqualTo(STOP);
+ assertThat(readByte(commands, offset)).isNotEqualTo(STOP);
assertThat(commands.askedForStop(PROCESS_NUMBER)).isFalse();
commands.askForStop(PROCESS_NUMBER);
assertThat(commands.askedForStop(PROCESS_NUMBER)).isTrue();
- assertThat(commands.mappedByteBuffer.get(commands.offset(PROCESS_NUMBER) + 1)).isEqualTo(STOP);
+ assertThat(readByte(commands, offset)).isEqualTo(STOP);
}
@Test
public void ask_for_restart() throws Exception {
- File dir = temp.newFolder();
+ AllProcessesCommands commands = new AllProcessesCommands(temp.newFolder());
+ int offset = 2;
- AllProcessesCommands commands = new AllProcessesCommands(dir);
- assertThat(commands.mappedByteBuffer.get(commands.offset(PROCESS_NUMBER) +2)).isNotEqualTo(RESTART);
+ assertThat(readByte(commands, offset)).isNotEqualTo(RESTART);
assertThat(commands.askedForRestart(PROCESS_NUMBER)).isFalse();
commands.askForRestart(PROCESS_NUMBER);
assertThat(commands.askedForRestart(PROCESS_NUMBER)).isTrue();
- assertThat(commands.mappedByteBuffer.get(commands.offset(PROCESS_NUMBER) + 2)).isEqualTo(RESTART);
+ assertThat(readByte(commands, offset)).isEqualTo(RESTART);
}
@Test
public void acknowledgeAskForRestart_has_no_effect_when_no_restart_asked() throws Exception {
- File dir = temp.newFolder();
+ AllProcessesCommands commands = new AllProcessesCommands(temp.newFolder());
+ int offset = 2;
- AllProcessesCommands commands = new AllProcessesCommands(dir);
- assertThat(commands.mappedByteBuffer.get(commands.offset(PROCESS_NUMBER) + 2)).isNotEqualTo(RESTART);
+ assertThat(readByte(commands, offset)).isNotEqualTo(RESTART);
assertThat(commands.askedForRestart(PROCESS_NUMBER)).isFalse();
commands.acknowledgeAskForRestart(PROCESS_NUMBER);
- assertThat(commands.mappedByteBuffer.get(commands.offset(PROCESS_NUMBER) + 2)).isNotEqualTo(RESTART);
+ assertThat(readByte(commands, offset)).isNotEqualTo(RESTART);
assertThat(commands.askedForRestart(PROCESS_NUMBER)).isFalse();
}
@Test
public void acknowledgeAskForRestart_resets_askForRestart_has_no_effect_when_no_restart_asked() throws Exception {
- File dir = temp.newFolder();
-
- AllProcessesCommands commands = new AllProcessesCommands(dir);
+ AllProcessesCommands commands = new AllProcessesCommands(temp.newFolder());
+ int offset = 2;
commands.askForRestart(PROCESS_NUMBER);
assertThat(commands.askedForRestart(PROCESS_NUMBER)).isTrue();
- assertThat(commands.mappedByteBuffer.get(commands.offset(PROCESS_NUMBER) + 2)).isEqualTo(RESTART);
+ assertThat(readByte(commands, offset)).isEqualTo(RESTART);
commands.acknowledgeAskForRestart(PROCESS_NUMBER);
- assertThat(commands.mappedByteBuffer.get(commands.offset(PROCESS_NUMBER) + 2)).isNotEqualTo(RESTART);
+ assertThat(readByte(commands, offset)).isNotEqualTo(RESTART);
assertThat(commands.askedForRestart(PROCESS_NUMBER)).isFalse();
}
@Test
public void getProcessCommands_fails_if_processNumber_is_less_than_0() throws Exception {
- File dir = temp.newFolder();
+ AllProcessesCommands allProcessesCommands = new AllProcessesCommands(temp.newFolder());
int processNumber = -2;
- AllProcessesCommands allProcessesCommands = new AllProcessesCommands(dir);
-
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Process number " + processNumber + " is not valid");
@@ -143,14 +162,20 @@ public class AllProcessesCommandsTest {
@Test
public void getProcessCommands_fails_if_processNumber_is_higher_than_MAX_PROCESSES() throws Exception {
- File dir = temp.newFolder();
+ AllProcessesCommands allProcessesCommands = new AllProcessesCommands(temp.newFolder());
int processNumber = MAX_PROCESSES + 1;
- AllProcessesCommands allProcessesCommands = new AllProcessesCommands(dir);
-
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Process number " + processNumber + " is not valid");
allProcessesCommands.createAfterClean(processNumber);
}
+
+ private byte readByte(AllProcessesCommands commands, int offset) {
+ return commands.mappedByteBuffer.get(commands.offset(PROCESS_NUMBER) + offset);
+ }
+
+ private long readLong(AllProcessesCommands commands, int offset) {
+ return commands.mappedByteBuffer.getLong(offset + commands.offset(PROCESS_NUMBER));
+ }
}