J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. |
| 8 | * |
| 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 12 | * version 2 for more details (a copy is included in the LICENSE file that |
| 13 | * accompanied this code). |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License version |
| 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 18 | * |
| 19 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 21 | * have any questions. |
| 22 | */ |
| 23 | |
| 24 | import java.util.regex.*; |
| 25 | import java.util.*; |
| 26 | import java.net.URISyntaxException; |
| 27 | import java.io.IOException; |
| 28 | import sun.jvmstat.monitor.*; |
| 29 | import sun.jvmstat.monitor.event.*; |
| 30 | |
| 31 | public class MonitorVmStartTerminate { |
| 32 | |
| 33 | private static final int SLEEPERS = 10; |
| 34 | private static final int SLEEPTIME = 5000; // sleep time for a sleeper |
| 35 | private static final int EXECINTERVAL = 3000; // wait time between exec's |
| 36 | private static final int JOINTIME = (SLEEPERS * EXECINTERVAL) |
| 37 | + SLEEPTIME * 2; |
| 38 | |
| 39 | public static void main(String args[]) throws Exception { |
| 40 | |
| 41 | long now = System.currentTimeMillis(); |
| 42 | |
| 43 | String sleeperArgs = SLEEPTIME + " " + now; |
| 44 | String sleeperPattern = "Sleeper " + sleeperArgs + " \\d+$"; |
| 45 | |
| 46 | MonitoredHost host = MonitoredHost.getMonitoredHost("localhost"); |
| 47 | host.setInterval(200); |
| 48 | |
| 49 | SleeperListener listener = new SleeperListener(host, sleeperPattern); |
| 50 | host.addHostListener(listener); |
| 51 | |
| 52 | SleeperStarter ss = new SleeperStarter(SLEEPERS, EXECINTERVAL, |
| 53 | sleeperArgs); |
| 54 | ss.start(); |
| 55 | |
| 56 | System.out.println("Waiting for " |
| 57 | + SLEEPERS + " sleepers to terminate"); |
| 58 | try { |
| 59 | ss.join(JOINTIME); |
| 60 | } catch (InterruptedException e) { |
| 61 | System.err.println("Timed out waiting for sleepers"); |
| 62 | } |
| 63 | |
| 64 | if (listener.getStarted() != SLEEPERS) { |
| 65 | throw new RuntimeException( |
| 66 | "Too few sleepers started: " |
| 67 | + " started = " + listener.getStarted() |
| 68 | + " SLEEPERS = " + SLEEPERS); |
| 69 | } |
| 70 | |
| 71 | if (listener.getStarted() != listener.getTerminated()) { |
| 72 | throw new RuntimeException( |
| 73 | "Started count != terminated count: " |
| 74 | + " started = " + listener.getStarted() |
| 75 | + " terminated = " + listener.getTerminated()); |
| 76 | } |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | class SleeperListener implements HostListener { |
| 81 | private static final boolean DEBUG = false; |
| 82 | |
| 83 | int started; |
| 84 | int terminated; |
| 85 | MonitoredHost host; |
| 86 | Matcher patternMatcher; |
| 87 | ArrayList targets; |
| 88 | |
| 89 | public SleeperListener(MonitoredHost host, String sleeperPattern) { |
| 90 | this.host = host; |
| 91 | Pattern pattern = Pattern.compile(sleeperPattern); |
| 92 | patternMatcher = pattern.matcher(""); |
| 93 | targets = new ArrayList(); |
| 94 | } |
| 95 | |
| 96 | private void printList(Iterator i, String msg) { |
| 97 | System.out.println(msg + ":"); |
| 98 | while (i.hasNext()) { |
| 99 | Integer lvmid = (Integer)i.next(); |
| 100 | try { |
| 101 | VmIdentifier vmid = new VmIdentifier("//" + lvmid.intValue()); |
| 102 | MonitoredVm target = host.getMonitoredVm(vmid); |
| 103 | |
| 104 | StringMonitor cmdMonitor = |
| 105 | (StringMonitor)target.findByName("sun.rt.javaCommand"); |
| 106 | String cmd = cmdMonitor.stringValue(); |
| 107 | |
| 108 | System.out.println("\t" + lvmid.intValue() + ": " |
| 109 | + "\"" + cmd + "\"" + ": "); |
| 110 | } catch (URISyntaxException e) { |
| 111 | System.err.println("Unexpected URISyntaxException: " |
| 112 | + e.getMessage()); |
| 113 | } catch (MonitorException e) { |
| 114 | System.out.println("\t" + lvmid.intValue() |
| 115 | + ": error reading monitoring data: " |
| 116 | + " target possibly terminated?"); |
| 117 | } |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | |
| 122 | private int addStarted(Iterator i) { |
| 123 | int found = 0; |
| 124 | while (i.hasNext()) { |
| 125 | try { |
| 126 | Integer lvmid = (Integer)i.next(); |
| 127 | VmIdentifier vmid = new VmIdentifier("//" + lvmid.intValue()); |
| 128 | MonitoredVm target = host.getMonitoredVm(vmid); |
| 129 | |
| 130 | StringMonitor cmdMonitor = |
| 131 | (StringMonitor)target.findByName("sun.rt.javaCommand"); |
| 132 | String cmd = cmdMonitor.stringValue(); |
| 133 | |
| 134 | patternMatcher.reset(cmd); |
| 135 | System.out.print("Started: " + lvmid.intValue() |
| 136 | + ": " + "\"" + cmd + "\"" + ": "); |
| 137 | |
| 138 | if (patternMatcher.matches()) { |
| 139 | System.out.println("matches pattern - recorded"); |
| 140 | targets.add(lvmid); |
| 141 | found++; |
| 142 | } |
| 143 | else { |
| 144 | System.out.println("does not match pattern - ignored"); |
| 145 | } |
| 146 | } catch (URISyntaxException e) { |
| 147 | System.err.println("Unexpected URISyntaxException: " |
| 148 | + e.getMessage()); |
| 149 | } catch (MonitorException e) { |
| 150 | System.err.println("Unexpected MonitorException: " |
| 151 | + e.getMessage()); |
| 152 | } |
| 153 | } |
| 154 | return found; |
| 155 | } |
| 156 | |
| 157 | private int removeTerminated(Iterator i) { |
| 158 | int found = 0; |
| 159 | while (i.hasNext()) { |
| 160 | Integer lvmid = (Integer)i.next(); |
| 161 | /* |
| 162 | * we don't attempt to attach to the target here as it's |
| 163 | * now dead and has no jvmstat share memory file. Just see |
| 164 | * if the process id is among those that we saved when we |
| 165 | * started the targets (note - duplicated allowed and somewhat |
| 166 | * expected on windows); |
| 167 | */ |
| 168 | System.out.print("Terminated: " + lvmid.intValue() + ": "); |
| 169 | if (targets.contains(lvmid)) { |
| 170 | System.out.println("matches pattern - termination recorded"); |
| 171 | targets.remove(lvmid); |
| 172 | found++; |
| 173 | } |
| 174 | else { |
| 175 | System.out.println("does not match pattern - ignored"); |
| 176 | } |
| 177 | } |
| 178 | return found; |
| 179 | } |
| 180 | |
| 181 | public synchronized int getStarted() { |
| 182 | return started; |
| 183 | } |
| 184 | |
| 185 | public synchronized int getTerminated() { |
| 186 | return terminated; |
| 187 | } |
| 188 | |
| 189 | public void vmStatusChanged(VmStatusChangeEvent ev) { |
| 190 | if (DEBUG) { |
| 191 | printList(ev.getActive().iterator(), "Active"); |
| 192 | printList(ev.getStarted().iterator(), "Started"); |
| 193 | printList(ev.getTerminated().iterator(), "Terminated"); |
| 194 | } |
| 195 | |
| 196 | int recentlyStarted = addStarted(ev.getStarted().iterator()); |
| 197 | int recentlyTerminated = removeTerminated( |
| 198 | ev.getTerminated().iterator()); |
| 199 | |
| 200 | synchronized (this) { |
| 201 | started += recentlyStarted; |
| 202 | terminated += recentlyTerminated; |
| 203 | } |
| 204 | } |
| 205 | |
| 206 | public void disconnected(HostEvent ev) { |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | class SleeperStarter extends Thread { |
| 211 | |
| 212 | JavaProcess[] processes; |
| 213 | int execInterval; |
| 214 | String args; |
| 215 | |
| 216 | public SleeperStarter(int sleepers, int execInterval, String args) { |
| 217 | this.execInterval = execInterval; |
| 218 | this.args = args; |
| 219 | this.processes = new JavaProcess[sleepers]; |
| 220 | } |
| 221 | |
| 222 | private synchronized int active() { |
| 223 | int active = processes.length; |
| 224 | for(int i = 0; i < processes.length; i++) { |
| 225 | try { |
| 226 | int exitValue = processes[i].exitValue(); |
| 227 | active--; |
| 228 | } catch (IllegalThreadStateException e) { |
| 229 | // process hasn't exited yet |
| 230 | } |
| 231 | } |
| 232 | return active; |
| 233 | } |
| 234 | |
| 235 | public void run() { |
| 236 | System.out.println("Starting " + processes.length + " sleepers"); |
| 237 | |
| 238 | String[] classpath = { |
| 239 | "-classpath", |
| 240 | System.getProperty("java.class.path") |
| 241 | }; |
| 242 | |
| 243 | for (int i = 0; i < processes.length; i++) { |
| 244 | try { |
| 245 | System.out.println("Starting Sleeper " + i); |
| 246 | synchronized(this) { |
| 247 | processes[i] = new JavaProcess("Sleeper", args + " " + i); |
| 248 | processes[i].addOptions(classpath); |
| 249 | } |
| 250 | processes[i].start(); |
| 251 | Thread.sleep(execInterval); |
| 252 | } catch (InterruptedException ignore) { |
| 253 | } catch (IOException e) { |
| 254 | System.err.println( |
| 255 | "IOException trying to start Sleeper " + i + ": " |
| 256 | + e.getMessage()); |
| 257 | } |
| 258 | } |
| 259 | |
| 260 | // spin waiting for the processes to terminate |
| 261 | while (active() > 0) ; |
| 262 | |
| 263 | // give final termination event a change to propogate to |
| 264 | // the HostListener |
| 265 | try { Thread.sleep(2000); } catch (InterruptedException ignore) { } |
| 266 | } |
| 267 | } |