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
129
130
131 public long getCreated() {
132 return created;
133 }
134
135 public long getUpdated() {
136 return this.updated;
137 }
138
139 public Deadline getExpiryDeadline() {
140 return this.expiryDeadline;
141 }
142
143
144
145
146 public boolean hasConnection() {
147 return this.connRef.get() != null;
148 }
149
150
151
152
153 public void assignConnection(final C conn) {
154 Args.notNull(conn, "connection");
155 if (this.connRef.compareAndSet(null, conn)) {
156 this.created = getCurrentTime();
157 this.updated = this.created;
158 this.validityDeadline = Deadline.calculate(this.created, this.timeToLive);
159 this.expiryDeadline = this.validityDeadline;
160 this.state = null;
161 } else {
162 throw new IllegalStateException("Connection already assigned");
163 }
164 }
165
166
167
168
169 public void discardConnection(final CloseMode closeMode) {
170 final C connection = this.connRef.getAndSet(null);
171 if (connection != null) {
172 this.state = null;
173 this.created = 0;
174 this.updated = 0;
175 this.expiryDeadline = Deadline.MIN_VALUE;
176 this.validityDeadline = Deadline.MIN_VALUE;
177 if (this.disposalCallback != null) {
178 this.disposalCallback.execute(connection, closeMode);
179 } else {
180 connection.close(closeMode);
181 }
182 }
183 }
184
185
186
187
188 public void updateExpiry(final TimeValue expiryTime) {
189 Args.notNull(expiryTime, "Expiry time");
190 final long currentTime = getCurrentTime();
191 final Deadline newExpiry = Deadline.calculate(currentTime, expiryTime);
192 this.expiryDeadline = newExpiry.min(this.validityDeadline);
193 this.updated = currentTime;
194 }
195
196
197
198
199 public void updateState(final Object state) {
200 this.state = state;
201 this.updated = getCurrentTime();
202 }
203
204 @Override
205 public String toString() {
206 final StringBuilder buffer = new StringBuilder();
207 buffer.append("[route:");
208 buffer.append(this.route);
209 buffer.append("][state:");
210 buffer.append(this.state);
211 buffer.append("]");
212 return buffer.toString();
213 }
214
215 }