Coverage Report - org.apache.commons.dbcp.AbandonedObjectPool
 
Classes in this File Line Coverage Branch Coverage Complexity
AbandonedObjectPool
94%
51/54
71%
27/38
5.4
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 package org.apache.commons.dbcp;
 19  
 
 20  
 import java.util.ArrayList;
 21  
 import java.util.Iterator;
 22  
 import java.util.List;
 23  
 
 24  
 import org.apache.commons.pool.PoolableObjectFactory;
 25  
 import org.apache.commons.pool.impl.GenericObjectPool;
 26  
 
 27  
 /**
 28  
  * <p>An implementation of a Jakarta-Commons ObjectPool which
 29  
  * tracks JDBC connections and can recover abandoned db connections.
 30  
  * If logAbandoned=true, a stack trace will be printed for any
 31  
  * abandoned db connections recovered.
 32  
  *                                                                        
 33  
  * @author Glenn L. Nielsen
 34  
  * @version $Revision: 1023401 $ $Date: 2010-10-16 21:54:24 -0400 (Sat, 16 Oct 2010) $
 35  
  */
 36  
 public class AbandonedObjectPool extends GenericObjectPool {
 37  
 
 38  
     /** 
 39  
      * DBCP AbandonedConfig 
 40  
      */
 41  
     private final AbandonedConfig config;
 42  
     
 43  
     /**
 44  
      * A list of connections in use
 45  
      */
 46  94
     private final List trace = new ArrayList();
 47  
 
 48  
     /**
 49  
      * Create an ObjectPool which tracks db connections.
 50  
      *
 51  
      * @param factory PoolableObjectFactory used to create this
 52  
      * @param config configuration for abandoned db connections
 53  
      */
 54  
     public AbandonedObjectPool(PoolableObjectFactory factory,
 55  
                                AbandonedConfig config) {
 56  94
         super(factory);
 57  94
         this.config = config;
 58  94
     }
 59  
 
 60  
     /**
 61  
      * Get a db connection from the pool.
 62  
      *
 63  
      * If removeAbandoned=true, recovers db connections which
 64  
      * have been idle > removeAbandonedTimeout and
 65  
      * getNumActive() > getMaxActive() - 3 and
 66  
      * getNumIdle() < 2
 67  
      * 
 68  
      * @return Object jdbc Connection
 69  
      * @throws Exception if an exception occurs retrieving a 
 70  
      * connection from the pool
 71  
      */
 72  
     public Object borrowObject() throws Exception {
 73  1628
         if (config != null
 74  
                 && config.getRemoveAbandoned()
 75  
                 && (getNumIdle() < 2)
 76  
                 && (getNumActive() > getMaxActive() - 3) ) {
 77  93
             removeAbandoned();
 78  
         }
 79  1628
         Object obj = super.borrowObject();
 80  1624
         if (obj instanceof AbandonedTrace) {
 81  1624
             ((AbandonedTrace) obj).setStackTrace();
 82  
         }
 83  1624
         if (obj != null && config != null && config.getRemoveAbandoned()) {
 84  1624
             synchronized (trace) {
 85  1624
                 trace.add(obj);
 86  1624
             }
 87  
         }
 88  1624
         return obj;
 89  
     }
 90  
 
 91  
     /**
 92  
      * Return a db connection to the pool.
 93  
      *
 94  
      * @param obj db Connection to return
 95  
      * @throws Exception if an exception occurs returning the connection
 96  
      * to the pool
 97  
      */
 98  
     public void returnObject(Object obj) throws Exception {
 99  1536
         if (config != null && config.getRemoveAbandoned()) {
 100  1536
             synchronized (trace) {
 101  1536
                 boolean foundObject = trace.remove(obj);
 102  1536
                 if (!foundObject) {
 103  0
                     return; // This connection has already been invalidated.  Stop now.
 104  
                 }
 105  1536
             }
 106  
         }
 107  1536
         super.returnObject(obj);
 108  1536
     }
 109  
 
 110  
     /**
 111  
      * Invalidates an object from the pool.
 112  
      *
 113  
      * @param obj object to be returned
 114  
      * @throws Exception if an exception occurs invalidating the object
 115  
      */
 116  
     public void invalidateObject(Object obj) throws Exception {
 117  201
         if (config != null && config.getRemoveAbandoned()) {
 118  201
             synchronized (trace) {
 119  201
                 boolean foundObject = trace.remove(obj);
 120  201
                 if (!foundObject) {
 121  129
                     return; // This connection has already been invalidated.  Stop now.
 122  
                 }
 123  72
             }
 124  
         }
 125  72
         super.invalidateObject(obj);        
 126  68
     }
 127  
 
 128  
     /**
 129  
      * Recover abandoned db connections which have been idle
 130  
      * greater than the removeAbandonedTimeout.
 131  
      */
 132  
     private void removeAbandoned() {
 133  
         // Generate a list of abandoned connections to remove
 134  93
         long now = System.currentTimeMillis();
 135  93
         long timeout = now - (config.getRemoveAbandonedTimeout() * 1000);
 136  93
         ArrayList remove = new ArrayList();
 137  93
         synchronized (trace) {
 138  93
             Iterator it = trace.iterator();
 139  870
             while (it.hasNext()) {
 140  777
                 AbandonedTrace pc = (AbandonedTrace) it.next();
 141  777
                 if (pc.getLastUsed() > timeout) {
 142  466
                     continue;
 143  
                 }
 144  311
                 if (pc.getLastUsed() > 0) {
 145  197
                     remove.add(pc);
 146  
                 }
 147  311
             }
 148  93
         }
 149  
 
 150  
         // Now remove the abandoned connections
 151  93
         Iterator it = remove.iterator();
 152  290
         while (it.hasNext()) {
 153  197
             AbandonedTrace pc = (AbandonedTrace) it.next();
 154  197
             if (config.getLogAbandoned()) {
 155  8
                 pc.printStackTrace();
 156  
             }             
 157  
             try {
 158  197
                 invalidateObject(pc);
 159  0
             } catch (Exception e) {
 160  0
                 e.printStackTrace();
 161  197
             }
 162  
             
 163  197
         }
 164  93
     }
 165  
 }
 166