• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2005, 2008, 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.util.LinkedList;
30 import sun.net.NetProperties;
31 import java.security.AccessController;
32 import java.security.PrivilegedAction;
33 
34 /**
35  * This class is used to cleanup any remaining data that may be on a KeepAliveStream
36  * so that the connection can be cached in the KeepAliveCache.
37  * Instances of this class can be used as a FIFO queue for KeepAliveCleanerEntry objects.
38  * Executing this Runnable removes each KeepAliveCleanerEntry from the Queue, reads
39  * the reamining bytes on its KeepAliveStream, and if successful puts the connection in
40  * the KeepAliveCache.
41  *
42  * @author Chris Hegarty
43  */
44 
45 @SuppressWarnings("serial")  // never serialized
46 class KeepAliveStreamCleaner
47     extends LinkedList<KeepAliveCleanerEntry>
48     implements Runnable
49 {
50     // maximum amount of remaining data that we will try to cleanup
51     protected static int MAX_DATA_REMAINING = 512;
52 
53     // maximum amount of KeepAliveStreams to be queued
54     protected static int MAX_CAPACITY = 10;
55 
56     // timeout for both socket and poll on the queue
57     protected static final int TIMEOUT = 5000;
58 
59     // max retries for skipping data
60     private static final int MAX_RETRIES = 5;
61 
62     static {
63         final String maxDataKey = "http.KeepAlive.remainingData";
64         int maxData = AccessController.doPrivileged(
65             new PrivilegedAction<Integer>() {
66                 public Integer run() {
67                     return NetProperties.getInteger(maxDataKey, MAX_DATA_REMAINING);
68                 }}).intValue() * 1024;
69         MAX_DATA_REMAINING = maxData;
70 
71         final String maxCapacityKey = "http.KeepAlive.queuedConnections";
72         int maxCapacity = AccessController.doPrivileged(
73             new PrivilegedAction<Integer>() {
74                 public Integer run() {
75                     return NetProperties.getInteger(maxCapacityKey, MAX_CAPACITY);
76                 }}).intValue();
77         MAX_CAPACITY = maxCapacity;
78 
79     }
80 
81 
82     @Override
offer(KeepAliveCleanerEntry e)83     public boolean offer(KeepAliveCleanerEntry e) {
84         if (size() >= MAX_CAPACITY)
85             return false;
86 
87         return super.offer(e);
88     }
89 
90     @Override
run()91     public void run()
92     {
93         KeepAliveCleanerEntry kace = null;
94 
95         do {
96             try {
97                 synchronized(this) {
98                     long before = System.currentTimeMillis();
99                     long timeout = TIMEOUT;
100                     while ((kace = poll()) == null) {
101                         this.wait(timeout);
102 
103                         long after = System.currentTimeMillis();
104                         long elapsed = after - before;
105                         if (elapsed > timeout) {
106                             /* one last try */
107                             kace = poll();
108                             break;
109                         }
110                         before = after;
111                         timeout -= elapsed;
112                     }
113                 }
114 
115                 if(kace == null)
116                     break;
117 
118                 KeepAliveStream kas = kace.getKeepAliveStream();
119 
120                 if (kas != null) {
121                     synchronized(kas) {
122                         HttpClient hc = kace.getHttpClient();
123                         try {
124                             if (hc != null && !hc.isInKeepAliveCache()) {
125                                 int oldTimeout = hc.getReadTimeout();
126                                 hc.setReadTimeout(TIMEOUT);
127                                 long remainingToRead = kas.remainingToRead();
128                                 if (remainingToRead > 0) {
129                                     long n = 0;
130                                     int retries = 0;
131                                     while (n < remainingToRead && retries < MAX_RETRIES) {
132                                         remainingToRead = remainingToRead - n;
133                                         n = kas.skip(remainingToRead);
134                                         if (n == 0)
135                                             retries++;
136                                     }
137                                     remainingToRead = remainingToRead - n;
138                                 }
139                                 if (remainingToRead == 0) {
140                                     hc.setReadTimeout(oldTimeout);
141                                     hc.finished();
142                                 } else
143                                     hc.closeServer();
144                             }
145                         } catch (IOException ioe) {
146                             hc.closeServer();
147                         } finally {
148                             kas.setClosed();
149                         }
150                     }
151                 }
152             } catch (InterruptedException ie) { }
153         } while (kace != null);
154     }
155 }
156