1 16 17 package org.apache.commons.pool.impl; 18 19 import java.util.HashMap ; 20 import java.util.Iterator ; 21 import java.util.ListIterator ; 22 import java.util.Map ; 23 import java.util.NoSuchElementException ; 24 import java.util.Set ; 25 import java.util.TreeMap ; 26 27 import org.apache.commons.collections.CursorableLinkedList; 28 import org.apache.commons.pool.BaseKeyedObjectPool; 29 import org.apache.commons.pool.KeyedObjectPool; 30 import org.apache.commons.pool.KeyedPoolableObjectFactory; 31 32 129 public class GenericKeyedObjectPool extends BaseKeyedObjectPool implements KeyedObjectPool { 130 131 133 142 public static final byte WHEN_EXHAUSTED_FAIL = 0; 143 144 156 public static final byte WHEN_EXHAUSTED_BLOCK = 1; 157 158 167 public static final byte WHEN_EXHAUSTED_GROW = 2; 168 169 175 public static final int DEFAULT_MAX_IDLE = 8; 176 177 183 public static final int DEFAULT_MAX_ACTIVE = 8; 184 185 190 public static final int DEFAULT_MAX_TOTAL = -1; 191 192 199 public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = WHEN_EXHAUSTED_BLOCK; 200 201 210 public static final long DEFAULT_MAX_WAIT = -1L; 211 212 217 public static final boolean DEFAULT_TEST_ON_BORROW = false; 218 219 224 public static final boolean DEFAULT_TEST_ON_RETURN = false; 225 226 233 public static final boolean DEFAULT_TEST_WHILE_IDLE = false; 234 235 240 public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L; 241 242 250 public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3; 251 252 257 public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L; 258 259 264 public static final int DEFAULT_MIN_IDLE = 0; 265 266 268 271 public GenericKeyedObjectPool() { 272 this(null,DEFAULT_MAX_ACTIVE,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE); 273 } 274 275 279 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory) { 280 this(factory,DEFAULT_MAX_ACTIVE,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE); 281 } 282 283 288 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, GenericKeyedObjectPool.Config config) { 289 this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.maxTotal,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle); 290 } 291 292 297 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive) { 298 this(factory,maxActive,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE); 299 } 300 301 308 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) { 309 this(factory,maxActive,whenExhaustedAction,maxWait,DEFAULT_MAX_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE); 310 } 311 312 321 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) { 322 this(factory,maxActive,whenExhaustedAction,maxWait,DEFAULT_MAX_IDLE,testOnBorrow,testOnReturn,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE); 323 } 324 325 333 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) { 334 this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE); 335 } 336 337 347 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) { 348 this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,testOnBorrow,testOnReturn,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE); 349 } 350 351 365 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) { 366 this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle); 367 } 368 369 384 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) { 385 this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, GenericKeyedObjectPool.DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle); 386 } 387 388 404 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) { 405 _factory = factory; 406 _maxActive = maxActive; 407 switch(whenExhaustedAction) { 408 case WHEN_EXHAUSTED_BLOCK: 409 case WHEN_EXHAUSTED_FAIL: 410 case WHEN_EXHAUSTED_GROW: 411 _whenExhaustedAction = whenExhaustedAction; 412 break; 413 default: 414 throw new IllegalArgumentException ("whenExhaustedAction " + whenExhaustedAction + " not recognized."); 415 } 416 _maxWait = maxWait; 417 _maxIdle = maxIdle; 418 _maxTotal = maxTotal; 419 _minIdle = minIdle; 420 _testOnBorrow = testOnBorrow; 421 _testOnReturn = testOnReturn; 422 _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; 423 _numTestsPerEvictionRun = numTestsPerEvictionRun; 424 _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; 425 _testWhileIdle = testWhileIdle; 426 427 _poolMap = new HashMap (); 428 _activeMap = new HashMap (); 429 _poolList = new CursorableLinkedList(); 430 431 startEvictor(_timeBetweenEvictionRunsMillis); 432 } 433 434 436 438 443 public synchronized int getMaxActive() { 444 return _maxActive; 445 } 446 447 453 public synchronized void setMaxActive(int maxActive) { 454 _maxActive = maxActive; 455 notifyAll(); 456 } 457 458 463 public synchronized int getMaxTotal() { 464 return _maxTotal; 465 } 466 467 473 public synchronized void setMaxTotal(int maxTotal) { 474 _maxTotal = maxTotal; 475 notifyAll(); 476 } 477 478 486 public synchronized byte getWhenExhaustedAction() { 487 return _whenExhaustedAction; 488 } 489 490 500 public synchronized void setWhenExhaustedAction(byte whenExhaustedAction) { 501 switch(whenExhaustedAction) { 502 case WHEN_EXHAUSTED_BLOCK: 503 case WHEN_EXHAUSTED_FAIL: 504 case WHEN_EXHAUSTED_GROW: 505 _whenExhaustedAction = whenExhaustedAction; 506 notifyAll(); 507 break; 508 default: 509 throw new IllegalArgumentException ("whenExhaustedAction " + whenExhaustedAction + " not recognized."); 510 } 511 } 512 513 514 528 public synchronized long getMaxWait() { 529 return _maxWait; 530 } 531 532 546 public synchronized void setMaxWait(long maxWait) { 547 _maxWait = maxWait; 548 } 549 550 555 public synchronized int getMaxIdle() { 556 return _maxIdle; 557 } 558 559 566 public synchronized void setMaxIdle(int maxIdle) { 567 _maxIdle = maxIdle; 568 notifyAll(); 569 } 570 571 576 public synchronized void setMinIdle(int poolSize) { 577 _minIdle = poolSize; 578 } 579 580 585 public synchronized int getMinIdle() { 586 return _minIdle; 587 } 588 589 599 public synchronized boolean getTestOnBorrow() { 600 return _testOnBorrow; 601 } 602 603 613 public synchronized void setTestOnBorrow(boolean testOnBorrow) { 614 _testOnBorrow = testOnBorrow; 615 } 616 617 625 public synchronized boolean getTestOnReturn() { 626 return _testOnReturn; 627 } 628 629 637 public synchronized void setTestOnReturn(boolean testOnReturn) { 638 _testOnReturn = testOnReturn; 639 } 640 641 649 public synchronized long getTimeBetweenEvictionRunsMillis() { 650 return _timeBetweenEvictionRunsMillis; 651 } 652 653 661 public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { 662 _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; 663 startEvictor(_timeBetweenEvictionRunsMillis); 664 } 665 666 673 public synchronized int getNumTestsPerEvictionRun() { 674 return _numTestsPerEvictionRun; 675 } 676 677 688 public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { 689 _numTestsPerEvictionRun = numTestsPerEvictionRun; 690 } 691 692 700 public synchronized long getMinEvictableIdleTimeMillis() { 701 return _minEvictableIdleTimeMillis; 702 } 703 704 714 public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { 715 _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; 716 } 717 718 727 public synchronized boolean getTestWhileIdle() { 728 return _testWhileIdle; 729 } 730 731 740 public synchronized void setTestWhileIdle(boolean testWhileIdle) { 741 _testWhileIdle = testWhileIdle; 742 } 743 744 748 public synchronized void setConfig(GenericKeyedObjectPool.Config conf) { 749 setMaxIdle(conf.maxIdle); 750 setMaxActive(conf.maxActive); 751 setMaxTotal(conf.maxTotal); 752 setMinIdle(conf.minIdle); 753 setMaxWait(conf.maxWait); 754 setWhenExhaustedAction(conf.whenExhaustedAction); 755 setTestOnBorrow(conf.testOnBorrow); 756 setTestOnReturn(conf.testOnReturn); 757 setTestWhileIdle(conf.testWhileIdle); 758 setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun); 759 setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis); 760 setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis); 761 } 762 763 765 public synchronized Object borrowObject(Object key) throws Exception { 766 long starttime = System.currentTimeMillis(); 767 boolean newlyCreated = false; 768 for(;;) { 769 CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key)); 770 if(null == pool) { 771 pool = new CursorableLinkedList(); 772 _poolMap.put(key,pool); 773 _poolList.add(key); 774 } 775 ObjectTimestampPair pair = null; 776 try { 778 pair = (ObjectTimestampPair)(pool.removeFirst()); 779 if(null != pair) { 780 _totalIdle--; 781 } 782 } catch(NoSuchElementException e) { 783 } 784 if(null == pair) { 786 if ((_maxTotal > 0) && (_totalActive + _totalIdle >= _maxTotal)) { 789 clearOldest(); 790 } 791 792 int active = getActiveCount(key); 795 if ((_maxActive < 0 || active < _maxActive) && 796 (_maxTotal < 0 || _totalActive + _totalIdle < _maxTotal)) { 797 Object obj = _factory.makeObject(key); 798 pair = new ObjectTimestampPair(obj); 799 newlyCreated = true; 800 } else { 801 switch(_whenExhaustedAction) { 803 case WHEN_EXHAUSTED_GROW: 804 Object obj = _factory.makeObject(key); 805 pair = new ObjectTimestampPair(obj); 806 break; 807 case WHEN_EXHAUSTED_FAIL: 808 throw new NoSuchElementException (); 809 case WHEN_EXHAUSTED_BLOCK: 810 try { 811 if(_maxWait <= 0) { 812 wait(); 813 } else { 814 wait(_maxWait); 815 } 816 } catch(InterruptedException e) { 817 } 819 if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) { 820 throw new NoSuchElementException ("Timeout waiting for idle object"); 821 } else { 822 continue; } 824 default: 825 throw new IllegalArgumentException ("whenExhaustedAction " + _whenExhaustedAction + " not recognized."); 826 } 827 } 828 } 829 _factory.activateObject(key,pair.value); 830 if(_testOnBorrow && !_factory.validateObject(key,pair.value)) { 831 _factory.destroyObject(key,pair.value); 832 if(newlyCreated) { 833 throw new NoSuchElementException ("Could not create a validated object"); 834 } } else { 836 incrementActiveCount(key); 837 return pair.value; 838 } 839 } 840 } 841 842 public synchronized void clear() { 843 for(Iterator keyiter = _poolList.iterator(); keyiter.hasNext(); ) { 844 Object key = keyiter.next(); 845 CursorableLinkedList list = (CursorableLinkedList)(_poolMap.get(key)); 846 for(Iterator it = list.iterator(); it.hasNext(); ) { 847 try { 848 _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value); 849 } catch(Exception e) { 850 } 852 it.remove(); 853 } 854 } 855 _poolMap.clear(); 856 _poolList.clear(); 857 _totalIdle = 0; 858 notifyAll(); 859 } 860 861 865 public synchronized void clearOldest() { 866 TreeMap map = new TreeMap (); 868 for (Iterator keyiter = _poolList.iterator(); keyiter.hasNext();) { 869 Object key = keyiter.next(); 870 CursorableLinkedList list = (CursorableLinkedList) _poolMap.get(key); 871 for (Iterator it = list.iterator(); it.hasNext();) { 872 ObjectTimestampPair pair = (ObjectTimestampPair) it.next(); 876 map.put(pair, key); 877 } 878 } 879 880 Set setPairKeys = map.entrySet(); 882 int itemsToRemove = ((int) (map.size() * 0.15)) + 1; 883 884 Iterator iter = setPairKeys.iterator(); 885 while (iter.hasNext() && itemsToRemove > 0) { 886 Map.Entry entry = (Map.Entry ) iter.next(); 887 Object key = entry.getValue(); 891 ObjectTimestampPair pairTimeStamp = (ObjectTimestampPair) entry.getKey(); 892 CursorableLinkedList list = (CursorableLinkedList) _poolMap.get(key); 893 list.remove(pairTimeStamp); 894 895 try { 896 _factory.destroyObject(key, pairTimeStamp.value); 897 } catch (Exception e) { 898 } 900 if (list.isEmpty()) { 902 _poolMap.remove(key); 903 _poolList.remove(key); 904 } 905 _totalIdle--; 906 itemsToRemove--; 907 } 908 notifyAll(); 909 } 910 911 public synchronized void clear(Object key) { 912 CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.remove(key)); 913 if(null == pool) { 914 return; 915 } else { 916 _poolList.remove(key); 917 for(Iterator it = pool.iterator(); it.hasNext(); ) { 918 try { 919 _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value); 920 } catch(Exception e) { 921 } 923 it.remove(); 924 _totalIdle--; 925 } 926 } 927 notifyAll(); 928 } 929 930 public synchronized int getNumActive() { 931 return _totalActive; 932 } 933 934 public synchronized int getNumIdle() { 935 return _totalIdle; 936 } 937 938 public synchronized int getNumActive(Object key) { 939 return getActiveCount(key); 940 } 941 942 public synchronized int getNumIdle(Object key) { 943 try { 944 return((CursorableLinkedList)(_poolMap.get(key))).size(); 945 } catch(Exception e) { 946 return 0; 947 } 948 } 949 950 public void returnObject(Object key, Object obj) throws Exception { 951 952 boolean success = true; if(_testOnReturn && !_factory.validateObject(key, obj)) { 955 success = false; 956 try { 957 _factory.destroyObject(key, obj); 958 } catch(Exception e) { 959 } 961 } else { 962 try { 963 _factory.passivateObject(key, obj); 964 } catch(Exception e) { 965 success = false; 966 } 967 } 968 969 boolean shouldDestroy = false; 970 synchronized(this) { 971 CursorableLinkedList pool = (CursorableLinkedList) (_poolMap.get(key)); 973 if(null == pool) { 975 pool = new CursorableLinkedList(); 976 _poolMap.put(key, pool); 977 _poolList.add(key); 978 } 979 decrementActiveCount(key); 980 if(_maxIdle >= 0 && (pool.size() >= _maxIdle)) { 983 shouldDestroy = true; 984 } else if(success) { 985 pool.addFirst(new ObjectTimestampPair(obj)); 986 _totalIdle++; 987 } 988 notifyAll(); 989 } 990 991 if(shouldDestroy) { 992 try { 993 _factory.destroyObject(key, obj); 994 } catch(Exception e) { 995 } 997 } 998 } 999 1000 public void invalidateObject(Object key, Object obj) throws Exception { 1001 try { 1002 _factory.destroyObject(key, obj); 1003 } 1004 finally { 1005 synchronized(this) { 1006 decrementActiveCount(key); 1007 notifyAll(); } 1009 } 1010 } 1011 1012 public void addObject(Object key) throws Exception { 1013 Object obj = _factory.makeObject(key); 1014 synchronized(this) { 1015 incrementActiveCount(key); returnObject(key,obj); 1017 } 1018 } 1019 1020 1031 public void preparePool(Object key, boolean populateImmediately) { 1032 synchronized(this) { 1033 CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key)); 1034 if (null == pool) { 1035 pool = new CursorableLinkedList(); 1036 _poolMap.put(key,pool); 1037 _poolList.add(key); 1038 } 1039 } 1040 if (populateImmediately) { 1041 try { 1042 ensureMinIdle(key); 1044 } 1045 catch (Exception e) { 1046 } 1048 } 1049 } 1050 1051 public synchronized void close() throws Exception { 1052 clear(); 1053 _poolList = null; 1054 _poolMap = null; 1055 _activeMap = null; 1056 if(null != _evictionCursor) { 1057 _evictionCursor.close(); 1058 _evictionCursor = null; 1059 } 1060 if(null != _evictionKeyCursor) { 1061 _evictionKeyCursor.close(); 1062 _evictionKeyCursor = null; 1063 } 1064 if(null != _evictor) { 1065 _evictor.cancel(); 1066 _evictor = null; 1067 } 1068 } 1069 1070 public synchronized void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException { 1071 if(0 < getNumActive()) { 1072 throw new IllegalStateException ("Objects are already active"); 1073 } else { 1074 clear(); 1075 _factory = factory; 1076 } 1077 } 1078 1079 public synchronized void evict() throws Exception { 1080 Object key = null; 1081 for(int i=0,m=getNumTests();i<m;i++) { 1082 if(_poolMap.size() > 0) { 1083 if(null == _evictionKeyCursor) { 1085 _evictionKeyCursor = _poolList.cursor(); 1086 key = null; 1087 if(null != _evictionCursor) { 1088 _evictionCursor.close(); 1089 _evictionCursor = null; 1090 } 1091 } 1092 if(null == _evictionCursor) { 1094 if(_evictionKeyCursor.hasNext()) { 1096 key = _evictionKeyCursor.next(); 1097 CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key)); 1098 _evictionCursor = pool.cursor(pool.size()); 1099 } else { 1100 if(null != _evictionKeyCursor) { 1102 _evictionKeyCursor.close(); 1103 _evictionKeyCursor = _poolList.cursor(); 1104 if(null != _evictionCursor) { 1105 _evictionCursor.close(); 1106 _evictionCursor = null; 1107 } 1108 } 1109 continue; 1110 } 1111 } 1112 if(_evictionCursor.hasPrevious()) { 1114 ObjectTimestampPair pair = (ObjectTimestampPair)(_evictionCursor.previous()); 1115 boolean removeObject=false; 1116 if(_minEvictableIdleTimeMillis > 0 && 1117 System.currentTimeMillis() - pair.tstamp > _minEvictableIdleTimeMillis) { 1118 removeObject=true; 1119 } else if(_testWhileIdle) { 1120 boolean active = false; 1121 try { 1122 _factory.activateObject(key,pair.value); 1123 active = true; 1124 } catch(Exception e) { 1125 removeObject=true; 1126 } 1127 if(active) { 1128 if(!_factory.validateObject(key,pair.value)) { 1129 removeObject=true; 1130 } else { 1131 try { 1132 _factory.passivateObject(key,pair.value); 1133 } catch(Exception e) { 1134 removeObject=true; 1135 } 1136 } 1137 } 1138 } 1139 if(removeObject) { 1140 try { 1141 _evictionCursor.remove(); 1142 _totalIdle--; 1143 _factory.destroyObject(key,pair.value); 1144 1145 if ((_minIdle == 0) && (((CursorableLinkedList)(_poolMap.get(key))).isEmpty())) { 1151 _poolMap.remove(key); 1152 _poolList.remove(key); 1153 } 1154 } catch(Exception e) { 1155 ; } 1157 } 1158 } else { 1159 if(_evictionCursor != null) { 1161 _evictionCursor.close(); 1162 _evictionCursor = null; 1163 } 1164 } 1165 } 1166 } 1167 } 1168 1169 1176 private synchronized void ensureMinIdle() throws Exception { 1177 ListIterator iterator = _poolList.cursor(); 1178 1179 if (_minIdle > 0) { 1181 while (iterator.hasNext()) { 1186 Object key = iterator.next(); 1188 ensureMinIdle(key); 1189 } 1190 } 1191 } 1192 1193 1204 private synchronized void ensureMinIdle(Object key) throws Exception { 1205 int numberToCreate = calculateDefecit(key); 1207 1208 for (int i = 0; i < numberToCreate; i++) { 1210 addObject(key); 1211 } 1212 } 1213 1214 1216 1221 protected synchronized void startEvictor(long delay) { 1222 if(null != _evictor) { 1223 _evictor.cancel(); 1224 _evictor = null; 1225 } 1226 if(delay > 0) { 1227 _evictor = new Evictor(delay); 1228 Thread t = new Thread (_evictor); 1229 t.setDaemon(true); 1230 t.start(); 1231 } 1232 } 1233 1234 synchronized String debugInfo() { 1235 StringBuffer buf = new StringBuffer (); 1236 buf.append("Active: ").append(getNumActive()).append("\n"); 1237 buf.append("Idle: ").append(getNumIdle()).append("\n"); 1238 Iterator it = _poolList.iterator(); 1239 while(it.hasNext()) { 1240 buf.append("\t").append(_poolMap.get(it.next())).append("\n"); 1241 } 1242 return buf.toString(); 1243 } 1244 1245 private synchronized int getNumTests() { 1246 if(_numTestsPerEvictionRun >= 0) { 1247 return _numTestsPerEvictionRun; 1248 } else { 1249 return(int)(Math.ceil((double)_totalIdle/Math.abs((double)_numTestsPerEvictionRun))); 1250 } 1251 } 1252 1253 private synchronized void incrementActiveCount(Object key) { 1254 _totalActive++; 1255 Integer active = (Integer )(_activeMap.get(key)); 1256 if(null == active) { 1257 _activeMap.put(key,new Integer (1)); 1258 } else { 1259 _activeMap.put(key,new Integer (active.intValue() + 1)); 1260 } 1261 } 1262 1263 private synchronized void decrementActiveCount(Object key) { 1264 _totalActive--; 1265 Integer active = (Integer )(_activeMap.get(key)); 1266 if(null == active) { 1267 } else if(active.intValue() <= 1) { 1269 _activeMap.remove(key); 1270 } else { 1271 _activeMap.put(key, new Integer (active.intValue() - 1)); 1272 } 1273 } 1274 1275 private synchronized int getActiveCount(Object key) { 1276 int active = 0; 1277 Integer act = (Integer )(_activeMap.get(key)); 1278 if(null != act) { 1279 active = act.intValue(); 1280 } 1281 return active; 1282 } 1283 1296 private synchronized int calculateDefecit(Object key) { 1297 int objectDefecit = 0; 1298 1299 objectDefecit = getMinIdle() - getNumIdle(key); 1302 if (getMaxActive() > 0) { 1303 int growLimit = Math.max(0, getMaxActive() - getNumActive(key) - getNumIdle(key)); 1304 objectDefecit = Math.min(objectDefecit, growLimit); 1305 } 1306 1307 if (getMaxTotal() > 0) { 1309 int growLimit = Math.max(0, getMaxTotal() - getNumActive() - getNumIdle()); 1310 objectDefecit = Math.min(objectDefecit, growLimit); 1311 } 1312 1313 return objectDefecit; 1314 } 1315 1316 1318 1323 class ObjectTimestampPair implements Comparable { 1324 Object value; 1325 long tstamp; 1326 1327 ObjectTimestampPair(Object val) { 1328 value = val; 1329 tstamp = System.currentTimeMillis(); 1330 } 1331 1332 ObjectTimestampPair(Object val, long time) { 1333 value = val; 1334 tstamp = time; 1335 } 1336 1337 public String toString() { 1338 return value + ";" + tstamp; 1339 } 1340 1341 public int compareTo(Object obj) { 1342 return compareTo((ObjectTimestampPair) obj); 1343 } 1344 1345 public int compareTo(ObjectTimestampPair other) { 1346 return (int) (this.tstamp - other.tstamp); 1347 } 1348 } 1349 1350 1354 class Evictor implements Runnable { 1355 private boolean _cancelled = false; 1356 private long _delay = 0L; 1357 1358 public Evictor(long delay) { 1359 _delay = delay; 1360 } 1361 1362 void cancel() { 1363 _cancelled = true; 1364 } 1365 1366 public void run() { 1367 while(!_cancelled) { 1368 long sleeptime = 0L; 1369 synchronized(GenericKeyedObjectPool.this) { 1370 sleeptime = _timeBetweenEvictionRunsMillis; 1371 } 1372 try { 1373 Thread.sleep(sleeptime); 1374 } catch(Exception e) { 1375 ; } 1377 try { 1379 evict(); 1380 } catch(Exception e) { 1381 ; } 1383 try { 1385 ensureMinIdle(); 1386 } catch (Exception e) { 1387 ; } 1389 } 1390 synchronized(GenericKeyedObjectPool.this) { 1391 if(null != _evictionCursor) { 1392 _evictionCursor.close(); 1393 _evictionCursor = null; 1394 } 1395 if(null != _evictionKeyCursor) { 1396 _evictionKeyCursor.close(); 1397 _evictionKeyCursor = null; 1398 } 1399 } 1400 } 1401 } 1402 1403 1409 public static class Config { 1410 public int maxIdle = GenericKeyedObjectPool.DEFAULT_MAX_IDLE; 1411 public int maxActive = GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE; 1412 public int maxTotal = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL; 1413 public int minIdle = GenericKeyedObjectPool.DEFAULT_MIN_IDLE; 1414 public long maxWait = GenericKeyedObjectPool.DEFAULT_MAX_WAIT; 1415 public byte whenExhaustedAction = GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION; 1416 public boolean testOnBorrow = GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW; 1417 public boolean testOnReturn = GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN; 1418 public boolean testWhileIdle = GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE; 1419 public long timeBetweenEvictionRunsMillis = GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; 1420 public int numTestsPerEvictionRun = GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; 1421 public long minEvictableIdleTimeMillis = GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; 1422 } 1423 1424 1426 1431 private int _maxIdle = DEFAULT_MAX_IDLE; 1432 1433 1438 private int _minIdle = DEFAULT_MIN_IDLE; 1439 1440 1445 private int _maxActive = DEFAULT_MAX_ACTIVE; 1446 1447 1452 private int _maxTotal = DEFAULT_MAX_TOTAL; 1453 1454 1470 private long _maxWait = DEFAULT_MAX_WAIT; 1471 1472 1484 private byte _whenExhaustedAction = DEFAULT_WHEN_EXHAUSTED_ACTION; 1485 1486 1497 private boolean _testOnBorrow = DEFAULT_TEST_ON_BORROW; 1498 1499 1508 private boolean _testOnReturn = DEFAULT_TEST_ON_RETURN; 1509 1510 1521 private boolean _testWhileIdle = DEFAULT_TEST_WHILE_IDLE; 1522 1523 1532 private long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; 1533 1534 1547 private int _numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN; 1548 1549 1561 private long _minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; 1562 1563 1564 private HashMap _poolMap = null; 1565 1566 1570 private CursorableLinkedList _poolList = null; 1571 1572 1573 private HashMap _activeMap = null; 1574 1575 1576 private int _totalActive = 0; 1577 1578 1579 private int _totalIdle = 0; 1580 1581 1582 private KeyedPoolableObjectFactory _factory = null; 1583 1584 1587 private Evictor _evictor = null; 1588 1589 private CursorableLinkedList.Cursor _evictionCursor = null; 1590 private CursorableLinkedList.Cursor _evictionKeyCursor = null; 1591 1592} 1593 | Popular Tags |