1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.hc.core5.pool;
28
29 import java.util.concurrent.atomic.AtomicReference;
30
31 import org.apache.hc.core5.function.Supplier;
32 import org.apache.hc.core5.io.CloseMode;
33 import org.apache.hc.core5.io.ModalCloseable;
34 import org.apache.hc.core5.util.Args;
35 import org.apache.hc.core5.util.Deadline;
36 import org.apache.hc.core5.util.TimeValue;
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public final class PoolEntry<T, C extends ModalCloseable> {
51
52 private final T route;
53 private final TimeValue timeToLive;
54 private final AtomicReference<C> connRef;
55 private final DisposalCallback<C> disposalCallback;
56 private final Supplier<Long> currentTimeSupplier;
57
58 private volatile Object state;
59 private volatile long created;
60 private volatile long updated;
61 private volatile Deadline expiryDeadline = Deadline.MIN_VALUE;
62 private volatile Deadline validityDeadline = Deadline.MIN_VALUE;
63
64 PoolEntry(final T route, final TimeValue timeToLive, final DisposalCallback<C> disposalCallback,
65 final Supplier<Long> currentTimeSupplier) {
66 super();
67 this.route = Args.notNull(route, "Route");
68 this.timeToLive = TimeValue.defaultsToNegativeOneMillisecond(timeToLive);
69 this.connRef = new AtomicReference<>();
70 this.disposalCallback = disposalCallback;
71 this.currentTimeSupplier = currentTimeSupplier;
72 }
73
74 PoolEntry(final T route, final TimeValue timeToLive, final Supplier<Long> currentTimeSupplier) {
75 this(route, timeToLive, null, currentTimeSupplier);
76 }
77
78
79
80
81
82
83
84
85
86 public PoolEntry(final T route, final TimeValue timeToLive, final DisposalCallback<C> disposalCallback) {
87 this(route, timeToLive, disposalCallback, null);
88 }
89
90
91
92
93
94
95
96
97 public PoolEntry(final T route, final TimeValue timeToLive) {
98 this(route, timeToLive, null, null);
99 }
100
101 public PoolEntry(final T route) {
102 this(route, null);
103 }
104
105 long getCurrentTime() {
106 return currentTimeSupplier != null ? currentTimeSupplier.get() : System.currentTimeMillis();
107 }
108
109 public T getRoute() {
110 return this.route;
111 }
112
113 public C getConnection() {
114 return this.connRef.get();
115 }
116
117
118
119
120 public Deadline getValidityDeadline() {
121 return this.validityDeadline;
122 }
123
124 public Object getState() {
125 return this.state;
126 }
127
128 public long getUpdated() {
129 return this.updated;
130 }
131
132 public Deadline getExpiryDeadline() {
133 return this.expiryDeadline;
134 }
135
136
137
138
139 public boolean hasConnection() {
140 return this.connRef.get() != null;
141 }
142
143
144
145
146 public void assignConnection(final C conn) {
147 Args.notNull(conn, "connection");
148 if (this.connRef.compareAndSet(null, conn)) {
149 this.created = getCurrentTime();
150 this.updated = this.created;
151 this.validityDeadline = Deadline.calculate(this.created, this.timeToLive);
152 this.expiryDeadline = this.validityDeadline;
153 this.state = null;
154 } else {
155 throw new IllegalStateException("Connection already assigned");
156 }
157 }
158
159
160
161
162 public void discardConnection(final CloseMode closeMode) {
163 final C connection = this.connRef.getAndSet(null);
164 if (connection != null) {
165 this.state = null;
166 this.created = 0;
167 this.updated = 0;
168 this.expiryDeadline = Deadline.MIN_VALUE;
169 this.validityDeadline = Deadline.MIN_VALUE;
170 if (this.disposalCallback != null) {
171 this.disposalCallback.execute(connection, closeMode);
172 } else {
173 connection.close(closeMode);
174 }
175 }
176 }
177
178
179
180
181 public void updateExpiry(final TimeValue expiryTime) {
182 Args.notNull(expiryTime, "Expiry time");
183 final long currentTime = getCurrentTime();
184 final Deadline newExpiry = Deadline.calculate(currentTime, expiryTime);
185 this.expiryDeadline = newExpiry.min(this.validityDeadline);
186 this.updated = currentTime;
187 }
188
189
190
191
192 public void updateState(final Object state) {
193 this.state = state;
194 this.updated = getCurrentTime();
195 }
196
197 @Override
198 public String toString() {
199 final StringBuilder buffer = new StringBuilder();
200 buffer.append("[route:");
201 buffer.append(this.route);
202 buffer.append("][state:");
203 buffer.append(this.state);
204 buffer.append("]");
205 return buffer.toString();
206 }
207
208 }