    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 *      https://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() &gt; 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}