Home | History | Annotate | Download | only in http
      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 
     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.
    133   void set_mode(Mode value) { mode_ = value; }
    134   Mode mode() { return mode_; }
    135 
    136   void set_type(CacheType 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 
    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