|
21 | 21 | import com.ning.http.util.AsyncHttpProviderUtils;
|
22 | 22 | import com.ning.http.util.ProxyUtils;
|
23 | 23 | import java.io.IOException;
|
24 |
| -import java.util.HashSet; |
25 |
| -import java.util.Set; |
26 | 24 | import org.glassfish.grizzly.CloseListener;
|
27 | 25 | import org.glassfish.grizzly.CloseType;
|
28 | 26 | import org.glassfish.grizzly.Closeable;
|
@@ -86,8 +84,8 @@ public final class HttpTransactionContext {
|
86 | 84 | /**
|
87 | 85 | * <tt>true</tt> if the request is fully sent, or <tt>false</tt>otherwise.
|
88 | 86 | */
|
89 |
| - volatile boolean isRequestFullySent; |
90 |
| - Set<CompletionHandler<HttpTransactionContext>> reqFullySentHandlers; |
| 87 | + private boolean isRequestFullySent; |
| 88 | + private CleanupTask cleanupTask; |
91 | 89 |
|
92 | 90 | private final CloseListener listener = new CloseListener<Closeable, CloseType>() {
|
93 | 91 | @Override
|
@@ -125,24 +123,9 @@ static void cleanupTransaction(final HttpContext httpCtx,
|
125 | 123 |
|
126 | 124 | assert httpTxContext != null;
|
127 | 125 |
|
128 |
| - if (httpTxContext.isRequestFullySent) { |
129 |
| - cleanupTransaction(httpCtx, httpTxContext); |
130 |
| - completionHandler.completed(httpTxContext); |
131 |
| - } else { |
132 |
| - httpTxContext.addRequestSentCompletionHandler(completionHandler); |
133 |
| - if (httpTxContext.isRequestFullySent && |
134 |
| - httpTxContext.removeRequestSentCompletionHandler(completionHandler)) { |
135 |
| - completionHandler.completed(httpTxContext); |
136 |
| - } |
137 |
| - } |
| 126 | + httpTxContext.scheduleCleanup(httpCtx, completionHandler); |
138 | 127 | }
|
139 | 128 |
|
140 |
| - static void cleanupTransaction(final HttpContext httpCtx, |
141 |
| - final HttpTransactionContext httpTxContext) { |
142 |
| - httpCtx.getCloseable().removeCloseListener(httpTxContext.listener); |
143 |
| - REQUEST_STATE_ATTR.remove(httpCtx); |
144 |
| - } |
145 |
| - |
146 | 129 | static HttpTransactionContext currentTransaction(
|
147 | 130 | final HttpHeader httpHeader) {
|
148 | 131 | return currentTransaction(httpHeader.getProcessingState().getHttpContext());
|
@@ -269,44 +252,56 @@ void closeConnection() {
|
269 | 252 | connection.closeSilently();
|
270 | 253 | }
|
271 | 254 |
|
272 |
| - private synchronized void addRequestSentCompletionHandler( |
| 255 | + private void scheduleCleanup(final HttpContext httpCtx, |
273 | 256 | final CompletionHandler<HttpTransactionContext> completionHandler) {
|
274 |
| - if (reqFullySentHandlers == null) { |
275 |
| - reqFullySentHandlers = new HashSet<>(); |
| 257 | + synchronized (this) { |
| 258 | + if (!isRequestFullySent) { |
| 259 | + assert cleanupTask == null; // scheduleCleanup should be called only once |
| 260 | + cleanupTask = new CleanupTask(httpCtx, completionHandler); |
| 261 | + return; |
| 262 | + } |
276 | 263 | }
|
277 |
| - reqFullySentHandlers.add(completionHandler); |
278 |
| - } |
279 | 264 |
|
280 |
| - private synchronized boolean removeRequestSentCompletionHandler( |
281 |
| - final CompletionHandler<HttpTransactionContext> completionHandler) { |
282 |
| - return reqFullySentHandlers != null |
283 |
| - ? reqFullySentHandlers.remove(completionHandler) |
284 |
| - : false; |
| 265 | + assert isRequestFullySent; |
| 266 | + cleanup(httpCtx); |
| 267 | + completionHandler.completed(this); |
285 | 268 | }
|
286 | 269 |
|
287 |
| - boolean isRequestFullySent() { |
288 |
| - return isRequestFullySent; |
| 270 | + private void cleanup(final HttpContext httpCtx) { |
| 271 | + httpCtx.getCloseable().removeCloseListener(listener); |
| 272 | + REQUEST_STATE_ATTR.remove(httpCtx); |
289 | 273 | }
|
290 | 274 |
|
291 | 275 | @SuppressWarnings("unchecked")
|
292 | 276 | void onRequestFullySent() {
|
293 |
| - this.isRequestFullySent = true; |
294 |
| - |
295 |
| - Object[] handlers = null; |
296 | 277 | synchronized (this) {
|
297 |
| - if (reqFullySentHandlers != null) { |
298 |
| - handlers = reqFullySentHandlers.toArray(); |
299 |
| - reqFullySentHandlers = null; |
| 278 | + if (isRequestFullySent) { |
| 279 | + return; |
300 | 280 | }
|
| 281 | + |
| 282 | + isRequestFullySent = true; |
301 | 283 | }
|
302 | 284 |
|
303 |
| - if (handlers != null) { |
304 |
| - for (Object o : handlers) { |
305 |
| - try { |
306 |
| - ((CompletionHandler<HttpTransactionContext>) o).completed(this); |
307 |
| - } catch (Exception e) { |
308 |
| - } |
309 |
| - } |
| 285 | + if (cleanupTask != null) { |
| 286 | + cleanupTask.run(); |
| 287 | + } |
| 288 | + } |
| 289 | + |
| 290 | + private class CleanupTask implements Runnable { |
| 291 | + private final HttpContext httpCtx; |
| 292 | + private final CompletionHandler<HttpTransactionContext> completionHandler; |
| 293 | + |
| 294 | + private CleanupTask(final HttpContext httpCtx, |
| 295 | + final CompletionHandler<HttpTransactionContext> completionHandler) { |
| 296 | + this.httpCtx = httpCtx; |
| 297 | + this.completionHandler = completionHandler; |
| 298 | + } |
| 299 | + |
| 300 | + @Override |
| 301 | + public void run() { |
| 302 | + cleanup(httpCtx); |
| 303 | + completionHandler.completed(HttpTransactionContext.this); |
310 | 304 | }
|
| 305 | + |
311 | 306 | }
|
312 | 307 | } // END HttpTransactionContext
|
0 commit comments