You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2014/01/27 15:15:06 UTC
svn commit: r1561685 - in
/httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src:
main/java/org/apache/http/impl/client/cache/
test/java/org/apache/http/impl/client/cache/
Author: olegk
Date: Mon Jan 27 14:15:06 2014
New Revision: 1561685
URL: http://svn.apache.org/r1561685
Log:
HTTPASYNC-64: race conditions in async caching module
Added:
httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/ChainedFutureCallback.java (with props)
Removed:
httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/FutureHttpResponse.java
Modified:
httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousAsyncValidationRequest.java
httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpAsyncClient.java
httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/test/java/org/apache/http/impl/client/cache/CachingHttpAsyncClientExecChain.java
Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousAsyncValidationRequest.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousAsyncValidationRequest.java?rev=1561685&r1=1561684&r2=1561685&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousAsyncValidationRequest.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousAsyncValidationRequest.java Mon Jan 27 14:15:06 2014
@@ -26,7 +26,7 @@
*/
package org.apache.http.impl.client.cache;
-import java.io.IOException;
+import java.util.concurrent.ExecutionException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -35,6 +35,7 @@ import org.apache.http.HttpResponse;
import org.apache.http.ProtocolException;
import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.methods.HttpRequestWrapper;
+import org.apache.http.concurrent.BasicFuture;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.protocol.HttpContext;
@@ -71,25 +72,28 @@ class AsynchronousAsyncValidationRequest
public void run() {
try {
- this.cachingAsyncClient.revalidateCacheEntry(this.target, this.request, this.context,
- this.cacheEntry, new FutureCallback<HttpResponse>() {
+ final FutureCallback<HttpResponse> callback = new FutureCallback<HttpResponse>() {
- public void cancelled() {
- }
+ public void cancelled() {
+ }
- public void completed(final HttpResponse httpResponse) {
- }
+ public void completed(final HttpResponse httpResponse) {
+ }
- public void failed(final Exception e) {
- if (e instanceof IOException) {
- AsynchronousAsyncValidationRequest.this.log
- .debug("Asynchronous revalidation failed due to exception: "
- + e);
- }
- }
- });
+ public void failed(final Exception e) {
+ log.debug("Asynchronous revalidation failed", e);
+ }
+ };
+ final BasicFuture<HttpResponse> future = new BasicFuture<HttpResponse>(callback);
+ this.cachingAsyncClient.revalidateCacheEntry(future, this.target, this.request, this.context,
+ this.cacheEntry);
+ future.get();
} catch (final ProtocolException pe) {
- this.log.error("ProtocolException thrown during asynchronous revalidation: " + pe);
+ this.log.error("ProtocolException thrown during asynchronous revalidation", pe);
+ } catch (ExecutionException e) {
+ this.log.error("Exception thrown during asynchronous revalidation", e.getCause());
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
} finally {
this.parent.markComplete(this.identifier);
}
Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpAsyncClient.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpAsyncClient.java?rev=1561685&r1=1561684&r2=1561685&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpAsyncClient.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpAsyncClient.java Mon Jan 27 14:15:06 2014
@@ -279,6 +279,7 @@ public class CachingHttpAsyncClient impl
final HttpRequest originalRequest,
final HttpContext context,
final FutureCallback<HttpResponse> futureCallback) {
+ final BasicFuture<HttpResponse> future = new BasicFuture<HttpResponse>(futureCallback);
final HttpRequestWrapper request = HttpRequestWrapper.wrap(originalRequest);
// default response context
setResponseStatus(context, CacheResponseStatus.CACHE_MISS);
@@ -287,7 +288,6 @@ public class CachingHttpAsyncClient impl
if (clientRequestsOurOptions(request)) {
setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE);
- final BasicFuture<HttpResponse> future = new BasicFuture<HttpResponse>(futureCallback);
future.completed(new OptionsHttp11Response());
return future;
}
@@ -295,7 +295,6 @@ public class CachingHttpAsyncClient impl
final HttpResponse fatalErrorResponse = getFatallyNoncompliantResponse(
request, context);
if (fatalErrorResponse != null) {
- final BasicFuture<HttpResponse> future = new BasicFuture<HttpResponse>(futureCallback);
future.completed(fatalErrorResponse);
return future;
}
@@ -303,7 +302,6 @@ public class CachingHttpAsyncClient impl
try {
this.requestCompliance.makeRequestCompliant(request);
} catch (final ClientProtocolException e) {
- final BasicFuture<HttpResponse> future = new BasicFuture<HttpResponse>(futureCallback);
future.failed(e);
return future;
}
@@ -313,32 +311,30 @@ public class CachingHttpAsyncClient impl
if (!this.cacheableRequestPolicy.isServableFromCache(request)) {
log.debug("Request is not servable from cache");
- return callBackend(target, request, context, futureCallback);
+ callBackend(future, target, request, context);
+ return future;
}
final HttpCacheEntry entry = satisfyFromCache(target, request);
if (entry == null) {
log.debug("Cache miss");
- return handleCacheMiss(target, request, context, futureCallback);
- }
-
- try {
- return handleCacheHit(target, request, context, entry, futureCallback);
- } catch (final ClientProtocolException e) {
- final BasicFuture<HttpResponse> future = new BasicFuture<HttpResponse>(futureCallback);
- future.failed(e);
- return future;
- } catch (final IOException e) {
- final BasicFuture<HttpResponse> future = new BasicFuture<HttpResponse>(futureCallback);
- future.failed(e);
- return future;
+ handleCacheMiss(future, target, request, context);
+ } else {
+ try {
+ handleCacheHit(future, target, request, context, entry);
+ } catch (final IOException e) {
+ future.failed(e);
+ }
}
+ return future;
}
- private Future<HttpResponse> handleCacheHit(final HttpHost target, final HttpRequestWrapper request,
- final HttpContext context, final HttpCacheEntry entry,
- final FutureCallback<HttpResponse> futureCallback)
- throws ClientProtocolException, IOException {
+ private void handleCacheHit(
+ final BasicFuture<HttpResponse> future,
+ final HttpHost target,
+ final HttpRequestWrapper request,
+ final HttpContext context,
+ final HttpCacheEntry entry) throws IOException {
recordCacheHit(target, request);
final HttpResponse out;
final Date now = getCurrentDate();
@@ -352,24 +348,28 @@ public class CachingHttpAsyncClient impl
&& !(entry.getStatusCode() == HttpStatus.SC_NOT_MODIFIED
&& !suitabilityChecker.isConditional(request))) {
log.debug("Revalidating cache entry");
- return revalidateCacheEntry(target, request, context, entry, now, futureCallback);
+ revalidateCacheEntry(future, target, request, context, entry, now);
+ return;
} else {
log.debug("Cache entry not usable; calling backend");
- return callBackend(target, request, context, futureCallback);
+ callBackend(future, target, request, context);
+ return;
}
context.setAttribute(HttpClientContext.HTTP_ROUTE, new HttpRoute(target));
context.setAttribute(HttpClientContext.HTTP_TARGET_HOST, target);
context.setAttribute(HttpClientContext.HTTP_REQUEST, request);
context.setAttribute(HttpClientContext.HTTP_RESPONSE, out);
context.setAttribute(HttpClientContext.HTTP_REQ_SENT, Boolean.TRUE);
- final BasicFuture<HttpResponse> future = new BasicFuture<HttpResponse>(futureCallback);
future.completed(out);
- return future;
}
- private Future<HttpResponse> revalidateCacheEntry(final HttpHost target,
- final HttpRequestWrapper request, final HttpContext context, final HttpCacheEntry entry,
- final Date now, final FutureCallback<HttpResponse> futureCallback) throws ClientProtocolException {
+ private void revalidateCacheEntry(
+ final BasicFuture<HttpResponse> future,
+ final HttpHost target,
+ final HttpRequestWrapper request,
+ final HttpContext context,
+ final HttpCacheEntry entry,
+ final Date now) throws ClientProtocolException {
try {
if (this.asynchAsyncRevalidator != null
@@ -381,11 +381,13 @@ public class CachingHttpAsyncClient impl
this.asynchAsyncRevalidator.revalidateCacheEntry(target, request, context, entry);
- final BasicFuture<HttpResponse> future = new BasicFuture<HttpResponse>(futureCallback);
future.completed(resp);
- return future;
+ return;
}
- final FutureHttpResponse future = new FutureHttpResponse(futureCallback) {
+
+ final ChainedFutureCallback<HttpResponse> chainedFutureCallback = new ChainedFutureCallback<HttpResponse>(future) {
+
+ @Override
public void failed(final Exception ex) {
if(ex instanceof IOException) {
super.completed(handleRevalidationFailure(request, context, entry, now));
@@ -393,34 +395,40 @@ public class CachingHttpAsyncClient impl
super.failed(ex);
}
}
+
};
- future.setDelegate(revalidateCacheEntry(target, request, context, entry, future));
- return future;
+
+ final BasicFuture<HttpResponse> compositeFuture = new BasicFuture<HttpResponse>(chainedFutureCallback);
+ revalidateCacheEntry(compositeFuture, target, request, context, entry);
} catch (final ProtocolException e) {
throw new ClientProtocolException(e);
}
}
- private Future<HttpResponse> handleCacheMiss(final HttpHost target, final HttpRequestWrapper request,
- final HttpContext context, final FutureCallback<HttpResponse> futureCallback) {
+ private void handleCacheMiss(
+ final BasicFuture<HttpResponse> future,
+ final HttpHost target,
+ final HttpRequestWrapper request,
+ final HttpContext context) {
recordCacheMiss(target, request);
if (!mayCallBackend(request)) {
- final BasicFuture<HttpResponse> future = new BasicFuture<HttpResponse>(futureCallback);
future.completed(new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"));
- return future;
+ return;
}
- final Map<String, Variant> variants =
- getExistingCacheVariants(target, request);
+ final Map<String, Variant> variants = getExistingCacheVariants(target, request);
if (variants != null && variants.size() > 0) {
- return negotiateResponseFromVariants(target, request, context, variants, futureCallback);
+ negotiateResponseFromVariants(future, target, request, context, variants);
+ return;
}
- return callBackend(target, request, context, futureCallback);
+ callBackend(future, target, request, context);
}
- private HttpCacheEntry satisfyFromCache(final HttpHost target, final HttpRequest request) {
+ private HttpCacheEntry satisfyFromCache(
+ final HttpHost target,
+ final HttpRequest request) {
HttpCacheEntry entry = null;
try {
entry = this.responseCache.getCacheEntry(target, request);
@@ -430,7 +438,8 @@ public class CachingHttpAsyncClient impl
return entry;
}
- private HttpResponse getFatallyNoncompliantResponse(final HttpRequest request,
+ private HttpResponse getFatallyNoncompliantResponse(
+ final HttpRequest request,
final HttpContext context) {
HttpResponse fatalErrorResponse = null;
final List<RequestProtocolError> fatalError = this.requestCompliance.requestIsFatallyNonCompliant(request);
@@ -442,7 +451,8 @@ public class CachingHttpAsyncClient impl
return fatalErrorResponse;
}
- private Map<String, Variant> getExistingCacheVariants(final HttpHost target,
+ private Map<String, Variant> getExistingCacheVariants(
+ final HttpHost target,
final HttpRequest request) {
Map<String,Variant> variants = null;
try {
@@ -483,8 +493,11 @@ public class CachingHttpAsyncClient impl
}
}
- private HttpResponse generateCachedResponse(final HttpRequest request,
- final HttpContext context, final HttpCacheEntry entry, final Date now) {
+ private HttpResponse generateCachedResponse(
+ final HttpRequest request,
+ final HttpContext context,
+ final HttpCacheEntry entry,
+ final Date now) {
final HttpResponse cachedResponse;
if (request.containsHeader(HeaderConstants.IF_NONE_MATCH)
|| request.containsHeader(HeaderConstants.IF_MODIFIED_SINCE)) {
@@ -499,8 +512,11 @@ public class CachingHttpAsyncClient impl
return cachedResponse;
}
- private HttpResponse handleRevalidationFailure(final HttpRequest request,
- final HttpContext context, final HttpCacheEntry entry, final Date now) {
+ private HttpResponse handleRevalidationFailure(
+ final HttpRequest request,
+ final HttpContext context,
+ final HttpCacheEntry entry,
+ final Date now) {
if (staleResponseNotAllowed(request, entry, now)) {
return generateGatewayTimeout(context);
}
@@ -513,7 +529,8 @@ public class CachingHttpAsyncClient impl
HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout");
}
- private HttpResponse unvalidatedCacheHit(final HttpContext context,
+ private HttpResponse unvalidatedCacheHit(
+ final HttpContext context,
final HttpCacheEntry entry) {
final HttpResponse cachedResponse = this.responseGenerator.generateResponse(entry);
setResponseStatus(context, CacheResponseStatus.CACHE_HIT);
@@ -521,8 +538,10 @@ public class CachingHttpAsyncClient impl
return cachedResponse;
}
- private boolean staleResponseNotAllowed(final HttpRequest request,
- final HttpCacheEntry entry, final Date now) {
+ private boolean staleResponseNotAllowed(
+ final HttpRequest request,
+ final HttpCacheEntry entry,
+ final Date now) {
return this.validityPolicy.mustRevalidate(entry)
|| (isSharedCache() && this.validityPolicy.proxyRevalidate(entry))
|| explicitFreshnessRequest(request, entry, now);
@@ -540,7 +559,10 @@ public class CachingHttpAsyncClient impl
return true;
}
- private boolean explicitFreshnessRequest(final HttpRequest request, final HttpCacheEntry entry, final Date now) {
+ private boolean explicitFreshnessRequest(
+ final HttpRequest request,
+ final HttpCacheEntry entry,
+ final Date now) {
for(final Header h : request.getHeaders(HeaderConstants.CACHE_CONTROL)) {
for(final HeaderElement elt : h.getElements()) {
if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
@@ -631,12 +653,17 @@ public class CachingHttpAsyncClient impl
return "0".equals(request.getFirstHeader(HeaderConstants.MAX_FORWARDS).getValue());
}
- Future<HttpResponse> callBackend(
- final HttpHost target, final HttpRequestWrapper request, final HttpContext context,
- final FutureCallback<HttpResponse> futureCallback) {
+ void callBackend(
+ final BasicFuture<HttpResponse> future,
+ final HttpHost target,
+ final HttpRequestWrapper request,
+ final HttpContext context) {
final Date requestDate = getCurrentDate();
this.log.trace("Calling the backend");
- final FutureHttpResponse future = new FutureHttpResponse(futureCallback) {
+
+ final ChainedFutureCallback<HttpResponse> chainedFutureCallback = new ChainedFutureCallback<HttpResponse>(future) {
+
+ @Override
public void completed(final HttpResponse httpResponse) {
httpResponse.addHeader(HeaderConstants.VIA, generateViaHeader(httpResponse));
try {
@@ -647,12 +674,13 @@ public class CachingHttpAsyncClient impl
}
}
+
};
- future.setDelegate(this.backend.execute(target, request, context, future));
- return future;
+ this.backend.execute(target, request, context, chainedFutureCallback);
}
- private boolean revalidationResponseIsTooOld(final HttpResponse backendResponse,
+ private boolean revalidationResponseIsTooOld(
+ final HttpResponse backendResponse,
final HttpCacheEntry cacheEntry) {
final Header entryDateHeader = cacheEntry.getFirstHeader(HTTP.DATE_HEADER);
final Header responseDateHeader = backendResponse.getFirstHeader(HTTP.DATE_HEADER);
@@ -666,20 +694,19 @@ public class CachingHttpAsyncClient impl
return false;
}
- Future<HttpResponse> negotiateResponseFromVariants(final HttpHost target,
- final HttpRequestWrapper request, final HttpContext context,
- final Map<String, Variant> variants,
- final FutureCallback<HttpResponse> futureCallback) {
+ void negotiateResponseFromVariants(
+ final BasicFuture<HttpResponse> future,
+ final HttpHost target,
+ final HttpRequestWrapper request,
+ final HttpContext context,
+ final Map<String, Variant> variants) {
final HttpRequest conditionalRequest = this.conditionalRequestBuilder.buildConditionalRequestFromVariants(request, variants);
final Date requestDate = getCurrentDate();
- final FutureHttpResponse future = new FutureHttpResponse(futureCallback);
- final Future<HttpResponse> backendFuture = this.backend.execute(target, conditionalRequest, context, new FutureCallback<HttpResponse> () {
- public void cancelled() {
- future.cancelled();
- }
+ final ChainedFutureCallback<HttpResponse> chainedFutureCallback = new ChainedFutureCallback<HttpResponse>(future) {
+ @Override
public void completed(final HttpResponse httpResponse) {
final Date responseDate = getCurrentDate();
@@ -698,7 +725,7 @@ public class CachingHttpAsyncClient impl
final Header resultEtagHeader = httpResponse.getFirstHeader(HeaderConstants.ETAG);
if (resultEtagHeader == null) {
CachingHttpAsyncClient.this.log.warn("304 response did not contain ETag");
- callBackend(target, request, context, future);
+ callBackend(future, target, request, context);
return;
}
@@ -706,14 +733,14 @@ public class CachingHttpAsyncClient impl
final Variant matchingVariant = variants.get(resultEtag);
if (matchingVariant == null) {
CachingHttpAsyncClient.this.log.debug("304 response did not contain ETag matching one sent in If-None-Match");
- callBackend(target, request, context, future);
+ callBackend(future, target, request, context);
}
final HttpCacheEntry matchedEntry = matchingVariant.getEntry();
if (revalidationResponseIsTooOld(httpResponse, matchedEntry)) {
EntityUtils.consumeQuietly(httpResponse.getEntity());
- retryRequestUnconditionally(target, request, context, matchedEntry, future);
+ retryRequestUnconditionally(future, target, request, context, matchedEntry);
return;
}
@@ -734,26 +761,30 @@ public class CachingHttpAsyncClient impl
future.completed(resp);
}
- public void failed(final Exception ex) {
- future.failed(ex);
- }
- });
- future.setDelegate(backendFuture);
- return future;
+ };
+
+ this.backend.execute(target, conditionalRequest, context, chainedFutureCallback);
}
- private void retryRequestUnconditionally(final HttpHost target,
- final HttpRequestWrapper request, final HttpContext context,
- final HttpCacheEntry matchedEntry, final FutureCallback<HttpResponse> futureCallback) {
+ private void retryRequestUnconditionally(
+ final BasicFuture<HttpResponse> future,
+ final HttpHost target,
+ final HttpRequestWrapper request,
+ final HttpContext context,
+ final HttpCacheEntry matchedEntry) {
final HttpRequestWrapper unconditional = this.conditionalRequestBuilder
.buildUnconditionalRequest(request, matchedEntry);
- callBackend(target, unconditional, context, futureCallback);
+ callBackend(future, target, unconditional, context);
}
- private HttpCacheEntry getUpdatedVariantEntry(final HttpHost target,
- final HttpRequest conditionalRequest, final Date requestDate,
- final Date responseDate, final HttpResponse backendResponse,
- final Variant matchingVariant, final HttpCacheEntry matchedEntry) {
+ private HttpCacheEntry getUpdatedVariantEntry(
+ final HttpHost target,
+ final HttpRequest conditionalRequest,
+ final Date requestDate,
+ final Date responseDate,
+ final HttpResponse backendResponse,
+ final Variant matchingVariant,
+ final HttpCacheEntry matchedEntry) {
HttpCacheEntry responseEntry = matchedEntry;
try {
responseEntry = this.responseCache.updateVariantCacheEntry(target, conditionalRequest,
@@ -764,7 +795,9 @@ public class CachingHttpAsyncClient impl
return responseEntry;
}
- private void tryToUpdateVariantMap(final HttpHost target, final HttpRequest request,
+ private void tryToUpdateVariantMap(
+ final HttpHost target,
+ final HttpRequest request,
final Variant matchingVariant) {
try {
this.responseCache.reuseVariantEntryFor(target, request, matchingVariant);
@@ -773,75 +806,65 @@ public class CachingHttpAsyncClient impl
}
}
- private boolean shouldSendNotModifiedResponse(final HttpRequest request,
+ private boolean shouldSendNotModifiedResponse(
+ final HttpRequest request,
final HttpCacheEntry responseEntry) {
return (this.suitabilityChecker.isConditional(request)
&& this.suitabilityChecker.allConditionalsMatch(request, responseEntry, new Date()));
}
- Future<HttpResponse> revalidateCacheEntry(
+ void revalidateCacheEntry(
+ final BasicFuture<HttpResponse> future,
final HttpHost target,
final HttpRequestWrapper request,
final HttpContext context,
- final HttpCacheEntry cacheEntry,
- final FutureCallback<HttpResponse> futureCallback) throws ProtocolException {
+ final HttpCacheEntry cacheEntry) throws ProtocolException {
final HttpRequestWrapper conditionalRequest = this.conditionalRequestBuilder.buildConditionalRequest(request, cacheEntry);
final Date requestDate = getCurrentDate();
- final FutureHttpResponse future = new FutureHttpResponse(futureCallback);
- future.setDelegate(this.backend.execute(target, conditionalRequest, context, new FutureCallback<HttpResponse>() {
- public void cancelled() {
- future.cancelled();
- }
+ final ChainedFutureCallback<HttpResponse> chainedFutureCallback = new ChainedFutureCallback<HttpResponse>(future) {
+ @Override
public void completed(final HttpResponse httpResponse) {
final Date responseDate = getCurrentDate();
if (revalidationResponseIsTooOld(httpResponse, cacheEntry)) {
final HttpRequest unconditional = CachingHttpAsyncClient.this.conditionalRequestBuilder.buildUnconditionalRequest(request, cacheEntry);
final Date innerRequestDate = getCurrentDate();
- CachingHttpAsyncClient.this.backend.execute(target, unconditional, context, new FutureCallback<HttpResponse>() {
- public void cancelled() {
- future.cancelled();
- }
+ final ChainedFutureCallback<HttpResponse> chainedFutureCallback2 = new ChainedFutureCallback<HttpResponse>(future) {
+ @Override
public void completed(final HttpResponse innerHttpResponse) {
final Date innerResponseDate = getCurrentDate();
- revalidateCacheEntryCompleted(target, request,
- context, cacheEntry, future,
+ revalidateCacheEntryCompleted(future,
+ target, request, context, cacheEntry,
conditionalRequest, innerRequestDate,
innerHttpResponse, innerResponseDate);
}
- public void failed(final Exception ex) {
- future.failed(ex);
- }
-
- });
- return;
+ };
+ CachingHttpAsyncClient.this.backend.execute(target, unconditional, context, chainedFutureCallback2);
}
- revalidateCacheEntryCompleted(target, request,
- context, cacheEntry, future,
+
+ revalidateCacheEntryCompleted(future,
+ target, request, context, cacheEntry,
conditionalRequest, requestDate,
httpResponse, responseDate);
}
- public void failed(final Exception ex) {
- future.failed(ex);
- }
+ };
- }));
- return future;
+ this.backend.execute(target, conditionalRequest, context, chainedFutureCallback);
}
private void revalidateCacheEntryCompleted(
+ final BasicFuture<HttpResponse> future,
final HttpHost target,
final HttpRequestWrapper request,
final HttpContext context,
final HttpCacheEntry cacheEntry,
- final FutureHttpResponse futureCallback,
final HttpRequestWrapper conditionalRequest,
final Date requestDate,
final HttpResponse httpResponse,
@@ -860,15 +883,15 @@ public class CachingHttpAsyncClient impl
updatedEntry = CachingHttpAsyncClient.this.responseCache.updateCacheEntry(target, request, cacheEntry,
httpResponse, requestDate, responseDate);
} catch (final IOException e) {
- futureCallback.failed(e);
+ future.failed(e);
return;
}
if (CachingHttpAsyncClient.this.suitabilityChecker.isConditional(request)
&& CachingHttpAsyncClient.this.suitabilityChecker.allConditionalsMatch(request, updatedEntry, new Date())) {
- futureCallback.completed(CachingHttpAsyncClient.this.responseGenerator.generateNotModifiedResponse(updatedEntry));
+ future.completed(CachingHttpAsyncClient.this.responseGenerator.generateNotModifiedResponse(updatedEntry));
return;
}
- futureCallback.completed(CachingHttpAsyncClient.this.responseGenerator.generateResponse(updatedEntry));
+ future.completed(CachingHttpAsyncClient.this.responseGenerator.generateResponse(updatedEntry));
return;
}
@@ -877,16 +900,16 @@ public class CachingHttpAsyncClient impl
&& CachingHttpAsyncClient.this.validityPolicy.mayReturnStaleIfError(request, cacheEntry, responseDate)) {
final HttpResponse cachedResponse = CachingHttpAsyncClient.this.responseGenerator.generateResponse(cacheEntry);
cachedResponse.addHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\"");
- futureCallback.completed(cachedResponse);
+ future.completed(cachedResponse);
return;
}
try {
final HttpResponse backendResponse = handleBackendResponse(target, conditionalRequest,
requestDate, responseDate, httpResponse);
- futureCallback.completed(backendResponse);
+ future.completed(backendResponse);
} catch (final IOException e) {
- futureCallback.failed(e);
+ future.failed(e);
}
}
@@ -934,7 +957,8 @@ public class CachingHttpAsyncClient impl
* included in the resulting response.
*/
private void storeRequestIfModifiedSinceFor304Response(
- final HttpRequest request, final HttpResponse backendResponse) {
+ final HttpRequest request,
+ final HttpResponse backendResponse) {
if (backendResponse.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
final Header h = request.getFirstHeader("If-Modified-Since");
if (h != null) {
@@ -943,7 +967,9 @@ public class CachingHttpAsyncClient impl
}
}
- private boolean alreadyHaveNewerCacheEntry(final HttpHost target, final HttpRequest request,
+ private boolean alreadyHaveNewerCacheEntry(
+ final HttpHost target,
+ final HttpRequest request,
final HttpResponse backendResponse) {
HttpCacheEntry existing = null;
try {
Added: httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/ChainedFutureCallback.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/ChainedFutureCallback.java?rev=1561685&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/ChainedFutureCallback.java (added)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/ChainedFutureCallback.java Mon Jan 27 14:15:06 2014
@@ -0,0 +1,52 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.http.impl.client.cache;
+
+import org.apache.http.concurrent.BasicFuture;
+import org.apache.http.concurrent.FutureCallback;
+
+class ChainedFutureCallback<T> implements FutureCallback<T> {
+
+ private final BasicFuture<T> wrapped;
+
+ public ChainedFutureCallback(final BasicFuture<T> delegate) {
+ this.wrapped = delegate;
+ }
+
+ public void completed(final T result) {
+ this.wrapped.completed(result);
+ }
+
+ public void failed(final Exception ex) {
+ this.wrapped.failed(ex);
+ }
+
+ public void cancelled() {
+ this.wrapped.cancel();
+ }
+
+}
Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/ChainedFutureCallback.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/ChainedFutureCallback.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/ChainedFutureCallback.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/test/java/org/apache/http/impl/client/cache/CachingHttpAsyncClientExecChain.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/test/java/org/apache/http/impl/client/cache/CachingHttpAsyncClientExecChain.java?rev=1561685&r1=1561684&r2=1561685&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/test/java/org/apache/http/impl/client/cache/CachingHttpAsyncClientExecChain.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/test/java/org/apache/http/impl/client/cache/CachingHttpAsyncClientExecChain.java Mon Jan 27 14:15:06 2014
@@ -26,37 +26,23 @@
*/
package org.apache.http.impl.client.cache;
+import java.io.IOException;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
-import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpExecutionAware;
import org.apache.http.client.methods.HttpRequestWrapper;
import org.apache.http.client.protocol.HttpClientContext;
-import org.apache.http.concurrent.FutureCallback;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.impl.execchain.ClientExecChain;
-import java.io.IOException;
-import java.lang.reflect.UndeclaredThrowableException;
-import java.util.concurrent.ExecutionException;
-
public class CachingHttpAsyncClientExecChain implements ClientExecChain {
private final CachingHttpAsyncClient client;
- private final FutureCallback<HttpResponse> dummyCallback = new FutureCallback<HttpResponse>() {
- public void failed(final Exception ex) {
- // failed
- }
-
- public void completed(final HttpResponse result) {
- // completed
- }
-
- public void cancelled() {
- // cancelled
- }
- };
public CachingHttpAsyncClientExecChain(final ClientExecChain backend) {
this(backend, new BasicHttpCache(), CacheConfig.DEFAULT);
@@ -111,9 +97,8 @@ public class CachingHttpAsyncClientExecC
final HttpClientContext context,
final HttpExecutionAware execAware) throws IOException, HttpException {
try {
- return Proxies.enhanceResponse(client.execute(
- route.getTargetHost(), request, context, dummyCallback)
- .get());
+ final Future<HttpResponse> future = client.execute(route.getTargetHost(), request, context, null);
+ return Proxies.enhanceResponse(future.get());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return null;
@@ -146,33 +131,4 @@ public class CachingHttpAsyncClientExecC
return client.getCacheUpdates();
}
- CloseableHttpResponse revalidateCacheEntry(
- final HttpRoute route,
- final HttpRequestWrapper request,
- final HttpClientContext context,
- final HttpCacheEntry cacheEntry) throws IOException, HttpException {
- try {
- return Proxies.enhanceResponse(client.revalidateCacheEntry(
- route.getTargetHost(), request, context, cacheEntry,
- dummyCallback).get());
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- return null;
- } catch (ExecutionException e) {
- try {
- throw e.getCause();
- } catch (IOException ex) {
- throw ex;
- } catch (HttpException ex) {
- throw ex;
- } catch (RuntimeException ex) {
- throw ex;
- } catch (Error ex) {
- throw ex;
- } catch (Throwable ex) {
- throw new UndeclaredThrowableException(ex);
- }
- }
- }
-
}