poolitem.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,127 行 · 第 1/2 页

JAVA
1,127
字号
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * *   Free Software Foundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Scott Ferguson */package com.caucho.jca;import com.caucho.log.Log;import com.caucho.util.Alarm;import com.caucho.util.L10N;import javax.resource.NotSupportedException;import javax.resource.ResourceException;import javax.resource.spi.ConnectionEvent;import javax.resource.spi.ConnectionEventListener;import javax.resource.spi.ConnectionRequestInfo;import javax.resource.spi.LocalTransaction;import javax.resource.spi.ManagedConnection;import javax.resource.spi.ManagedConnectionFactory;import javax.security.auth.Subject;import javax.transaction.xa.XAException;import javax.transaction.xa.XAResource;import javax.transaction.xa.Xid;import java.util.logging.Level;import java.util.logging.Logger;/** * Implementation of the connection manager manager. */class PoolItem implements ConnectionEventListener, XAResource {  private static final L10N L = new L10N(PoolItem.class);  private static final Logger log = Log.open(PoolItem.class);  private ConnectionPool _cm;    private ManagedConnectionFactory _mcf;  private ManagedConnection _mConn;  private UserTransactionImpl _transaction;  private String _id;  private XAResource _xaResource;  private LocalTransaction _localTransaction;  private int _defaultTransactionTimeout;  private int _transactionTimeout;  private Subject _subject;  private ConnectionRequestInfo _requestInfo;  final Object _shareLock = new Object();    // The head shared connection for transaction  // The UserPoolItem code is responsible for this field  UserPoolItem _shareHead;    // The other pool items joined transaction  private PoolItem _xaHead;  private PoolItem _xaNext;    private boolean _hasConnectionError;  private long _poolStartTime;  private long _poolEventTime;  private Xid _xid;  private int _endFlags = -1;  // flag forcing an XA transaction (for the local transaction optimization)  private boolean _isXATransaction = true;      // true if in local transaction  private boolean _isLocalTransaction;  private IllegalStateException _allocationStackTrace;  public PoolItem(ConnectionPool cm,		  ManagedConnectionFactory mcf,		  ManagedConnection conn)  {    _cm = cm;    _id = _cm.generateId();    _mcf = mcf;    _mConn = conn;    _poolStartTime = Alarm.getCurrentTime();    _poolEventTime = Alarm.getCurrentTime();    // Gets the resource object from the driver    try {      if (cm.isXATransaction()) {	XAResource xaResource = conn.getXAResource();	try {	  _defaultTransactionTimeout = xaResource.getTransactionTimeout();	} catch (Throwable e) {	  log.log(Level.FINE, e.toString(), e);	}		_xaResource = xaResource;      }    } catch (NotSupportedException e) {      _cm.setXATransaction(false);      log.log(Level.FINER, e.toString(), e);    } catch (Exception e) {      log.log(Level.FINE, e.toString(), e);    }    if (_xaResource == null)      _isXATransaction = false;    // Gets the local transaction from the driver    try {      if (_cm.isLocalTransaction())	_localTransaction = conn.getLocalTransaction();    } catch (NotSupportedException e) {      _cm.setLocalTransaction(false);      log.log(Level.FINE, e.toString(), e);    } catch (Exception e) {      log.log(Level.FINE, e.toString(), e);    }        _mConn.addConnectionEventListener(this);    if (log.isLoggable(Level.FINE))      log.fine("create: " + this +	       "(active:" + _cm.getConnectionActiveCount() +	       ", total:" + _cm.getConnectionCount() + ")");  }  /**   * Sets the subject.   */  public void setSubject(Subject subject)  {    _subject = subject;  }  /**   * Sets the info.   */  public void setInfo(ConnectionRequestInfo info)  {    _requestInfo = info;  }  /**   * Returns true if the connection is active.   */  public boolean isActive()  {    return _shareHead != null;  }  /**   * Returns true if the connection is dead   */  public boolean isDead()  {    return _mConn == null;  }  /**   * Returns the time of the last event.   */  public long getEventTime()  {    return _poolEventTime;  }  /**   * Returns the time the connection was first used.   */  public long getStartTime()  {    return _poolStartTime;  }  /**   * Sets the item's transaction.   */  void setTransaction(UserTransactionImpl transaction)  {    _transaction = transaction;  }  /**   * Make this connection active.   *   * @return true if the pool item is valid, false if it should be removed.   */  synchronized UserPoolItem toActive(Subject subject,				     ConnectionRequestInfo info,				     UserPoolItem userPoolItem)    throws ResourceException  {    long now = Alarm.getCurrentTime();    long maxIdleTime = _cm.getMaxIdleTime();    long maxPoolTime = _cm.getMaxPoolTime();    if (_hasConnectionError)      return null;    else if (0 < maxIdleTime && _poolEventTime + maxIdleTime < now)      return null;    else if (0 < maxPoolTime && _poolStartTime + maxPoolTime < now)      return null;    else if (_shareHead != null)      throw new IllegalStateException(L.l("trying to activate active pool item."));    _poolEventTime = now;    _isXATransaction = _xaResource != null; // disable LT-optim by default    if (userPoolItem != null) {      Object uConn = userPoolItem.getUserConnection();      if (uConn != null)	_mConn.associateConnection(uConn);      userPoolItem.associatePoolItem(this);    }    else      userPoolItem = new UserPoolItem(_cm, this);        if (! isValid(subject, info, userPoolItem))      return null;    _subject = subject;    _requestInfo = info;    userPoolItem.associate(this, _mcf, subject, info);    if (log.isLoggable(Level.FINE))      log.fine("allocate " + this);    if (_cm.getSaveAllocationStackTrace())      _allocationStackTrace = new IllegalStateException(L.l("Connection {0} allocation stack trace", this));    return userPoolItem;  }  /**   * Checks if the pool item is still valid.   *   * @return true if the pool item is valid, false if it should be removed.   */  boolean isValid()  {    synchronized (this) {      long now = Alarm.getCurrentTime();      long maxIdleTime = _cm.getMaxIdleTime();      long maxPoolTime = _cm.getMaxPoolTime();      long maxActiveTime = _cm.getMaxActiveTime();      boolean isActive = isActive() || _xid != null;      boolean isDead = false;      if (! isActive && _hasConnectionError) {	isDead = true;	log.fine("closing pool item from connection error:" + this);      }      else if (! isActive &&	       0 < maxIdleTime && _poolEventTime + maxIdleTime < now) {	isDead = true;	log.fine("closing pool item from idle timeout:" + this);      }      else if (! isActive &&	       0 < maxPoolTime && _poolStartTime + maxPoolTime < now) {	isDead = true;	log.fine("closing pool item from pool timeout:" + this);      }      else if (isActive &&	       0 < maxActiveTime && _poolEventTime + maxActiveTime < now) {	isDead = true;	log.warning("closing pool item from active timeout:" + this);      }      if (isDead) {	_hasConnectionError = true;	return false;      }      else	return true;    }  }    /**   * Use the item only if it's already been used for the current transaction   * and is available.  allocateXA returns the same connection for the   * following case:   *   * <pre>   * UserTransaction.begin();   *   * conn = ds.getConnection();   * ...   * conn.close();   *   * conn = ds.getConnection();   * ...   * conn.close();   * </pre>   *   * <p>Nested connections are not reused.   *   * @param xid the current transaction id   *   * @return true if the pool item has been allocated   */  UserPoolItem allocateXA(ManagedConnectionFactory mcf,			  Subject subject,			  ConnectionRequestInfo info)  {    if (_mConn == null)      // already closed      return null;    else if (_subject != subject)      return null;    else if (_requestInfo != info)      return null;    else if (_mcf != mcf)      return null;    else if (_shareHead != null && ! _cm.isShareable()) // is currently in use      return null;    /* server/14g9, #2708    else if (_hasConnectionError) // had a fatal error      return null;    */        if (log.isLoggable(Level.FINER))      log.finer("sharing xa-pool item: " + this);    UserPoolItem userPoolItem = new UserPoolItem(_cm);    userPoolItem.associate(this, _mcf, _subject, _requestInfo);    return userPoolItem;  }  /**   * Returns true if the tested pool item is the Xid leader.   */  boolean isJoin(PoolItem item)  {    if (this == item)      return false;    else if (_xid != item._xid)      return false;    else if (_mcf != item._mcf)      return false;    else      return true;  }  /**   * Try to share the connection.   */  boolean share(UserPoolItem userPoolItem)  {    if (this == userPoolItem.getOwnPoolItem())      return true;    else if (_mConn == null)           // already closed      return false;    else if (! _cm.isShareable()) // not shareable      return false;    else if (_mcf != userPoolItem.getManagedConnectionFactory())      return false;    else if (_subject != userPoolItem.getSubject())      return false;    else if (_requestInfo != userPoolItem.getInfo())      return false;    else if (_hasConnectionError) // had a fatal error      return false;    // skip for now    if (true)      return false;        userPoolItem.associate(this, _mcf, _subject, _requestInfo);    return true;  }  /**   * Returns the managed connection.   */  ManagedConnection getManagedConnection()  {    return _mConn;  }  /**   * Returns the user connection.   */  /*  Object getUserConnection()    throws ResourceException  {    return _userPoolItem.getUserConnection();  }  */  /**   * Returns the user connection.   */  Object allocateConnection()    throws ResourceException  {    return _mConn.getConnection(_subject, _requestInfo);  }  /**   * Returns true for a valid connection.   */  boolean isValid(Subject subject,		  ConnectionRequestInfo requestInfo,		  UserPoolItem userPoolItem)  {    try {      ManagedConnection mConn = getManagedConnection();      if (mConn == null)	return false;      Object userConn = userPoolItem.getUserConnection();      if (userConn == null) {	userConn = mConn.getConnection(subject, requestInfo);	userPoolItem.setUserConnection(userConn);      }      return userConn != null;    } catch (ResourceException e) {      log.log(Level.WARNING, e.toString(), e);      return false;    }  }  /**   * Returns the XA resource.   */  void enableLocalTransactionOptimization(boolean enableOptimization)  {    if (_xaResource == null)      _isXATransaction = false;    else if (_localTransaction == null)      _isXATransaction = true;    else if (! _cm.isLocalTransactionOptimization())      _isXATransaction = true;    else if (! _cm.isShareable())      _isXATransaction = true;    else      _isXATransaction = ! enableOptimization;  }  /**   * Returns true if the pooled connection supports transactions.   */  boolean supportsTransaction()  {    // server/164j    return _xaResource != null || _localTransaction != null;  }  /**   * Returns the XA resource.   */  XAResource getXAResource()  {    return _xaResource;  }  /**   * Returns the Xid resource.   */  Xid getXid()  {    return _xid;  }  /**   * Notifies that an application has closed the connection.   */  public void connectionClosed(ConnectionEvent event)  {    boolean addIdle = false;    Object handle = event.getConnectionHandle();    if (! _hasConnectionError && handle == null && _shareHead != null) {      log.fine(L.l("JCA close event '{0}' for {1} did not have a connection handle.  Please notify the JCA resource provider.",		  event, _mConn));    }    if (_shareHead == null) {      toIdle();      return;    }        UserPoolItem userPoolItem = _shareHead;    while (userPoolItem != null) {      UserPoolItem next = userPoolItem.getShareNext();      Object userConn = userPoolItem.getUserConnection();      if (userConn == handle || handle == null)	userPoolItem.close();      userPoolItem = next;    }  }    /**   * Notifies that a local transaction has started.   */  public void localTransactionStarted(ConnectionEvent event)  {    if (_isLocalTransaction || _xid != null)      throw new IllegalStateException(L.l("attempted to start local transaction while transaction is in progress."));    // server/30c4, #2627    _isLocalTransaction = true;  }    /**   * Notifies that a local transaction has committed.   */  public void localTransactionCommitted(ConnectionEvent event)  {    if (_xid != null)      throw new IllegalStateException(L.l("attempted to commit() local transaction from an active XA transaction."));    else if (! _isLocalTransaction)      throw new IllegalStateException(L.l("attempted to commit() with no active local transaction."));    // #2627, server/30c4    _isLocalTransaction = false;  }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?