c6738c77cea34d061796b2ba4863179abcc9dcd2
[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
9 package org.opendaylight.controller.md.sal.common.util.jmx;
10
11 import com.google.common.base.Preconditions;
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 javax.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, @Nullable final String beanCategory) {
43         super(beanName, beanType, beanCategory);
44         this.executor = Preconditions.checkNotNull(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, @Nullable final 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.
81      *
82      * @param executor the backing {@link Executor}
83      * @return a ThreadExecutorStatsMXBeanImpl instance if the backing executor
84      *         is a ThreadPoolExecutor, otherwise null.
85      */
86     public static ThreadExecutorStatsMXBeanImpl create(final Executor executor) {
87         return createInternal(executor, "", "", null);
88     }
89
90     @Override
91     public long getCurrentThreadPoolSize() {
92         return executor.getPoolSize();
93     }
94
95     @Override
96     public long getLargestThreadPoolSize() {
97         return  executor.getLargestPoolSize();
98     }
99
100     @Override
101     public long getMaxThreadPoolSize() {
102         return executor.getMaximumPoolSize();
103     }
104
105     @Override
106     public long getCurrentQueueSize() {
107         return executor.getQueue().size();
108     }
109
110     @Override
111     public Long getLargestQueueSize() {
112         BlockingQueue<Runnable> queue = executor.getQueue();
113         if (queue instanceof TrackingLinkedBlockingQueue) {
114             return Long.valueOf(((TrackingLinkedBlockingQueue<?>)queue).getLargestQueueSize());
115         }
116
117         return null;
118     }
119
120     @Override
121     public long getMaxQueueSize() {
122         long queueSize = executor.getQueue().size();
123         return executor.getQueue().remainingCapacity() + queueSize;
124     }
125
126     @Override
127     public long getActiveThreadCount() {
128         return executor.getActiveCount();
129     }
130
131     @Override
132     public long getCompletedTaskCount() {
133         return  executor.getCompletedTaskCount();
134     }
135
136     @Override
137     public long getTotalTaskCount() {
138         return executor.getTaskCount();
139     }
140
141     @Override
142     public Long getRejectedTaskCount() {
143         RejectedExecutionHandler rejectedHandler = executor.getRejectedExecutionHandler();
144         if (rejectedHandler instanceof CountingRejectedExecutionHandler) {
145             return Long.valueOf(((CountingRejectedExecutionHandler)rejectedHandler)
146                                                                      .getRejectedTaskCount());
147         }
148
149         return null;
150     }
151
152     /**
153      * Returns a {@link ThreadExecutorStats} instance containing a snapshot of the statistic
154      * metrics.
155      */
156     public ThreadExecutorStats toThreadExecutorStats() {
157         return new ThreadExecutorStats(getActiveThreadCount(), getCurrentThreadPoolSize(),
158                 getLargestThreadPoolSize(), getMaxThreadPoolSize(), getCurrentQueueSize(),
159                 getLargestQueueSize(), getMaxQueueSize(), getCompletedTaskCount(),
160                 getTotalTaskCount(), getRejectedTaskCount());
161     }
162 }