1/* 2 * Copyright (c) 2004, 2017, 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 * @key randomness 28 * @summary Test that monitors can sample a large number of attributes 29 * @author Eamonn McManus 30 * 31 * @run clean MultiMonitorTest 32 * @run build MultiMonitorTest 33 * @run main MultiMonitorTest 34 */ 35 36import java.util.*; 37import javax.management.*; 38import javax.management.monitor.*; 39 40/* We create N MBeans and three monitors, one for each different 41 monitor type. Each monitor monitors a single attribute in each of 42 the N MBeans. We arrange for the trigger condition to be 43 satisfied, so the listener we register on each monitor should get N 44 notifications. */ 45public class MultiMonitorTest { 46 static final int N = 100; 47 static final ObjectName[] mbeanNames = new ObjectName[N]; 48 static final Monitored[] monitored = new Monitored[N]; 49 static final int COUNTER_THRESHOLD = 1000; 50 static final int OVER_COUNTER_THRESHOLD = 2000; 51 static final double GAUGE_THRESHOLD = 1000.0; 52 static final double OVER_GAUGE_THRESHOLD = 2000.0; 53 static final String STRING_TO_COMPARE = "chou"; 54 static final String DIFFERENT_STRING = "chevre"; 55 56 public static void main(String[] args) throws Exception { 57 System.out.println("Test that monitors can sample a large " + 58 "number of attributes"); 59 60 final MBeanServer mbs = MBeanServerFactory.createMBeanServer(); 61 for (int i = 0; i < N; i++) { 62 mbeanNames[i] = new ObjectName(":type=Monitored,instance=" + i); 63 monitored[i] = new Monitored(); 64 mbs.registerMBean(monitored[i], mbeanNames[i]); 65 } 66 final ObjectName counterMonitor = 67 new ObjectName(":type=CounterMonitor"); 68 final ObjectName gaugeMonitor = 69 new ObjectName(":type=GaugeMonitor"); 70 final ObjectName stringMonitor = 71 new ObjectName(":type=StringMonitor"); 72 final ObjectName[] monitorNames = 73 new ObjectName[] {counterMonitor, gaugeMonitor, stringMonitor}; 74 final String[] attrNames = 75 new String[] {"CounterValue", "GaugeValue", "StringValue"}; 76 mbs.createMBean(CounterMonitor.class.getName(), counterMonitor); 77 mbs.createMBean(GaugeMonitor.class.getName(), gaugeMonitor); 78 mbs.createMBean(StringMonitor.class.getName(), stringMonitor); 79 final CounterMonitorMBean counterProxy = (CounterMonitorMBean) 80 MBeanServerInvocationHandler 81 .newProxyInstance(mbs, counterMonitor, CounterMonitorMBean.class, 82 false); 83 final GaugeMonitorMBean gaugeProxy = (GaugeMonitorMBean) 84 MBeanServerInvocationHandler 85 .newProxyInstance(mbs, gaugeMonitor, GaugeMonitorMBean.class, 86 false); 87 final StringMonitorMBean stringProxy = (StringMonitorMBean) 88 MBeanServerInvocationHandler 89 .newProxyInstance(mbs, stringMonitor, StringMonitorMBean.class, 90 false); 91 final MonitorMBean[] proxies = new MonitorMBean[] { 92 counterProxy, gaugeProxy, stringProxy, 93 }; 94 for (int i = 0; i < 3; i++) { 95 proxies[i].setGranularityPeriod(1); 96 proxies[i].setObservedAttribute(attrNames[i]); 97 for (int j = 0; j < N; j++) 98 proxies[i].addObservedObject(mbeanNames[j]); 99 } 100 101 final CountListener[] listeners = new CountListener[] { 102 new CountListener(), new CountListener(), new CountListener() 103 }; 104 for (int i = 0; i < 3; i++) { 105 mbs.addNotificationListener(monitorNames[i], listeners[i], 106 null, null); 107 } 108 109 counterProxy.setInitThreshold(new Integer(COUNTER_THRESHOLD)); 110 counterProxy.setNotify(true); 111 gaugeProxy.setThresholds(new Double(GAUGE_THRESHOLD), new Double(0.0)); 112 gaugeProxy.setNotifyHigh(true); 113 stringProxy.setStringToCompare(STRING_TO_COMPARE); 114 stringProxy.setNotifyDiffer(true); 115 116 // A couple of granularity periods to detect bad behaviour 117 Thread.sleep(2); 118 119 System.out.println("Checking for all listeners to be 0"); 120 if (!listenersAreAll(0, listeners)) { 121 System.out.println("TEST FAILED: listeners not all 0"); 122 System.exit(1); 123 } 124 125 for (int i = 0; i < 3; i++) 126 proxies[i].start(); 127 128 System.out.println("Waiting for listeners to all : " + N); 129 int iterations = 0; 130 while (!listenersAreAll(N, listeners)) { 131 Thread.sleep(500); 132 133 if (++iterations == 10) { 134 for (int i = 0; i < listeners.length; i++) { 135 System.out.print(" " + listeners[i].getCount()); 136 } 137 System.out.println(); 138 iterations = 0; 139 } 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} 227