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