]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5409 - Added monitoring service to sonar-process
authorStephane Gamard <stephane.gamard@searchbox.com>
Thu, 10 Jul 2014 13:13:26 +0000 (15:13 +0200)
committerStephane Gamard <stephane.gamard@searchbox.com>
Thu, 10 Jul 2014 16:06:46 +0000 (18:06 +0200)
server/sonar-process/src/main/java/org/sonar/Application.java
server/sonar-process/src/main/java/org/sonar/process/Launcher.java [deleted file]
server/sonar-process/src/main/java/org/sonar/process/MonitorService.java [new file with mode: 0644]
server/sonar-process/src/main/java/org/sonar/process/Process.java
server/sonar-process/src/main/java/org/sonar/process/ProcessWrapper.java [new file with mode: 0644]
server/sonar-process/src/test/java/org/sonar/process/LauncherTest.java [deleted file]
server/sonar-process/src/test/java/org/sonar/process/MonitorServiceTest.java [new file with mode: 0644]

index 829f264940a1e813919da7c7f27a5e47b965d37d..9da457086d172568718516d11e586b5f6928a4b3 100644 (file)
@@ -21,16 +21,15 @@ package org.sonar;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.sonar.process.Launcher;
+import org.sonar.process.MonitorService;
+import org.sonar.process.ProcessWrapper;
 
 import java.io.IOException;
 import java.net.DatagramSocket;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
 
