You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2018/08/03 09:53:18 UTC

[karaf] branch karaf-4.1.x updated: [KARAF-5798] use a consistent way to get the Karaf process ID; write the pid file when the process launches so that it contains an accurate value for either a master or slave instance; only update the instance PID for the current running master (i.e. once lock is acquired)

This is an automated email from the ASF dual-hosted git repository.

jbonofre pushed a commit to branch karaf-4.1.x
in repository https://gitbox.apache.org/repos/asf/karaf.git


The following commit(s) were added to refs/heads/karaf-4.1.x by this push:
     new 796cba8  [KARAF-5798] use a consistent way to get the Karaf process ID; write the pid file when the process launches so that it contains an accurate value for either a master or slave instance; only update the instance PID for the current running master (i.e. once lock is acquired)
796cba8 is described below

commit 796cba8aa09d115d6bbd806f6f76ef6aa9b755ad
Author: Zipay, Matthew <mz...@contractor.express.com>
AuthorDate: Mon Jul 9 16:32:07 2018 -0400

    [KARAF-5798] use a consistent way to get the Karaf process ID; write the pid file when the process launches so that it contains an accurate value for either a master or slave instance; only update the instance PID for the current running master (i.e. once lock is acquired)
---
 .../java/org/apache/karaf/main/InstanceHelper.java |  35 ++++---
 main/src/main/java/org/apache/karaf/main/Main.java |   5 +-
 .../org/apache/karaf/main/MainLockingTest.java     | 101 +++++++++++++++++++--
 .../test/java/org/apache/karaf/main/MockLock.java  |   2 +
 4 files changed, 114 insertions(+), 29 deletions(-)

diff --git a/main/src/main/java/org/apache/karaf/main/InstanceHelper.java b/main/src/main/java/org/apache/karaf/main/InstanceHelper.java
index deeb739..d610a2d 100644
--- a/main/src/main/java/org/apache/karaf/main/InstanceHelper.java
+++ b/main/src/main/java/org/apache/karaf/main/InstanceHelper.java
@@ -25,7 +25,6 @@ import java.io.OutputStreamWriter;
 import java.io.RandomAccessFile;
 import java.io.Writer;
 import java.lang.management.ManagementFactory;
-import java.lang.management.RuntimeMXBean;
 import java.net.InetAddress;
 import java.net.ServerSocket;
 import java.nio.channels.FileLock;
@@ -112,27 +111,26 @@ public class InstanceHelper {
         }
     }
 
+    /* KARAF-5798: consistent way to obtain the process ID */
     private static String getPid() {
-        String pid = ManagementFactory.getRuntimeMXBean().getName();
-        if (pid.indexOf('@') > 0) {
-            pid = pid.substring(0, pid.indexOf('@'));
-        }
-        return pid;
-    }
+        String name = ManagementFactory.getRuntimeMXBean().getName();
+        /*
+         * RuntimeMXBean#getName() makes no guarantees about the name, so use a
+         * regex to match the common(?) "pid@host" format
+         */
+        Pattern pattern = Pattern.compile("^([0-9]+)@.+$");
+        Matcher matcher = pattern.matcher(name);
+        return matcher.matches() ? matcher.group(1) : name;
+     }
 
