Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java
38923 views
1
/*
2
* Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.net.www.http;
27
28
import java.io.IOException;
29
import java.io.NotSerializableException;
30
import java.util.ArrayList;
31
import java.util.HashMap;
32
import java.net.URL;
33
34
/**
35
* A class that implements a cache of idle Http connections for keep-alive
36
*
37
* @author Stephen R. Pietrowicz (NCSA)
38
* @author Dave Brown
39
*/
40
public class KeepAliveCache
41
extends HashMap<KeepAliveKey, ClientVector>
42
implements Runnable {
43
private static final long serialVersionUID = -2937172892064557949L;
44
45
/* maximum # keep-alive connections to maintain at once
46
* This should be 2 by the HTTP spec, but because we don't support pipe-lining
47
* a larger value is more appropriate. So we now set a default of 5, and the value
48
* refers to the number of idle connections per destination (in the cache) only.
49
* It can be reset by setting system property "http.maxConnections".
50
*/
51
static final int MAX_CONNECTIONS = 5;
52
static int result = -1;
53
static int getMaxConnections() {
54
if (result == -1) {
55
result = java.security.AccessController.doPrivileged(
56
new sun.security.action.GetIntegerAction("http.maxConnections",
57
MAX_CONNECTIONS))
58
.intValue();
59
if (result <= 0)
60
result = MAX_CONNECTIONS;
61
}
62
return result;
63
}
64
65
static final int LIFETIME = 5000;
66
67
private Thread keepAliveTimer = null;
68
69
/**
70
* Constructor
71
*/
72
public KeepAliveCache() {}
73
74
/**
75
* Register this URL and HttpClient (that supports keep-alive) with the cache
76
* @param url The URL contains info about the host and port
77
* @param http The HttpClient to be cached
78
*/
79
public synchronized void put(final URL url, Object obj, HttpClient http) {
80
boolean startThread = (keepAliveTimer == null);
81
if (!startThread) {
82
if (!keepAliveTimer.isAlive()) {
83
startThread = true;
84
}
85
}
86
if (startThread) {
87
clear();
88
/* Unfortunately, we can't always believe the keep-alive timeout we got
89
* back from the server. If I'm connected through a Netscape proxy
90
* to a server that sent me a keep-alive
91
* time of 15 sec, the proxy unilaterally terminates my connection
92
* The robustness to get around this is in HttpClient.parseHTTP()
93
*/
94
final KeepAliveCache cache = this;
95
java.security.AccessController.doPrivileged(
96
new java.security.PrivilegedAction<Void>() {
97
public Void run() {
98
// We want to create the Keep-Alive-Timer in the
99
// system threadgroup
100
ThreadGroup grp = Thread.currentThread().getThreadGroup();
101
ThreadGroup parent = null;
102
while ((parent = grp.getParent()) != null) {
103
grp = parent;
104
}
105
106
keepAliveTimer = new Thread(grp, cache, "Keep-Alive-Timer");
107
keepAliveTimer.setDaemon(true);
108
keepAliveTimer.setPriority(Thread.MAX_PRIORITY - 2);
109
// Set the context class loader to null in order to avoid
110
// keeping a strong reference to an application classloader.
111
keepAliveTimer.setContextClassLoader(null);
112
keepAliveTimer.start();
113
return null;
114
}
115
});
116
}
117
118
KeepAliveKey key = new KeepAliveKey(url, obj);
119
ClientVector v = super.get(key);
120
121
if (v == null) {
122
int keepAliveTimeout = http.getKeepAliveTimeout();
123
v = new ClientVector(keepAliveTimeout > 0?
124
keepAliveTimeout*1000 : LIFETIME);
125
v.put(http);
126
super.put(key, v);
127
} else {
128
v.put(http);
129
}
130
}
131
132
/* remove an obsolete HttpClient from its VectorCache */
133
public synchronized void remove (HttpClient h, Object obj) {
134
KeepAliveKey key = new KeepAliveKey(h.url, obj);
135
ClientVector v = super.get(key);
136
if (v != null) {
137
v.remove(h);
138
if (v.empty()) {
139
removeVector(key);
140
}
141
}
142
}
143
144
/* called by a clientVector thread when all its connections have timed out
145
* and that vector of connections should be removed.
146
*/
147
synchronized void removeVector(KeepAliveKey k) {
148
super.remove(k);
149
}
150
151
/**
152
* Check to see if this URL has a cached HttpClient
153
*/
154
public synchronized HttpClient get(URL url, Object obj) {
155
156
KeepAliveKey key = new KeepAliveKey(url, obj);
157
ClientVector v = super.get(key);
158
if (v == null) { // nothing in cache yet
159
return null;
160
}
161
return v.get();
162
}
163
164
/* Sleeps for an alloted timeout, then checks for timed out connections.
165
* Errs on the side of caution (leave connections idle for a relatively
166
* short time).
167
*/
168
@Override
169
public void run() {
170
do {
171
try {
172
Thread.sleep(LIFETIME);
173
} catch (InterruptedException e) {}
174
synchronized (this) {
175
/* Remove all unused HttpClients. Starting from the
176
* bottom of the stack (the least-recently used first).
177
* REMIND: It'd be nice to not remove *all* connections
178
* that aren't presently in use. One could have been added
179
* a second ago that's still perfectly valid, and we're
180
* needlessly axing it. But it's not clear how to do this
181
* cleanly, and doing it right may be more trouble than it's
182
* worth.
183
*/
184
185
long currentTime = System.currentTimeMillis();
186
187
ArrayList<KeepAliveKey> keysToRemove
188
= new ArrayList<KeepAliveKey>();
189
190
for (KeepAliveKey key : keySet()) {
191
ClientVector v = get(key);
192
synchronized (v) {
193
int i;
194
195
for (i = 0; i < v.size(); i++) {
196
KeepAliveEntry e = v.elementAt(i);
197
if ((currentTime - e.idleStartTime) > v.nap) {
198
HttpClient h = e.hc;
199
h.closeServer();
200
} else {
201
break;
202
}
203
}
204
v.subList(0, i).clear();
205
206
if (v.size() == 0) {
207
keysToRemove.add(key);
208
}
209
}
210
}
211
212
for (KeepAliveKey key : keysToRemove) {
213
removeVector(key);
214
}
215
}
216
} while (size() > 0);
217
218
return;
219
}
220
221
/*
222
* Do not serialize this class!
223
*/
224
private void writeObject(java.io.ObjectOutputStream stream)
225
throws IOException {
226
throw new NotSerializableException();
227
}
228
229
private void readObject(java.io.ObjectInputStream stream)
230
throws IOException, ClassNotFoundException {
231
throw new NotSerializableException();
232
}
233
}
234
235
/* FILO order for recycling HttpClients, should run in a thread
236
* to time them out. If > maxConns are in use, block.
237
*/
238
239
240
class ClientVector extends java.util.Stack<KeepAliveEntry> {
241
private static final long serialVersionUID = -8680532108106489459L;
242
243
// sleep time in milliseconds, before cache clear
244
int nap;
245
246
247
248
ClientVector (int nap) {
249
this.nap = nap;
250
}
251
252
synchronized HttpClient get() {
253
if (empty()) {
254
return null;
255
} else {
256
// Loop until we find a connection that has not timed out
257
HttpClient hc = null;
258
long currentTime = System.currentTimeMillis();
259
do {
260
KeepAliveEntry e = pop();
261
if ((currentTime - e.idleStartTime) > nap) {
262
e.hc.closeServer();
263
} else {
264
hc = e.hc;
265
}
266
} while ((hc== null) && (!empty()));
267
return hc;
268
}
269
}
270
271
/* return a still valid, unused HttpClient */
272
synchronized void put(HttpClient h) {
273
if (size() >= KeepAliveCache.getMaxConnections()) {
274
h.closeServer(); // otherwise the connection remains in limbo
275
} else {
276
push(new KeepAliveEntry(h, System.currentTimeMillis()));
277
}
278
}
279
280
/*
281
* Do not serialize this class!
282
*/
283
private void writeObject(java.io.ObjectOutputStream stream)
284
throws IOException {
285
throw new NotSerializableException();
286
}
287
288
private void readObject(java.io.ObjectInputStream stream)
289
throws IOException, ClassNotFoundException {
290
throw new NotSerializableException();
291
}
292
}
293
294
295
class KeepAliveKey {
296
private String protocol = null;
297
private String host = null;
298
private int port = 0;
299
private Object obj = null; // additional key, such as socketfactory
300
301
/**
302
* Constructor
303
*
304
* @param url the URL containing the protocol, host and port information
305
*/
306
public KeepAliveKey(URL url, Object obj) {
307
this.protocol = url.getProtocol();
308
this.host = url.getHost();
309
this.port = url.getPort();
310
this.obj = obj;
311
}
312
313
/**
314
* Determine whether or not two objects of this type are equal
315
*/
316
@Override
317
public boolean equals(Object obj) {
318
if ((obj instanceof KeepAliveKey) == false)
319
return false;
320
KeepAliveKey kae = (KeepAliveKey)obj;
321
return host.equals(kae.host)
322
&& (port == kae.port)
323
&& protocol.equals(kae.protocol)
324
&& this.obj == kae.obj;
325
}
326
327
/**
328
* The hashCode() for this object is the string hashCode() of
329
* concatenation of the protocol, host name and port.
330
*/
331
@Override
332
public int hashCode() {
333
String str = protocol+host+port;
334
return this.obj == null? str.hashCode() :
335
str.hashCode() + this.obj.hashCode();
336
}
337
}
338
339
class KeepAliveEntry {
340
HttpClient hc;
341
long idleStartTime;
342
343
KeepAliveEntry(HttpClient hc, long idleStartTime) {
344
this.hc = hc;
345
this.idleStartTime = idleStartTime;
346
}
347
}
348
349