1 /*
   2  * Copyright (c) 2005, 2015, 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 6222826
  27  * @summary Test that tasks are cancelled properly when
  28  *          monitors are started and stopped in a loop.
  29  * @author Luis-Miguel Alventosa
  30  *
  31  * @library /lib/testlibrary
  32  *
  33  * @build jdk.testlibrary.*
  34  * @run clean StartStopTest
  35  * @run build StartStopTest
  36  * @run main/othervm/timeout=300 StartStopTest 1
  37  * @run main/othervm/timeout=300 StartStopTest 2
  38  * @run main/othervm/timeout=300 StartStopTest 3
  39  * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 StartStopTest 1
  40  * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 StartStopTest 2
  41  * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 StartStopTest 3
  42  * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=-5 StartStopTest 1
  43  * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=-5 StartStopTest 2
  44  * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=-5 StartStopTest 3
  45  */
  46 
  47 import java.util.concurrent.atomic.AtomicInteger;
  48 import javax.management.MBeanServer;
  49 import javax.management.MBeanServerFactory;
  50 import javax.management.Notification;
  51 import javax.management.NotificationListener;
  52 import javax.management.ObjectName;
  53 import javax.management.monitor.CounterMonitor;
  54 import javax.management.monitor.GaugeMonitor;
  55 import javax.management.monitor.Monitor;
  56 import javax.management.monitor.MonitorNotification;
  57 import javax.management.monitor.StringMonitor;
  58 
  59 import jdk.testlibrary.Utils;
  60 
  61 public class StartStopTest {
  62     static int maxPoolSize;
  63     static final AtomicInteger counter = new AtomicInteger();
  64 
  65     // MBean class
  66     public class ObservedObject implements ObservedObjectMBean {
  67         volatile public boolean called = false;
  68         public Integer getInteger() {
  69             task("Integer");
  70             return 0;
  71         }
  72         public Double getDouble() {
  73             task("Double");
  74             return 0.0;
  75         }
  76         public String getString() {
  77             task("String");
  78             return "";
  79         }
  80         private void task(String prop) {
  81             called = true;
  82             final int c = counter.incrementAndGet();
  83             echo("\tTASK [" + c + "] in get" + prop);
  84         }
  85     }
  86 
  87     // MBean interface
  88     public interface ObservedObjectMBean {
  89         public Integer getInteger();
  90         public Double getDouble();
  91         public String getString();
  92     }
  93 
  94     /**
  95      * Run test
  96      */
  97     public int runTest(int monitorType) throws Exception {
  98 
  99         int nTasks = maxPoolSize + 2;
 100         ObjectName[] mbeanNames = new ObjectName[nTasks];
 101         ObservedObject[] monitored = new ObservedObject[nTasks];
 102         ObjectName[] monitorNames = new ObjectName[nTasks];
 103         Monitor[] monitor = new Monitor[nTasks];
 104         String[] attributes = { "Integer", "Double", "String" };
 105 
 106         try {
 107             echo(">>> CREATE MBeanServer");
 108             MBeanServer server = MBeanServerFactory.newMBeanServer();
 109 
 110             String domain = server.getDefaultDomain();
 111 
 112             for (int i = 0; i < nTasks; i++) {
 113                 mbeanNames[i] =
 114                     new ObjectName(":type=ObservedObject,instance=" + (i + 1));
 115                 monitored[i] = new ObservedObject();
 116                 echo(">>> CREATE ObservedObject = " + mbeanNames[i].toString());
 117                 server.registerMBean(monitored[i], mbeanNames[i]);
 118                 switch (monitorType) {
 119                 case 1:
 120                     monitorNames[i] = new ObjectName(":type=CounterMonitor," +
 121                                                      "instance=" + (i + 1));
 122                     monitor[i] = new CounterMonitor();
 123                     break;
 124                 case 2:
 125                     monitorNames[i] = new ObjectName(":type=GaugeMonitor," +
 126                                                      "instance=" + (i + 1));
 127                     monitor[i] = new GaugeMonitor();
 128                     break;
 129                 case 3:
 130                     monitorNames[i] = new ObjectName(":type=StringMonitor," +
 131                                                      "instance=" + (i + 1));
 132                     monitor[i] = new StringMonitor();
 133                     break;
 134                 default:
 135                     echo("Unsupported monitor type");
 136                     return 1;
 137                 }
 138                 echo(">>> CREATE Monitor = " + monitorNames[i].toString());
 139                 server.registerMBean(monitor[i], monitorNames[i]);
 140                 monitor[i].addObservedObject(mbeanNames[i]);
 141                 monitor[i].setObservedAttribute(attributes[monitorType-1]);
 142                 monitor[i].setGranularityPeriod(50);
 143             }
 144 
 145             for (int j = 0; j < 2; j++) {
 146                 echo(">>> Start MONITORS");
 147                 for (int i = 0; i < nTasks; i++)
 148                     monitor[i].start();
 149                 echo(">>> MONITORS started");
 150                 doSleep(500);
 151                 echo(">>> Check FLAGS true");
 152                 for (int i = 0; i < nTasks; i++)
 153                     if (!monitored[i].called) {
 154                         echo("KO: At least one attribute was not called");
 155                         return 1;
 156                     }
 157                 echo(">>> FLAGS checked true");
 158                 echo(">>> Stop MONITORS");
 159                 for (int i = 0; i < nTasks; i++)
 160                     monitor[i].stop();
 161                 echo(">>> MONITORS stopped");
 162                 doSleep(500);
 163                 echo(">>> Set FLAGS to false");
 164                 for (int i = 0; i < nTasks; i++)
 165                     monitored[i].called = false;
 166                 echo(">>> FLAGS set to false");
 167                 echo(">>> Check FLAGS remain false");
 168                 for (int i = 0; i < nTasks; i++)
 169                     if (monitored[i].called) {
 170                         echo("KO: At least one attribute " +
 171                              "continued to get called");
 172                         return 1;
 173                     }
 174                 echo(">>> FLAGS checked false");
 175             }
 176         } finally {
 177             for (int i = 0; i < nTasks; i++)
 178                 if (monitor[i] != null)
 179                     monitor[i].stop();
 180         }
 181 
 182         return 0;
 183     }
 184 
 185     /*
 186      * Print message
 187      */
 188     private static void echo(String message) {
 189         System.out.println(message);
 190     }
 191 
 192     /*
 193      * Standalone entry point.
 194      *
 195      * Run the test and report to stdout.
 196      */
 197     public static void main (String args[]) throws Exception {
 198         Integer size = Integer.getInteger("jmx.x.monitor.maximum.pool.size");
 199         if (size == null) {
 200             maxPoolSize = 10;
 201             echo(">>> MAXIMUM POOL SIZE = 10 [default value]");
 202         } else {
 203             maxPoolSize = size.intValue() < 1 ? 1 : size.intValue();
 204             echo(">>> MAXIMUM POOL SIZE = " + maxPoolSize);
 205         }
 206         StartStopTest test = new StartStopTest();
 207         int error = test.runTest(Integer.parseInt(args[0]));
 208         if (error > 0) {
 209             echo(">>> Unhappy Bye, Bye!");
 210             throw new IllegalStateException(
 211                 "Test FAILED: Unexpected Maximum Pool Size Overflow!");
 212         } else {
 213             echo(">>> Happy Bye, Bye!");
 214         }
 215     }
 216 
 217     private static void doSleep(long ms) throws Exception {
 218         Thread.sleep(Utils.adjustTimeout(ms));
 219     }
 220 }