1 /* 2 * Copyright (c) 2004, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 4984057 27 * @summary Test that monitors can sample a large number of attributes 28 * @author Eamonn McManus 29 * @run clean MultiMonitorTest 30 * @run build MultiMonitorTest 31 * @run main MultiMonitorTest 32 */ 33 34 import java.util.*; 35 import javax.management.*; 36 import javax.management.monitor.*; 37 38 /* We create N MBeans and three monitors, one for each different 39 monitor type. Each monitor monitors a single attribute in each of 40 the N MBeans. We arrange for the trigger condition to be 41 satisfied, so the listener we register on each monitor should get N 42 notifications. */ 43 public class MultiMonitorTest { 44 static final int N = 100; 45 static final ObjectName[] mbeanNames = new ObjectName[N]; 46 static final Monitored[] monitored = new Monitored[N]; 47 static final int COUNTER_THRESHOLD = 1000; 48 static final int OVER_COUNTER_THRESHOLD = 2000; 49 static final double GAUGE_THRESHOLD = 1000.0; 50 static final double OVER_GAUGE_THRESHOLD = 2000.0; 51 static final String STRING_TO_COMPARE = "chou"; 52 static final String DIFFERENT_STRING = "chevre"; 53 54 public static void main(String[] args) throws Exception { 55 System.out.println("Test that monitors can sample a large " + 56 "number of attributes"); 57 58 final MBeanServer mbs = MBeanServerFactory.createMBeanServer(); 59 for (int i = 0; i < N; i++) { 60 mbeanNames[i] = new ObjectName(":type=Monitored,instance=" + i); 61 monitored[i] = new Monitored(); 62 mbs.registerMBean(monitored[i], mbeanNames[i]); 63 } 64 final ObjectName counterMonitor = 65 new ObjectName(":type=CounterMonitor"); 66 final ObjectName gaugeMonitor = 67 new ObjectName(":type=GaugeMonitor"); 68 final ObjectName stringMonitor = 69 new ObjectName(":type=StringMonitor"); 70 final ObjectName[] monitorNames = 71 new ObjectName[] {counterMonitor, gaugeMonitor, stringMonitor}; 72 final String[] attrNames = 73 new String[] {"CounterValue", "GaugeValue", "StringValue"}; 74 mbs.createMBean(CounterMonitor.class.getName(), counterMonitor); 75 mbs.createMBean(GaugeMonitor.class.getName(), gaugeMonitor); 76 mbs.createMBean(StringMonitor.class.getName(), stringMonitor); 77 final CounterMonitorMBean counterProxy = (CounterMonitorMBean) 78 MBeanServerInvocationHandler 79 .newProxyInstance(mbs, counterMonitor, CounterMonitorMBean.class, 80 false); 81 final GaugeMonitorMBean gaugeProxy = (GaugeMonitorMBean) 82 MBeanServerInvocationHandler 83 .newProxyInstance(mbs, gaugeMonitor, GaugeMonitorMBean.class, 84 false); 85 final StringMonitorMBean stringProxy = (StringMonitorMBean) 86 MBeanServerInvocationHandler 87 .newProxyInstance(mbs, stringMonitor, StringMonitorMBean.class, 88 false); 89 final MonitorMBean[] proxies = new MonitorMBean[] { 90 counterProxy, gaugeProxy, stringProxy, 91 }; 92 for (int i = 0; i < 3; i++) { 93 proxies[i].setGranularityPeriod(1); 94 proxies[i].setObservedAttribute(attrNames[i]); 95 for (int j = 0; j < N; j++) 96 proxies[i].addObservedObject(mbeanNames[j]); 97 } 98 99 final CountListener[] listeners = new CountListener[] { 100 new CountListener(), new CountListener(), new CountListener() 101 }; 102 for (int i = 0; i < 3; i++) { 103 mbs.addNotificationListener(monitorNames[i], listeners[i], 104 null, null); 105 } 106 107 counterProxy.setInitThreshold(new Integer(COUNTER_THRESHOLD)); 108 counterProxy.setNotify(true); 109 gaugeProxy.setThresholds(new Double(GAUGE_THRESHOLD), new Double(0.0)); 110 gaugeProxy.setNotifyHigh(true); 111 stringProxy.setStringToCompare(STRING_TO_COMPARE); 112 stringProxy.setNotifyDiffer(true); 113 114 // A couple of granularity periods to detect bad behaviour 115 Thread.sleep(2); 116 117 if (!listenersAreAll(0, listeners)) { 118 System.out.println("TEST FAILED: listeners not all 0"); 119 System.exit(1); 120 } 121 122 for (int i = 0; i < 3; i++) 123 proxies[i].start(); 124 125 long startTime = System.currentTimeMillis(); 126 while (!listenersAreAll(N, listeners) 127 && System.currentTimeMillis() < startTime + 5000) 128 Thread.sleep(1); 129 130 // More time for bad behaviour 131 Thread.sleep(1000); 132 133 if (!listenersAreAll(N, listeners)) { 134 System.out.print("TEST FAILED: listener counts wrong:"); 135 for (int i = 0; i < listeners.length; i++) 136 System.out.print(" " + listeners[i].getCount()); 137 System.out.println(); 138 System.exit(1); 139 } 140 141 for (int i = 0; i < 3; i++) { 142 proxies[i].stop(); 143 for (int j = 0; j < N; j++) 144 proxies[i].removeObservedObject(mbeanNames[j]); 145 ObjectName[] observed = proxies[i].getObservedObjects(); 146 if (observed.length != 0) { 147 System.out.println("TEST FAILED: not all observed objects " + 148 "removed: " + Arrays.asList(observed)); 149 System.exit(1); 150 } 151 } 152 153 System.out.println("Test passed"); 154 } 155 156 public static interface MonitoredMBean { 157 public int getCounterValue(); 158 public double getGaugeValue(); 159 public String getStringValue(); 160 } 161 162 public static class Monitored implements MonitoredMBean { 163 /* We give a small random number of normal readings (possibly 164 zero) before giving a reading that provokes a 165 notification. */ 166 private int okCounter = randomInt(5); 167 private int okGauge = randomInt(5); 168 private int okString = randomInt(5); 169 170 public synchronized int getCounterValue() { 171 if (--okCounter >= 0) 172 return 0; 173 else 174 return OVER_COUNTER_THRESHOLD; 175 } 176 177 public synchronized double getGaugeValue() { 178 if (--okGauge >= 0) 179 return 0.0; 180 else 181 return OVER_GAUGE_THRESHOLD; 182 } 183 184 public synchronized String getStringValue() { 185 if (--okString >= 0) 186 return STRING_TO_COMPARE; 187 else 188 return DIFFERENT_STRING; 189 } 190 } 191 192 public static class CountListener implements NotificationListener { 193 private int count; 194 195 public synchronized void handleNotification(Notification n, Object h) { 196 if (!(n instanceof MonitorNotification)) { 197 System.out.println("TEST FAILED: bad notif: " + 198 n.getClass().getName()); 199 System.exit(1); 200 } 201 if (n.getType().indexOf("error") >= 0) { 202 System.out.println("TEST FAILED: error notif: " + n.getType()); 203 System.exit(1); 204 } 205 count++; 206 } 207 208 public synchronized int getCount() { 209 return count; 210 } 211 } 212 213 private static boolean listenersAreAll(int n, CountListener[] listeners) { 214 for (int i = 0; i < listeners.length; i++) { 215 if (listeners[i].getCount() != n) 216 return false; 217 } 218 return true; 219 } 220 221 private static final Random random = new Random(); 222 static synchronized int randomInt(int n) { 223 return random.nextInt(n); 224 } 225 }