Home | History | Annotate | Download | only in disk_cache
      1 // Copyright (c) 2012 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 #include "base/files/file_path.h"
      6 #include "base/metrics/field_trial.h"
      7 #include "base/strings/stringprintf.h"
      8 #include "net/base/cache_type.h"
      9 #include "net/base/net_errors.h"
     10 #include "net/disk_cache/backend_impl.h"
     11 #include "net/disk_cache/cache_util.h"
     12 #include "net/disk_cache/disk_cache.h"
     13 #include "net/disk_cache/mem_backend_impl.h"
     14 #include "net/disk_cache/simple/simple_backend_impl.h"
     15 
     16 #ifdef USE_TRACING_CACHE_BACKEND
     17 #include "net/disk_cache/tracing_cache_backend.h"
     18 #endif
     19 
     20 namespace {
     21 
     22 // Builds an instance of the backend depending on platform, type, experiments
     23 // etc. Takes care of the retry state. This object will self-destroy when
     24 // finished.
     25 class CacheCreator {
     26  public:
     27   CacheCreator(const base::FilePath& path, bool force, int max_bytes,
     28                net::CacheType type, net::BackendType backend_type, uint32 flags,
     29                base::MessageLoopProxy* thread, net::NetLog* net_log,
     30                scoped_ptr<disk_cache::Backend>* backend,
     31                const net::CompletionCallback& callback);
     32 
     33   // Creates the backend.
     34   int Run();
     35 
     36  private:
     37   ~CacheCreator();
     38 
     39   void DoCallback(int result);
     40 
     41   void OnIOComplete(int result);
     42 
     43   const base::FilePath path_;
     44   bool force_;
     45   bool retry_;
     46   int max_bytes_;
     47   net::CacheType type_;
     48   net::BackendType backend_type_;
     49   uint32 flags_;
     50   scoped_refptr<base::MessageLoopProxy> thread_;
     51   scoped_ptr<disk_cache::Backend>* backend_;
     52   net::CompletionCallback callback_;
     53   scoped_ptr<disk_cache::Backend> created_cache_;
     54   net::NetLog* net_log_;
     55 
     56   DISALLOW_COPY_AND_ASSIGN(CacheCreator);
     57 };
     58 
     59 CacheCreator::CacheCreator(
     60     const base::FilePath& path, bool force, int max_bytes,
     61     net::CacheType type, net::BackendType backend_type, uint32 flags,
     62     base::MessageLoopProxy* thread, net::NetLog* net_log,
     63     scoped_ptr<disk_cache::Backend>* backend,
     64     const net::CompletionCallback& callback)
     65     : path_(path),
     66       force_(force),
     67       retry_(false),
     68       max_bytes_(max_bytes),
     69       type_(type),
     70       backend_type_(backend_type),
     71       flags_(flags),
     72       thread_(thread),
     73       backend_(backend),
     74       callback_(callback),
     75       net_log_(net_log) {
     76 }
     77 
     78 CacheCreator::~CacheCreator() {
     79 }
     80 
     81 int CacheCreator::Run() {
     82   // TODO(gavinp,pasko): Turn Simple Cache on for more cache types as
     83   // appropriate.
     84   if (backend_type_ == net::CACHE_BACKEND_SIMPLE &&
     85       (type_ == net::DISK_CACHE || type_ == net::APP_CACHE ||
     86        type_ == net::MEDIA_CACHE)) {
     87     disk_cache::SimpleBackendImpl* simple_cache =
     88         new disk_cache::SimpleBackendImpl(path_, max_bytes_, type_,
     89                                           thread_.get(), net_log_);
     90     created_cache_.reset(simple_cache);
     91     return simple_cache->Init(
     92         base::Bind(&CacheCreator::OnIOComplete, base::Unretained(this)));
     93   }
     94   disk_cache::BackendImpl* new_cache =
     95       new disk_cache::BackendImpl(path_, thread_.get(), net_log_);
     96   created_cache_.reset(new_cache);
     97   new_cache->SetMaxSize(max_bytes_);
     98   new_cache->SetType(type_);
     99   new_cache->SetFlags(flags_);
    100   int rv = new_cache->Init(
    101       base::Bind(&CacheCreator::OnIOComplete, base::Unretained(this)));
    102   DCHECK_EQ(net::ERR_IO_PENDING, rv);
    103   return rv;
    104 }
    105 
    106 void CacheCreator::DoCallback(int result) {
    107   DCHECK_NE(net::ERR_IO_PENDING, result);
    108   if (result == net::OK) {
    109 #ifndef USE_TRACING_CACHE_BACKEND
    110     *backend_ = created_cache_.Pass();
    111 #else
    112     *backend_.reset(
    113         new disk_cache::TracingCacheBackend(created_cache_.Pass()));
    114 #endif
    115   } else {
    116     LOG(ERROR) << "Unable to create cache";
    117     created_cache_.reset();
    118   }
    119   callback_.Run(result);
    120   delete this;
    121 }
    122 
    123 // If the initialization of the cache fails, and |force| is true, we will
    124 // discard the whole cache and create a new one.
    125 void CacheCreator::OnIOComplete(int result) {
    126   if (result == net::OK || !force_ || retry_)
    127     return DoCallback(result);
    128 
    129   // This is a failure and we are supposed to try again, so delete the object,
    130   // delete all the files, and try again.
    131   retry_ = true;
    132   created_cache_.reset();
    133   if (!disk_cache::DelayedCacheCleanup(path_))
    134     return DoCallback(result);
    135 
    136   // The worker thread will start deleting files soon, but the original folder
    137   // is not there anymore... let's create a new set of files.
    138   int rv = Run();
    139   DCHECK_EQ(net::ERR_IO_PENDING, rv);
    140 }
    141 
    142 }  // namespace
    143 
    144 namespace disk_cache {
    145 
    146 int CreateCacheBackend(net::CacheType type,
    147                        net::BackendType backend_type,
    148                        const base::FilePath& path,
    149                        int max_bytes,
    150                        bool force, base::MessageLoopProxy* thread,
    151                        net::NetLog* net_log, scoped_ptr<Backend>* backend,
    152                        const net::CompletionCallback& callback) {
    153   DCHECK(!callback.is_null());
    154   if (type == net::MEMORY_CACHE) {
    155     *backend = disk_cache::MemBackendImpl::CreateBackend(max_bytes, net_log);
    156     return *backend ? net::OK : net::ERR_FAILED;
    157   }
    158   DCHECK(thread);
    159   CacheCreator* creator = new CacheCreator(path, force, max_bytes, type,
    160                                            backend_type, kNone,
    161                                            thread, net_log, backend, callback);
    162   return creator->Run();
    163 }
    164 
    165 }  // namespace disk_cache
    166