View Javadoc

1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.http.impl.client.cache;
28  
29  import java.util.Collections;
30  import java.util.HashSet;
31  import java.util.Set;
32  import java.util.concurrent.ArrayBlockingQueue;
33  import java.util.concurrent.ExecutorService;
34  import java.util.concurrent.RejectedExecutionException;
35  import java.util.concurrent.ThreadPoolExecutor;
36  import java.util.concurrent.TimeUnit;
37  
38  import org.apache.commons.logging.Log;
39  import org.apache.commons.logging.LogFactory;
40  import org.apache.http.HttpHost;
41  import org.apache.http.client.cache.HttpCacheEntry;
42  import org.apache.http.client.methods.HttpRequestWrapper;
43  import org.apache.http.protocol.HttpContext;
44  
45  /**
46   * Class used for asynchronous revalidations to be used when the "stale-
47   * while-revalidate" directive is present
48   */
49  class AsynchronousAsyncValidator {
50      private final CachingHttpAsyncClient cachingAsyncClient;
51      private final ExecutorService executor;
52      private final Set<String> queued;
53      private final CacheKeyGenerator cacheKeyGenerator;
54  
55      private final Log log = LogFactory.getLog(getClass());
56  
57      /**
58       * Create AsynchronousValidator which will make revalidation requests using
59       * the supplied {@link CachingHttpAsyncClient}, and a {@link ThreadPoolExecutor}
60       * generated according to the thread pool settings provided in the given
61       * {@link CacheConfig}.
62       *
63       * @param cachingClient
64       *            used to execute asynchronous requests
65       * @param config
66       *            specifies thread pool settings. See
67       *            {@link CacheConfig#getAsynchronousWorkersMax()},
68       *            {@link CacheConfig#getAsynchronousWorkersCore()},
69       *            {@link CacheConfig#getAsynchronousWorkerIdleLifetimeSecs()},
70       *            and {@link CacheConfig#getRevalidationQueueSize()}.
71       */
72      public AsynchronousAsyncValidator(final CachingHttpAsyncClient cachingClient, final CacheConfig config) {
73          this(cachingClient, new ThreadPoolExecutor(config.getAsynchronousWorkersCore(),
74                  config.getAsynchronousWorkersMax(), config.getAsynchronousWorkerIdleLifetimeSecs(),
75                  TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(
76                          config.getRevalidationQueueSize())));
77      }
78  
79      /**
80       * Create AsynchronousValidator which will make revalidation requests using
81       * the supplied {@link CachingHttpAsyncClient} and {@link ExecutorService}.
82       *
83       * @param cachingClient
84       *            used to execute asynchronous requests
85       * @param executor
86       *            used to manage a thread pool of revalidation workers
87       */
88      AsynchronousAsyncValidator(final CachingHttpAsyncClient cachingClient, final ExecutorService executor) {
89          this.cachingAsyncClient = cachingClient;
90          this.executor = executor;
91          this.queued = new HashSet<String>();
92          this.cacheKeyGenerator = new CacheKeyGenerator();
93      }
94  
95      /**
96       * Schedules an asynchronous revalidation
97       */
98      public synchronized void revalidateCacheEntry(final HttpHost target, final HttpRequestWrapper request,
99              final HttpContext context, final HttpCacheEntry entry) {
100         // getVariantURI will fall back on getURI if no variants exist
101         final String uri = this.cacheKeyGenerator.getVariantURI(target, request, entry);
102 
103         if (!this.queued.contains(uri)) {
104             final AsynchronousAsyncValidationRequest asyncRevalidationRequest = new AsynchronousAsyncValidationRequest(
105                     this, this.cachingAsyncClient, target, request, context, entry, uri);
106 
107             try {
108                 this.executor.execute(asyncRevalidationRequest);
109                 this.queued.add(uri);
110             } catch (final RejectedExecutionException ree) {
111                 this.log.debug("Revalidation for [" + uri + "] not scheduled: " + ree);
112             }
113         }
114     }
115 
116     /**
117      * Removes an identifier from the internal list of revalidation jobs in
118      * progress. This is meant to be called by
119      * {@link AsynchronousValidationRequest#run()} once the revalidation is
120      * complete, using the identifier passed in during constructions.
121      */
122     synchronized void markComplete(final String identifier) {
123         this.queued.remove(identifier);
124     }
125 
126     Set<String> getScheduledIdentifiers() {
127         return Collections.unmodifiableSet(this.queued);
128     }
129 
130     ExecutorService getExecutor() {
131         return this.executor;
132     }
133 
134 }