• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // This file declares a HttpTransactionFactory implementation that can be
6 // layered on top of another HttpTransactionFactory to add HTTP caching.  The
7 // caching logic follows RFC 2616 (any exceptions are called out in the code).
8 //
9 // The HttpCache takes a disk_cache::Backend as a parameter, and uses that for
10 // the cache storage.
11 //
12 // See HttpTransactionFactory and HttpTransaction for more details.
13 
14 #ifndef NET_HTTP_HTTP_CACHE_H_
15 #define NET_HTTP_HTTP_CACHE_H_
16 
17 #include <list>
18 #include <set>
19 
20 #include "base/basictypes.h"
21 #include "base/file_path.h"
22 #include "base/hash_tables.h"
23 #include "base/scoped_ptr.h"
24 #include "base/task.h"
25 #include "base/weak_ptr.h"
26 #include "net/base/cache_type.h"
27 #include "net/base/completion_callback.h"
28 #include "net/http/http_transaction_factory.h"
29 
30 namespace disk_cache {
31 class Backend;
32 class Entry;
33 }
34 
35 namespace net {
36 
37 class HostResolver;
38 class HttpNetworkSession;
39 class HttpRequestInfo;
40 class HttpResponseInfo;
41 class NetworkChangeNotifier;
42 class ProxyService;
43 class SSLConfigService;
44 
45 class HttpCache : public HttpTransactionFactory,
46                   public base::SupportsWeakPtr<HttpCache> {
47  public:
48   ~HttpCache();
49 
50   // The cache mode of operation.
51   enum Mode {
52     // Normal mode just behaves like a standard web cache.
53     NORMAL = 0,
54     // Record mode caches everything for purposes of offline playback.
55     RECORD,
56     // Playback mode replays from a cache without considering any
57     // standard invalidations.
58     PLAYBACK,
59     // Disables reads and writes from the cache.
60     // Equivalent to setting LOAD_DISABLE_CACHE on every request.
61     DISABLE
62   };
63 
64   // Initialize the cache from the directory where its data is stored. The
65   // disk cache is initialized lazily (by CreateTransaction) in this case. If
66   // |cache_size| is zero, a default value will be calculated automatically.
67   HttpCache(NetworkChangeNotifier* network_change_notifier,
68             HostResolver* host_resolver,
69             ProxyService* proxy_service,
70             SSLConfigService* ssl_config_service,
71             const FilePath& cache_dir,
72             int cache_size);
73 
74   // Initialize the cache from the directory where its data is stored. The
75   // disk cache is initialized lazily (by CreateTransaction) in  this case. If
76   // |cache_size| is zero, a default value will be calculated automatically.
77   // Provide an existing HttpNetworkSession, the cache can construct a
78   // network layer with a shared HttpNetworkSession in order for multiple
79   // network layers to share information (e.g. authenication data).
80   HttpCache(HttpNetworkSession* session, const FilePath& cache_dir,
81             int cache_size);
82 
83   // Initialize using an in-memory cache. The cache is initialized lazily
84   // (by CreateTransaction) in this case. If |cache_size| is zero, a default
85   // value will be calculated automatically.
86   HttpCache(NetworkChangeNotifier* network_change_notifier,
87             HostResolver* host_resolver,
88             ProxyService* proxy_service,
89             SSLConfigService* ssl_config_service,
90             int cache_size);
91 
92   // Initialize the cache from its component parts, which is useful for
93   // testing.  The lifetime of the network_layer and disk_cache are managed by
94   // the HttpCache and will be destroyed using |delete| when the HttpCache is
95   // destroyed.
96   HttpCache(HttpTransactionFactory* network_layer,
97             disk_cache::Backend* disk_cache);
98 
network_layer()99   HttpTransactionFactory* network_layer() { return network_layer_.get(); }
100 
101   // Returns the cache backend for this HttpCache instance. If the backend
102   // is not initialized yet, this method will initialize it. If the return
103   // value is NULL then the backend cannot be initialized.
104   disk_cache::Backend* GetBackend();
105 
106   // HttpTransactionFactory implementation:
107   virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans);
108   virtual HttpCache* GetCache();
109   virtual HttpNetworkSession* GetSession();
110   virtual void Suspend(bool suspend);
111 
112   // Helper function for reading response info from the disk cache.  If the
113   // cache doesn't have the whole resource *|request_truncated| is set to true.
114   // Avoid this function for performance critical paths as it uses blocking IO.
115   static bool ReadResponseInfo(disk_cache::Entry* disk_entry,
116                                HttpResponseInfo* response_info,
117                                bool* response_truncated);
118 
119   // Helper function for writing response info into the disk cache.  If the
120   // cache doesn't have the whole resource |request_truncated| should be true.
121   // Avoid this function for performance critical paths as it uses blocking IO.
122   static bool WriteResponseInfo(disk_cache::Entry* disk_entry,
123                                 const HttpResponseInfo* response_info,
124                                 bool skip_transient_headers,
125                                 bool response_truncated);
126 
127   // Given a header data blob, convert it to a response info object.
128   static bool ParseResponseInfo(const char* data, int len,
129                                 HttpResponseInfo* response_info,
130                                 bool* response_truncated);
131 
132   // Get/Set the cache's mode.
set_mode(Mode value)133   void set_mode(Mode value) { mode_ = value; }
mode()134   Mode mode() { return mode_; }
135 
set_type(CacheType type)136   void set_type(CacheType type) { type_ = type; }
type()137   CacheType type() { return type_; }
138 
139   // Close currently active sockets so that fresh page loads will not use any
140   // recycled connections.  For sockets currently in use, they may not close
141   // immediately, but they will not be reusable. This is for debugging.
142   void CloseCurrentConnections();
143 
set_enable_range_support(bool value)144   void set_enable_range_support(bool value) {
145     enable_range_support_ = value;
146   }
147 
148  private:
149 
150   // Types --------------------------------------------------------------------
151 
152   class BackendCallback;
153   class Transaction;
154   class WorkItem;
155   friend class Transaction;
156   struct NewEntry;  // Info for an entry under construction.
157 
158   typedef std::list<Transaction*> TransactionList;
159   typedef std::list<WorkItem*> WorkItemList;
160 
161   struct ActiveEntry {
162     disk_cache::Entry* disk_entry;
163     Transaction*       writer;
164     TransactionList    readers;
165     TransactionList    pending_queue;
166     bool               will_process_pending_queue;
167     bool               doomed;
168 
169     explicit ActiveEntry(disk_cache::Entry*);
170     ~ActiveEntry();
171   };
172 
173   typedef base::hash_map<std::string, ActiveEntry*> ActiveEntriesMap;
174   typedef base::hash_map<std::string, NewEntry*> NewEntriesMap;
175   typedef std::set<ActiveEntry*> ActiveEntriesSet;
176 
177 
178   // Methods ------------------------------------------------------------------
179 
180   // Generates the cache key for this request.
181   std::string GenerateCacheKey(const HttpRequestInfo*);
182 
183   // Dooms the entry selected by |key|. |callback| is used for completion
184   // notification if this function returns ERR_IO_PENDING. The entry can be
185   // currently in use or not.
186   int DoomEntry(const std::string& key, CompletionCallback* callback);
187 
188   // Dooms the entry selected by |key|. |callback| is used for completion
189   // notification if this function returns ERR_IO_PENDING. The entry should not
190   // be currently in use.
191   int AsyncDoomEntry(const std::string& key, CompletionCallback* callback);
192 
193   // Closes a previously doomed entry.
194   void FinalizeDoomedEntry(ActiveEntry* entry);
195 
196   // Returns an entry that is currently in use and not doomed, or NULL.
197   ActiveEntry* FindActiveEntry(const std::string& key);
198 
199   // Creates a new ActiveEntry and starts tracking it. |disk_entry| is the disk
200   // cache entry that corresponds to the desired |key|.
201   // TODO(rvargas): remove the |key| argument.
202   ActiveEntry* ActivateEntry(const std::string& key,
203                              disk_cache::Entry* disk_entry);
204 
205   // Deletes an ActiveEntry.
206   void DeactivateEntry(ActiveEntry* entry);
207 
208   // Deletes an ActiveEntry using an exhaustive search.
209   void SlowDeactivateEntry(ActiveEntry* entry);
210 
211   // Returns the NewEntry for the desired |key|. If an entry is not under
212   // construction already, a new NewEntry structure is created.
213   NewEntry* GetNewEntry(const std::string& key);
214 
215   // Deletes a NewEntry.
216   void DeleteNewEntry(NewEntry* entry);
217 
218   // Opens the disk cache entry associated with |key|, returning an ActiveEntry
219   // in |*entry|. |callback| is used for completion notification if this
220   // function returns ERR_IO_PENDING.
221   int OpenEntry(const std::string& key, ActiveEntry** entry,
222                 CompletionCallback* callback);
223 
224   // Creates the disk cache entry associated with |key|, returning an
225   // ActiveEntry in |*entry|. |callback| is used for completion notification if
226   // this function returns ERR_IO_PENDING.
227   int CreateEntry(const std::string& key, ActiveEntry** entry,
228                   CompletionCallback* callback);
229 
230   // Destroys an ActiveEntry (active or doomed).
231   void DestroyEntry(ActiveEntry* entry);
232 
233   // Adds a transaction to an ActiveEntry.
234   int AddTransactionToEntry(ActiveEntry* entry, Transaction* trans);
235 
236   // Called when the transaction has finished working with this entry. |cancel|
237   // is true if the operation was cancelled by the caller instead of running
238   // to completion.
239   void DoneWithEntry(ActiveEntry* entry, Transaction* trans, bool cancel);
240 
241   // Called when the transaction has finished writting to this entry. |success|
242   // is false if the cache entry should be deleted.
243   void DoneWritingToEntry(ActiveEntry* entry, bool success);
244 
245   // Called when the transaction has finished reading from this entry.
246   void DoneReadingFromEntry(ActiveEntry* entry, Transaction* trans);
247 
248   // Convers the active writter transaction to a reader so that other
249   // transactions can start reading from this entry.
250   void ConvertWriterToReader(ActiveEntry* entry);
251 
252   // Removes the transaction |trans|, waiting for |callback|, from the pending
253   // list of an entry (NewEntry, active or doomed entry).
254   void RemovePendingTransaction(Transaction* trans, CompletionCallback* cb);
255 
256   // Removes the transaction |trans|, from the pending list of |entry|.
257   bool RemovePendingTransactionFromEntry(ActiveEntry* entry,
258                                          Transaction* trans);
259 
260   // Removes the callback |cb|, from the pending list of |entry|.
261   bool RemovePendingCallbackFromNewEntry(NewEntry* entry,
262                                          CompletionCallback* cb);
263 
264   // Resumes processing the pending list of |entry|.
265   void ProcessPendingQueue(ActiveEntry* entry);
266 
267   // Events (called via PostTask) ---------------------------------------------
268 
269   void OnProcessPendingQueue(ActiveEntry* entry);
270 
271   // Callbacks ----------------------------------------------------------------
272 
273   // Processes BackendCallback notifications.
274   void OnIOComplete(int result, NewEntry* entry);
275 
276 
277   // Variables ----------------------------------------------------------------
278 
279   // Used when lazily constructing the disk_cache_.
280   FilePath disk_cache_dir_;
281 
282   Mode mode_;
283   CacheType type_;
284 
285   scoped_ptr<HttpTransactionFactory> network_layer_;
286   scoped_ptr<disk_cache::Backend> disk_cache_;
287 
288   // The set of active entries indexed by cache key.
289   ActiveEntriesMap active_entries_;
290 
291   // The set of doomed entries.
292   ActiveEntriesSet doomed_entries_;
293 
294   // The set of entries "under construction".
295   NewEntriesMap new_entries_;
296 
297   ScopedRunnableMethodFactory<HttpCache> task_factory_;
298 
299   bool enable_range_support_;
300   int cache_size_;
301 
302   typedef base::hash_map<std::string, int> PlaybackCacheMap;
303   scoped_ptr<PlaybackCacheMap> playback_cache_map_;
304 
305   DISALLOW_COPY_AND_ASSIGN(HttpCache);
306 };
307 
308 }  // namespace net
309 
310 #endif  // NET_HTTP_HTTP_CACHE_H_
311