/* */ package org.jboss.invocation.pooled.interfaces;
/* */
/* */ import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
/* */ import java.io.BufferedInputStream;
/* */ import java.io.BufferedOutputStream;
/* */ import java.io.EOFException;
/* */ import java.io.Externalizable;
/* */ import java.io.IOException;
/* */ import java.io.InterruptedIOException;
/* */ import java.io.ObjectInput;
/* */ import java.io.ObjectInputStream;
/* */ import java.io.ObjectOutput;
/* */ import java.io.ObjectOutputStream;
/* */ import java.io.OptionalDataException;
/* */ import java.io.UnsupportedEncodingException;
/* */ import java.net.Socket;
/* */ import java.net.SocketException;
/* */ import java.rmi.ConnectException;
/* */ import java.rmi.MarshalledObject;
/* */ import java.rmi.NoSuchObjectException;
/* */ import java.rmi.ServerException;
/* */ import java.util.Collection;
/* */ import java.util.Iterator;
/* */ import java.util.LinkedList;
/* */ import java.util.List;
/* */ import java.util.Map;
/* */ import java.util.Set;
/* */ import javax.net.SocketFactory;
/* */ import javax.net.ssl.HandshakeCompletedEvent;
/* */ import javax.net.ssl.HandshakeCompletedListener;
/* */ import javax.net.ssl.SSLException;
/* */ import javax.net.ssl.SSLSession;
/* */ import javax.net.ssl.SSLSocket;
/* */ import javax.transaction.SystemException;
/* */ import javax.transaction.TransactionRolledbackException;
/* */ import org.jboss.invocation.Invocation;
/* */ import org.jboss.invocation.Invoker;
/* */ import org.jboss.logging.Logger;
/* */ import org.jboss.tm.TransactionPropagationContextFactory;
/* */
/* */ public class PooledInvokerProxy
/* */ implements Invoker, Externalizable
/* */ {
/* 74 */ private static final Logger log = Logger.getLogger(PooledInvokerProxy.class);
/* */ private static final long serialVersionUID = -1456509931095566410L;
/* */ private static final int WIRE_VERSION = 1;
/* 90 */ protected static TransactionPropagationContextFactory tpcFactory = null;
/* */
/* 100 */ public static long getSocketTime = 0L;
/* 101 */ public static long readTime = 0L;
/* 102 */ public static long writeTime = 0L;
/* 103 */ public static long serializeTime = 0L;
/* 104 */ public static long deserializeTime = 0L;
/* */
/* 106 */ public static long usedPooled = 0L;
/* */
/* 108 */ private static int inUseCount = 0;
/* */
/* 110 */ private static long socketConnectCount = 0L;
/* */
/* 112 */ private static long socketCloseCount = 0L;
/* */
/* 117 */ public static int MAX_RETRIES = 10;
/* */
/* 120 */ protected static final Map connectionPools = new ConcurrentReaderHashMap();
/* */ protected ServerAddress address;
/* 132 */ protected LinkedList pool = null;
/* */ protected int maxPoolSize;
/* 136 */ protected int retryCount = 1;
/* */ private transient boolean trace;
/* */
/* */ public static void setTPCFactory(TransactionPropagationContextFactory tpcf)
/* */ {
/* 96 */ tpcFactory = tpcf;
/* */ }
/* */
/* */ public static void clearStats()
/* */ {
/* 264 */ getSocketTime = 0L;
/* 265 */ readTime = 0L;
/* 266 */ writeTime = 0L;
/* 267 */ serializeTime = 0L;
/* 268 */ deserializeTime = 0L;
/* 269 */ usedPooled = 0L;
/* */ }
/* */
/* */ public static long getInUseCount()
/* */ {
/* 277 */ return inUseCount;
/* */ }
/* */
/* */ public static long getUsedPooled()
/* */ {
/* 285 */ return usedPooled;
/* */ }
/* */
/* */ public static long getSocketConnectCount() {
/* 289 */ return socketConnectCount;
/* */ }
/* */
/* */ public static long getSocketCloseCount() {
/* 293 */ return socketCloseCount;
/* */ }
/* */
/* */ public static int getTotalPoolCount()
/* */ {
/* 301 */ int count = 0;
/* 302 */ Iterator iter = connectionPools.values().iterator();
/* 303 */ while (iter.hasNext())
/* */ {
/* 305 */ List pool = (List)iter.next();
/* 306 */ if (pool != null)
/* 307 */ count += pool.size();
/* */ }
/* 309 */ return count;
/* */ }
/* */
/* */ public long getPoolCount()
/* */ {
/* 317 */ return this.pool.size();
/* */ }
/* */
/* */ public PooledInvokerProxy()
/* */ {
/* 326 */ this.trace = log.isTraceEnabled();
/* */ }
/* */
/* */ public PooledInvokerProxy(ServerAddress sa, int maxPoolSize)
/* */ {
/* 335 */ this(sa, maxPoolSize, MAX_RETRIES);
/* */ }
/* */
/* */ public PooledInvokerProxy(ServerAddress sa, int maxPoolSize, int retryCount) {
/* 339 */ this.address = sa;
/* 340 */ this.maxPoolSize = maxPoolSize;
/* 341 */ this.retryCount = retryCount;
/* */ }
/* */
/* */ public static void clearPool(ServerAddress sa)
/* */ {
/* 349 */ boolean trace = log.isTraceEnabled();
/* 350 */ if (trace)
/* 351 */ log.trace("clearPool, sa: " + sa);
/* */ try
/* */ {
/* 354 */ LinkedList thepool = (LinkedList)connectionPools.get(sa);
/* 355 */ if (thepool == null) return;
/* 356 */ synchronized (thepool)
/* */ {
/* 358 */ int size = thepool.size();
/* 359 */ for (int i = 0; i < size; i++)
/* */ {
/* 361 */ ClientSocket cs = null;
/* */ try
/* */ {
/* 364 */ ClientSocket socket = (ClientSocket)thepool.removeFirst();
/* 365 */ cs = socket;
/* 366 */ if (trace)
/* 367 */ log.trace("Closing, ClientSocket: " + socket);
/* 368 */ socketCloseCount -= 1L;
/* 369 */ socket.socket.close();
/* */ }
/* */ catch (Exception ignored)
/* */ {
/* */ }
/* */ finally
/* */ {
/* 376 */ if (cs != null)
/* 377 */ cs.socket = null;
/* */ }
/* */ }
/* */ }
/* */ }
/* */ catch (Exception ex)
/* */ {
/* */ }
/* */ }
/* */
/* */ public static void clearPools()
/* */ {
/* 392 */ synchronized (connectionPools)
/* */ {
/* 394 */ Iterator it = connectionPools.keySet().iterator();
/* 395 */ while (it.hasNext())
/* */ {
/* 397 */ ServerAddress sa = (ServerAddress)it.next();
/* 398 */ clearPool(sa);
/* */ }
/* */ }
/* */ }
/* */
/* */ public boolean equals(Object other)
/* */ {
/* 405 */ if (!(other instanceof PooledInvokerProxy))
/* 406 */ return false;
/* 407 */ return this.address.equals(((PooledInvokerProxy)other).address);
/* */ }
/* */
/* */ public int hashCode()
/* */ {
/* 412 */ return this.address.hashCode();
/* */ }
/* */
/* */ protected void initPool()
/* */ {
/* 417 */ synchronized (connectionPools)
/* */ {
/* 419 */ this.pool = ((LinkedList)connectionPools.get(this.address));
/* 420 */ if (this.pool == null)
/* */ {
/* 422 */ this.pool = new LinkedList();
/* 423 */ connectionPools.put(this.address, this.pool);
/* */ }
/* */ }
/* */ }
/* */
/* */ protected ClientSocket getConnection() throws Exception
/* */ {
/* 430 */ Socket socket = null;
/* 431 */ ClientSocket cs = null;
/* */
/* 445 */ for (int i = 0; i < this.retryCount; i++)
/* */ {
/* 447 */ ClientSocket pooled = getPooledConnection();
/* 448 */ if (pooled != null)
/* */ {
/* 450 */ usedPooled += 1L;
/* 451 */ inUseCount += 1;
/* 452 */ return pooled;
/* */ }
/* */
/* */ try
/* */ {
/* 457 */ if (this.trace)
/* */ {
/* 459 */ log.trace("Connecting to addr: " + this.address.address + ", port: " + this.address.port + ",clientSocketFactory: " + this.address.clientSocketFactory + ",enableTcpNoDelay: " + this.address.enableTcpNoDelay + ",timeout: " + this.address.timeout);
/* */ }
/* */
/* 465 */ if (this.address.clientSocketFactory != null)
/* 466 */ socket = this.address.clientSocketFactory.createSocket(this.address.address, this.address.port);
/* */ else
/* 468 */ socket = new Socket(this.address.address, this.address.port);
/* 469 */ socketConnectCount += 1L;
/* 470 */ if (this.trace) {
/* 471 */ log.trace("Connected, socket=" + socket);
/* */ }
/* 473 */ socket.setTcpNoDelay(this.address.enableTcpNoDelay);
/* 474 */ cs = new ClientSocket(socket, this.address.timeout);
/* 475 */ inUseCount += 1;
/* 476 */ if (this.trace)
/* */ {
/* 478 */ log.trace("New ClientSocket: " + cs + ", usedPooled=" + usedPooled + ", inUseCount=" + inUseCount + ", socketConnectCount=" + socketConnectCount + ", socketCloseCount=" + socketCloseCount);
/* */ }
/* */
/* */ }
/* */ catch (Exception ex)
/* */ {
/* 489 */ if (((ex instanceof InterruptedIOException)) || ((ex instanceof SocketException)))
/* */ {
/* 491 */ if (this.trace)
/* 492 */ log.trace("Connect failed", ex);
/* 493 */ if (i + 1 < this.retryCount)
/* */ {
/* 495 */ Thread.sleep(1L);
/* 496 */ continue;
/* */ }
/* */ }
/* 499 */ throw ex;
/* */ }
/* */ }
/* */
/* 503 */ if (cs == null)
/* 504 */ throw new ConnectException("Failed to obtain a socket, tries=" + this.retryCount);
/* 505 */ return cs;
/* */ }
/* */
/* */ protected ClientSocket firstConnection()
/* */ {
/* 510 */ synchronized (this.pool)
/* */ {
/* 512 */ if (this.pool.size() > 0)
/* 513 */ return (ClientSocket)this.pool.removeFirst();
/* */ }
/* 515 */ return null;
/* */ }
/* */
/* */ protected ClientSocket getPooledConnection()
/* */ {
/* 520 */ ClientSocket socket = null;
/* 521 */ while ((socket = firstConnection()) != null)
/* */ {
/* */ try
/* */ {
/* 526 */ if (this.trace)
/* 527 */ log.trace("Checking pooled socket: " + socket + ", address: " + socket.socket.getLocalSocketAddress());
/* 528 */ byte ACK = 1;
/* 529 */ socket.out.writeByte(1);
/* 530 */ socket.out.flush();
/* 531 */ socket.in.readByte();
/* 532 */ if (this.trace)
/* */ {
/* 534 */ log.trace("Using pooled ClientSocket: " + socket + ", usedPooled=" + usedPooled + ", inUseCount=" + inUseCount + ", socketConnectCount=" + socketConnectCount + ", socketCloseCount=" + socketCloseCount);
/* */ }
/* */
/* 541 */ return socket;
/* */ }
/* */ catch (Exception ex)
/* */ {
/* 545 */ if (this.trace)
/* 546 */ log.trace("Failed to validate pooled socket: " + socket, ex);
/* */ try
/* */ {
/* 549 */ if (socket != null)
/* */ {
/* 551 */ socketCloseCount -= 1L;
/* 552 */ socket.socket.close();
/* */ }
/* */ }
/* */ catch (Exception ignored)
/* */ {
/* */ }
/* */ finally
/* */ {
/* 560 */ if (socket != null)
/* 561 */ socket.socket = null;
/* */ }
/* */ }
/* */ }
/* 565 */ return null;
/* */ }
/* */
/* */ protected boolean returnConnection(ClientSocket socket)
/* */ {
/* 576 */ boolean pooled = false;
/* 577 */ synchronized (this.pool)
/* */ {
/* 579 */ if (this.pool.size() < this.maxPoolSize)
/* */ {
/* 581 */ this.pool.add(socket);
/* 582 */ inUseCount -= 1;
/* 583 */ pooled = true;
/* */ }
/* */ }
/* 586 */ return pooled;
/* */ }
/* */
/* */ public String getServerHostName()
/* */ throws Exception
/* */ {
/* 594 */ return this.address.address;
/* */ }
/* */
/* */ public Object getTransactionPropagationContext()
/* */ throws SystemException
/* */ {
/* 610 */ return tpcFactory == null ? null : tpcFactory.getTransactionPropagationContext();
/* */ }
/* */
/* */ public Object invoke(Invocation invocation)
/* */ throws Exception
/* */ {
/* 621 */ boolean trace = log.isTraceEnabled();
/* */
/* 623 */ PooledMarshalledInvocation mi = new PooledMarshalledInvocation(invocation);
/* */
/* 627 */ mi.setTransactionPropagationContext(getTransactionPropagationContext());
/* */
/* 629 */ Object response = null;
/* 630 */ long start = System.currentTimeMillis();
/* 631 */ ClientSocket socket = getConnection();
/* 632 */ long end = System.currentTimeMillis() - start;
/* 633 */ getSocketTime += end;
/* */
/* 635 */ if (socket.sessionID != null)
/* */ {
/* 637 */ mi.setValue("SESSION_ID", socket.sessionID);
/* 638 */ if (trace) {
/* 639 */ log.trace("Added SESSION_ID to invocation");
/* */ }
/* */ }
/* */ try
/* */ {
/* 644 */ if (trace)
/* 645 */ log.trace("Sending invocation to: " + mi.getObjectName());
/* 646 */ socket.out.writeObject(mi);
/* 647 */ socket.out.reset();
/* 648 */ socket.out.writeObject(Boolean.TRUE);
/* 649 */ socket.out.flush();
/* 650 */ socket.out.reset();
/* 651 */ end = System.currentTimeMillis() - start;
/* 652 */ writeTime += end;
/* 653 */ start = System.currentTimeMillis();
/* 654 */ response = socket.in.readObject();
/* */
/* 658 */ socket.in.readObject();
/* 659 */ end = System.currentTimeMillis() - start;
/* 660 */ readTime += end;
/* */ }
/* */ catch (Exception ex)
/* */ {
/* 664 */ if (trace)
/* 665 */ log.trace("Failure during invoke", ex);
/* */ try
/* */ {
/* 668 */ socketCloseCount -= 1L;
/* 669 */ socket.socket.close();
/* */ }
/* */ catch (Exception ignored) {
/* */ }
/* */ finally {
/* 674 */ socket.socket = null;
/* */ }
/* 676 */ throw new ConnectException("Failure during invoke", ex);
/* */ }
/* */
/* 680 */ if (!returnConnection(socket))
/* */ {
/* 683 */ if (trace)
/* 684 */ log.trace("Closing unpooled socket: " + socket);
/* */ try
/* */ {
/* 687 */ socketCloseCount -= 1L;
/* 688 */ socket.socket.close();
/* */ }
/* */ catch (Exception ignored) {
/* */ }
/* */ finally {
/* 693 */ socket.socket = null;
/* */ }
/* */
/* */ }
/* */
/* */ try
/* */ {
/* 701 */ if ((response instanceof Exception))
/* */ {
/* 703 */ throw ((Exception)response);
/* */ }
/* 705 */ if ((response instanceof MarshalledObject))
/* */ {
/* 707 */ return ((MarshalledObject)response).get();
/* */ }
/* 709 */ return response;
/* */ }
/* */ catch (ServerException ex)
/* */ {
/* 716 */ if ((ex.detail instanceof NoSuchObjectException))
/* */ {
/* 718 */ throw ((NoSuchObjectException)ex.detail);
/* */ }
/* */
/* 721 */ if ((ex.detail instanceof TransactionRolledbackException))
/* */ {
/* 723 */ throw ((TransactionRolledbackException)ex.detail);
/* */ }
/* */ }
/* 725 */ throw ex;
/* */ }
/* */
/* */ public void writeExternal(ObjectOutput out)
/* */ throws IOException
/* */ {
/* 742 */ out.writeObject(this.address);
/* 743 */ out.writeInt(this.maxPoolSize);
/* */
/* 745 */ out.writeInt(1);
/* 746 */ out.writeInt(this.retryCount);
/* */ }
/* */
/* */ public void readExternal(ObjectInput in)
/* */ throws IOException, ClassNotFoundException
/* */ {
/* 752 */ this.trace = log.isTraceEnabled();
/* 753 */ this.address = ((ServerAddress)in.readObject());
/* 754 */ this.maxPoolSize = in.readInt();
/* 755 */ int version = 0;
/* */ try
/* */ {
/* 758 */ version = in.readInt();
/* */ }
/* */ catch (EOFException e)
/* */ {
/* */ }
/* */ catch (OptionalDataException e)
/* */ {
/* */ }
/* */
/* 769 */ switch (version)
/* */ {
/* */ case 0:
/* 773 */ this.retryCount = MAX_RETRIES;
/* 774 */ break;
/* */ case 1:
/* 776 */ readVersion1(in);
/* 777 */ break;
/* */ }
/* */
/* 784 */ initPool();
/* */ }
/* */
/* */ private void readVersion1(ObjectInput in)
/* */ throws IOException
/* */ {
/* 790 */ this.retryCount = in.readInt();
/* */ }
/* */
/* */ protected static class ClientSocket
/* */ implements HandshakeCompletedListener
/* */ {
/* */ public ObjectOutputStream out;
/* */ public ObjectInputStream in;
/* */ public Socket socket;
/* */ public int timeout;
/* */ public String sessionID;
/* 151 */ private boolean handshakeComplete = false;
/* */ private boolean trace;
/* */
/* */ public ClientSocket(Socket socket, int timeout)
/* */ throws Exception
/* */ {
/* 156 */ this.socket = socket;
/* 157 */ this.trace = PooledInvokerProxy.log.isTraceEnabled();
/* 158 */ boolean needHandshake = false;
/* */
/* 160 */ if ((socket instanceof SSLSocket))
/* */ {
/* 162 */ SSLSocket ssl = (SSLSocket)socket;
/* 163 */ ssl.addHandshakeCompletedListener(this);
/* 164 */ if (this.trace)
/* 165 */ PooledInvokerProxy.log.trace("Starting SSL handshake");
/* 166 */ needHandshake = true;
/* 167 */ this.handshakeComplete = false;
/* 168 */ ssl.startHandshake();
/* */ }
/* 170 */ socket.setSoTimeout(timeout);
/* 171 */ this.timeout = timeout;
/* 172 */ this.out = new OptimizedObjectOutputStream(new BufferedOutputStream(socket.getOutputStream()));
/* 173 */ this.out.flush();
/* 174 */ this.in = new OptimizedObjectInputStream(new BufferedInputStream(socket.getInputStream()));
/* 175 */ if (needHandshake)
/* */ {
/* 178 */ socket.setSoTimeout(1000);
/* 179 */ for (int n = 0; (!this.handshakeComplete) && (n < 60); n++)
/* */ {
/* */ try
/* */ {
/* 183 */ b = this.in.read();
/* */ }
/* */ catch (SSLException e)
/* */ {
/* */ int b;
/* 187 */ if (this.trace)
/* 188 */ PooledInvokerProxy.log.trace("Error while waiting for handshake to complete", e);
/* 189 */ throw e;
/* */ }
/* */ catch (IOException e)
/* */ {
/* 193 */ if (this.trace)
/* 194 */ PooledInvokerProxy.log.trace("Handshaked read()", e);
/* */ }
/* */ }
/* 197 */ if (!this.handshakeComplete) {
/* 198 */ throw new SSLException("Handshaked failed to complete in 60 seconds");
/* */ }
/* 200 */ socket.setSoTimeout(timeout);
/* */ }
/* */ }
/* */
/* */ public void handshakeCompleted(HandshakeCompletedEvent event)
/* */ {
/* 207 */ this.handshakeComplete = true;
/* 208 */ byte[] id = event.getSession().getId();
/* */ try
/* */ {
/* 211 */ this.sessionID = new String(id, "UTF-8");
/* */ }
/* */ catch (UnsupportedEncodingException e)
/* */ {
/* 215 */ PooledInvokerProxy.log.warn("Failed to create session id using UTF-8, using default", e);
/* 216 */ this.sessionID = new String(id);
/* */ }
/* 218 */ if (this.trace)
/* */ {
/* 220 */ PooledInvokerProxy.log.trace("handshakeCompleted, event=" + event + ", sessionID=" + this.sessionID);
/* */ }
/* */ }
/* */
/* */ public String toString()
/* */ {
/* 226 */ StringBuffer tmp = new StringBuffer("ClientSocket@");
/* 227 */ tmp.append(System.identityHashCode(this));
/* 228 */ tmp.append('[');
/* 229 */ tmp.append("socket=");
/* 230 */ tmp.append(this.socket.toString());
/* 231 */ tmp.append(']');
/* 232 */ return tmp.toString();
/* */ }
/* */
/* */ protected void finalize()
/* */ {
/* 241 */ if (this.socket != null)
/* */ {
/* 243 */ if (this.trace)
/* 244 */ PooledInvokerProxy.log.trace("Closing socket in finalize: " + this.socket);
/* */ try
/* */ {
/* 247 */ PooledInvokerProxy.access$110();
/* 248 */ this.socket.close();
/* */ }
/* */ catch (Exception ignored) {
/* */ }
/* */ finally {
/* 253 */ this.socket = null;
/* */ }
/* */ }
/* */ }
/* */ }
/* */ }
/* Location: /home/mnovotny/projects/EMBEDDED_JBOSS_BETA3_COMMUNITY/embedded/output/lib/embedded-jboss/lib/jboss-embedded-all.jar
* Qualified Name: org.jboss.invocation.pooled.interfaces.PooledInvokerProxy
* JD-Core Version: 0.6.0
*/