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/blockfile/backend_impl.h"
     11 #include "net/disk_cache/cache_util.h"
     12 #include "net/disk_cache/disk_cache.h"
     13 #include "net/disk_cache/memory/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 #if defined(OS_ANDROID)
     83   static const bool kSimpleBackendIsDefault = true;
     84 #else
     85   static const bool kSimpleBackendIsDefault = false;
     86 #endif
     87   if (backend_type_ == net::CACHE_BACKEND_SIMPLE ||
     88       (backend_type_ == net::CACHE_BACKEND_DEFAULT &&
     89        kSimpleBackendIsDefault)) {
     90     disk_cache::SimpleBackendImpl* simple_cache =
     91         new disk_cache::SimpleBackendImpl(path_, max_bytes_, type_,
     92                                           thread_.get(), net_log_);
     93     created_cache_.reset(simple_cache);
     94     return simple_cache->Init(
     95         base::Bind(&CacheCreator::OnIOComplete, base::Unretained(this)));
     96   }
     97 
     98   // Avoid references to blockfile functions on Android to reduce binary size.
     99 #if defined(OS_ANDROID)
    100   return net::ERR_FAILED;
    101 #else
    102   disk_cache::BackendImpl* new_cache =
    103       new disk_cache::BackendImpl(path_, thread_.get(), net_log_);
    104   created_cache_.reset(new_cache);
    105   new_cache->SetMaxSize(max_bytes_);
    106   new_cache->SetType(type_);
    107   new_cache->SetFlags(flags_);
    108   int rv = new_cache->Init(
    109       base::Bind(&CacheCreator::OnIOComplete, base::Unretained(this)));
    110   DCHECK_EQ(net::ERR_IO_PENDING, rv);
    111   return rv;
    112 #endif
    113 }
    114 
    115 void CacheCreator::DoCallback(int result) {
    116   DCHECK_NE(net::ERR_IO_PENDING, result);
    117   if (result == net::OK) {
    118 #ifndef USE_TRACING_CACHE_BACKEND
    119     *backend_ = created_cache_.Pass();
    120 #else
    121     *backend_.reset(
    122         new disk_cache::TracingCacheBackend(created_cache_.Pass()));
    123 #endif
    124   } else {
    125     LOG(ERROR) << "Unable to create cache";
    126     created_cache_.reset();
    127   }
    128   callback_.Run(result);
    129   delete this;
    130 }
    131 
    132 // If the initialization of the cache fails, and |force| is true, we will
    133 // discard the whole cache and create a new one.
    134 void CacheCreator::OnIOComplete(int result) {
    135   if (result == net::OK || !force_ || retry_)
    136     return DoCallback(result);
    137 
    138   // This is a failure and we are supposed to try again, so delete the object,
    139   // delete all the files, and try again.
    140   retry_ = true;
    141   created_cache_.reset();
    142   if (!disk_cache::DelayedCacheCleanup(path_))
    143     return DoCallback(result);
    144 
    145   // The worker thread will start deleting files soon, but the original folder
    146   // is not there anymore... let's create a new set of files.
    147   int rv = Run();
    148   DCHECK_EQ(net::ERR_IO_PENDING, rv);
    149 }
    150 
    151 }  // namespace
    152 
    153 namespace disk_cache {
    154 
    155 int CreateCacheBackend(net::CacheType type,
    156                        net::BackendType backend_type,
    157                        const base::FilePath& path,
    158                        int max_bytes,
    159                        bool force, base::MessageLoopProxy* thread,
    160                        net::NetLog* net_log, scoped_ptr<Backend>* backend,
    161                        const net::CompletionCallback& callback) {
    162   DCHECK(!callback.is_null());
    163   if (type == net::MEMORY_CACHE) {
    164     *backend = disk_cache::MemBackendImpl::CreateBackend(max_bytes, net_log);
    165     return *backend ? net::OK : net::ERR_FAILED;
    166   }
    167   DCHECK(thread);
    168   CacheCreator* creator = new CacheCreator(path, force, max_bytes, type,
    169                                            backend_type, kNone,
    170                                            thread, net_log, backend, callback);
    171   return creator->Run();
    172 }
    173 
    174 }  // namespace disk_cache
    175