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 */ 017package org.apache.commons.pool2.impl; 018 019import java.io.OutputStreamWriter; 020import java.io.PrintWriter; 021import java.nio.charset.Charset; 022import java.time.Duration; 023 024import org.apache.commons.pool2.TrackedUse; 025import org.apache.commons.pool2.UsageTracking; 026 027/** 028 * Configuration settings for abandoned object removal. 029 * 030 * @since 2.0 031 */ 032public class AbandonedConfig { 033 034 /** 035 * The 5 minutes Duration. 036 */ 037 private static final Duration DEFAULT_REMOVE_ABANDONED_TIMEOUT_DURATION = Duration.ofMinutes(5); 038 039 /** 040 * Creates a new instance with values from the given instance. 041 * 042 * @param abandonedConfig the source, may be null. 043 * @return A new instance or null if the input is null. 044 * @since 2.11.0 045 */ 046 public static AbandonedConfig copy(final AbandonedConfig abandonedConfig) { 047 return abandonedConfig == null ? null : new AbandonedConfig(abandonedConfig); 048 } 049 050 /** 051 * Whether or not borrowObject performs abandoned object removal. 052 */ 053 private boolean removeAbandonedOnBorrow; 054 055 /** 056 * Whether or not pool maintenance (evictor) performs abandoned object 057 * removal. 058 */ 059 private boolean removeAbandonedOnMaintenance; 060 061 /** 062 * Timeout before an abandoned object can be removed. 063 */ 064 private Duration removeAbandonedTimeoutDuration = DEFAULT_REMOVE_ABANDONED_TIMEOUT_DURATION; 065 066 /** 067 * Determines whether or not to log stack traces for application code 068 * which abandoned an object. 069 */ 070 private boolean logAbandoned; 071 072 /** 073 * Determines whether or not to log full stack traces when logAbandoned is true. 074 * If disabled, then a faster method for logging stack traces with only class data 075 * may be used if possible. 076 * 077 * @since 2.5 078 */ 079 private boolean requireFullStackTrace = true; 080 081 /** 082 * PrintWriter to use to log information on abandoned objects. 083 * Use of default system encoding is deliberate. 084 */ 085 private PrintWriter logWriter = new PrintWriter(new OutputStreamWriter(System.out, Charset.defaultCharset())); 086 087 /** 088 * If the pool implements {@link UsageTracking}, should the pool record a 089 * stack trace every time a method is called on a pooled object and retain 090 * the most recent stack trace to aid debugging of abandoned objects? 091 */ 092 private boolean useUsageTracking; 093 094 /** 095 * Creates a new instance. 096 */ 097 public AbandonedConfig() { 098 // empty 099 } 100 101 /** 102 * Creates a new instance with values from the given instance. 103 * 104 * @param abandonedConfig the source. 105 */ 106 @SuppressWarnings("resource") 107 private AbandonedConfig(final AbandonedConfig abandonedConfig) { 108 this.setLogAbandoned(abandonedConfig.getLogAbandoned()); 109 this.setLogWriter(abandonedConfig.getLogWriter()); 110 this.setRemoveAbandonedOnBorrow(abandonedConfig.getRemoveAbandonedOnBorrow()); 111 this.setRemoveAbandonedOnMaintenance(abandonedConfig.getRemoveAbandonedOnMaintenance()); 112 this.setRemoveAbandonedTimeout(abandonedConfig.getRemoveAbandonedTimeoutDuration()); 113 this.setUseUsageTracking(abandonedConfig.getUseUsageTracking()); 114 this.setRequireFullStackTrace(abandonedConfig.getRequireFullStackTrace()); 115 } 116 117 /** 118 * Flag to log stack traces for application code which abandoned 119 * an object. 120 * 121 * Defaults to false. 122 * Logging of abandoned objects adds overhead for every object created 123 * because a stack trace has to be generated. 124 * 125 * @return boolean true if stack trace logging is turned on for abandoned 126 * objects 127 */ 128 public boolean getLogAbandoned() { 129 return this.logAbandoned; 130 } 131 132 /** 133 * Gets the log writer being used by this configuration to log 134 * information on abandoned objects. If not set, a PrintWriter based on 135 * System.out with the system default encoding is used. 136 * 137 * @return log writer in use 138 */ 139 public PrintWriter getLogWriter() { 140 return logWriter; 141 } 142 143 /** 144 * <p>Flag to remove abandoned objects if they exceed the 145 * removeAbandonedTimeout when borrowObject is invoked.</p> 146 * 147 * <p>The default value is false.</p> 148 * 149 * <p>If set to true, abandoned objects are removed by borrowObject if 150 * there are fewer than 2 idle objects available in the pool and 151 * {@code getNumActive() > getMaxTotal() - 3}</p> 152 * 153 * @return true if abandoned objects are to be removed by borrowObject 154 */ 155 public boolean getRemoveAbandonedOnBorrow() { 156 return this.removeAbandonedOnBorrow; 157 } 158 159 /** 160 * <p>Flag to remove abandoned objects if they exceed the 161 * removeAbandonedTimeout when pool maintenance (the "evictor") 162 * runs.</p> 163 * 164 * <p>The default value is false.</p> 165 * 166 * <p>If set to true, abandoned objects are removed by the pool 167 * maintenance thread when it runs. This setting has no effect 168 * unless maintenance is enabled by setting 169 * {@link GenericObjectPool#getDurationBetweenEvictionRuns()} 170 * to a positive number.</p> 171 * 172 * @return true if abandoned objects are to be removed by the evictor 173 */ 174 public boolean getRemoveAbandonedOnMaintenance() { 175 return this.removeAbandonedOnMaintenance; 176 } 177 178 /** 179 * <p>Timeout in seconds before an abandoned object can be removed.</p> 180 * 181 * <p>The time of most recent use of an object is the maximum (latest) of 182 * {@link TrackedUse#getLastUsedInstant()} (if this class of the object implements 183 * TrackedUse) and the time when the object was borrowed from the pool.</p> 184 * 185 * <p>The default value is 300 seconds.</p> 186 * 187 * @return the abandoned object timeout in seconds. 188 * @deprecated Use {@link #getRemoveAbandonedTimeoutDuration()}. 189 */ 190 @Deprecated 191 public int getRemoveAbandonedTimeout() { 192 return (int) this.removeAbandonedTimeoutDuration.getSeconds(); 193 } 194 195 /** 196 * <p>Timeout before an abandoned object can be removed.</p> 197 * 198 * <p>The time of most recent use of an object is the maximum (latest) of 199 * {@link TrackedUse#getLastUsedInstant()} (if this class of the object implements 200 * TrackedUse) and the time when the object was borrowed from the pool.</p> 201 * 202 * <p>The default value is 300 seconds.</p> 203 * 204 * @return the abandoned object timeout. 205 * @since 2.10.0 206 */ 207 public Duration getRemoveAbandonedTimeoutDuration() { 208 return this.removeAbandonedTimeoutDuration; 209 } 210 211 /** 212 * Indicates if full stack traces are required when {@link #getLogAbandoned() logAbandoned} 213 * is true. Defaults to true. Logging of abandoned objects requiring a full stack trace will 214 * generate an entire stack trace to generate for every object created. If this is disabled, 215 * a faster but less informative stack walking mechanism may be used if available. 216 * 217 * @return true if full stack traces are required for logging abandoned connections, or false 218 * if abbreviated stack traces are acceptable 219 * @see CallStack 220 * @since 2.5 221 */ 222 public boolean getRequireFullStackTrace() { 223 return requireFullStackTrace; 224 } 225 226 /** 227 * If the pool implements {@link UsageTracking}, should the pool record a 228 * stack trace every time a method is called on a pooled object and retain 229 * the most recent stack trace to aid debugging of abandoned objects? 230 * 231 * @return {@code true} if usage tracking is enabled 232 */ 233 public boolean getUseUsageTracking() { 234 return useUsageTracking; 235 } 236 237 /** 238 * Sets the flag to log stack traces for application code which abandoned 239 * an object. 240 * 241 * @param logAbandoned true turns on abandoned stack trace logging 242 * @see #getLogAbandoned() 243 */ 244 public void setLogAbandoned(final boolean logAbandoned) { 245 this.logAbandoned = logAbandoned; 246 } 247 248 /** 249 * Sets the log writer to be used by this configuration to log 250 * information on abandoned objects. 251 * 252 * @param logWriter The new log writer 253 */ 254 public void setLogWriter(final PrintWriter logWriter) { 255 this.logWriter = logWriter; 256 } 257 258 /** 259 * Flag to remove abandoned objects if they exceed the 260 * removeAbandonedTimeout when borrowObject is invoked. 261 * 262 * @param removeAbandonedOnBorrow true means abandoned objects will be 263 * removed by borrowObject 264 * @see #getRemoveAbandonedOnBorrow() 265 */ 266 public void setRemoveAbandonedOnBorrow(final boolean removeAbandonedOnBorrow) { 267 this.removeAbandonedOnBorrow = removeAbandonedOnBorrow; 268 } 269 270 /** 271 * Flag to remove abandoned objects if they exceed the 272 * removeAbandonedTimeout when pool maintenance runs. 273 * 274 * @param removeAbandonedOnMaintenance true means abandoned objects will be 275 * removed by pool maintenance 276 * @see #getRemoveAbandonedOnMaintenance 277 */ 278 public void setRemoveAbandonedOnMaintenance(final boolean removeAbandonedOnMaintenance) { 279 this.removeAbandonedOnMaintenance = removeAbandonedOnMaintenance; 280 } 281 282 /** 283 * Sets the timeout before an abandoned object can be 284 * removed. 285 * 286 * <p>Setting this property has no effect if 287 * {@link #getRemoveAbandonedOnBorrow() removeAbandonedOnBorrow} and 288 * {@link #getRemoveAbandonedOnMaintenance() removeAbandonedOnMaintenance} 289 * are both false.</p> 290 * 291 * @param removeAbandonedTimeout new abandoned timeout 292 * @see #getRemoveAbandonedTimeoutDuration() 293 * @since 2.10.0 294 */ 295 public void setRemoveAbandonedTimeout(final Duration removeAbandonedTimeout) { 296 this.removeAbandonedTimeoutDuration = PoolImplUtils.nonNull(removeAbandonedTimeout, DEFAULT_REMOVE_ABANDONED_TIMEOUT_DURATION); 297 } 298 299 /** 300 * Sets the timeout in seconds before an abandoned object can be 301 * removed. 302 * 303 * <p>Setting this property has no effect if 304 * {@link #getRemoveAbandonedOnBorrow() removeAbandonedOnBorrow} and 305 * {@link #getRemoveAbandonedOnMaintenance() removeAbandonedOnMaintenance} 306 * are both false.</p> 307 * 308 * @param removeAbandonedTimeoutSeconds new abandoned timeout in seconds 309 * @see #getRemoveAbandonedTimeoutDuration() 310 * @deprecated Use {@link #setRemoveAbandonedTimeout(Duration)}. 311 */ 312 @Deprecated 313 public void setRemoveAbandonedTimeout(final int removeAbandonedTimeoutSeconds) { 314 setRemoveAbandonedTimeout(Duration.ofSeconds(removeAbandonedTimeoutSeconds)); 315 } 316 317 /** 318 * Sets the flag to require full stack traces for logging abandoned connections when enabled. 319 * 320 * @param requireFullStackTrace indicates whether or not full stack traces are required in 321 * abandoned connection logs 322 * @see CallStack 323 * @see #getRequireFullStackTrace() 324 * @since 2.5 325 */ 326 public void setRequireFullStackTrace(final boolean requireFullStackTrace) { 327 this.requireFullStackTrace = requireFullStackTrace; 328 } 329 330 /** 331 * If the pool implements {@link UsageTracking}, configure whether the pool 332 * should record a stack trace every time a method is called on a pooled 333 * object and retain the most recent stack trace to aid debugging of 334 * abandoned objects. 335 * 336 * @param useUsageTracking A value of {@code true} will enable 337 * the recording of a stack trace on every use 338 * of a pooled object 339 */ 340 public void setUseUsageTracking(final boolean useUsageTracking) { 341 this.useUsageTracking = useUsageTracking; 342 } 343 344 /** 345 * @since 2.4.3 346 */ 347 @Override 348 public String toString() { 349 final StringBuilder builder = new StringBuilder(); 350 builder.append("AbandonedConfig [removeAbandonedOnBorrow="); 351 builder.append(removeAbandonedOnBorrow); 352 builder.append(", removeAbandonedOnMaintenance="); 353 builder.append(removeAbandonedOnMaintenance); 354 builder.append(", removeAbandonedTimeoutDuration="); 355 builder.append(removeAbandonedTimeoutDuration); 356 builder.append(", logAbandoned="); 357 builder.append(logAbandoned); 358 builder.append(", logWriter="); 359 builder.append(logWriter); 360 builder.append(", useUsageTracking="); 361 builder.append(useUsageTracking); 362 builder.append("]"); 363 return builder.toString(); 364 } 365}