History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/net/www/http/KeepAliveStream.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/net/www/http/KeepAliveStream.java+237−0
@@ -0,0 +1,237 @@
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.*;
29+import sun.net.ProgressSource;
30+import sun.net.www.MeteredStream;
31+
32+/**
33+ * A stream that has the property of being able to be kept alive for
34+ * multiple downloads from the same server.
35+ *
36+ * @author Stephen R. Pietrowicz (NCSA)
37+ * @author Dave Brown
38+ */
39+public
40+class KeepAliveStream extends MeteredStream implements Hurryable {
41+
42+ // instance variables
43+ HttpClient hc;
44+
45+ boolean hurried;
46+
47+ // has this KeepAliveStream been put on the queue for asynchronous cleanup.
48+ protected boolean queuedForCleanup = false;
49+
50+ private static final KeepAliveStreamCleaner queue = new KeepAliveStreamCleaner();
51+ private static Thread cleanerThread; // null
52+
53+ /**
54+ * Constructor
55+ */
56+ public KeepAliveStream(InputStream is, ProgressSource pi, long expected, HttpClient hc) {
57+ super(is, pi, expected);
58+ this.hc = hc;
59+ }
60+
61+ /**
62+ * Attempt to cache this connection
63+ */
64+ public void close() throws IOException {
65+ // If the inputstream is closed already, just return.
66+ if (closed) {
67+ return;
68+ }
69+
70+ // If this stream has already been queued for cleanup.
71+ if (queuedForCleanup) {
72+ return;
73+ }
74+
75+ // Skip past the data that's left in the Inputstream because
76+ // some sort of error may have occurred.
77+ // Do this ONLY if the skip won't block. The stream may have
78+ // been closed at the beginning of a big file and we don't want
79+ // to hang around for nothing. So if we can't skip without blocking
80+ // we just close the socket and, therefore, terminate the keepAlive
81+ // NOTE: Don't close super class
82+ try {
83+ if (expected > count) {
84+ long nskip = (long) (expected - count);
85+ if (nskip <= available()) {
86+ long n = 0;
87+ while (n < nskip) {
88+ nskip = nskip - n;
89+ n = skip(nskip);
90+ }
91+ } else if (expected <= KeepAliveStreamCleaner.MAX_DATA_REMAINING && !hurried) {
92+ //put this KeepAliveStream on the queue so that the data remaining
93+ //on the socket can be cleanup asyncronously.
94+ queueForCleanup(new KeepAliveCleanerEntry(this, hc));
95+ } else {
96+ hc.closeServer();
97+ }
98+ }
99+ if (!closed && !hurried && !queuedForCleanup) {
100+ hc.finished();
101+ }
102+ } finally {
103+ if (pi != null)
104+ pi.finishTracking();
105+
106+ if (!queuedForCleanup) {
107+ // nulling out the underlying inputstream as well as
108+ // httpClient to let gc collect the memories faster
109+ in = null;
110+ hc = null;
111+ closed = true;
112+ }
113+ }
114+ }
115+
116+ /* we explicitly do not support mark/reset */
117+
118+ public boolean markSupported() {
119+ return false;
120+ }
121+
122+ public void mark(int limit) {}
123+
124+ public void reset() throws IOException {
125+ throw new IOException("mark/reset not supported");
126+ }
127+
128+ public synchronized boolean hurry() {
129+ try {
130+ /* CASE 0: we're actually already done */
131+ if (closed || count >= expected) {
132+ return false;
133+ } else if (in.available() < (expected - count)) {
134+ /* CASE I: can't meet the demand */
135+ return false;
136+ } else {
137+ /* CASE II: fill our internal buffer
138+ * Remind: possibly check memory here
139+ */
140+ int size = (int) (expected - count);
141+ byte[] buf = new byte[size];
142+ DataInputStream dis = new DataInputStream(in);
143+ dis.readFully(buf);
144+ in = new ByteArrayInputStream(buf);
145+ hurried = true;
146+ return true;
147+ }
148+ } catch (IOException e) {
149+ // e.printStackTrace();
150+ return false;
151+ }
152+ }
153+
154+ private static void queueForCleanup(KeepAliveCleanerEntry kace) {
155+ synchronized(queue) {
156+ if(!kace.getQueuedForCleanup()) {
157+ if (!queue.offer(kace)) {
158+ kace.getHttpClient().closeServer();
159+ return;
160+ }
161+
162+ kace.setQueuedForCleanup();
163+ queue.notifyAll();
164+ }
165+
166+ boolean startCleanupThread = (cleanerThread == null);
167+ if (!startCleanupThread) {
168+ if (!cleanerThread.isAlive()) {
169+ startCleanupThread = true;
170+ }
171+ }
172+
173+ if (startCleanupThread) {
174+ java.security.AccessController.doPrivileged(
175+ new java.security.PrivilegedAction<Void>() {
176+ public Void run() {
177+ // We want to create the Keep-Alive-SocketCleaner in the
178+ // system threadgroup
179+ ThreadGroup grp = Thread.currentThread().getThreadGroup();
180+ ThreadGroup parent = null;
181+ while ((parent = grp.getParent()) != null) {
182+ grp = parent;
183+ }
184+
185+ cleanerThread = new Thread(grp, queue, "Keep-Alive-SocketCleaner");
186+ cleanerThread.setDaemon(true);
187+ cleanerThread.setPriority(Thread.MAX_PRIORITY - 2);
188+ // Set the context class loader to null in order to avoid
189+ // keeping a strong reference to an application classloader.
190+ cleanerThread.setContextClassLoader(null);
191+ cleanerThread.start();
192+ return null;
193+ }
194+ });
195+ }
196+ } // queue
197+ }
198+
199+ protected long remainingToRead() {
200+ return expected - count;
201+ }
202+
203+ protected void setClosed() {
204+ in = null;
205+ hc = null;
206+ closed = true;
207+ }
208+}
209+
210+
211+class KeepAliveCleanerEntry
212+{
213+ KeepAliveStream kas;
214+ HttpClient hc;
215+
216+ public KeepAliveCleanerEntry(KeepAliveStream kas, HttpClient hc) {
217+ this.kas = kas;
218+ this.hc = hc;
219+ }
220+
221+ protected KeepAliveStream getKeepAliveStream() {
222+ return kas;
223+ }
224+
225+ protected HttpClient getHttpClient() {
226+ return hc;
227+ }
228+
229+ protected void setQueuedForCleanup() {
230+ kas.queuedForCleanup = true;
231+ }
232+
233+ protected boolean getQueuedForCleanup() {
234+ return kas.queuedForCleanup;
235+ }
236+
237+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t