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 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() > 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 }