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