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