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