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 */ 022package org.granite.gravity; 023 024import java.util.ArrayList; 025import java.util.List; 026import java.util.concurrent.LinkedBlockingQueue; 027import java.util.concurrent.RejectedExecutionException; 028import java.util.concurrent.ThreadPoolExecutor; 029import java.util.concurrent.TimeUnit; 030 031import org.granite.logging.Logger; 032 033/** 034 * @author Franck WOLFF 035 */ 036public 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}