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