1 17 18 package org.apache.geronimo.connector.outbound; 19 20 import java.util.ArrayList ; 21 import java.util.Collections ; 22 import java.util.Arrays ; 23 import javax.resource.ResourceException ; 24 import javax.resource.spi.ManagedConnection ; 25 26 import org.apache.commons.logging.Log; 27 import org.apache.commons.logging.LogFactory; 28 29 40 public class SinglePoolConnectionInterceptor extends AbstractSinglePoolConnectionInterceptor { 41 private static final Log log = LogFactory.getLog(SinglePoolConnectionInterceptor.class.getName()); 42 43 private boolean selectOneAssumeMatch; 44 45 private PoolDeque pool; 46 47 public SinglePoolConnectionInterceptor(final ConnectionInterceptor next, 48 int maxSize, 49 int minSize, 50 int blockingTimeoutMilliseconds, 51 int idleTimeoutMinutes, 52 boolean selectOneAssumeMatch) { 53 super(next, maxSize, minSize, blockingTimeoutMilliseconds, idleTimeoutMinutes); 54 pool = new PoolDeque(maxSize); 55 this.selectOneAssumeMatch = selectOneAssumeMatch; 56 } 57 58 protected void internalGetConnection(ConnectionInfo connectionInfo) throws ResourceException { 59 synchronized (pool) { 60 if (destroyed) { 61 throw new ResourceException ("ManagedConnection pool has been destroyed"); 62 } 63 64 ManagedConnectionInfo newMCI = null; 65 if (pool.isEmpty()) { 66 next.getConnection(connectionInfo); 67 connectionCount++; 68 if (log.isTraceEnabled()) { 69 log.trace("Supplying new connection MCI: " + connectionInfo.getManagedConnectionInfo() + " MC: " + connectionInfo.getManagedConnectionInfo().getManagedConnection() + " from pool: " + this); 70 } 71 return; 72 } else { 73 newMCI = pool.removeLast(); 74 } 75 if (connectionCount < minSize) { 76 timer.schedule(new FillTask(connectionInfo), 10); 77 } 78 if (selectOneAssumeMatch) { 79 connectionInfo.setManagedConnectionInfo(newMCI); 80 if (log.isTraceEnabled()) { 81 log.trace("Supplying pooled connection without checking matching MCI: " + connectionInfo.getManagedConnectionInfo() + " MC: " + connectionInfo.getManagedConnectionInfo().getManagedConnection() + " from pool: " + this); 82 } 83 return; 84 } 85 try { 86 ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo(); 87 ManagedConnection matchedMC = 88 newMCI 89 .getManagedConnectionFactory() 90 .matchManagedConnections(Collections.singleton(newMCI.getManagedConnection()), 91 mci.getSubject(), 92 mci.getConnectionRequestInfo()); 93 if (matchedMC != null) { 94 connectionInfo.setManagedConnectionInfo(newMCI); 95 if (log.isTraceEnabled()) { 96 log.trace("Supplying pooled connection MCI: " + connectionInfo.getManagedConnectionInfo() + " MC: " + connectionInfo.getManagedConnectionInfo().getManagedConnection() + " from pool: " + this); 97 } 98 return; 99 } else { 100 ConnectionInfo returnCI = new ConnectionInfo(); 102 returnCI.setManagedConnectionInfo(newMCI); 103 returnConnection(returnCI, 104 ConnectionReturnAction.RETURN_HANDLE); 105 throw new ResourceException ("The pooling strategy does not match the MatchManagedConnections implementation. Please investigate and reconfigure this pool"); 106 } 107 } catch (ResourceException e) { 108 ConnectionInfo returnCI = new ConnectionInfo(); 110 returnCI.setManagedConnectionInfo(newMCI); 111 returnConnection(returnCI, 112 ConnectionReturnAction.DESTROY); 113 throw e; 114 } 115 } 116 } 117 118 protected void internalDestroy() { 119 synchronized (pool) { 120 while (!pool.isEmpty()) { 121 ManagedConnection mc = pool.removeLast().getManagedConnection(); 122 if (mc != null) { 123 try { 124 mc.destroy(); 125 } 126 catch (ResourceException re) { } } 128 } 129 } 130 } 131 132 protected boolean internalReturn(ConnectionInfo connectionInfo, ConnectionReturnAction connectionReturnAction) { 133 ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo(); 134 ManagedConnection mc = mci.getManagedConnection(); 135 if (connectionReturnAction == ConnectionReturnAction.RETURN_HANDLE) { 136 try { 137 mc.cleanup(); 138 } catch (ResourceException e) { 139 connectionReturnAction = ConnectionReturnAction.DESTROY; 140 } 141 } 142 boolean wasInPool = false; 143 synchronized (pool) { 144 if (destroyed) { 147 try { 148 mc.destroy(); 149 } 150 catch (ResourceException re) { } return pool.remove(mci); 152 } 153 154 if (shrinkLater > 0) { 155 connectionReturnAction = ConnectionReturnAction.DESTROY; 157 shrinkLater--; 158 } else if (connectionReturnAction == ConnectionReturnAction.RETURN_HANDLE) { 159 mci.setLastUsed(System.currentTimeMillis()); 160 pool.add(mci); 161 return wasInPool; 162 } else { 163 wasInPool = pool.remove(mci); 164 } 165 } 166 next.returnConnection(connectionInfo, connectionReturnAction); 168 connectionCount--; 169 return wasInPool; 170 } 171 172 public int getPartitionMaxSize() { 173 return pool.capacity(); 174 } 175 176 protected void transferConnections(int maxSize, int shrinkNow) { 177 PoolDeque oldPool = pool; 180 pool = new PoolDeque(maxSize); 181 for (int i = 0; i < shrinkNow; i++) { 183 ConnectionInfo killInfo = new ConnectionInfo(oldPool.peek(i)); 184 internalReturn(killInfo, ConnectionReturnAction.DESTROY); 185 } 186 for (int i = shrinkNow; i < connectionCount; i++) { 187 pool.add(oldPool.peek(i)); 188 } 189 } 190 191 public int getIdleConnectionCount() { 192 return pool.currentSize(); 193 } 194 195 196 protected void getExpiredManagedConnectionInfos(long threshold, ArrayList killList) { 197 synchronized (pool) { 198 for (int i = 0; i < pool.currentSize(); i++) { 199 ManagedConnectionInfo mci = pool.peek(i); 200 if (mci.getLastUsed() < threshold) { 201 killList.add(mci); 202 } 203 } 204 } 205 } 206 207 protected boolean addToPool(ManagedConnectionInfo mci) { 208 boolean added; 209 synchronized (pool) { 210 connectionCount++; 211 added = getPartitionMaxSize() > getIdleConnectionCount(); 212 if (added) { 213 pool.add(mci); 214 } 215 } 216 return added; 217 } 218 219 static class PoolDeque { 220 221 private final ManagedConnectionInfo[] deque; 222 private final int first = 0; 223 private int last = -1; 224 225 public PoolDeque(int size) { 226 deque = new ManagedConnectionInfo[size]; 227 } 228 229 public boolean isEmpty() { 231 return first > last; 232 } 233 234 public void add(ManagedConnectionInfo mci) { 236 if (last == deque.length - 1) { 237 throw new IllegalStateException ("deque is full: contents: " + Arrays.asList(deque)); 238 } 239 deque[++last] = mci; 240 } 241 242 public ManagedConnectionInfo peek(int i) { 244 if (i < first || i > last) { 245 throw new IllegalStateException ("index is out of current range"); 246 } 247 return deque[i]; 248 } 249 250 public ManagedConnectionInfo removeLast() { 252 if (isEmpty()) { 253 throw new IllegalStateException ("deque is empty"); 254 } 255 256 return deque[last--]; 257 } 258 259 public boolean remove(ManagedConnectionInfo mci) { 261 for (int i = first; i <= last; i++) { 262 if (deque[i] == mci) { 263 for (int j = i + 1; j <= last; j++) { 264 deque[j - 1] = deque[j]; 265 } 266 last--; 267 return true; 268 } 269 270 } 271 return false; 272 } 273 274 public int capacity() { 276 return deque.length; 277 } 278 279 public int currentSize() { 281 return last - first + 1; 282 } 283 } 284 285 } 286 | Popular Tags |