1 30 31 package org.objectweb.jonas.resource.pool.lib; 32 33 import java.util.HashSet ; 34 import java.util.Hashtable ; 35 import java.util.LinkedList ; 36 import java.util.Iterator ; 37 import java.util.Vector ; 38 39 import javax.resource.spi.ManagedConnection ; 40 41 import org.objectweb.jonas.resource.ConnectionManagerImpl; 42 import org.objectweb.jonas.resource.pool.api.Pool; 43 import org.objectweb.jonas.resource.pool.api.PoolItemStats; 44 import org.objectweb.jonas.resource.pool.api.PoolMatchFactory; 45 import org.objectweb.util.monolog.api.BasicLevel; 46 import org.objectweb.util.monolog.api.Logger; 47 48 56 public class HArrayPool implements Pool { 57 58 61 private Logger logger = null; 62 63 66 private long timeout = 0; 67 70 private PoolMatchFactory matchFactory = null; 71 74 private HashSet freeList = null; 75 78 private HashSet activeList = null; 79 82 private Hashtable infoList = null; 83 84 87 private static final int NO_LIMIT = -1; 88 89 92 private static final long ONE_DAY = 1440L * 60L * 1000L; 93 94 98 private static final int MAX_REMOVE_FREELIST = 10; 99 100 103 private int busyMin = 0; 104 105 108 private int busyMax = 0; 109 110 113 private int initSize = -1; 114 115 118 private int maxAge = 0; 119 120 123 private int maxOpentime = 0; 124 125 128 private int maxSize = -1; 129 130 133 private int maxWaiters = 1000; 134 135 138 private long maxWaitTimeout = 10000; 139 140 143 private int minSize = 0; 144 145 148 private HArrayPoolMonitor poolMonitor = null; 149 150 153 private int samplingPeriod = 60; 155 158 private int waiterCount = 0; 159 160 163 private long waitingTime = 0; 164 165 166 170 public HArrayPool(Logger logger) { 171 this.logger = logger; 172 freeList = new HashSet (); 173 activeList = new HashSet (); 174 infoList = new Hashtable (); 175 } 176 177 181 184 public int getCurrentBusy() { 185 return activeList.size(); 186 } 187 188 191 public int getCurrentOpened() { 192 return getSize(); 193 } 194 195 198 public int getInitSize() { 199 return initSize; 200 } 201 202 205 public synchronized void setInitSize(int initsize) throws Exception { 206 if (matchFactory == null) { 207 throw new Exception ("The matchFactory is mandatory!"); 208 } 209 if (initSize < 0 && initsize >= 0) { 210 initSize = initsize; 211 setInitSize(); 212 } 213 } 214 215 219 private void setInitSize() throws Exception { 220 int initsize; 221 222 if (initSize <= 0) { 223 return; 224 } 225 226 if (maxSize < 0) { 227 initsize = initSize; 228 } else { 229 initsize = initSize < maxSize ? initSize : maxSize; 230 } 231 initsize = initsize < minSize ? 0 : initsize - minSize; 232 233 ManagedConnection res; 234 synchronized (this) { 235 for (int i = 0; i < initsize; i++) { 236 res = createResource(null); 237 freeList.add(res); 238 infoList.put(res, new PoolItemStats()); 239 } 240 } 241 } 242 243 246 public int getMaxAge() { 247 return maxAge; 248 } 249 250 253 public void setMaxAge(int maxAge) { 254 this.maxAge = maxAge; 255 } 256 257 260 public int getMaxOpentime() { 261 return maxOpentime; 262 } 263 264 267 public void setMaxOpentime(int mx) { 268 maxOpentime = mx; 269 } 270 271 274 public int getMaxSize() { 275 return maxSize; 276 } 277 278 281 public synchronized void setMaxSize(int maxsize) throws Exception { 282 if (matchFactory == null) { 283 throw new Exception ("The matchFactory mandatory!!"); 284 } 285 if (maxsize < minSize || maxsize == maxSize) { 286 return; 287 } 288 289 if (maxsize < 0) { 291 if (currentWaiters > 0) { 292 notify(); 293 } 294 maxSize = maxsize; 295 } else { 296 if (currentWaiters > 0 && maxSize < maxsize) { 297 notify(); 298 } 299 maxSize = maxsize; 300 adjust(); 301 } 302 } 303 304 307 public int getMaxWaiters() { 308 return maxWaiters; 309 } 310 311 314 public void setMaxWaiters(int nb) { 315 maxWaiters = nb; 316 } 317 318 321 public int getMaxWaitTime() { 322 return (int) (maxWaitTimeout / 1000L); 323 } 324 325 328 public void setMaxWaitTime(int sec) { 329 maxWaitTimeout = sec * 1000L; 330 } 331 332 335 public int getMinSize() { 336 return minSize; 337 } 338 339 342 public synchronized void setMinSize(int minsize) throws Exception { 343 if (matchFactory == null) { 344 throw new Exception ("A matchFactory is mandatory!"); 345 } 346 if ((minsize < 0) || (minsize > maxSize) || (minsize == minSize)) { 347 return; 348 } 349 if (minsize < minSize) { 350 minSize = minsize; 351 return; 352 } 353 minSize = minsize; 354 adjust(); 355 } 356 357 360 public int getSamplingPeriod() { 361 return samplingPeriod; 362 } 363 364 367 public void setSamplingPeriod(int sec) { 368 if (sec > 0) { 369 samplingPeriod = sec; 370 poolMonitor.setSamplingPeriod(sec); 371 } 372 } 373 374 378 public synchronized int getSize() { 379 return (activeList.size() + freeList.size()); 380 } 381 382 385 public long getTimeout() { 386 return timeout; 387 } 388 389 392 public synchronized void setTimeout(long crto) { 393 } 394 395 396 401 404 private int busyMaxRecent = 0; 405 406 409 public int getBusyMaxRecent() { 410 return busyMaxRecent; 411 } 412 413 416 private int busyMinRecent = 0; 417 418 421 public int getBusyMinRecent() { 422 return busyMinRecent; 423 } 424 425 428 private int currentWaiters = 0; 429 430 433 public int getCurrentWaiters() { 434 return currentWaiters; 435 } 436 437 440 private int openedCount = 0; 441 442 445 public int getOpenedCount() { 446 return openedCount; 447 } 448 449 452 private int connectionFailures = 0; 453 454 457 public int getConnectionFailures() { 458 return connectionFailures; 459 } 460 461 466 private int connectionLeaks = 0; 467 468 471 public int getConnectionLeaks() { 472 return connectionLeaks; 473 } 474 475 478 private int servedOpen = 0; 479 480 483 public int getServedOpen() { 484 return servedOpen; 485 } 486 487 490 private int rejectedFull = 0; 491 492 495 public int getRejectedFull() { 496 return rejectedFull; 497 } 498 499 502 private int rejectedTimeout = 0; 503 504 507 public int getRejectedTimeout() { 508 return rejectedTimeout; 509 } 510 511 514 private int rejectedOther = 0; 515 516 519 public int getRejectedOther() { 520 return rejectedOther; 521 } 522 523 526 public int getRejectedOpen() { 527 return rejectedFull + rejectedTimeout + rejectedOther; 528 } 529 530 533 private int waitersHigh = 0; 534 535 538 public int getWaitersHigh() { 539 return waitersHigh; 540 } 541 542 545 private int waitersHighRecent = 0; 546 547 550 public int getWaitersHighRecent() { 551 return waitersHighRecent; 552 } 553 554 557 private int totalWaiterCount = 0; 558 559 562 public int getWaiterCount() { 563 return totalWaiterCount; 564 } 565 566 569 private long totalWaitingTime = 0; 570 571 574 public long getWaitingTime() { 575 return totalWaitingTime; 576 } 577 578 581 private long waitingHigh = 0; 582 583 586 public long getWaitingHigh() { 587 return waitingHigh; 588 } 589 590 593 private long waitingHighRecent = 0; 594 595 598 public long getWaitingHighRecent() { 599 return waitingHighRecent; 600 } 601 602 604 607 public synchronized Object getResource(Object hints) 608 throws Exception { 609 610 if (matchFactory == null) { 611 throw new Exception ("The matchFactory mandatory!!"); 612 } 613 ManagedConnection res = null; 614 long timetowait = maxWaitTimeout; 615 long starttime = 0; 616 while (res == null) { 617 if (!freeList.isEmpty()) { 618 try { 619 if (logger.isLoggable(BasicLevel.DEBUG)) { 620 logger.log(BasicLevel.DEBUG, "Free entries available"); 621 } 622 res = (ManagedConnection ) matchFactory.matchResource(freeList, hints); 623 if (res != null) { 624 freeList.remove(res); 625 activeList.add(res); 626 } 627 } catch (Exception ex) { 628 if (logger.isLoggable(BasicLevel.DEBUG)) { 629 logger.log(BasicLevel.DEBUG, "Error from matchResource", ex); 630 } 631 } 632 } 633 if (res == null) { 634 int curSize = activeList.size() + freeList.size(); 635 if (maxSize < 0 || curSize < maxSize) { 636 res = createResource(hints); 637 activeList.add(res); 638 } else if (freeList.size() > 0) { 639 res = (ManagedConnection ) freeList.iterator().next(); 640 matchFactory.releaseResource(res); 641 res.destroy(); 642 freeList.remove(res); 643 infoList.remove(res); 644 res = createResource(hints); 646 activeList.add(res); 647 } else { 648 boolean stoplooping = true; 649 if (timetowait > 0) { 651 if (currentWaiters < maxWaiters) { 652 currentWaiters++; 653 if (waiterCount < currentWaiters) { 655 waiterCount = currentWaiters; 656 } 657 if (starttime == 0) { 658 starttime = System.currentTimeMillis(); 659 if (logger.isLoggable(BasicLevel.DEBUG)) { 660 logger.log(BasicLevel.DEBUG, "Wait for a free Connection"); 661 } 662 } 663 try { 664 wait(timetowait); 665 } catch (InterruptedException ign) { 666 logger.log(BasicLevel.WARN, "Interrupted"); 667 } finally { 668 currentWaiters--; 669 } 670 long stoptime = System.currentTimeMillis(); 671 long stillwaited = stoptime - starttime; 672 timetowait = maxWaitTimeout - stillwaited; 673 stoplooping = (timetowait <= 0); 674 if (stoplooping) { 675 totalWaiterCount++; 677 totalWaitingTime += stillwaited; 678 if (waitingTime < stillwaited) { 679 waitingTime = stillwaited; 680 } 681 } else { 682 if (!freeList.isEmpty()) { 683 if (logger.isLoggable(BasicLevel.DEBUG)) { 685 logger.log(BasicLevel.DEBUG, "Notified after " + stillwaited); 686 } 687 totalWaiterCount++; 688 totalWaitingTime += stillwaited; 689 if (waitingTime < stillwaited) { 690 waitingTime = stillwaited; 691 } 692 } 693 continue; 694 } 695 } 696 } 697 if (stoplooping && freeList.isEmpty()) { 698 if (starttime > 0) { 699 rejectedTimeout++; 700 logger.log(BasicLevel.WARN, "Cannot create a Connection - timeout"); 701 } else { 702 rejectedFull++; 703 logger.log(BasicLevel.WARN, "Cannot create a Connection"); 704 } 705 throw new Exception ("No more connections"); 706 } 707 } 708 } 709 } 710 infoList.put(res, new PoolItemStats()); 711 712 printLists(); 713 setItemStats(res); 714 recomputeBusy(); 715 return res; 716 } 717 718 724 private ManagedConnection createResource(Object hints) throws Exception { 725 ManagedConnection res = null; 726 try { 727 res = (ManagedConnection ) matchFactory.createResource(hints); 728 if (res == null) { 729 Exception exc = new Exception ("A null ManagedConnection was returned."); 730 throw exc; 731 } 732 openedCount++; 733 } catch (Exception ex) { 734 connectionFailures++; 735 rejectedOther++; 736 if (logger.isLoggable(BasicLevel.DEBUG)) { 737 logger.log(BasicLevel.DEBUG, "Cannot create new Connection", ex); 738 } 739 throw ex; 740 } 741 if (logger.isLoggable(BasicLevel.DEBUG)) { 742 logger.log(BasicLevel.DEBUG, "Created Resource: " + res); 743 } 744 return res; 745 } 746 747 750 public synchronized void releaseResource(Object resource, boolean destroy, boolean adjustment) 751 throws Exception { 752 753 ManagedConnection res = (ManagedConnection ) resource; 754 if (matchFactory == null) { 755 throw new Exception ("The matchFactory mandatory!!"); 756 } 757 if (activeList == null) { 758 throw new Exception ("No active resources to releases!!"); 759 } 760 if (!activeList.contains(res)) { 761 return; 763 } 765 activeList.remove(res); 766 if (!destroy) { 767 freeList.add(res); 768 PoolItemStats pis = (PoolItemStats) infoList.get(res); 769 if (pis != null) { 770 pis.setTotalConnectionTime(System.currentTimeMillis() - pis.getStartTime()); 771 } 772 } else { 773 infoList.remove(res); 774 res.destroy(); 775 } 776 if (currentWaiters > 0) { 778 notify(); 779 } 780 if (adjustment) { 781 adjust(); 782 } 783 } 784 785 788 public PoolMatchFactory getMatchFactory() { 789 return matchFactory; 790 } 791 792 795 public synchronized void setMatchFactory(PoolMatchFactory pmf) { 796 matchFactory = pmf; 797 } 798 799 802 public void startMonitor() { 803 poolMonitor = new HArrayPoolMonitor(this); 804 poolMonitor.start(); 805 } 806 807 810 public synchronized void validateMCs() throws Exception { 811 matchFactory.validateResource(freeList); 812 } 813 814 819 public synchronized void adjust() throws Exception { 820 int count = activeList.size() - minSize; 825 long curTime = System.currentTimeMillis(); 826 if (count >= 0) { 828 if (count > MAX_REMOVE_FREELIST) { 829 count = MAX_REMOVE_FREELIST; 830 } 831 Vector rList = new Vector (); 832 Iterator it = null; 833 for (it = freeList.iterator(); it.hasNext();) { 834 ManagedConnection res = (ManagedConnection ) it.next(); 835 PoolItemStats pis = (PoolItemStats) infoList.get(res); 836 if (maxAge > 0 && pis != null && pis.getMaxAgeTimeout() > 0 837 && curTime > pis.getMaxAgeTimeout()) { 838 rList.add(res); 839 } 840 } 841 it = rList.iterator(); 843 while (it.hasNext()) { 844 ManagedConnection res = (ManagedConnection ) it.next(); 845 try { 846 matchFactory.releaseResource(res); 847 } catch (Exception ex) { 848 ex.printStackTrace(); 849 } 850 freeList.remove(res); 851 try { 852 res.destroy(); 853 } catch (Exception ex) { 854 ex.printStackTrace(); 855 } 856 } 857 } 858 859 curTime = System.currentTimeMillis(); 861 Vector aList = new Vector (); 862 Iterator it = null; 863 for (it = activeList.iterator(); it.hasNext();) { 864 ManagedConnection res = (ManagedConnection ) it.next(); 865 PoolItemStats pis = (PoolItemStats) infoList.get(res); 866 if (maxOpentime > 0 && pis != null && pis.getMaxOpenTimeout() > 0 867 && curTime > pis.getMaxOpenTimeout()) { 868 aList.add(res); 869 } 870 } 871 it = aList.iterator(); 872 while (it.hasNext()) { 873 ManagedConnection item = (ManagedConnection ) it.next(); 874 logger.log(BasicLevel.WARN, "close a timed out active connection"); 875 logger.log(BasicLevel.WARN, "MC = " + item); 876 releaseResource(item, true, false); 877 connectionLeaks++; 878 } 879 880 881 int curSize = activeList.size() + freeList.size(); 882 if (maxSize > 0 && maxSize < curSize) { 883 int nbRemove = curSize - maxSize; 885 if (freeList != null) { 886 while (!freeList.isEmpty() && nbRemove > 0) { 887 ManagedConnection res = (ManagedConnection ) freeList.iterator().next(); 888 matchFactory.releaseResource(res); 889 res.destroy(); 890 freeList.remove(res); 891 infoList.remove(res); 892 nbRemove--; 893 curSize--; 894 } 895 } 896 } 897 898 ManagedConnection res; 900 while (minSize > curSize) { 901 res = createResource(null); 902 freeList.add(res); 903 infoList.put(res, new PoolItemStats()); 904 curSize++; 905 } 906 907 recomputeBusy(); 908 } 909 910 913 public void recomputeBusy() { 914 int busy = getCurrentBusy(); 915 if (busyMax < busy) { 916 busyMax = busy; 917 } 918 if (busyMin > busy) { 919 busyMin = busy; 920 } 921 } 922 923 926 public void sampling() throws Exception { 927 waitingHighRecent = waitingTime; 929 if (waitingHigh < waitingTime) { 930 waitingHigh = waitingTime; 931 } 932 waitingTime = 0; 933 934 waitersHighRecent = waiterCount; 935 if (waitersHigh < waiterCount) { 936 waitersHigh = waiterCount; 937 } 938 waiterCount = 0; 939 940 busyMaxRecent = busyMax; 941 busyMax = getCurrentBusy(); 942 busyMinRecent = busyMin; 943 busyMin = getCurrentBusy(); 944 } 945 946 950 private void setItemStats(Object res) { 951 PoolItemStats pis = (PoolItemStats) infoList.get(res); 952 if (pis != null) { 953 pis.incrementUses(); 954 long sTime = System.currentTimeMillis(); 955 pis.setStartTime(sTime); 956 if (maxAge > 0 && pis.getMaxAgeTimeout() == 0) { 957 pis.setMaxAgeTimeout(sTime + (maxAge * 60L * 1000)); 958 } 959 if (maxOpentime > 0) { 960 pis.setMaxOpenTimeout(sTime + (maxOpentime * 60L * 1000)); 961 } 962 } 963 servedOpen++; 964 } 965 966 970 void printLists() { 971 int count = 0; 972 if (logger.isLoggable(BasicLevel.DEBUG)) { 973 logger.log(BasicLevel.DEBUG, "minSize=" + minSize + ", maxSize=" + maxSize 974 + ", freeSize=" + freeList.size()); 975 logger.log(BasicLevel.DEBUG, "activeList:"); 976 if (activeList == null) { 977 logger.log(BasicLevel.DEBUG, " null"); 978 } else { 979 Iterator it = activeList.iterator(); 980 while (it.hasNext() && ++count < 40) { 981 logger.log(BasicLevel.DEBUG, " " + (ManagedConnection ) it.next()); 982 } 983 } 984 logger.log(BasicLevel.DEBUG, "freeList:"); 985 if (freeList == null) { 986 logger.log(BasicLevel.DEBUG, " null"); 987 } else { 988 count = 0; 989 Iterator it = freeList.iterator(); 990 while (it.hasNext() && ++count < 40) { 991 logger.log(BasicLevel.DEBUG, " " + (ManagedConnection ) it.next()); 992 } 993 } 994 } 995 } 996 997 } | Popular Tags |