001 /**
002 * GRANITE DATA SERVICES
003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 * This file is part of the Granite Data Services Platform.
006 *
007 * Granite Data Services is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * Granite Data Services is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
015 * General Public License for more details.
016 *
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
020 * USA, or see <http://www.gnu.org/licenses/>.
021 */
022 package org.granite.gravity;
023
024 import java.util.ArrayList;
025 import java.util.List;
026 import java.util.concurrent.LinkedBlockingQueue;
027 import java.util.concurrent.RejectedExecutionException;
028 import java.util.concurrent.ThreadPoolExecutor;
029 import java.util.concurrent.TimeUnit;
030
031 import org.granite.logging.Logger;
032
033 /**
034 * @author Franck WOLFF
035 */
036 public class GravityPool {
037
038 private static final Logger log = Logger.getLogger(GravityPool.class);
039
040 public static final int DEFAULT_CORE_POOL_SIZE = 5;
041 public static final int DEFAULT_MAXIMUM_POOL_SIZE = 20;
042 public static final long DEFAULT_KEEP_ALIVE_TIME = 10000L;
043 public static final int DEFAULT_QUEUE_CAPACITY = Integer.MAX_VALUE;
044
045 private final ThreadPoolExecutor pool;
046 private final int queueCapacity;
047
048 public GravityPool() {
049 this(DEFAULT_CORE_POOL_SIZE, DEFAULT_MAXIMUM_POOL_SIZE, DEFAULT_KEEP_ALIVE_TIME, DEFAULT_QUEUE_CAPACITY);
050 }
051
052 public GravityPool(GravityConfig config) {
053 this(config.getCorePoolSize(), config.getMaximumPoolSize(), config.getKeepAliveTimeMillis(), config.getQueueCapacity());
054 }
055
056 public GravityPool(int corePoolSize, int maximumPoolSize, long keepAliveTimeMillis, int queueCapacity) {
057 log.info(
058 "Starting Gravity Pool (corePoolSize=%d, maximumPoolSize=%d, keepAliveTimeMillis=%d, queueCapacity=%d)...",
059 corePoolSize, maximumPoolSize, keepAliveTimeMillis, queueCapacity
060 );
061
062 this.queueCapacity = queueCapacity;
063 this.pool = new ThreadPoolExecutor(
064 corePoolSize,
065 maximumPoolSize,
066 keepAliveTimeMillis,
067 TimeUnit.MILLISECONDS,
068 new LinkedBlockingQueue<Runnable>(queueCapacity),
069 new ThreadPoolExecutor.AbortPolicy()
070 );
071 }
072
073 public int getQueueCapacity() {
074 return queueCapacity;
075 }
076
077 public int getQueueRemainingCapacity() {
078 return pool.getQueue().remainingCapacity();
079 }
080
081 public int getQueueSize() {
082 return pool.getQueue().size();
083 }
084
085 public int getCorePoolSize() {
086 return pool.getCorePoolSize();
087 }
088 public void setCorePoolSize(int corePoolSize) {
089 pool.setCorePoolSize(corePoolSize);
090 }
091
092 public int getMaximumPoolSize() {
093 return pool.getMaximumPoolSize();
094 }
095 public void setMaximumPoolSize(int maximumPoolSize) {
096 pool.setMaximumPoolSize(maximumPoolSize);
097 }
098
099 public long getKeepAliveTimeMillis() {
100 return pool.getKeepAliveTime(TimeUnit.MILLISECONDS);
101 }
102 public void setKeepAliveTimeMillis(long keepAliveTimeMillis) {
103 pool.setKeepAliveTime(keepAliveTimeMillis, TimeUnit.MILLISECONDS);
104 }
105
106 public void reconfigure(GravityConfig config) {
107 pool.setCorePoolSize(config.getCorePoolSize());
108 pool.setKeepAliveTime(config.getKeepAliveTimeMillis(), TimeUnit.MILLISECONDS);
109 pool.setMaximumPoolSize(config.getMaximumPoolSize());
110 }
111
112 public void execute(AsyncChannelRunner runner) {
113 if (runner == null)
114 throw new NullPointerException("runner cannot be null");
115
116 if (!pool.isShutdown()) {
117 try {
118 pool.execute(runner);
119 }
120 catch (RejectedExecutionException e) {
121 runner.reset();
122 throw e;
123 }
124 }
125 else
126 runner.reset();
127 }
128
129 public boolean contains(AsyncChannelRunner runner) {
130 return pool.getQueue().contains(runner);
131 }
132
133 public boolean remove(AsyncChannelRunner runner) {
134 if (pool.getQueue().remove(runner)) {
135 runner.reset();
136 return true;
137 }
138 return false;
139 }
140
141 public void clear() {
142 List<Runnable> runnables = new ArrayList<Runnable>(pool.getQueue().size());
143 pool.getQueue().drainTo(runnables);
144 for (Runnable runnable : runnables)
145 ((AsyncChannelRunner)runnable).reset();
146 }
147
148 public boolean isShutdown() {
149 return pool.isShutdown();
150 }
151
152 public boolean isTerminated() {
153 return pool.isTerminated();
154 }
155
156 public void shutdown() {
157 log.info("Stopping Gravity Pool...");
158 pool.shutdown();
159 }
160
161 public List<AsyncChannelRunner> shutdownNow() {
162 log.info("Stopping Gravity Pool Now...");
163 List<Runnable> runnables = pool.shutdownNow();
164 List<AsyncChannelRunner> runners = new ArrayList<AsyncChannelRunner>(runnables.size());
165 for (Runnable runnable : runnables) {
166 AsyncChannelRunner runner = (AsyncChannelRunner)runnable;
167 runner.reset();
168 runners.add(runner);
169 }
170 return runners;
171 }
172 }