blob: 779e38ac9ea94cc00522c822ab35606edf278104 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.net.www.http;
27
28import java.util.concurrent.LinkedBlockingQueue;
29import java.util.concurrent.TimeUnit;
30import java.io.IOException;
31import sun.net.NetProperties;
32import java.security.AccessController;
33import java.security.PrivilegedAction;
34
35/**
36 * This class is used to cleanup any remaining data that may be on a KeepAliveStream
37 * so that the connection can be cached in the KeepAliveCache.
38 * Instances of this class can be used as a FIFO queue for KeepAliveCleanerEntry objects.
39 * Executing this Runnable removes each KeepAliveCleanerEntry from the Queue, reads
40 * the reamining bytes on its KeepAliveStream, and if successful puts the connection in
41 * the KeepAliveCache.
42 *
43 * @author Chris Hegarty
44 */
45
46public class KeepAliveStreamCleaner extends LinkedBlockingQueue<KeepAliveCleanerEntry> implements Runnable
47{
48 // maximum amount of remaining data that we will try to cleanup
49 protected static int MAX_DATA_REMAINING = 512;
50
51 // maximum amount of KeepAliveStreams to be queued
52 protected static int MAX_CAPACITY = 10;
53
54 // timeout for both socket and poll on the queue
55 protected static final int TIMEOUT = 5000;
56
57 // max retries for skipping data
58 private static final int MAX_RETRIES = 5;
59
60 static {
61 final String maxDataKey = "http.KeepAlive.remainingData";
62 int maxData = ((Integer) AccessController.doPrivileged(
63 new PrivilegedAction() {
64 public Object run() {
65 return new Integer(NetProperties.getInteger(maxDataKey, MAX_DATA_REMAINING));
66 }})).intValue() * 1024;
67 MAX_DATA_REMAINING = maxData;
68
69 final String maxCapacityKey = "http.KeepAlive.queuedConnections";
70 int maxCapacity = ((Integer) AccessController.doPrivileged(
71 new PrivilegedAction() {
72 public Object run() {
73 return new Integer(NetProperties.getInteger(maxCapacityKey, MAX_CAPACITY));
74 }})).intValue();
75 MAX_CAPACITY = maxCapacity;
76
77 }
78
79
80 public KeepAliveStreamCleaner()
81 {
82 super(MAX_CAPACITY);
83 }
84
85 public KeepAliveStreamCleaner(int capacity)
86 {
87 super(capacity);
88 }
89
90 public void run()
91 {
92 KeepAliveCleanerEntry kace = null;
93
94 do {
95 try {
96 kace = poll((long)TIMEOUT, TimeUnit.MILLISECONDS);
97 if(kace == null)
98 break;
99
100 KeepAliveStream kas = kace.getKeepAliveStream();
101
102 if (kas != null) {
103 synchronized(kas) {
104 HttpClient hc = kace.getHttpClient();
105 try {
106 if (hc != null && !hc.isInKeepAliveCache()) {
107 int oldTimeout = hc.setTimeout(TIMEOUT);
108 long remainingToRead = kas.remainingToRead();
109 if (remainingToRead > 0) {
110 long n = 0;
111 int retries = 0;
112 while (n < remainingToRead && retries < MAX_RETRIES) {
113 remainingToRead = remainingToRead - n;
114 n = kas.skip(remainingToRead);
115 if (n == 0)
116 retries++;
117 }
118 remainingToRead = remainingToRead - n;
119 }
120 if (remainingToRead == 0) {
121 hc.setTimeout(oldTimeout);
122 hc.finished();
123 } else
124 hc.closeServer();
125 }
126 } catch (IOException ioe) {
127 hc.closeServer();
128 } finally {
129 kas.setClosed();
130 }
131 }
132 }
133 } catch (InterruptedException ie) { }
134 } while (kace != null);
135 }
136}