001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.commons.dbcp;
019:
020: import java.util.ArrayList;
021: import java.util.Iterator;
022: import java.util.List;
023:
024: import org.apache.commons.pool.PoolableObjectFactory;
025: import org.apache.commons.pool.impl.GenericObjectPool;
026:
027: /**
028: * <p>An implementation of a Jakarta-Commons ObjectPool which
029: * tracks JDBC connections and can recover abandoned db connections.
030: * If logAbandoned=true, a stack trace will be printed for any
031: * abandoned db connections recovered.
032: *
033: * @author Glenn L. Nielsen
034: * @version $Revision: 482015 $ $Date: 2006-12-03 19:22:09 -0700 (Sun, 03 Dec 2006) $
035: * @deprecated This will be removed in a future version of DBCP.
036: */
037: public class AbandonedObjectPool extends GenericObjectPool {
038:
039: /**
040: * DBCP AbandonedConfig
041: */
042: private AbandonedConfig config = null;
043:
044: /**
045: * A list of connections in use
046: */
047: private List trace = new ArrayList();
048:
049: /**
050: * Create an ObjectPool which tracks db connections.
051: *
052: * @param factory PoolableObjectFactory used to create this
053: * @param config configuration for abandoned db connections
054: */
055: public AbandonedObjectPool(PoolableObjectFactory factory,
056: AbandonedConfig config) {
057: super (factory);
058: this .config = config;
059: System.out
060: .println("AbandonedObjectPool is used (" + this + ")");
061: System.out.println(" LogAbandoned: "
062: + config.getLogAbandoned());
063: System.out.println(" RemoveAbandoned: "
064: + config.getRemoveAbandoned());
065: System.out.println(" RemoveAbandonedTimeout: "
066: + config.getRemoveAbandonedTimeout());
067: }
068:
069: /**
070: * Get a db connection from the pool.
071: *
072: * If removeAbandoned=true, recovers db connections which
073: * have been idle > removeAbandonedTimeout and
074: * getNumActive() > getMaxActive() - 3 and
075: * getNumIdle() < 2
076: *
077: * @return Object jdbc Connection
078: * @throws Exception if an exception occurs retrieving a
079: * connection from the pool
080: */
081: public Object borrowObject() throws Exception {
082: if (config != null && config.getRemoveAbandoned()
083: && (getNumIdle() < 2)
084: && (getNumActive() > getMaxActive() - 3)) {
085: removeAbandoned();
086: }
087: Object obj = super .borrowObject();
088: if (obj instanceof AbandonedTrace) {
089: ((AbandonedTrace) obj).setStackTrace();
090: }
091: if (obj != null && config != null
092: && config.getRemoveAbandoned()) {
093: synchronized (trace) {
094: trace.add(obj);
095: }
096: }
097: return obj;
098: }
099:
100: /**
101: * Return a db connection to the pool.
102: *
103: * @param obj db Connection to return
104: * @throws Exception if an exception occurs returning the connection
105: * to the pool
106: */
107: public void returnObject(Object obj) throws Exception {
108: if (config != null && config.getRemoveAbandoned()) {
109: synchronized (trace) {
110: boolean foundObject = trace.remove(obj);
111: if (!foundObject) {
112: return; // This connection has already been invalidated. Stop now.
113: }
114: }
115: }
116: super .returnObject(obj);
117: }
118:
119: /**
120: * Invalidates an object from the pool.
121: *
122: * @param obj object to be returned
123: * @throws Exception if an exception occurs invalidating the object
124: */
125: public void invalidateObject(Object obj) throws Exception {
126: if (config != null && config.getRemoveAbandoned()) {
127: synchronized (trace) {
128: boolean foundObject = trace.remove(obj);
129: if (!foundObject) {
130: return; // This connection has already been invalidated. Stop now.
131: }
132: }
133: }
134: super .invalidateObject(obj);
135: }
136:
137: /**
138: * Recover abandoned db connections which have been idle
139: * greater than the removeAbandonedTimeout.
140: */
141: private void removeAbandoned() {
142: // Generate a list of abandoned connections to remove
143: long now = System.currentTimeMillis();
144: long timeout = now
145: - (config.getRemoveAbandonedTimeout() * 1000);
146: ArrayList remove = new ArrayList();
147: synchronized (trace) {
148: Iterator it = trace.iterator();
149: while (it.hasNext()) {
150: AbandonedTrace pc = (AbandonedTrace) it.next();
151: if (pc.getLastUsed() > timeout) {
152: continue;
153: }
154: if (pc.getLastUsed() > 0) {
155: remove.add(pc);
156: }
157: }
158: }
159:
160: // Now remove the abandoned connections
161: Iterator it = remove.iterator();
162: while (it.hasNext()) {
163: AbandonedTrace pc = (AbandonedTrace) it.next();
164: if (config.getLogAbandoned()) {
165: pc.printStackTrace();
166: }
167: try {
168: invalidateObject(pc);
169: } catch (Exception e) {
170: e.printStackTrace();
171: }
172:
173: }
174: }
175: }
|