diff -r 746229cc1ab0 -r cc29d7717e3a test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/MemoryMonitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/MemoryMonitor.java Wed May 02 16:43:56 2018 -0700 @@ -0,0 +1,1611 @@ +/* + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package nsk.monitoring.share; + +import java.lang.management.*; +import javax.management.*; +import javax.management.openmbean.*; +import java.util.*; + +import nsk.share.*; + +/** + * MemoryMonitor class is a wrapper of MemoryMXBean and + * MemoryPoolMXBean interfaces. Depending on command line arguments, + * an instance of this class redirects invocations to the + * MemoryMXBean (or MemoryPoolMXBean) interface. If + * -testMode="directly" option is set, this instance directly + * invokes corresponding method of the MemoryMXBean (or + * MemoryPoolMXBean) interface. If -testMode="server" + * option is set it will make invocations via MBeanServer. + * + * @see ArgumentHandler + */ +public class MemoryMonitor extends Monitor implements NotificationListener, + NotificationFilter { + + // Constants to define type of memory that will be allocated in + // MemoryMonitor. For heap memory objects will be allocated; for nonheap + // type classes will be loaded; for mixed type -- both (objects will be + // allocated and classes will be loaded). + public final static String HEAP_TYPE = "heap"; + public final static String NONHEAP_TYPE = "nonheap"; + public final static String MIXED_TYPE = "mixed"; + // Names of the attributes of MemoryMXBean + private final static String POOL_TYPE = "Type"; + private final static String POOL_RESET_PEAK = "resetPeakUsage"; + private final static String POOL_PEAK = "PeakUsage"; + private final static String POOL_VALID = "Valid"; + private final static String POOL_U = "Usage"; + private final static String UT = "UsageThreshold"; + private final static String UT_COUNT = "UsageThresholdCount"; + private final static String UT_SUPPORT = "UsageThresholdSupported"; + private final static String UT_EXCEEDED = "UsageThresholdExceeded"; + private final static String POOL_CU = "CollectionUsage"; + private final static String CT = "CollectionUsageThreshold"; + private final static String CT_COUNT = "CollectionUsageThresholdCount"; + private final static String CT_SUPPORT = "CollectionUsageThresholdSupported"; + private final static String CT_EXCEEDED = "CollectionUsageThresholdExceeded"; + // Varibales to store options that are passed to the test + private static String memory; + private static int mode; + private static boolean isNotification; + private static boolean isUsageThreshold; + private static volatile boolean passed = true; + private Polling polling = new Polling(); + + static { + Monitor.logPrefix = "MemoryMonitor > "; + } + + /** + * Creates a new MemoryMonitor object. + * + * @param log Log object to print info to. + * @param handler ArgumentHandler object that saves + * all info about test's arguments. + * + */ + public MemoryMonitor(Log log, ArgumentHandler handler) { + super(log, handler); + + memory = handler.getTestedMemory(); + mode = getTestMode(); + isNotification = (handler.MON_NOTIF.equals(handler.getMonitoring())); + isUsageThreshold = (handler.TH_USAGE.equals(handler.getThreshold())); + + String s = "\t(This setting is used in lowmem* tests only)"; + + display("Memory:\t" + handler.getTestedMemory() + s); + display("Monitoring:\t" + handler.getMonitoring() + s); + display("Threshold:\t" + handler.getThreshold() + s); + display("Timeout:\t" + handler.getTimeout() + s); + } + + /** + * Returns true if no failures were revealed during the test, + * false otherwise. + * + * @return true if no failures were revealed during the test, + * false otherwise. + * + */ + public boolean getPassedStatus() { + return passed; + } + + /** + * Enables memory monitoring. + *

+ * If notification type of monitoring is chosen, the method adds {@link + * javax.management.NotificationListener + * javax.management.NotificationListener} to enables low + * memory detection support. If monitoring type is polling, a new thread + * that manages the low memory detection is started. + * + * @throws InstanceNotFoundException The MemoryMXBean is not registered on + * the server. + */ + public void enableMonitoring() throws InstanceNotFoundException { + if (isNotification) { + switch (mode) { + case DIRECTLY_MODE: + MemoryMXBean mbean = ManagementFactory.getMemoryMXBean(); + NotificationEmitter emitter = (NotificationEmitter) mbean; + emitter.addNotificationListener(this, this, null); + break; + + case SERVER_MODE: + case PROXY_MODE: + getMBeanServer().addNotificationListener(mbeanObjectName, + this, this, null); + break; + + default: + throw new TestBug("Unknown testMode " + mode); + } + } else { + + // Polling + // Start a thread that will manage all test modes + polling.start(); + + } + } // enableMonitoring() + + /** + * Disables memory monitoring. + *

+ * If monitoring type is polling, the thread that manages the low memory + * detection is stopped. + */ + public void disableMonitoring() { + if (!isNotification) { + + // Stop polling thread + polling.goOn = false; + } + } // disableMonitoring() + + /** + * Updates thresholds. Thresholds values for all pools will be greater + * than used value. + *

+ * If usage thresholds are chosen, the method updates just + * pools that support usage thresholds. If collection + * thresholds are chosen, the method updates memory pools that support + * collection usage thresholds. + * + * This method is synchronized because it may be invoked from + * handleNotification which is potentially done from + * multiple threads. + */ + public synchronized void updateThresholds() { + if (isUsageThreshold) { + updateUsageThresholds(); + } else { + updateCollectionThresholds(); + } + } + + /** + * Reset thresholds. Thresholds values for all pools will be 1. + * If usage thresholds are chosen, the method updates just + * pools that support usage thresholds. If collection + * thresholds are chosen, the method updates memory pools that support + * collection usage thresholds. + * + * This method is synchronized because it may be invoked from + * multiple threads. + */ + public synchronized void resetThresholds(MemoryType type) { + List pools = getMemoryPoolMBeans(); + for (int i = 0; i < pools.size(); i++) { + Object pool = pools.get(i); + if (isUsageThresholdSupported(pool)) { + if (getType(pool).equals(type)) { + setUsageThreshold(pool, 1); + } + } + } + } + + /** + * The method is invoked before sending the notification to the listener. + * + * @param notification The notification to be sent. + * @return true if the notification has to be sent to the listener; + * false otherwise. + * + * @see javax.management.NotificationFilter + */ + public boolean isNotificationEnabled(Notification notification) { + String type = notification.getType(); + String usage = MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED; + String collection = MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED; + + if (isUsageThreshold) { + return type.equals(usage); + } else { + return type.equals(collection); + } + } // isNotificationEnabled() + + /** + * The method is invoked when a JMX notification occurs. + * + * @param notification The notification to be sent. + * @param handback An opaque object which helps the listener to associate + * information regarding the MBean emitter. + * @see javax.management.NotificationListener + */ + public void handleNotification(Notification notification, Object handback) { + CompositeData data = (CompositeData) notification.getUserData(); + MemoryNotificationInfo mn = MemoryNotificationInfo.from(data); + + display(mn.getCount() + " notification \"" + notification.getMessage() + + "\" is caught on " + (new Date(notification.getTimeStamp())) + + " by " + mn.getPoolName() + " (" + mn.getUsage() + ")"); + updateThresholds(); + } // handleNotification() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#resetPeakUsage + * MemoryPoolMXBean.resetPeakUsage()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + */ + public void resetPeakUsage(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + directPool.resetPeakUsage(); + break; + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + + try { + getMBeanServer().invoke(serverPool, POOL_RESET_PEAK, + null, null); + } catch (Exception e) { + e.printStackTrace(logger.getOutStream()); + throw new Failure(e); + } + break; + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + proxyPool.resetPeakUsage(); + break; + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // resetPeakUsage() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#getPeakUsage + * MemoryPoolMXBean.getPeakUsage()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @return a MemoryUsage object representing the peak memory + * usage; null otherwise. + */ + public MemoryUsage getPeakUsage(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + return directPool.getPeakUsage(); + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + return getMemoryUsageAttribute(serverPool, POOL_PEAK); + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + return proxyPool.getPeakUsage(); + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // getPeakUsage() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#getUsage + * MemoryPoolMXBean.getUsage()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @return a MemoryUsage object; or null if this + * pool not valid. + */ + public MemoryUsage getUsage(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + return directPool.getUsage(); + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + return getUsageOnServer(serverPool); + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + return proxyPool.getUsage(); + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // getUsage() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#getCollectionUsage + * MemoryPoolMXBean.getCollectionUsage()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @return a MemoryUsage object; or null if this + * method is not supported. + */ + public MemoryUsage getCollectionUsage(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + return directPool.getCollectionUsage(); + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + return getCollectionUsageOnServer(serverPool); + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + return proxyPool.getCollectionUsage(); + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // getCollectionUsage() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#isValid + * MemoryPoolMXBean.isValid()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @return a true if the memory pool is valid in the running + * JVM; null otherwise. + */ + public boolean isValid(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + return directPool.isValid(); + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + return getBooleanAttribute(serverPool, POOL_VALID); + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + return proxyPool.isValid(); + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // isValid() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#isUsageThresholdSupported + * MemoryPoolMXBean.isUsageThresholdSupported()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @return a true if the memory pool supports usage threshold; + * null otherwise. + */ + public boolean isUsageThresholdSupported(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + return directPool.isUsageThresholdSupported(); + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + return isUsageThresholdSupportedOnServer(serverPool); + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + return proxyPool.isUsageThresholdSupported(); + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // isUsageThresholdSupported() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#isCollectionUsageThresholdSupported + * MemoryPoolMXBean.isCollectionUsageThresholdSupported()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @return a true if the memory pool supports collection + * usage threshold; null otherwise. + */ + public boolean isCollectionThresholdSupported(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + return directPool.isCollectionUsageThresholdSupported(); + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + return isCollectionThresholdSupportedOnServer(serverPool); + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + return proxyPool.isCollectionUsageThresholdSupported(); + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // isCollectionThresholdSupported() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#isUsageThresholdExceeded + * MemoryPoolMXBean.isUsageThresholdExceeded()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @return a true if the memory usage of this pool reaches or + * exceeds the threshold value; null otherwise. + */ + public boolean isUsageThresholdExceeded(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + return directPool.isUsageThresholdExceeded(); + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + return isUsageThresholdExceededOnServer(serverPool); + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + return proxyPool.isUsageThresholdExceeded(); + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // isUsageThresholdExceeded() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#isCollectionUsageThresholdExceeded + * MemoryPoolMXBean.isCollectionUsageThresholdExceeded()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @return a true if the memory usage of this pool reaches or + * exceeds the collection usage threshold value in the most recent + * collection; null otherwise. + */ + public boolean isCollectionThresholdExceeded(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + return directPool.isCollectionUsageThresholdExceeded(); + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + return isCollectionThresholdExceededOnServer(serverPool); + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + return proxyPool.isCollectionUsageThresholdExceeded(); + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // isCollectionThresholdExceeded() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#getUsageThreshold + * MemoryPoolMXBean.getUsageThreshold()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @return the usage threshold value of this memory pool in bytes. + */ + public long getUsageThreshold(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + return directPool.getUsageThreshold(); + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + return getUsageThresholdOnServer(serverPool); + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + return proxyPool.getUsageThreshold(); + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // getUsageThreshold() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#getCollectionUsageThreshold + * MemoryPoolMXBean.getCollectionUsageThreshold()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @return the collection usage threshold value of this memory pool in + * bytes. + */ + public long getCollectionThreshold(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + return directPool.getCollectionUsageThreshold(); + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + return getCollectionThresholdOnServer(serverPool); + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + return proxyPool.getCollectionUsageThreshold(); + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // getCollectionThreshold() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#getUsageThresholdCount + * MemoryPoolMXBean.getUsageThresholdCount()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @return number of times that the memory usage has crossed its usage + * threshold value. + */ + public long getUsageThresholdCount(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + return directPool.getUsageThresholdCount(); + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + return getUsageThresholdCountOnServer(serverPool); + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + return proxyPool.getUsageThresholdCount(); + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // getUsageThresholdCount() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#getCollectionUsageThresholdCount + * MemoryPoolMXBean.getCollectionUsageThresholdCount()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @return number of times that the memory usage has crossed its collection + * usage threshold value. + */ + public long getCollectionThresholdCount(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + return directPool.getCollectionUsageThresholdCount(); + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + return getCollectionThresholdCountOnServer(serverPool); + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + return proxyPool.getCollectionUsageThresholdCount(); + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // getCollectionThresholdCount() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#setUsageThreshold + * MemoryPoolMXBean.setUsageThreshold()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @param threshold the new threshold value. + */ + public void setUsageThreshold(Object poolObject, long threshold) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + directPool.setUsageThreshold(threshold); + break; + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + setUsageThresholdOnServer(serverPool, threshold); + break; + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + proxyPool.setUsageThreshold(threshold); + break; + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // setUsageThreshold() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#setCollectionUsageThreshold + * MemoryPoolMXBean.setCollectionUsageThreshold()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @param threshold the new collection usage threshold value. + */ + public void setCollectionThreshold(Object poolObject, long threshold) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + directPool.setCollectionUsageThreshold(threshold); + break; + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + setCollectionThresholdOnServer(serverPool, threshold); + break; + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + proxyPool.setCollectionUsageThreshold(threshold); + break; + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // setCollectionThreshold() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#getName + * MemoryPoolMXBean.getName()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @return the name of the memory pool. + */ + public String getName(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + return directPool.getName(); + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + return serverPool.toString(); + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + return proxyPool.getName(); + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // getName() + + /** + * Redirects the invocation to {@link + * java.lang.management.MemoryPoolMXBean#getType + * MemoryPoolMXBean.getType()}. + * + * @param poolObject reference to the pool. The pool may be specified + * either by ObjectName, or + * MemoryPoolMXBean. + * @return the name of the memory pool. + */ + public MemoryType getType(Object poolObject) { + switch (mode) { + case DIRECTLY_MODE: + MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; + return directPool.getType(); + + case SERVER_MODE: + ObjectName serverPool = (ObjectName) poolObject; + return getType(serverPool); + + case PROXY_MODE: + MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; + return proxyPool.getType(); + + default: + throw new TestBug("Unknown testMode " + mode); + } + } + + /** + * Redirects the invocation to {@link + * java.lang.management.ManagementFactory#getMemoryPoolMXBeans + * ManagementFactory.getMemoryPoolMXBeans()}. + * + * @return a list of MemoryPoolMXBean objects. + */ + public List getMemoryPoolMBeans() { + switch (mode) { + case DIRECTLY_MODE: + return ManagementFactory.getMemoryPoolMXBeans(); + + case SERVER_MODE: { + ObjectName[] names = getMemoryPoolMXBeansOnServer(); + ArrayList list = new ArrayList(); + + for (int i = 0; i < names.length; i++) { + list.add(names[i]); + } + return list; + } + + case PROXY_MODE: { + ObjectName[] names = getMemoryPoolMXBeansOnServer(); + ArrayList list = new ArrayList(); + + for (int i = 0; i < names.length; i++) { + list.add(getProxy(names[i])); + } + return list; + } + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // getMemoryPoolMXBeans() + + // ********************************************************************** + // + // Private methods + // + // ********************************************************************** + private MemoryPoolMXBean getProxy(ObjectName objectName) { + try { + MemoryPoolMXBean proxy = (MemoryPoolMXBean) ManagementFactory.newPlatformMXBeanProxy( + getMBeanServer(), + objectName.toString(), + MemoryPoolMXBean.class); + return proxy; + } catch (Exception e) { + throw new Failure(e); + } + } + + // Sets new usage threasholds in all pools that match the tested memory and + // support low memory detetion. A new value will be greater than used value + // for the pool. + private void updateUsageThresholds() { + switch (mode) { + case DIRECTLY_MODE: + // we can use the same code here for direct and proxy modes + case PROXY_MODE: + List poolsMBean = ManagementFactory.getMemoryPoolMXBeans(); + + for (int i = 0; i < poolsMBean.size(); i++) { + MemoryPoolMXBean pool = (MemoryPoolMXBean) poolsMBean.get(i); + if (!pool.isUsageThresholdSupported()) { + continue; + } + + MemoryType mt = pool.getType(); + if ((!mt.equals(MemoryType.HEAP) + || !memory.equals(HEAP_TYPE)) + && (!mt.equals(MemoryType.NON_HEAP) + || !memory.equals(NONHEAP_TYPE)) + && !memory.equals(MIXED_TYPE)) { + continue; + } + + // Yes! We got the pool that + // 1. supports usage threshold + // 2. has type that match tested type + // So, update the pool with new threshold + long oldT = pool.getUsageThreshold(); + MemoryUsage usage = pool.getUsage(); + long newT = newThreshold(usage, oldT, pool.getName()); + + try { + pool.setUsageThreshold(newT); + } catch (IllegalArgumentException e) { + /* + * Max value might have changed since the call to newThreshold() + * above. If it has fallen below the value of newT, which is certainly + * possible, an exception like this one will be thrown from + * sun.management.MemoryPoolImpl.setUsageThreshold(): + * + * java.lang.IllegalArgumentException: Invalid threshold: 48332800 > max (47251456). + * + * We don't know the max value at the time of the failed call, and it + * might have changed since the call once more. So there is no point + * trying to detect whether the IllegalArgumentException had been + * justified, we cannot know it at this point. + * + * The best we can do is log the fact and continue. + */ + displayInfo("setUsageThreshold() failed with " + e + ", ignoring... ", + pool, + "current usage after the call to setUsageThreshold(): ", getUsage(pool), + "threshold: ", newT); + continue; + } + displayInfo("Usage threshold is set", pool, "usage: ", pool.getUsage(), "threshold: ", pool.getUsageThreshold()); + if (pool.getUsageThreshold() != newT) { + complain("Cannot reset usage threshold from " + oldT + + " to " + newT + " in pool " + pool.getName() + " " + + pool.getUsageThreshold()); + passed = false; + } + } // for i + break; + + case SERVER_MODE: + ObjectName[] pools = getMemoryPoolMXBeansOnServer(); + + for (int i = 0; i < pools.length; i++) { + if (!isUsageThresholdSupportedOnServer(pools[i])) { + continue; + } + + MemoryType mt = getType(pools[i]); + if ((!mt.equals(MemoryType.HEAP) + || !memory.equals(HEAP_TYPE)) + && (!mt.equals(MemoryType.NON_HEAP) + || !memory.equals(NONHEAP_TYPE)) + && !memory.equals(MIXED_TYPE)) { + continue; + } + + // Yes! We got the pool that + // 1. supports usage threshold + // 2. has type that match tested type + // So, update the pool with new threshold + long oldT = getUsageThreshold(pools[i]); + long newT = newThreshold(getUsageOnServer(pools[i]), oldT, + pools[i].toString()); + try { + setUsageThresholdOnServer(pools[i], newT); + } catch (Failure e) { + /* + * Max value might have changed since the call to newThreshold() + * above. If it has fallen below the value of newT, which is certainly + * possible, an exception like this one will be thrown from + * sun.management.MemoryPoolImpl.setUsageThreshold(): + * + * java.lang.IllegalArgumentException: Invalid threshold: 48332800 > max (47251456). + * + * and we'll catch Failure here as a result (it'll be thrown by + * Monitor.setLongAttribute). + * + * We don't know the max value at the time of the failed call, and it + * might have changed since the call once more. So there is no point + * trying to detect whether the IllegalArgumentException had been + * justified, we cannot know it at this point. + * + * The best we can do is log the fact and continue. + */ + displayInfo("setUsageThresholdOnServer() failed with " + e + ", ignoring... ", + pools[i], + "current usage after the call to setUsageThresholdOnServer(): ", getUsageOnServer(pools[i]), + "threshold: ", newT); + continue; + } + displayInfo("Usage threshold is set", null, "pool: ", pools[i], "usage:", getUsageOnServer(pools[i])); + if (getUsageThreshold(pools[i]) != newT) { + complain("Cannot reset usage threshold from " + oldT + " to " + + newT + " in pool " + pools[i].toString()); + passed = false; + } + } // for i + break; + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // updateUsageThresholds() + + // Sets new collection usage threasholds in all pools that match the tested + // memory and support low memory detetion. A new value will be greater than + // used value for the pool. + private void updateCollectionThresholds() { + switch (mode) { + case DIRECTLY_MODE: + // we can use the same code here for direct and proxy modes + case PROXY_MODE: + List poolsMBean = ManagementFactory.getMemoryPoolMXBeans(); + + for (int i = 0; i < poolsMBean.size(); i++) { + MemoryPoolMXBean pool = (MemoryPoolMXBean) poolsMBean.get(i); + if (!pool.isCollectionUsageThresholdSupported()) { + continue; + } + + MemoryType mt = pool.getType(); + if ((!mt.equals(MemoryType.HEAP) + || !memory.equals(HEAP_TYPE)) + && (!mt.equals(MemoryType.NON_HEAP) + || !memory.equals(NONHEAP_TYPE)) + && !memory.equals(MIXED_TYPE)) { + continue; + } + + // Yes! We got the pool that + // 1. supports collection threshold + // 2. has type that match tested type + // So, update the pool with new threshold + long oldT = pool.getCollectionUsageThreshold(); + MemoryUsage usage = pool.getUsage(); + long newT = newThreshold(usage, oldT, pool.getName()); + + try { + pool.setCollectionUsageThreshold(newT); + } catch (IllegalArgumentException e) { + + /* + * Max value might have changed since the call to newThreshold() + * above. If it has fallen below the value of newT, which is certainly + * possible, an exception like this one will be thrown from + * sun.management.MemoryPoolImpl.setCollectionUsageThreshold(): + * + * java.lang.IllegalArgumentException: Invalid threshold: 48332800 > max (47251456). + * + * We don't know the max value at the time of the failed call, and it + * might have changed since the call once more. So there is no point + * trying to detect whether the IllegalArgumentException had been + * justified, we cannot know it at this point. + * + * The best we can do is log the fact and continue. + */ + displayInfo("setCollectionUsageThreshold() failed with " + e + ", ignoring... ", + pool, + "current usage after the call to setCollectionUsageThreshold(): ", getUsage(pool), + "threshold: ", newT); + continue; + } + displayInfo("Collection threshold is set", pool, "usage: ", getUsage(pool), "threshold: ", newT); + if (pool.getCollectionUsageThreshold() != newT) { + complain("Cannot reset collection threshold from " + oldT + + " to " + newT + " in pool " + pool.getName() + " " + + pool.getCollectionUsageThreshold()); + passed = false; + } + } // for i + break; + + case SERVER_MODE: + ObjectName[] pools = getMemoryPoolMXBeansOnServer(); + + for (int i = 0; i < pools.length; i++) { + if (!isCollectionThresholdSupportedOnServer(pools[i])) { + continue; + } + + MemoryType mt = getType(pools[i]); + if ((!mt.equals(MemoryType.HEAP) + || !memory.equals(HEAP_TYPE)) + && (!mt.equals(MemoryType.NON_HEAP) + || !memory.equals(NONHEAP_TYPE)) + && !memory.equals(MIXED_TYPE)) { + continue; + } + + // Yes! We got the pool that + // 1. supports usage threshold + // 2. has type that match tested type + // So, update the pool with new threshold + long oldT = getCollectionThresholdOnServer(pools[i]); + long newT = newThreshold(getUsageOnServer(pools[i]), oldT, + pools[i].toString()); + try { + setCollectionThresholdOnServer(pools[i], newT); + } catch (Failure e) { + /* + * Max value might have changed since the call to newThreshold() + * above. If it has fallen below the value of newT, which is certainly + * possible, an exception like this one will be thrown from + * sun.management.MemoryPoolImpl.setCollectionUsageThreshold(): + * + * java.lang.IllegalArgumentException: Invalid threshold: 48332800 > max (47251456). + * + * and we'll catch Failure here as a result (it'll be thrown by + * Monitor.setLongAttribute). + * + * We don't know the max value at the time of the failed call, and it + * might have changed since the call once more. So there is no point + * trying to detect whether the IllegalArgumentException had been + * justified, we cannot know it at this point. + * + * The best we can do is log the fact and continue. + */ + displayInfo("setCollectionThresholdOnServer() failed with " + e + ", ignoring... ", + pools[i], + "current usage after the call to setCollectionThresholdOnServer(): ", getUsageOnServer(pools[i]), + "threshold: ", newT); + continue; + } + displayInfo("Collection threshold is set", pools[i], "usage: ", getUsageOnServer(pools[i]), "threshold: ", newT); + if (getCollectionThresholdOnServer(pools[i]) != newT) { + complain("Cannot reset collaction threshold from " + oldT + + " to " + newT + " in pool " + pools[i].toString()); + passed = false; + } + } // for i + break; + + default: + throw new TestBug("Unknown testMode " + mode); + } + } // updateCollectionThresholds() + + // Calculates a new value of threshold based on MemoryUsage and old value of + // the threshold. New one will be not less than previous one. + private long newThreshold(MemoryUsage mu, long oldT, String poolName) { + long newT = mu.getCommitted() / 2 + mu.getUsed() / 2; + long max = mu.getMax(); + + if (newT < oldT) { + newT = mu.getCommitted() / 2 + oldT / 2; + } + if ((max > -1) && (newT > max)) { + newT = max; + } + displayInfo("Changing threshold", poolName, null, null, "new threshold: ", newT); + return newT; + } + + // ********************************************************************** + // + // Methods to work with MBean server in SERVER_MODE + // + // ********************************************************************** + // Returns usage threshold value of the pool MBean that is accessed via + // MBeanServer + private long getUsageThresholdOnServer(ObjectName pool) { + return getLongAttribute(pool, UT); + } + + // Returns collection threshold value of the pool MBean that is accessed via + // MBeanServer + private long getCollectionThresholdOnServer(ObjectName pool) { + return getLongAttribute(pool, CT); + } + + // Sets new usage threshold value for the pool MBean that is accessed via + // MBeanServer + private void setUsageThresholdOnServer(ObjectName pool, long value) { + setLongAttribute(pool, UT, value); + } + + // Sets new collection threshold value for the pool MBean that is accessed + // via MBeanServer + private void setCollectionThresholdOnServer(ObjectName pool, long value) { + setLongAttribute(pool, CT, value); + } + + // Returns MemoryType of the pool MBean that is accessed via MBeanServer. + private MemoryType getType(ObjectName pool) { + try { + Object value = getMBeanServer().getAttribute(pool, POOL_TYPE); + if (value instanceof MemoryType) { + return (MemoryType) value; + } else if (value instanceof String) { + String name = (String) value; + return MemoryType.valueOf(name); + } else { + return null; + } + } catch (Exception e) { + e.printStackTrace(logger.getOutStream()); + throw new Failure(e); + } + } + + // Returns MemoryUsage of the pool MBean that is accessed via MBeanServer + private MemoryUsage getUsageOnServer(ObjectName pool) { + return getMemoryUsageAttribute(pool, POOL_U); + } + + // Returns collection usage of the pool MBean that is accessed via + // MBeanServer + private MemoryUsage getCollectionUsageOnServer(ObjectName pool) { + return getMemoryUsageAttribute(pool, POOL_CU); + } + + // Returns if usage threshold is supported in the pool + private boolean isUsageThresholdSupportedOnServer(ObjectName pool) { + return getBooleanAttribute(pool, UT_SUPPORT); + } + + // Returns if collection threshold is supported in the pool + private boolean isCollectionThresholdSupportedOnServer(ObjectName pool) { + return getBooleanAttribute(pool, CT_SUPPORT); + } + + // Returns if usage threshold is exceeded in the pool + private boolean isUsageThresholdExceededOnServer(ObjectName pool) { + return getBooleanAttribute(pool, UT_EXCEEDED); + } + + // Returns if collection threshold is exceeded in the pool + private boolean isCollectionThresholdExceededOnServer(ObjectName pool) { + return getBooleanAttribute(pool, CT_EXCEEDED); + } + + // Returns the usage threshold count of the pool + private long getUsageThresholdCountOnServer(ObjectName pool) { + return getLongAttribute(pool, UT_COUNT); + } + + // Returns the collection threshold count of the pool. + private long getCollectionThresholdCountOnServer(ObjectName pool) { + return getLongAttribute(pool, CT_COUNT); + } + private final StringBuffer buffer = new StringBuffer(1000); + + /** + * Display information about execution ignoring OOM. + */ + private void displayInfo(String message, Object pool, String message1, Object n1, String message2, long n2) { + try { + buffer.delete(0, buffer.length()); + buffer.append(message); + if (pool != null) { + buffer.append(", pool: "); + buffer.append(pool.toString()); + } + buffer.append(", "); + buffer.append(message1); + buffer.append(n1); + if (message2 != null) { + buffer.append(", "); + buffer.append(message2); + buffer.append(n2); + } + display(buffer.toString()); + } catch (OutOfMemoryError e) { + // Ignore. + } + } + + /** + * Display information about execution ignoring OOM. + */ + private void displayInfo(String message, MemoryPoolMXBean pool, String message1, Object n1, String message2, Object n2) { + try { + buffer.delete(0, buffer.length()); + buffer.append(message); + if (pool != null) { + buffer.append(", pool: "); + buffer.append(pool.getName()); + } + buffer.append(", "); + buffer.append(message1); + buffer.append(n1); + if (message2 != null) { + buffer.append(", "); + buffer.append(message2); + buffer.append(n2); + } + display(buffer.toString()); + } catch (OutOfMemoryError e) { + // Ignore. + } + } + + // Returns all MemoryPoolMXBeans that are registered on the MBeanServer + private ObjectName[] getMemoryPoolMXBeansOnServer() { + + // Get all registered MBeans on the server + ObjectName filterName = null; + try { + filterName = new ObjectName( + ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",*"); + + Set filteredSet = getMBeanServer().queryNames(filterName, null); + return filteredSet.toArray(new ObjectName[0]); + } catch(Exception e) { + return new ObjectName[0]; + } + + } // getMemoryPoolMXBeansOnServer() + + // ********************************************************************** + // + // Class to implement polling mechanism of monitoring + // + // ********************************************************************** + class Polling extends Thread { + + final static long WAIT_TIME = 100; // Milliseconds + Object object = new Object(); + long[] thresholdCounts; + boolean goOn = true; + + public void run() { + try { + if (isUsageThreshold) { + pollUsageThresholds(); + } else { + pollCollectionThresholds(); + } + } catch (Failure e) { + complain("Unexpected " + e + " in Polling thread"); + e.printStackTrace(logger.getOutStream()); + passed = false; + } + } // run() + + private void pollUsageThresholds() { + switch (mode) { + case DIRECTLY_MODE: + // we can use the same code here for direct and proxy modes + case PROXY_MODE: + List poolsMBean = ManagementFactory.getMemoryPoolMXBeans(); + + // Create an array to store all threshold values + thresholdCounts = new long[poolsMBean.size()]; + for (int i = 0; i < thresholdCounts.length; i++) { + thresholdCounts[i] = 0; + } + + while (goOn) { + synchronized (object) { + try { + object.wait(WAIT_TIME); + } catch (InterruptedException e) { + + // Stop the thread + return; + } + } // synchronized + + for (int i = 0; i < poolsMBean.size(); i++) { + MemoryPoolMXBean pool = (MemoryPoolMXBean) poolsMBean.get(i); + MemoryType mt = pool.getType(); + + if (!pool.isUsageThresholdSupported()) { + continue; + } + + if ((!mt.equals(MemoryType.HEAP) + || !memory.equals(HEAP_TYPE)) + && (!mt.equals(MemoryType.NON_HEAP) + || !memory.equals(NONHEAP_TYPE)) + && !memory.equals(MIXED_TYPE)) { + continue; + } + + boolean exceeded; + + // The exception is not documented, but it may be + // erroneously thrown + try { + exceeded = pool.isUsageThresholdExceeded(); + } catch (IllegalArgumentException e) { + complain("Unexpected exception while retrieving " + + "isUsageThresholdExceeded() for pool " + + pool.getName()); + e.printStackTrace(logger.getOutStream()); + passed = false; + continue; + } + + if (!exceeded + || pool.getUsageThresholdCount() == thresholdCounts[i]) { + continue; + } + + // Yes! We got the pool that + // 1. supports usage threshold + // 2. has type that match tested type + // 3. its threshold is exceeded + // So, update all thresholds + long c = pool.getUsageThresholdCount(); + if (c <= thresholdCounts[i]) { + complain("Usage threshold count is not greater " + + "than previous one: " + c + " < " + + thresholdCounts[i] + " in pool " + + pool.getName()); + passed = false; + } + thresholdCounts[i] = c; + displayInfo("Crossing is noticed", pool, "usage: ", pool.getUsage(), "count: ", c); + updateThresholds(); + } // for i + } // while + break; + + case SERVER_MODE: + ObjectName[] pools = getMemoryPoolMXBeansOnServer(); + + // Create an array to store all threshold values + thresholdCounts = new long[pools.length]; + for (int i = 0; i < thresholdCounts.length; i++) { + thresholdCounts[i] = 0; + } + + while (goOn) { + synchronized (object) { + try { + object.wait(WAIT_TIME); + } catch (InterruptedException e) { + + // Stop the thread + return; + } + } // synchronized + + for (int i = 0; i < pools.length; i++) { + MemoryType mt = getType(pools[i]); + + if (!isUsageThresholdSupportedOnServer(pools[i])) { + continue; + } + + if ((!mt.equals(MemoryType.HEAP) + || !memory.equals(HEAP_TYPE)) + && (!mt.equals(MemoryType.NON_HEAP) + || !memory.equals(NONHEAP_TYPE)) + && !memory.equals(MIXED_TYPE)) { + continue; + } + + boolean exceeded; + + // The exception is not documented, but it may be + // erroneously thrown + try { + exceeded = isUsageThresholdExceededOnServer(pools[i]); + } catch (Failure e) { + complain("Unexpected exception while retrieving " + + "isUsageThresholdExceeded() for pool " + + pools[i].toString()); + e.printStackTrace(logger.getOutStream()); + passed = false; + continue; + } + + if (!exceeded + || getUsageThresholdCount(pools[i]) == thresholdCounts[i]) { + continue; + } + + // Yes! We got the pool that + // 1. supports usage threshold + // 2. has type that match tested type + // 3. its threshold is exceeded + // So, update all thresholds + long c = getUsageThresholdCount(pools[i]); + if (c <= thresholdCounts[i]) { + complain("Usage threshold count is not greater " + + "than previous one: " + c + " < " + + thresholdCounts[i] + " in pool " + + pools[i].toString()); + passed = false; + } + thresholdCounts[i] = c; + displayInfo("Crossing is noticed", null, "pool: ", pools[i], "usage: ", getUsageOnServer(pools[i])); + updateThresholds(); + } // for i + } // while + break; + + default: + throw new TestBug("Unknown testMode " + mode); + } // switch + } // pollUsageThresholds() + + private void pollCollectionThresholds() { + switch (mode) { + case DIRECTLY_MODE: + // we can use the same code here for direct and proxy modes + case PROXY_MODE: + List poolsMBean = ManagementFactory.getMemoryPoolMXBeans(); + + // Create an array to store all threshold values + thresholdCounts = new long[poolsMBean.size()]; + for (int i = 0; i < thresholdCounts.length; i++) { + thresholdCounts[i] = 0; + } + + while (goOn) { + synchronized (object) { + try { + object.wait(WAIT_TIME); + } catch (InterruptedException e) { + + // Stop the thread + return; + } + } // synchronized + + for (int i = 0; i < poolsMBean.size(); i++) { + MemoryPoolMXBean pool = (MemoryPoolMXBean) poolsMBean.get(i); + MemoryType mt = pool.getType(); + + if (!pool.isCollectionUsageThresholdSupported()) { + continue; + } + + if ((!mt.equals(MemoryType.HEAP) + || !memory.equals(HEAP_TYPE)) + && (!mt.equals(MemoryType.NON_HEAP) + || !memory.equals(NONHEAP_TYPE)) + && !memory.equals(MIXED_TYPE)) { + continue; + } + + boolean exceeded; + + // The exception is not documented, but it may be + // erroneously thrown + try { + exceeded = pool.isCollectionUsageThresholdExceeded(); + } catch (IllegalArgumentException e) { + complain("Unexpected exception while retrieving " + + "isCollectionUsageThresholdExceeded()" + + " for pool " + pool.getName()); + e.printStackTrace(logger.getOutStream()); + passed = false; + continue; + } + + if (!exceeded + || pool.getCollectionUsageThresholdCount() + == thresholdCounts[i]) { + continue; + } + + // Yes! We got thet pool that + // 1. supports collection usage threshold + // 2. has type that match tested type + // 3. its threshold is exceeded + // So, update all thresholds + long c = pool.getCollectionUsageThresholdCount(); + if (c <= thresholdCounts[i]) { + complain("Collection usage threshold count is " + + "not greater than previous one: " + c + + " < " + thresholdCounts[i] + " in pool " + + pool.getName()); + passed = false; + } + thresholdCounts[i] = c; + displayInfo("Crossing is noticed", pool, "usage: ", pool.getUsage(), "count: ", c); + updateThresholds(); + } // for i + } // while + break; + + case SERVER_MODE: + ObjectName[] pools = getMemoryPoolMXBeansOnServer(); + + // Create an array to store all threshold values + thresholdCounts = new long[pools.length]; + for (int i = 0; i < thresholdCounts.length; i++) { + thresholdCounts[i] = 0; + } + + while (goOn) { + synchronized (object) { + try { + object.wait(WAIT_TIME); + } catch (InterruptedException e) { + + // Stop the thread + return; + } + } // synchronized + + for (int i = 0; i < pools.length; i++) { + MemoryType mt = getType(pools[i]); + + if (!isCollectionThresholdSupportedOnServer(pools[i])) { + continue; + } + + if ((!mt.equals(MemoryType.HEAP) + || !memory.equals(HEAP_TYPE)) + && (!mt.equals(MemoryType.NON_HEAP) + || !memory.equals(NONHEAP_TYPE)) + && !memory.equals(MIXED_TYPE)) { + continue; + } + + boolean exceeded; + + // The exception is not documented, but it may be + // erroneously thrown + try { + exceeded = isCollectionThresholdExceededOnServer(pools[i]); + } catch (Failure e) { + complain("Unexpected exception while retrieving " + + "isCollectionUsageThresholdExceeded() " + + "for pool " + pools[i].toString()); + e.printStackTrace(logger.getOutStream()); + passed = false; + continue; + } + + if (!exceeded + || getCollectionThresholdCountOnServer(pools[i]) + == thresholdCounts[i]) { + continue; + } + + // Yes! We got thet pool that + // 1. supports collection usage threshold + // 2. has type that match tested type + // 3. its threshold is exceeded + // So, update all thresholds + long c = getCollectionThresholdCountOnServer(pools[i]); + if (c <= thresholdCounts[i]) { + complain("Collection usage threshold count is " + + "not greater than previous one: " + c + + " < " + thresholdCounts[i] + " in pool " + + pools[i].toString()); + passed = false; + } + thresholdCounts[i] = c; + displayInfo("Crossing is noticed", pools[i], "usage: ", getUsageOnServer(pools[i]), "count: ", c); + updateThresholds(); + } // for i + } // while + break; + + default: + throw new TestBug("Unknown testMode " + mode); + } // switch + } // pollCollectionThresholds() + } // class Polling +} // MemoryMonitor