95 InetSocketAddress proxy = req.proxy(); |
95 InetSocketAddress proxy = req.proxy(); |
96 String key = Http2Connection.keyFor(uri, proxy); |
96 String key = Http2Connection.keyFor(uri, proxy); |
97 |
97 |
98 synchronized (this) { |
98 synchronized (this) { |
99 Http2Connection connection = connections.get(key); |
99 Http2Connection connection = connections.get(key); |
100 if (connection != null) { // fast path if connection already exists |
100 if (connection != null) { |
101 return MinimalFuture.completedFuture(connection); |
101 if (connection.closed) { |
|
102 debug.log(Level.DEBUG, "removing found closed connection: %s", connection); |
|
103 connections.remove(key); |
|
104 } else { |
|
105 // fast path if connection already exists |
|
106 debug.log(Level.DEBUG, "found connection in the pool: %s", connection); |
|
107 return MinimalFuture.completedFuture(connection); |
|
108 } |
102 } |
109 } |
103 |
110 |
104 if (!req.secure() || failures.contains(key)) { |
111 if (!req.secure() || failures.contains(key)) { |
105 // secure: negotiate failed before. Use http/1.1 |
112 // secure: negotiate failed before. Use http/1.1 |
106 // !secure: no connection available in cache. Attempt upgrade |
113 // !secure: no connection available in cache. Attempt upgrade |
|
114 debug.log(Level.DEBUG, "not found in connection pool"); |
107 return MinimalFuture.completedFuture(null); |
115 return MinimalFuture.completedFuture(null); |
108 } |
116 } |
109 } |
117 } |
110 return Http2Connection |
118 return Http2Connection |
111 .createAsync(req, this) |
119 .createAsync(req, this) |
128 * complete but allow it to close itself upon completion. |
136 * complete but allow it to close itself upon completion. |
129 * This situation should not arise with https because the request |
137 * This situation should not arise with https because the request |
130 * has not been sent as part of the initial alpn negotiation |
138 * has not been sent as part of the initial alpn negotiation |
131 */ |
139 */ |
132 boolean offerConnection(Http2Connection c) { |
140 boolean offerConnection(Http2Connection c) { |
|
141 debug.log(Level.DEBUG, "offering to the connection pool: %s", c); |
|
142 if (c.closed) { |
|
143 debug.log(Level.DEBUG, "skipping offered closed connection: %s", c); |
|
144 return false; |
|
145 } |
|
146 |
133 String key = c.key(); |
147 String key = c.key(); |
134 Http2Connection c1 = connections.putIfAbsent(key, c); |
148 synchronized(this) { |
135 if (c1 != null) { |
149 Http2Connection c1 = connections.putIfAbsent(key, c); |
136 c.setSingleStream(true); |
150 if (c1 != null) { |
137 return false; |
151 c.setSingleStream(true); |
138 } |
152 debug.log(Level.DEBUG, "existing entry in connection pool for %s", key); |
139 return true; |
153 return false; |
|
154 } |
|
155 debug.log(Level.DEBUG, "put in the connection pool: %s", c); |
|
156 return true; |
|
157 } |
140 } |
158 } |
141 |
159 |
142 void deleteConnection(Http2Connection c) { |
160 void deleteConnection(Http2Connection c) { |
143 connections.remove(c.key()); |
161 debug.log(Level.DEBUG, "removing from the connection pool: %s", c); |
|
162 synchronized (this) { |
|
163 connections.remove(c.key()); |
|
164 debug.log(Level.DEBUG, "removed from the connection pool: %s", c); |
|
165 } |
144 } |
166 } |
145 |
167 |
146 void stop() { |
168 void stop() { |
147 debug.log(Level.DEBUG, "stopping"); |
169 debug.log(Level.DEBUG, "stopping"); |
148 connections.values().forEach(this::close); |
170 connections.values().forEach(this::close); |