-/**
- * @Since 4.5
- */
 public class Application {
 
   private final static Logger LOGGER = LoggerFactory.getLogger(Application.class);
@@ -43,27 +42,39 @@ public class Application {
   public static void main(String... args) throws InterruptedException, IOException {
 
     final ExecutorService executor = Executors.newFixedThreadPool(2);
-    final Launcher sonarQube = new Launcher("SQ", systemAvailableSocket());
-    final Launcher elasticsearch = new Launcher("ES", systemAvailableSocket());
+    final MonitorService monitor = new MonitorService(systemAvailableSocket());
+
+    //Create the processes
+    //final ProcessWrapper sonarQube = new ProcessWrapper("SQ", monitor);
+    final ProcessWrapper elasticsearch = null;//new ProcessWrapper("ES", monitor.getMonitoringPort());
+
+    //Register processes to monitor
+    monitor.register(elasticsearch);
 
     Runtime.getRuntime().addShutdownHook(new Thread() {
       @Override
       public void run() {
         LOGGER.info("Shutting down sonar Node");
-        sonarQube.interrupt();
+        //sonarQube.shutdown();
         elasticsearch.interrupt();
-        executor.shutdownNow();
+        executor.shutdown();
+        try {
+          executor.awaitTermination(10L, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+          LOGGER.warn("Executing terminated", e);
+        }
       }
     });
 
-    LOGGER.info("Starting SQ Node...");
-    executor.submit(sonarQube);
-
-    LOGGER.info("Starting ES Node...");
+    // Start our processes
+    LOGGER.info("Starting Child processes...");
     executor.submit(elasticsearch);
+    //executor.submit(sonarQube);
+
+    // And monitor the activity
+    monitor.run();
 
-    while (!executor.isTerminated()) {
-      Thread.sleep(1000);
-    }
+    // If monitor is finished, we're done. Cleanup
+    executor.shutdown();
   }
 }
diff --git a/server/sonar-process/src/main/java/org/sonar/process/Launcher.java b/server/sonar-process/src/main/java/org/sonar/process/Launcher.java
deleted file mode 100644 (file)
index fd354c4..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-
-/**
- * @Since 4.5
- */
-public class Launcher extends Thread {
-
-  private final static Logger LOGGER = LoggerFactory.getLogger(Launcher.class);
-
-  final String name;
-  final DatagramSocket socket;
-  java.lang.Process process;
-
-
-  public Launcher(String name, DatagramSocket socket) {
-    LOGGER.info("Creating Launcher for '{}' with base port: {}", name, socket.getLocalPort());
-    this.name = name;
-    this.socket = socket;
-  }
-
-  private void launch() {
-//    new Thread(new Runnable() {
-//      @Override
-//      public void run() {
-//        Runner.main(name, socket.getLocalPort() + "");
-//      }
-//    }).start();
-  }
-
-  private void shutdown() {
-    process.destroy();
-  }
-
-  private void monitor() {
-    long ping = Long.MAX_VALUE;
-    while (true) {
-      LOGGER.info("My heart is beating");
-      DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
-      try {
-        socket.setSoTimeout(3000);
-        socket.receive(packet);
-      } catch (Exception e) {
-        // Do nothing
-      }
-      long newPing = System.currentTimeMillis();
-      String message = new String(packet.getData(), 0, 0, packet.getLength());
-      LOGGER.info("{} last seen since {}ms", message, (newPing - ping));
-      if ((newPing - ping) > 3000) {
-        // close everything here...
-      }
-      ping = newPing;
-    }
-  }
-
-  @Override
-  public void run() {
-    LOGGER.info("launching child VM for " + name);
-    launch();
-
-    LOGGER.info("Monitoring VM for " + name);
-    while (true) {
-      monitor();
-    }
-  }
-}
diff --git a/server/sonar-process/src/main/java/org/sonar/process/MonitorService.java b/server/sonar-process/src/main/java/org/sonar/process/MonitorService.java
new file mode 100644 (file)
index 0000000..ba4bf79
--- /dev/null
@@ -0,0 +1,81 @@
+package org.sonar.process;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.util.HashMap;
+import java.util.Map;
+
+public class MonitorService extends Thread {
+
+  private final static Logger LOGGER = LoggerFactory.getLogger(ProcessWrapper.class);
+
+  final DatagramSocket socket;
+  final Map<String, Thread> processes;
+  final Map<String, Long> processesPing;
+
+  public MonitorService(DatagramSocket socket) {
+    this.socket = socket;
+    processes = new HashMap<String, Thread>();
+    processesPing = new HashMap<String, Long>();
+  }
+
+  public void register(ProcessWrapper process) {
+    this.processes.put(process.getName(), process);
+    this.processesPing.put(process.getName(), System.currentTimeMillis());
+  }
+
+  @Override
+  public void run() {
+    LOGGER.info("Launching Monitoring Thread");
+    long time = System.currentTimeMillis();
+    while (!currentThread().isInterrupted()) {
+      DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
+      try {
+        socket.setSoTimeout(200);
+        socket.receive(packet);
+        time = System.currentTimeMillis();
+        String message = new String(packet.getData());
+        long lastTime = processesPing.get(message);
+        processesPing.put(message, time);
+        LOGGER.info("{} last seen since {}ms", message, (time - lastTime));
+      } catch (Exception e) {
+        // Do nothing
+      }
+      if (!checkAllProcessPing(time)) {
+        break;
+      }
+    }
+    LOGGER.info("Some app has not been pinging");
+    for (Thread process : processes.values()) {
+      if (!process.isInterrupted()) {
+        process.interrupt();
+      }
+    }
+  }
+
+
+  private boolean checkAllProcessPing(long now) {
+
+    //check that all thread wrapper are running
+    for (Thread thread : processes.values()) {
+      if (thread.isInterrupted() || !thread.isAlive()) {
+        return false;
+      }
+    }
+
+    //check that all heartbeats are OK
+    for (Long ping : processesPing.values()) {
+      if ((now - ping) > 3000) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  public Integer getMonitoringPort() {
+    return socket.getPort();
+  }
+}
index b0adaf64431c0d7a4a531913d9bc2ebf046322d7..f170eb393c3b7a7b40f2daf9facb140104d39052 100644 (file)
@@ -28,9 +28,6 @@ import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 
-/**
- * @Since 4.5
- */
 public abstract class Process implements Runnable {
 
   public static final String NAME_PROPERTY = "pName";
diff --git a/server/sonar-process/src/main/java/org/sonar/process/ProcessWrapper.java b/server/sonar-process/src/main/java/org/sonar/process/ProcessWrapper.java
new file mode 100644 (file)
index 0000000..03190f0
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ProcessWrapper extends Thread {
+
+  private final static Logger LOGGER = LoggerFactory.getLogger(ProcessWrapper.class);
+
+  final String name;
+
+  @VisibleForTesting
+  ProcessWrapper(String name, Integer port) {
+    LOGGER.info("Creating Launcher for '{}' with base port: {}", name, port);
+    this.name = name;
+  }
+
+  public ProcessWrapper(String className, String[] classPath, String name, Integer port) {
+    LOGGER.info("Creating Launcher for '{}' with base port: {}", name, port);
+    this.name = name;
+  }
+
+  public void run() {
+
+  }
+}
diff --git a/server/sonar-process/src/test/java/org/sonar/process/LauncherTest.java b/server/sonar-process/src/test/java/org/sonar/process/LauncherTest.java
deleted file mode 100644 (file)
index 22bdd96..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 class LauncherTest  {
-
-}
\ No newline at end of file
diff --git a/server/sonar-process/src/test/java/org/sonar/process/MonitorServiceTest.java b/server/sonar-process/src/test/java/org/sonar/process/MonitorServiceTest.java
new file mode 100644 (file)
index 0000000..4723c22
--- /dev/null
@@ -0,0 +1,46 @@
+package org.sonar.process;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.net.DatagramSocket;
+
+public class MonitorServiceTest {
+
+
+  private DatagramSocket socket;
+
+  @Before
+  public void setUp() throws Exception {
+    socket = new DatagramSocket(0);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    if (socket != null && !socket.isClosed()) {
+      socket.close();
+    }
+  }
+
+  @Test
+  public void should_build() {
+    MonitorService monitor = new MonitorService(socket);
+  }
+
+  class LongProcessWrapper extends ProcessWrapper {
+
+    LongProcessWrapper(String name, Integer port) {
+      super(name, port);
+    }
+
+    @Override
+    public void run() {
+      try {
+        Thread.sleep(10000L);
+      } catch (InterruptedException e) {
+        e.printStackTrace();
+      }
+    }
+  }
+}
\ No newline at end of file