6543856: MonitorVmStartTerminate.sh fails intermittently
authoregahlin
Tue, 12 Nov 2013 17:40:26 +0100
changeset 21652 e935e26bd5ec
parent 21651 07756e24916a
child 21653 8cb51c29ab64
6543856: MonitorVmStartTerminate.sh fails intermittently Reviewed-by: sla, dholmes
jdk/test/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java
jdk/test/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.sh
jdk/test/sun/jvmstat/testlibrary/JavaProcess.java
--- a/jdk/test/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java	Tue Nov 12 16:59:51 2013 +0100
+++ b/jdk/test/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java	Tue Nov 12 17:40:26 2013 +0100
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import java.util.concurrent.CountDownLatch;
 import java.util.regex.*;
 import java.util.*;
 import java.net.URISyntaxException;
@@ -33,8 +34,6 @@
     private static final int SLEEPERS = 10;
     private static final int SLEEPTIME = 5000;     // sleep time for a sleeper
     private static final int EXECINTERVAL = 3000;   // wait time between exec's
-    private static final int JOINTIME = (SLEEPERS * EXECINTERVAL)
-                                        + SLEEPTIME * 2;
 
     public static void main(String args[]) throws Exception {
 
@@ -46,7 +45,8 @@
         MonitoredHost host = MonitoredHost.getMonitoredHost("localhost");
         host.setInterval(200);
 
-        SleeperListener listener = new SleeperListener(host, sleeperPattern);
+        Matcher matcher = Pattern.compile(sleeperPattern).matcher("");
+        SleeperListener listener = new SleeperListener(host, matcher, SLEEPERS);
         host.addHostListener(listener);
 
         SleeperStarter ss = new SleeperStarter(SLEEPERS, EXECINTERVAL,
@@ -56,212 +56,193 @@
         System.out.println("Waiting for "
                            + SLEEPERS + " sleepers to terminate");
         try {
-            ss.join(JOINTIME);
+            ss.join();
         } catch (InterruptedException e) {
-            System.err.println("Timed out waiting for sleepers");
-        }
-
-        if (listener.getStarted() != SLEEPERS) {
-            throw new RuntimeException(
-                    "Too few sleepers started: "
-                    + " started = " + listener.getStarted()
-                    + " SLEEPERS = " + SLEEPERS);
-        }
-
-        if (listener.getStarted() != listener.getTerminated()) {
-            throw new RuntimeException(
-                    "Started count != terminated count: "
-                    + " started = " + listener.getStarted()
-                    + " terminated = " + listener.getTerminated());
+            throw new Exception("Timed out waiting for sleepers");
         }
-    }
-}
-
-class SleeperListener implements HostListener {
-    private static final boolean DEBUG = false;
-
-    int started;
-    int terminated;
-    MonitoredHost host;
-    Matcher patternMatcher;
-    ArrayList targets;
-
-    public SleeperListener(MonitoredHost host, String sleeperPattern) {
-        this.host = host;
-        Pattern pattern = Pattern.compile(sleeperPattern);
-        patternMatcher = pattern.matcher("");
-        targets = new ArrayList();
+        listener.waitForSleepersToStart();
+        listener.waitForSleepersToTerminate();
     }
 
-    private void printList(Iterator i, String msg) {
-        System.out.println(msg + ":");
-        while (i.hasNext()) {
-            Integer lvmid = (Integer)i.next();
-            try {
-                VmIdentifier vmid = new VmIdentifier("//" + lvmid.intValue());
-                MonitoredVm target = host.getMonitoredVm(vmid);
+    public static class SleeperListener implements HostListener {
+
+        private final List<Integer> targets =  new ArrayList<>();
+        private final CountDownLatch terminateLatch;
+        private final CountDownLatch startLatch;
+        private final MonitoredHost host;
+        private final Matcher patternMatcher;
+
+        public SleeperListener(MonitoredHost host, Matcher matcher, int count) {
+            this.host = host;
+            this.patternMatcher = matcher;
+            this.terminateLatch = new CountDownLatch(count);
+            this.startLatch = new CountDownLatch(count);
+        }
+
+        public void waitForSleepersToTerminate() throws InterruptedException {
+            terminateLatch.await();
+        }
 
-                StringMonitor cmdMonitor =
-                        (StringMonitor)target.findByName("sun.rt.javaCommand");
-                String cmd = cmdMonitor.stringValue();
+        public void waitForSleepersToStart() throws InterruptedException {
+            startLatch.await();
+        }
+
+        private void printList(Set<Integer> list, String msg) {
+            System.out.println(msg + ":");
+            for (Integer lvmid : list) {
+                try {
+                    VmIdentifier vmid = new VmIdentifier("//" + lvmid.intValue());
+                    MonitoredVm target = host.getMonitoredVm(vmid);
 
-                System.out.println("\t" + lvmid.intValue() + ": "
-                                   + "\"" + cmd + "\"" + ": ");
-            } catch (URISyntaxException e) {
-                System.err.println("Unexpected URISyntaxException: "
-                                   + e.getMessage());
-            } catch (MonitorException e) {
-                System.out.println("\t" + lvmid.intValue()
-                                   + ": error reading monitoring data: "
-                                   + " target possibly terminated?");
+                    StringMonitor cmdMonitor =
+                            (StringMonitor)target.findByName("sun.rt.javaCommand");
+                    String cmd = cmdMonitor.stringValue();
+
+                    System.out.println("\t" + lvmid.intValue() + ": "
+                                       + "\"" + cmd + "\"" + ": ");
+                } catch (URISyntaxException e) {
+                    System.err.println("Unexpected URISyntaxException: "
+                                       + e.getMessage());
+                } catch (MonitorException e) {
+                    System.out.println("\t" + lvmid.intValue()
+                                       + ": error reading monitoring data: "
+                                       + " target possibly terminated?");
+                }
             }
         }
-    }
 
 
-    private int addStarted(Iterator i) {
-        int found = 0;
-        while (i.hasNext()) {
-            try {
-                Integer lvmid = (Integer)i.next();
-                VmIdentifier vmid = new VmIdentifier("//" + lvmid.intValue());
-                MonitoredVm target = host.getMonitoredVm(vmid);
+        private int addStarted(Set<Integer> started) {
+            int found = 0;
+            for (Integer lvmid : started) {
+                try {
+                    VmIdentifier vmid = new VmIdentifier("//" + lvmid.intValue());
+                    MonitoredVm target = host.getMonitoredVm(vmid);
+
+                    StringMonitor cmdMonitor =
+                            (StringMonitor)target.findByName("sun.rt.javaCommand");
+                    String cmd = cmdMonitor.stringValue();
+
+                    patternMatcher.reset(cmd);
+                    System.out.print("Started: " + lvmid.intValue()
+                                     + ": " + "\"" + cmd + "\"" + ": ");
 
-                StringMonitor cmdMonitor =
-                        (StringMonitor)target.findByName("sun.rt.javaCommand");
-                String cmd = cmdMonitor.stringValue();
+                    if (patternMatcher.matches()) {
+                        System.out.println("matches pattern - recorded");
+                        targets.add(lvmid);
+                        found++;
+                    }
+                    else {
+                        System.out.println("does not match pattern - ignored");
+                    }
+                } catch (URISyntaxException e) {
+                    System.err.println("Unexpected URISyntaxException: "
+                                       + e.getMessage());
+                } catch (MonitorException e) {
+                    System.err.println("Unexpected MonitorException: "
+                                       + e.getMessage());
+                }
+            }
+            return found;
+        }
 
-                patternMatcher.reset(cmd);
-                System.out.print("Started: " + lvmid.intValue()
-                                 + ": " + "\"" + cmd + "\"" + ": ");
-
-                if (patternMatcher.matches()) {
-                    System.out.println("matches pattern - recorded");
-                    targets.add(lvmid);
+        private int removeTerminated(Set<Integer> terminated) {
+            int found = 0;
+            for (Integer lvmid : terminated) {
+                /*
+                 * we don't attempt to attach to the target here as it's
+                 * now dead and has no jvmstat share memory file. Just see
+                 * if the process id is among those that we saved when we
+                 * started the targets (note - duplicated allowed and somewhat
+                 * expected on windows);
+                 */
+                System.out.print("Terminated: " + lvmid.intValue() + ": ");
+                if (targets.contains(lvmid)) {
+                    System.out.println("matches pattern - termination recorded");
+                    targets.remove(lvmid);
                     found++;
                 }
                 else {
                     System.out.println("does not match pattern - ignored");
                 }
-            } catch (URISyntaxException e) {
-                System.err.println("Unexpected URISyntaxException: "
-                                   + e.getMessage());
-            } catch (MonitorException e) {
-                System.err.println("Unexpected MonitorException: "
-                                   + e.getMessage());
+            }
+            return found;
+        }
+
+        @SuppressWarnings("unchecked")
+        public void vmStatusChanged(VmStatusChangeEvent ev) {
+            printList(ev.getActive(), "Active");
+            printList(ev.getStarted(), "Started");
+            printList(ev.getTerminated(), "Terminated");
+
+            int recentlyStarted = addStarted(ev.getStarted());
+            int recentlyTerminated = removeTerminated(ev.getTerminated());
+
+            for (int i = 0; i < recentlyTerminated; i++) {
+                terminateLatch.countDown();
+            }
+            for (int i = 0; i < recentlyStarted; i++) {
+                startLatch.countDown();
             }
         }
-        return found;
-    }
 
-    private int removeTerminated(Iterator i) {
-        int found = 0;
-        while (i.hasNext()) {
-            Integer lvmid = (Integer)i.next();
-            /*
-             * we don't attempt to attach to the target here as it's
-             * now dead and has no jvmstat share memory file. Just see
-             * if the process id is among those that we saved when we
-             * started the targets (note - duplicated allowed and somewhat
-             * expected on windows);
-             */
-            System.out.print("Terminated: " + lvmid.intValue() + ": ");
-            if (targets.contains(lvmid)) {
-                System.out.println("matches pattern - termination recorded");
-                targets.remove(lvmid);
-                found++;
-            }
-            else {
-                System.out.println("does not match pattern - ignored");
-            }
-        }
-        return found;
-    }
-
-    public synchronized int getStarted() {
-        return started;
-    }
-
-    public synchronized int getTerminated() {
-        return terminated;
-    }
-
-    public void vmStatusChanged(VmStatusChangeEvent ev) {
-        if (DEBUG) {
-            printList(ev.getActive().iterator(), "Active");
-            printList(ev.getStarted().iterator(), "Started");
-            printList(ev.getTerminated().iterator(), "Terminated");
-        }
-
-        int recentlyStarted = addStarted(ev.getStarted().iterator());
-        int recentlyTerminated = removeTerminated(
-                ev.getTerminated().iterator());
-
-        synchronized (this) {
-            started += recentlyStarted;
-            terminated += recentlyTerminated;
+        public void disconnected(HostEvent ev) {
         }
     }
 
-    public void disconnected(HostEvent ev) {
+    public static class SleeperStarter extends Thread {
+
+        private final JavaProcess[] processes;
+        private final int execInterval;
+        private final String args;
+
+        public SleeperStarter(int sleepers, int execInterval, String args) {
+            this.execInterval = execInterval;
+            this.args = args;
+            this.processes = new JavaProcess[sleepers];
+        }
+
+        private synchronized int active() {
+            int active = processes.length;
+            for(JavaProcess jp : processes) {
+                try {
+                    jp.exitValue();
+                    active--;
+                } catch (IllegalThreadStateException e) {
+                    // process hasn't exited yet
+                }
+            }
+            return active;
+        }
+
+        public void run() {
+           System.out.println("Starting " + processes.length + " sleepers");
+
+           String[] classpath = {
+               "-classpath",
+               System.getProperty("java.class.path")
+           };
+
+           for (int i = 0; i < processes.length; i++) {
+               try {
+                   System.out.println("Starting Sleeper " + i);
+                   synchronized(this) {
+                       processes[i] = new JavaProcess("Sleeper", args + " " + i);
+                       processes[i].addOptions(classpath);
+                   }
+                   processes[i].start();
+                   Thread.sleep(execInterval);
+               } catch (InterruptedException ignore) {
+               } catch (IOException e) {
+                   System.err.println(
+                           "IOException trying to start Sleeper " + i + ": "
+                           + e.getMessage());
+               }
+           }
+
+           // spin waiting for the processes to terminate
+           while (active() > 0) ;
+        }
     }
 }
 
-class SleeperStarter extends Thread {
-
-    JavaProcess[] processes;
-    int execInterval;
-    String args;
-
-    public SleeperStarter(int sleepers, int execInterval, String args) {
-        this.execInterval = execInterval;
-        this.args = args;
-        this.processes = new JavaProcess[sleepers];
-    }
-
-    private synchronized int active() {
-        int active = processes.length;
-        for(int i = 0; i < processes.length; i++) {
-            try {
-                int exitValue = processes[i].exitValue();
-                active--;
-            } catch (IllegalThreadStateException e) {
-                // process hasn't exited yet
-            }
-        }
-        return active;
-    }
-
-    public void run() {
-       System.out.println("Starting " + processes.length + " sleepers");
-
-       String[] classpath = {
-           "-classpath",
-           System.getProperty("java.class.path")
-       };
-
-       for (int i = 0; i < processes.length; i++) {
-           try {
-               System.out.println("Starting Sleeper " + i);
-               synchronized(this) {
-                   processes[i] = new JavaProcess("Sleeper", args + " " + i);
-                   processes[i].addOptions(classpath);
-               }
-               processes[i].start();
-               Thread.sleep(execInterval);
-           } catch (InterruptedException ignore) {
-           } catch (IOException e) {
-               System.err.println(
-                       "IOException trying to start Sleeper " + i + ": "
-                       + e.getMessage());
-           }
-       }
-
-       // spin waiting for the processes to terminate
-       while (active() > 0) ;
-
-       // give final termination event a change to propogate to
-       // the HostListener
-       try { Thread.sleep(2000); } catch (InterruptedException ignore) { }
-    }
-}
--- a/jdk/test/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.sh	Tue Nov 12 16:59:51 2013 +0100
+++ b/jdk/test/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.sh	Tue Nov 12 17:40:26 2013 +0100
@@ -23,7 +23,6 @@
 
 #
 # @test
-# @ignore until 6543856 is fixed
 # @bug 4990825
 # @summary attach to external but local JVM processes
 # @library ../../testlibrary
--- a/jdk/test/sun/jvmstat/testlibrary/JavaProcess.java	Tue Nov 12 16:59:51 2013 +0100
+++ b/jdk/test/sun/jvmstat/testlibrary/JavaProcess.java	Tue Nov 12 17:40:26 2013 +0100
@@ -26,7 +26,6 @@
  */
 
 import java.io.*;
-import java.util.Properties;
 
 public class JavaProcess {