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