]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7435 add operational flag to shared memory IPC
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Wed, 9 Mar 2016 11:01:36 +0000 (12:01 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 21 Mar 2016 15:44:03 +0000 (16:44 +0100)
server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java
server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java
server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java
server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java

index 52f5bcfd9fd08360faf00fa809d891e8dd88bcac..fe11a0e9fa3e1ba4a25ac371b8ea38af4a6e7c8c 100644 (file)
@@ -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());
   }
@@ -205,6 +219,16 @@ public class AllProcessesCommands {
       AllProcessesCommands.this.setUp(processNumber);
     }
 
+    @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);
index 0ef4413aa7577c325b246fa988842ae64d2ae43a..6d726ee9172976bdb48e7f0383bb6b8d971ac8d5 100644 (file)
@@ -49,6 +49,16 @@ public class DefaultProcessCommands implements ProcessCommands {
     delegate.setUp();
   }
 
+  @Override
+  public boolean isOperational() {
+    return delegate.isOperational();
+  }
+
+  @Override
+  public void setOperational() {
+    delegate.setOperational();
+  }
+
   @Override
   public void ping() {
     delegate.ping();
index f52f5b5f5df8a2ef31b810a5cf5b0ce06672849c..1057ad5415804a6230b1e9d9689069814c851124 100644 (file)
@@ -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();
index ad92121b8248ced747999776fba51d893a361b9e..bda42cf07e7cd3e993cd1f0e09e4c91b6df2021f 100644 (file)
@@ -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));
+  }
 }