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