Reduce JSR305 proliferation
[controller.git] / opendaylight / md-sal / sal-common-util / src / main / java / org / opendaylight / controller / md / sal / common / util / jmx / ThreadExecutorStatsMXBeanImpl.java
1 /*
2  * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.md.sal.common.util.jmx;
9
10 import static java.util.Objects.requireNonNull;
11
12 import java.util.concurrent.BlockingQueue;
13 import java.util.concurrent.Executor;
14 import java.util.concurrent.RejectedExecutionHandler;
15 import java.util.concurrent.ThreadPoolExecutor;
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.opendaylight.yangtools.util.concurrent.CountingRejectedExecutionHandler;
18 import org.opendaylight.yangtools.util.concurrent.TrackingLinkedBlockingQueue;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 /**
23  * MXBean implementation of the ThreadExecutorStatsMXBean interface that retrieves statistics
24  * from a backing {@link java.util.concurrent.ExecutorService}.
25  *
26  * @author Thomas Pantelis
27  */
28 public class ThreadExecutorStatsMXBeanImpl extends AbstractMXBean
29                                            implements ThreadExecutorStatsMXBean {
30     private static final Logger LOG = LoggerFactory.getLogger(ThreadExecutorStatsMXBeanImpl.class);
31     private final ThreadPoolExecutor executor;
32
33     /**
34      * Constructs an instance for the given {@link Executor}.
35      *
36      * @param executor the backing {@link Executor}
37      * @param beanName Used as the <code>name</code> property in the bean's ObjectName.
38      * @param beanType Used as the <code>type</code> property in the bean's ObjectName.
39      * @param beanCategory Used as the <code>Category</code> property in the bean's ObjectName.
40      */
41     public ThreadExecutorStatsMXBeanImpl(final ThreadPoolExecutor executor, final String beanName,
42             final String beanType, final @Nullable String beanCategory) {
43         super(beanName, beanType, beanCategory);
44         this.executor = requireNonNull(executor);
45     }
46
47     private static ThreadExecutorStatsMXBeanImpl createInternal(final Executor executor,
48             final String beanName, final String beanType, final String beanCategory) {
49         if (executor instanceof ThreadPoolExecutor) {
50             final ThreadExecutorStatsMXBeanImpl ret = new ThreadExecutorStatsMXBeanImpl(
51                     (ThreadPoolExecutor) executor, beanName, beanType, beanCategory);
52             return ret;
53         }
54
55         LOG.info("Executor {} is not supported", executor);
56         return null;
57     }
58
59     /**
60      * Creates a new bean if the backing executor is a ThreadPoolExecutor and registers it.
61      *
62      * @param executor the backing {@link Executor}
63      * @param beanName Used as the <code>name</code> property in the bean's ObjectName.
64      * @param beanType Used as the <code>type</code> property in the bean's ObjectName.
65      * @param beanCategory Used as the <code>Category</code> property in the bean's ObjectName.
66      * @return a registered ThreadExecutorStatsMXBeanImpl instance if the backing executor
67      *         is a ThreadPoolExecutor, otherwise null.
68      */
69     public static ThreadExecutorStatsMXBeanImpl create(final Executor executor, final String beanName,
70             final String beanType, final @Nullable String beanCategory) {
71         ThreadExecutorStatsMXBeanImpl ret = createInternal(executor, beanName, beanType, beanCategory);
72         if (ret != null) {
73             ret.registerMBean();
74         }
75
76         return ret;
77     }
78
79     /**
80      * Creates a new bean if the backing executor is a ThreadPoolExecutor and registers it.
81      *
82      * @param executor the backing {@link Executor}
83      * @param beanName Used as the <code>name</code> property in the bean's ObjectName.
84      * @param beanType Used as the <code>type</code> property in the bean's ObjectName.
85      * @return a registered ThreadExecutorStatsMXBeanImpl instance if the backing executor
86      *         is a ThreadPoolExecutor, otherwise null.
87      */
88     public static ThreadExecutorStatsMXBeanImpl create(final Executor executor, final String beanName,
89             final String beanType) {
90         return create(executor, beanName, beanType, null);
91     }
92
93     /**
94      * Creates a new bean if the backing executor is a ThreadPoolExecutor.
95      *
96      * @param executor the backing {@link Executor}
97      * @return a ThreadExecutorStatsMXBeanImpl instance if the backing executor
98      *         is a ThreadPoolExecutor, otherwise null.
99      */
100     public static ThreadExecutorStatsMXBeanImpl create(final Executor executor) {
101         return createInternal(executor, "", "", null);
102     }
103
104     @Override
105     public long getCurrentThreadPoolSize() {
106         return executor.getPoolSize();
107     }
108
109     @Override
110     public long getLargestThreadPoolSize() {
111         return  executor.getLargestPoolSize();
112     }
113
114     @Override
115     public long getMaxThreadPoolSize() {
116         return executor.getMaximumPoolSize();
117     }
118
119     @Override
120     public long getCurrentQueueSize() {
121         return executor.getQueue().size();
122     }
123
124     @Override
125     public Long getLargestQueueSize() {
126         BlockingQueue<Runnable> queue = executor.getQueue();
127         if (queue instanceof TrackingLinkedBlockingQueue) {
128             return Long.valueOf(((TrackingLinkedBlockingQueue<?>)queue).getLargestQueueSize());
129         }
130
131         return null;
132     }
133
134     @Override
135     public long getMaxQueueSize() {
136         long queueSize = executor.getQueue().size();
137         return executor.getQueue().remainingCapacity() + queueSize;
138     }
139
140     @Override
141     public long getActiveThreadCount() {
142         return executor.getActiveCount();
143     }
144
145     @Override
146     public long getCompletedTaskCount() {
147         return  executor.getCompletedTaskCount();
148     }
149
150     @Override
151     public long getTotalTaskCount() {
152         return executor.getTaskCount();
153     }
154
155     @Override
156     public Long getRejectedTaskCount() {
157         RejectedExecutionHandler rejectedHandler = executor.getRejectedExecutionHandler();
158         if (rejectedHandler instanceof CountingRejectedExecutionHandler) {
159             return Long.valueOf(((CountingRejectedExecutionHandler)rejectedHandler)
160                                                                      .getRejectedTaskCount());
161         }
162
163         return null;
164     }
165
166     /**
167      * Returns a {@link ThreadExecutorStats} instance containing a snapshot of the statistic
168      * metrics.
169      */
170     public ThreadExecutorStats toThreadExecutorStats() {
171         return new ThreadExecutorStats(getActiveThreadCount(), getCurrentThreadPoolSize(),
172                 getLargestThreadPoolSize(), getMaxThreadPoolSize(), getCurrentQueueSize(),
173                 getLargestQueueSize(), getMaxQueueSize(), getCompletedTaskCount(),
174                 getTotalTaskCount(), getRejectedTaskCount());
175     }
176 }