    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     */
    129    public boolean getLogAbandoned() {
    130        return this.logAbandoned;
    131    }
    132
    133    /**
    134     * Gets the log writer being used by this configuration to log
    135     * information on abandoned objects. If not set, a PrintWriter based on
    136     * System.out with the system default encoding is used.
    137     *
    138     * @return log writer in use
    139     */
    140    public PrintWriter getLogWriter() {
    141        return logWriter;
    142    }
    143
    144    /**
    145     * <p>Flag to remove abandoned objects if they exceed the
    146     * removeAbandonedTimeout when borrowObject is invoked.</p>
    147     *
    148     * <p>The default value is false.</p>
    149     *
    150     * <p>If set to true, abandoned objects are removed by borrowObject if
    151     * there are fewer than 2 idle objects available in the pool and
    152     * {@code getNumActive() &gt; getMaxTotal() - 3}</p>
    153     *
    154     * @return true if abandoned objects are to be removed by borrowObject
    155     */
    156    public boolean getRemoveAbandonedOnBorrow() {
    157        return this.removeAbandonedOnBorrow;
    158    }
    159
    160    /**
    161     * <p>Flag to remove abandoned objects if they exceed the
    162     * removeAbandonedTimeout when pool maintenance (the "evictor")
    163     * runs.</p>
    164     *
    165     * <p>The default value is false.</p>
    166     *
    167     * <p>If set to true, abandoned objects are removed by the pool
    168     * maintenance thread when it runs.  This setting has no effect
    169     * unless maintenance is enabled by setting
    170     * {@link GenericObjectPool#getTimeBetweenEvictionRunsMillis()}
    171     * to a positive number.</p>
    172     *
    173     * @return true if abandoned objects are to be removed by the evictor
    174     */
    175    public boolean getRemoveAbandonedOnMaintenance() {
    176        return this.removeAbandonedOnMaintenance;
    177    }
    178
    179    /**
    180     * <p>Timeout in seconds before an abandoned object can be removed.</p>
    181     *
    182     * <p>The time of most recent use of an object is the maximum (latest) of
    183     * {@link TrackedUse#getLastUsedInstant()} (if this class of the object implements
    184     * TrackedUse) and the time when the object was borrowed from the pool.</p>
    185     *
    186     * <p>The default value is 300 seconds.</p>
    187     *
    188     * @return the abandoned object timeout in seconds.
    189     * @deprecated Use {@link #getRemoveAbandonedTimeoutDuration()}.
    190     */
    191    @Deprecated
    192    public int getRemoveAbandonedTimeout() {
    193        return (int) this.removeAbandonedTimeoutDuration.getSeconds();
    194    }
    195
    196    /**
    197     * <p>Timeout before an abandoned object can be removed.</p>
    198     *
    199     * <p>The time of most recent use of an object is the maximum (latest) of
    200     * {@link TrackedUse#getLastUsedInstant()} (if this class of the object implements
    201     * TrackedUse) and the time when the object was borrowed from the pool.</p>
    202     *
    203     * <p>The default value is 300 seconds.</p>
    204     *
    205     * @return the abandoned object timeout.
    206     * @since 2.10.0
    207     */
    208    public Duration getRemoveAbandonedTimeoutDuration() {
    209        return this.removeAbandonedTimeoutDuration;
    210    }
    211
    212    /**
    213     * Indicates if full stack traces are required when {@link #getLogAbandoned() logAbandoned}
    214     * is true. Defaults to true. Logging of abandoned objects requiring a full stack trace will
    215     * generate an entire stack trace to generate for every object created. If this is disabled,
    216     * a faster but less informative stack walking mechanism may be used if available.
    217     *
    218     * @return true if full stack traces are required for logging abandoned connections, or false
    219     * if abbreviated stack traces are acceptable
    220     * @see CallStack
    221     * @since 2.5
    222     */
    223    public boolean getRequireFullStackTrace() {
    224        return requireFullStackTrace;
    225    }
    226
    227    /**
    228     * If the pool implements {@link UsageTracking}, should the pool record a
    229     * stack trace every time a method is called on a pooled object and retain
    230     * the most recent stack trace to aid debugging of abandoned objects?
    231     *
    232     * @return {@code true} if usage tracking is enabled
    233     */
    234    public boolean getUseUsageTracking() {
    235        return useUsageTracking;
    236    }
    237
    238    /**
    239     * Sets the flag to log stack traces for application code which abandoned
    240     * an object.
    241     *
    242     * @param logAbandoned true turns on abandoned stack trace logging
    243     * @see #getLogAbandoned()
    244     *
    245     */
    246    public void setLogAbandoned(final boolean logAbandoned) {
    247        this.logAbandoned = logAbandoned;
    248    }
    249
    250    /**
    251     * Sets the log writer to be used by this configuration to log
    252     * information on abandoned objects.
    253     *
    254     * @param logWriter The new log writer
    255     */
    256    public void setLogWriter(final PrintWriter logWriter) {
    257        this.logWriter = logWriter;
    258    }
    259
    260    /**
    261     * Flag to remove abandoned objects if they exceed the
    262     * removeAbandonedTimeout when borrowObject is invoked.
    263     *
    264     * @param removeAbandonedOnBorrow true means abandoned objects will be
    265     *   removed by borrowObject
    266     * @see #getRemoveAbandonedOnBorrow()
    267     */
    268    public void setRemoveAbandonedOnBorrow(final boolean removeAbandonedOnBorrow) {
    269        this.removeAbandonedOnBorrow = removeAbandonedOnBorrow;
    270    }
    271
    272    /**
    273     * Flag to remove abandoned objects if they exceed the
    274     * removeAbandonedTimeout when pool maintenance runs.
    275     *
    276     * @param removeAbandonedOnMaintenance true means abandoned objects will be
    277     *   removed by pool maintenance
    278     * @see #getRemoveAbandonedOnMaintenance
    279     */
    280    public void setRemoveAbandonedOnMaintenance(final boolean removeAbandonedOnMaintenance) {
    281        this.removeAbandonedOnMaintenance = removeAbandonedOnMaintenance;
    282    }
    283
    284    /**
    285     * Sets the timeout before an abandoned object can be
    286     * removed.
    287     *
    288     * <p>Setting this property has no effect if
    289     * {@link #getRemoveAbandonedOnBorrow() removeAbandonedOnBorrow} and
    290     * {@link #getRemoveAbandonedOnMaintenance() removeAbandonedOnMaintenance}
    291     * are both false.</p>
    292     *
    293     * @param removeAbandonedTimeout new abandoned timeout
    294     * @see #getRemoveAbandonedTimeoutDuration()
    295     * @since 2.10.0
    296     */
    297    public void setRemoveAbandonedTimeout(final Duration removeAbandonedTimeout) {
    298        this.removeAbandonedTimeoutDuration = PoolImplUtils.nonNull(removeAbandonedTimeout, DEFAULT_REMOVE_ABANDONED_TIMEOUT_DURATION);
    299    }
    300
    301    /**
    302     * Sets the timeout in seconds before an abandoned object can be
    303     * removed.
    304     *
    305     * <p>Setting this property has no effect if
    306     * {@link #getRemoveAbandonedOnBorrow() removeAbandonedOnBorrow} and
    307     * {@link #getRemoveAbandonedOnMaintenance() removeAbandonedOnMaintenance}
    308     * are both false.</p>
    309     *
    310     * @param removeAbandonedTimeoutSeconds new abandoned timeout in seconds
    311     * @see #getRemoveAbandonedTimeoutDuration()
    312     * @deprecated Use {@link #setRemoveAbandonedTimeout(Duration)}.
    313     */
    314    @Deprecated
    315    public void setRemoveAbandonedTimeout(final int removeAbandonedTimeoutSeconds) {
    316        setRemoveAbandonedTimeout(Duration.ofSeconds(removeAbandonedTimeoutSeconds));
    317    }
    318
    319    /**
    320     * Sets the flag to require full stack traces for logging abandoned connections when enabled.
    321     *
    322     * @param requireFullStackTrace indicates whether or not full stack traces are required in
    323     *                              abandoned connection logs
    324     * @see CallStack
    325     * @see #getRequireFullStackTrace()
    326     * @since 2.5
    327     */
    328    public void setRequireFullStackTrace(final boolean requireFullStackTrace) {
    329        this.requireFullStackTrace = requireFullStackTrace;
    330    }
    331
    332    /**
    333     * If the pool implements {@link UsageTracking}, configure whether the pool
    334     * should record a stack trace every time a method is called on a pooled
    335     * object and retain the most recent stack trace to aid debugging of
    336     * abandoned objects.
    337     *
    338     * @param   useUsageTracking    A value of {@code true} will enable
    339     *                              the recording of a stack trace on every use
    340     *                              of a pooled object
    341     */
    342    public void setUseUsageTracking(final boolean useUsageTracking) {
    343        this.useUsageTracking = useUsageTracking;
    344    }
    345
    346    /**
    347     * @since 2.4.3
    348     */
    349    @Override
    350    public String toString() {
    351        final StringBuilder builder = new StringBuilder();
    352        builder.append("AbandonedConfig [removeAbandonedOnBorrow=");
    353        builder.append(removeAbandonedOnBorrow);
    354        builder.append(", removeAbandonedOnMaintenance=");
    355        builder.append(removeAbandonedOnMaintenance);
    356        builder.append(", removeAbandonedTimeoutDuration=");
    357        builder.append(removeAbandonedTimeoutDuration);
    358        builder.append(", logAbandoned=");
    359        builder.append(logAbandoned);
    360        builder.append(", logWriter=");
    361        builder.append(logWriter);
    362        builder.append(", useUsageTracking=");
    363        builder.append(useUsageTracking);
    364        builder.append("]");
    365        return builder.toString();
    366    }
    367}