File: ExecutorShutdownTest.java

package info (click to toggle)
openjdk-11 11.0.4%2B11-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 757,028 kB
  • sloc: java: 5,016,041; xml: 1,191,974; cpp: 934,731; ansic: 555,697; sh: 24,299; objc: 12,703; python: 3,602; asm: 3,415; makefile: 2,772; awk: 351; sed: 172; perl: 114; jsp: 24; csh: 3
file content (148 lines) | stat: -rw-r--r-- 5,728 bytes parent folder | download | duplicates (16)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * Copyright (c) 2016, 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.
 */

 /*
 * @test
 * @bug 8141591
 * @summary Tests if notifications are received after executor is shutdown
 * @author Harsha Wardhana B
 *
 * @run clean ExecutorShutdownTest
 * @run build ExecutorShutdownTest
 * @run main ExecutorShutdownTest
 */
import java.util.*;
import java.util.concurrent.*;
import javax.management.*;
import javax.management.remote.*;

/*
  When you create a JMXConnector client, you can supply a
  "fetch-notifications Executor", which is a
  java.util.concurrent.Executor that will be used each time the
  connector client wants to call RMIConnection.fetchNotifications.
  If such executor is not supplies, the connector client will fallback
  on default LinearExecutor. This test checks if user supplied executor
  is shutdown abruptly, LinearExecutor is used to handle notifications.
 */
public class ExecutorShutdownTest {

    private static final String EXECUTOR_PROPERTY
            = "jmx.remote.x.fetch.notifications.executor";
    private static final String NOTIF_TYPE = "test.type";

    public static void main(String[] args) throws Exception {

        // Start JMXConnector Server
        JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
        MBeanServer mbs = MBeanServerFactory.newMBeanServer();
        ObjectName emitName = new ObjectName("blah:type=Emitter");
        mbs.registerMBean(new Emitter(), emitName);
        JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url,
                null,
                mbs);
        cs.start();

        // Create executor to provide to JMXConnector client
        ExecutorService executor = Executors.newCachedThreadPool();
        Map<String, Executor> env = new HashMap<>();
        env.put(EXECUTOR_PROPERTY, executor);
        JMXServiceURL addr = cs.getAddress();

        try (JMXConnector cc = JMXConnectorFactory.connect(addr, env)) {
            MBeanServerConnection mbsc = cc.getMBeanServerConnection();
            EmitterMBean emitter = (EmitterMBean) MBeanServerInvocationHandler.newProxyInstance(mbsc,
                    emitName,
                    EmitterMBean.class,
                    false);
            SemaphoreListener listener = new SemaphoreListener();
            NotificationFilterSupport filter = new NotificationFilterSupport();
            filter.enableType(NOTIF_TYPE);
            mbsc.addNotificationListener(emitName, listener, filter, null);

            final int NOTIF_COUNT = 3;
            for (int i = 0; i < NOTIF_COUNT; i++) {
                emitter.emit();
                listener.await();
            }
            Thread.sleep(1);
            listener.checkUnavailable();
            System.out.println("Got notifications with client provided executor");

            // After shutting down executor, notifications are handled by linear executor
            executor.shutdown();
            for (int i = 0; i < NOTIF_COUNT; i++) {
                emitter.emit();
                listener.await();
            }
            Thread.sleep(1);
            listener.checkUnavailable();
            System.out.println("Got notifications with linear executor");
        }
        cs.stop();
        System.out.println("TEST PASSED !!!");
    }

    /* Simple MBean that sends a notification every time we ask it to.  */
    public static interface EmitterMBean {

        public void emit();
    }

    public static class Emitter
            extends NotificationBroadcasterSupport implements EmitterMBean {

        public void emit() {
            sendNotification(new Notification(NOTIF_TYPE, this, seq++));
        }

        private long seq = 1;
    }

    /* Simple NotificationListener that allows you to wait until a
       notification has been received.  Since it uses a semaphore, you
       can wait either before or after the notification has in fact
       been received and it will work in either case.  */
    private static class SemaphoreListener implements NotificationListener {

        void await() throws InterruptedException {
            semaphore.acquire();
        }

        /* Ensure no extra notifications were received.  If we can acquire
           the semaphore, that means its release() method was called more
           times than its acquire() method, which means there were too
           many notifications.  */
        void checkUnavailable() throws Exception {
            if (semaphore.tryAcquire()) {
                throw new Exception("Got extra notifications!");
            }
        }

        public void handleNotification(Notification n, Object h) {
            semaphore.release();
        }

        private final Semaphore semaphore = new Semaphore(0);
    }
}