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