1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.dbcp2;
18
19 import java.lang.ref.WeakReference;
20 import java.sql.SQLException;
21 import java.time.Instant;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.function.Consumer;
27
28 import org.apache.commons.pool2.TrackedUse;
29
30
31
32
33
34
35
36
37
38 public class AbandonedTrace implements TrackedUse, AutoCloseable {
39
40 static void add(final AbandonedTrace receiver, final AbandonedTrace trace) {
41 if (receiver != null) {
42 receiver.addTrace(trace);
43 }
44 }
45
46
47 private final List<WeakReference<AbandonedTrace>> traceList = new ArrayList<>();
48
49
50 private volatile Instant lastUsedInstant = Instant.EPOCH;
51
52
53
54
55 public AbandonedTrace() {
56 init(null);
57 }
58
59
60
61
62
63
64
65 public AbandonedTrace(final AbandonedTrace parent) {
66 init(parent);
67 }
68
69
70
71
72
73
74
75 protected void addTrace(final AbandonedTrace trace) {
76 synchronized (this.traceList) {
77 this.traceList.add(new WeakReference<>(trace));
78 }
79 setLastUsed();
80 }
81
82
83
84
85 protected void clearTrace() {
86 synchronized (this.traceList) {
87 this.traceList.clear();
88 }
89 }
90
91
92
93
94
95
96
97 @Override
98 public void close() throws SQLException {
99
100 }
101
102
103
104
105
106
107
108 protected void close(final Consumer<Exception> exceptionHandler) {
109 Utils.close(this, exceptionHandler);
110 }
111
112
113
114
115
116
117 @Override
118 @Deprecated
119 public long getLastUsed() {
120 return lastUsedInstant.toEpochMilli();
121 }
122
123 @Override
124 public Instant getLastUsedInstant() {
125 return lastUsedInstant;
126 }
127
128
129
130
131
132
133 protected List<AbandonedTrace> getTrace() {
134 final int size = traceList.size();
135 if (size == 0) {
136 return Collections.emptyList();
137 }
138 final ArrayList<AbandonedTrace> result = new ArrayList<>(size);
139 synchronized (this.traceList) {
140 final Iterator<WeakReference<AbandonedTrace>> iter = traceList.iterator();
141 while (iter.hasNext()) {
142 final AbandonedTrace trace = iter.next().get();
143 if (trace == null) {
144
145 iter.remove();
146 } else {
147 result.add(trace);
148 }
149 }
150 }
151 return result;
152 }
153
154
155
156
157
158
159
160 private void init(final AbandonedTrace parent) {
161 AbandonedTrace.add(parent, this);
162 }
163
164
165
166
167
168
169
170 protected void removeThisTrace(final Object source) {
171 if (source instanceof AbandonedTrace) {
172 AbandonedTrace.class.cast(source).removeTrace(this);
173 }
174 }
175
176
177
178
179
180
181
182 protected void removeTrace(final AbandonedTrace trace) {
183 synchronized (this.traceList) {
184 final Iterator<WeakReference<AbandonedTrace>> iter = traceList.iterator();
185 while (iter.hasNext()) {
186 final AbandonedTrace traceInList = iter.next().get();
187 if (trace != null && trace.equals(traceInList)) {
188 iter.remove();
189 break;
190 }
191 if (traceInList == null) {
192
193 iter.remove();
194 }
195 }
196 }
197 }
198
199
200
201
202 protected void setLastUsed() {
203 lastUsedInstant = Instant.now();
204 }
205
206
207
208
209
210
211
212
213 protected void setLastUsed(final Instant lastUsedInstant) {
214 this.lastUsedInstant = lastUsedInstant;
215 }
216
217
218
219
220
221
222
223
224 @Deprecated
225 protected void setLastUsed(final long lastUsedMillis) {
226 this.lastUsedInstant = Instant.ofEpochMilli(lastUsedMillis);
227 }
228 }