|
80 | 80 | * int socketConnectTO = 1000 * 3; // 3 seconds to block on initial connections. If 0, then will use blocking connect (default) |
81 | 81 | * boolean failover = false; // turn off auto-failover in event of server down |
82 | 82 | * boolean nagleAlg = false; // turn off Nagle's algorithm on all sockets in pool |
| 83 | + * boolean aliveCheck = false; // disable health check of socket on checkout |
83 | 84 | * |
84 | 85 | * SockIOPool pool = SockIOPool.getInstance(); |
85 | 86 | * pool.setServers( serverlist ); |
|
92 | 93 | * pool.setMaintSleep( maintThreadSleep ); |
93 | 94 | * pool.setSocketTO( socketTimeOut ); |
94 | 95 | * pool.setNagle( nagleAlg ); |
95 | | - * pool.setHashingAlg( SockIOPool.NEW_COMPAT_HASH ); |
| 96 | + * pool.setHashingAlg( SockIOPool.NEW_COMPAT_HASH ); |
| 97 | + * pool.setAliveCheck( true ); |
96 | 98 | * pool.initialize(); |
97 | 99 | * } |
98 | 100 | * </pre> |
@@ -146,6 +148,7 @@ public class SockIOPool { |
146 | 148 | private long maintSleep = 1000 * 5; // maintenance thread sleep time |
147 | 149 | private int socketTO = 1000 * 10; // default timeout of socket reads |
148 | 150 | private int socketConnectTO = 1000 * 3; // default timeout of socket connections |
| 151 | + private boolean aliveCheck = false; // default to not check each connection for being alive |
149 | 152 | private boolean failover = true; // default to failover in event of cache server dead |
150 | 153 | private boolean failback = true; // only used if failover is also set ... controls putting a dead server back into rotation |
151 | 154 | private boolean nagle = true; // enable/disable Nagle's algorithm |
@@ -366,6 +369,27 @@ public static SockIOPool getInstance() { |
366 | 369 | */ |
367 | 370 | public boolean getFailback() { return this.failback; } |
368 | 371 |
|
| 372 | + /** |
| 373 | + * Sets the aliveCheck flag for the pool. |
| 374 | + * |
| 375 | + * When true, this will attempt to talk to the server on |
| 376 | + * every connection checkout to make sure the connection is |
| 377 | + * still valid. This adds extra network chatter and thus is |
| 378 | + * defaulted off. May be useful if you want to ensure you do |
| 379 | + * not have any problems talking to the server on a dead connection. |
| 380 | + * |
| 381 | + * @param aliveCheck true/false |
| 382 | + */ |
| 383 | + public void setAliveCheck( boolean aliveCheck ) { this.aliveCheck = aliveCheck; } |
| 384 | + |
| 385 | + |
| 386 | + /** |
| 387 | + * Returns the current status of the aliveCheck flag. |
| 388 | + * |
| 389 | + * @return true / false |
| 390 | + */ |
| 391 | + public boolean getAliveCheck() { return this.aliveCheck; } |
| 392 | + |
369 | 393 | /** |
370 | 394 | * Sets the Nagle alg flag for the pool. |
371 | 395 | * |
@@ -667,8 +691,31 @@ public SockIO getSock( String key, Integer hashCode ) { |
667 | 691 | return null; |
668 | 692 |
|
669 | 693 | // if only one server, return it |
670 | | - if ( buckets.size() == 1 ) |
671 | | - return getConnection( (String) buckets.get( 0 ) ); |
| 694 | + if ( buckets.size() == 1 ) { |
| 695 | + SockIO sock = getConnection( (String) buckets.get( 0 ) ); |
| 696 | + if ( sock != null && sock.isConnected() ) { |
| 697 | + |
| 698 | + if ( aliveCheck ) { |
| 699 | + if ( sock.isAlive() ) { |
| 700 | + return sock; |
| 701 | + } |
| 702 | + else { |
| 703 | + sock.close(); |
| 704 | + try { sock.trueClose(); } catch ( IOException ioe ) { log.error( "failed to close dead socket" ); } |
| 705 | + sock = null; |
| 706 | + } |
| 707 | + } |
| 708 | + else { |
| 709 | + return sock; |
| 710 | + } |
| 711 | + } |
| 712 | + else { |
| 713 | + sock = null; |
| 714 | + } |
| 715 | + |
| 716 | + if ( !failover ) |
| 717 | + return null; |
| 718 | + } |
672 | 719 |
|
673 | 720 | int tries = 0; |
674 | 721 |
|
@@ -719,8 +766,24 @@ public SockIO getSock( String key, Integer hashCode ) { |
719 | 766 |
|
720 | 767 | log.debug( "cache choose " + buckets.get( bucket ) + " for " + key ); |
721 | 768 |
|
722 | | - if ( sock != null ) |
723 | | - return sock; |
| 769 | + if ( sock != null && sock.isConnected() ) { |
| 770 | + if ( aliveCheck ) { |
| 771 | + if ( sock.isAlive() ) { |
| 772 | + return sock; |
| 773 | + } |
| 774 | + else { |
| 775 | + sock.close(); |
| 776 | + try { sock.trueClose(); } catch ( IOException ioe ) { log.error( "failed to close dead socket" ); } |
| 777 | + sock = null; |
| 778 | + } |
| 779 | + } |
| 780 | + else { |
| 781 | + return sock; |
| 782 | + } |
| 783 | + } |
| 784 | + else { |
| 785 | + sock = null; |
| 786 | + } |
724 | 787 |
|
725 | 788 | // if we do not want to failover, then bail here |
726 | 789 | if ( !failover ) |
@@ -993,27 +1056,24 @@ public void checkIn( SockIO socket ) { |
993 | 1056 | * @param pool pool to close |
994 | 1057 | */ |
995 | 1058 | protected void closePool( Map<String,Map<SockIO,Long>> pool ) { |
| 1059 | + for ( Iterator<String> i = pool.keySet().iterator(); i.hasNext(); ) { |
| 1060 | + String host = i.next(); |
| 1061 | + Map<SockIO,Long> sockets = pool.get( host ); |
996 | 1062 |
|
997 | | - synchronized( this ) { |
998 | | - for ( Iterator<String> i = pool.keySet().iterator(); i.hasNext(); ) { |
999 | | - String host = i.next(); |
1000 | | - Map<SockIO,Long> sockets = pool.get( host ); |
1001 | | - |
1002 | | - for ( Iterator<SockIO> j = sockets.keySet().iterator(); j.hasNext(); ) { |
1003 | | - SockIO socket = j.next(); |
1004 | | - |
1005 | | - try { |
1006 | | - socket.trueClose(); |
1007 | | - } |
1008 | | - catch ( IOException ioe ) { |
1009 | | - log.error( "++++ failed to trueClose socket: " + socket.toString() + " for host: " + host ); |
1010 | | - } |
1011 | | - |
1012 | | - j.remove(); |
1013 | | - socket = null; |
| 1063 | + for ( Iterator<SockIO> j = sockets.keySet().iterator(); j.hasNext(); ) { |
| 1064 | + SockIO socket = j.next(); |
| 1065 | + |
| 1066 | + try { |
| 1067 | + socket.trueClose(); |
| 1068 | + } |
| 1069 | + catch ( IOException ioe ) { |
| 1070 | + log.error( "++++ failed to trueClose socket: " + socket.toString() + " for host: " + host ); |
1014 | 1071 | } |
| 1072 | + |
| 1073 | + j.remove(); |
| 1074 | + socket = null; |
1015 | 1075 | } |
1016 | | - } |
| 1076 | + } |
1017 | 1077 | } |
1018 | 1078 |
|
1019 | 1079 | /** |
@@ -1441,7 +1501,30 @@ void close() { |
1441 | 1501 | * @return true if connected |
1442 | 1502 | */ |
1443 | 1503 | boolean isConnected() { |
1444 | | - return (sock != null && sock.isConnected()); |
| 1504 | + return ( sock != null && sock.isConnected() ); |
| 1505 | + } |
| 1506 | + |
| 1507 | + /* |
| 1508 | + * checks to see that the connection is still working |
| 1509 | + * |
| 1510 | + * @return true if still alive |
| 1511 | + */ |
| 1512 | + boolean isAlive() { |
| 1513 | + |
| 1514 | + if ( !isConnected() ) |
| 1515 | + return false; |
| 1516 | + |
| 1517 | + // try to talk to the server w/ a dumb query to ask its version |
| 1518 | + try { |
| 1519 | + this.write( "version\r\n".getBytes() ); |
| 1520 | + this.flush(); |
| 1521 | + String response = this.readLine(); |
| 1522 | + } |
| 1523 | + catch ( IOException ex ) { |
| 1524 | + return false; |
| 1525 | + } |
| 1526 | + |
| 1527 | + return true; |
1445 | 1528 | } |
1446 | 1529 |
|
1447 | 1530 | /** |
|
0 commit comments