-    private static void writePid(String pidFile) {
+    /* KARAF-5798: now called by Main#launch() */
+    static void writePid(String pidFile) {
         try {
             if (pidFile != null) {
-                RuntimeMXBean rtb = ManagementFactory.getRuntimeMXBean();
-                String processName = rtb.getName();
-                Pattern pattern = Pattern.compile("^([0-9]+)@.+$", Pattern.CASE_INSENSITIVE);
-                Matcher matcher = pattern.matcher(processName);
-                if (matcher.matches()) {
-                    int pid = Integer.parseInt(matcher.group(1));
-                    Writer w = new OutputStreamWriter(new FileOutputStream(pidFile));
-                    w.write(Integer.toString(pid));
-                    w.close();
-                }
+                int pid = Integer.parseInt(getPid());
+                Writer w = new OutputStreamWriter(new FileOutputStream(pidFile));
+                w.write(Integer.toString(pid));
+                w.close();
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -140,7 +138,6 @@ public class InstanceHelper {
     }
 
     static void setupShutdown(ConfigProperties config, Framework framework) {
-        writePid(config.pidFile);
         try {
             int port = config.shutdownPort;
             String host = config.shutdownHost;
diff --git a/main/src/main/java/org/apache/karaf/main/Main.java b/main/src/main/java/org/apache/karaf/main/Main.java
index 66b6a81..817a30d 100644
--- a/main/src/main/java/org/apache/karaf/main/Main.java
+++ b/main/src/main/java/org/apache/karaf/main/Main.java
@@ -240,7 +240,8 @@ public class Main {
         }
         String log4jConfigPath = System.getProperty("karaf.etc") + "/org.ops4j.pax.logging.cfg";
         BootstrapLogManager.setProperties(config.props, log4jConfigPath);
-        InstanceHelper.updateInstancePid(config.karafHome, config.karafBase, true);
+        /* KARAF-5798: write the PID whether or not the lock has been acquired */
+        InstanceHelper.writePid(config.pidFile);
         BootstrapLogManager.configureLogger(LOG);
 
         for (String provider : config.securityProviders) {
@@ -717,6 +718,8 @@ public class Main {
         @Override
         public void lockAquired() {
             LOG.info("Lock acquired. Setting startlevel to " + config.defaultStartLevel);
+            /* KARAF-5798: instance PID should reflect the current running master */
+            InstanceHelper.updateInstancePid(config.karafHome, config.karafBase, true);
             InstanceHelper.setupShutdown(config, framework);
             setStartLevel(config.defaultStartLevel);
         }
diff --git a/main/src/test/java/org/apache/karaf/main/MainLockingTest.java b/main/src/test/java/org/apache/karaf/main/MainLockingTest.java
index 78d5a32..46585ec 100644
--- a/main/src/test/java/org/apache/karaf/main/MainLockingTest.java
+++ b/main/src/test/java/org/apache/karaf/main/MainLockingTest.java
@@ -21,9 +21,12 @@ package org.apache.karaf.main;
 import static org.ops4j.pax.tinybundles.core.TinyBundles.withBnd;
 
 import java.io.File;
+import java.io.IOException;
 
 import org.apache.karaf.main.util.Utils;
+import org.junit.After;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 import org.ops4j.pax.tinybundles.core.TinyBundles;
 import org.osgi.framework.Bundle;
@@ -32,24 +35,36 @@ import org.osgi.framework.launch.Framework;
 import org.osgi.framework.startlevel.FrameworkStartLevel;
 
 public class MainLockingTest {
-    
-    @Test
-    public void testLostMasterLock() throws Exception {
+    private File home;
+
+    private File data;
+
+    @Before
+    public void setUp() throws IOException {
         File basedir = new File(getClass().getClassLoader().getResource("foo").getPath()).getParentFile();
-        File home = new File(basedir, "test-karaf-home");
-        File data = new File(home, "data");
+        home = new File(basedir, "test-karaf-home");
+        data = new File(home, "data");
 
         Utils.deleteDirectory(data);
 
-        String[] args = new String[0];
         System.setProperty("karaf.home", home.toString());
         System.setProperty("karaf.data", data.toString());
         System.setProperty("karaf.framework.factory", "org.apache.felix.framework.FrameworkFactory");
 
-        System.setProperty("karaf.lock","true");
-        System.setProperty("karaf.lock.delay","1000");
-        System.setProperty("karaf.lock.class","org.apache.karaf.main.MockLock");
+        System.setProperty("karaf.lock", "true");
+        System.setProperty("karaf.lock.delay", "1000");
+        System.setProperty("karaf.lock.class", "org.apache.karaf.main.MockLock");
+    }
+
+    @After
+    public void tearDown() {
+        home = null;
+        data = null;
+    }
 
+    @Test
+    public void testLostMasterLock() throws Exception {
+        String[] args = new String[0];
         Main main = new Main(args);
         main.launch();
         Framework framework = main.getFramework();
@@ -89,4 +104,72 @@ public class MainLockingTest {
         // exit framework + lock loop
         main.destroy();
     }    
+
+    @Test
+    public void testMasterWritesPid() throws Exception {
+        // use data because it's always deleted at the beginning of the test
+        File pidFile = new File(data, "test-karaf.pid");
+        System.setProperty("karaf.pid.file", pidFile.toString());
+
+        try {
+            Assert.assertFalse(pidFile.isFile());
+
+            String[] args = new String[0];
+            Main main = new Main(args);
+            main.launch();
+
+            Thread.sleep(1000);
+
+            Framework framework = main.getFramework();
+            FrameworkStartLevel sl = framework.adapt(FrameworkStartLevel.class);
+            Assert.assertEquals(100, sl.getStartLevel());
+
+            MockLock lock = (MockLock) main.getLock();
+
+            Assert.assertTrue(lock.lock());
+            Assert.assertTrue(lock.isAlive());
+            Assert.assertTrue(pidFile.isFile());
+
+            main.destroy();
+        } finally {
+            System.clearProperty("karaf.pid.file");
+        }
+    }
+
+    @Test
+    public void testSlaveWritesPid() throws Exception {
+        // simulate that the lock is not acquired (i.e. instance runs as slave)
+        System.setProperty("test.karaf.mocklock.initiallyLocked", "false");
+        System.setProperty("karaf.lock.level", "59");
+
+        // use data because it's always deleted at the beginning of the test
+        File pidFile = new File(data, "test-karaf.pid");
+        System.setProperty("karaf.pid.file", pidFile.toString());
+
+        try {
+            Assert.assertFalse(pidFile.isFile());
+
+            String[] args = new String[0];
+            Main main = new Main(args);
+            main.launch();
+
+            Thread.sleep(1000);
+
+            Framework framework = main.getFramework();
+            FrameworkStartLevel sl = framework.adapt(FrameworkStartLevel.class);
+            Assert.assertEquals(59, sl.getStartLevel());
+
+            MockLock lock = (MockLock) main.getLock();
+
+            Assert.assertFalse(lock.lock());
+            Assert.assertTrue(lock.isAlive());
+            Assert.assertTrue(pidFile.isFile());
+
+            main.destroy();
+        } finally {
+            System.clearProperty("test.karaf.mocklock.initiallyLocked");
+            System.clearProperty("karaf.lock.level");
+            System.clearProperty("karaf.pid.file");
+        }
+    }
 }
diff --git a/main/src/test/java/org/apache/karaf/main/MockLock.java b/main/src/test/java/org/apache/karaf/main/MockLock.java
index e2ac2b2..13b7564 100644
--- a/main/src/test/java/org/apache/karaf/main/MockLock.java
+++ b/main/src/test/java/org/apache/karaf/main/MockLock.java
@@ -31,6 +31,8 @@ public class MockLock implements Lock {
     private Object lockLock = new Object();
     
     public MockLock(Properties props) {
+        /* KARAF-5798: allow tests to simulate slave instances */
+        lock = Boolean.valueOf(System.getProperty("test.karaf.mocklock.initiallyLocked", "true"));
     }
     
     public boolean lock() throws Exception {