View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.pool2.impl;
18  
19  import java.io.OutputStreamWriter;
20  import java.io.PrintWriter;
21  import java.nio.charset.Charset;
22  import java.time.Duration;
23  
24  import org.apache.commons.pool2.TrackedUse;
25  import org.apache.commons.pool2.UsageTracking;
26  
27  /**
28   * Configuration settings for abandoned object removal.
29   *
30   * @since 2.0
31   */
32  public class AbandonedConfig {
33  
34      /**
35       * The 5 minutes Duration.
36       */
37      private static final Duration DEFAULT_REMOVE_ABANDONED_TIMEOUT_DURATION = Duration.ofMinutes(5);
38  
39      /**
40       * Creates a new instance with values from the given instance.
41       *
42       * @param abandonedConfig the source, may be null.
43       * @return A new instance or null if the input is null.
44       * @since 2.11.0
45       */
46      public static AbandonedConfig copy(final AbandonedConfig abandonedConfig) {
47          return abandonedConfig == null ? null : new AbandonedConfig(abandonedConfig);
48      }
49  
50      /**
51       * Whether or not borrowObject performs abandoned object removal.
52       */
53      private boolean removeAbandonedOnBorrow;
54  
55      /**
56       * Whether or not pool maintenance (evictor) performs abandoned object
57       * removal.
58       */
59      private boolean removeAbandonedOnMaintenance;
60  
61      /**
62       * Timeout before an abandoned object can be removed.
63       */
64      private Duration removeAbandonedTimeoutDuration = DEFAULT_REMOVE_ABANDONED_TIMEOUT_DURATION;
65  
66      /**
67       * Determines whether or not to log stack traces for application code
68       * which abandoned an object.
69       */
70      private boolean logAbandoned;
71  
72      /**
73       * Determines whether or not to log full stack traces when logAbandoned is true.
74       * If disabled, then a faster method for logging stack traces with only class data
75       * may be used if possible.
76       *
77       * @since 2.5
78       */
79      private boolean requireFullStackTrace = true;
80  
81      /**
82       * PrintWriter to use to log information on abandoned objects.
83       * Use of default system encoding is deliberate.
84       */
85      private PrintWriter logWriter = new PrintWriter(new OutputStreamWriter(System.out, Charset.defaultCharset()));
86  
87      /**
88       * If the pool implements {@link UsageTracking}, should the pool record a
89       * stack trace every time a method is called on a pooled object and retain
90       * the most recent stack trace to aid debugging of abandoned objects?
91       */
92      private boolean useUsageTracking;
93  
94      /**
95       * Creates a new instance.
96       */
97      public AbandonedConfig() {
98          // empty
99      }
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 }