Home | History | Annotate | Download | only in disk_cache
      1 // Copyright (c) 2013 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 "net/disk_cache/tracing_cache_backend.h"
      6 
      7 #include "net/base/net_errors.h"
      8 
      9 namespace disk_cache {
     10 
     11 // Proxies entry objects created by the real underlying backend. Backend users
     12 // will only see the proxy entries. It is necessary for recording the backend
     13 // operations since often non-trivial work is invoked directly on entries.
     14 class EntryProxy : public Entry, public base::RefCountedThreadSafe<EntryProxy> {
     15  public:
     16   EntryProxy(Entry *entry, TracingCacheBackend* backend);
     17   virtual void Doom() OVERRIDE;
     18   virtual void Close() OVERRIDE;
     19   virtual std::string GetKey() const OVERRIDE;
     20   virtual base::Time GetLastUsed() const OVERRIDE;
     21   virtual base::Time GetLastModified() const OVERRIDE;
     22   virtual int32 GetDataSize(int index) const OVERRIDE;
     23   virtual int ReadData(int index, int offset, IOBuffer* buf, int buf_len,
     24                        const CompletionCallback& callback) OVERRIDE;
     25   virtual int WriteData(int index, int offset, IOBuffer* buf, int buf_len,
     26                         const CompletionCallback& callback,
     27                         bool truncate) OVERRIDE;
     28   virtual int ReadSparseData(int64 offset, IOBuffer* buf, int buf_len,
     29                              const CompletionCallback& callback) OVERRIDE;
     30   virtual int WriteSparseData(int64 offset, IOBuffer* buf, int buf_len,
     31                               const CompletionCallback& callback) OVERRIDE;
     32   virtual int GetAvailableRange(int64 offset, int len, int64* start,
     33                                 const CompletionCallback& callback) OVERRIDE;
     34   virtual bool CouldBeSparse() const OVERRIDE;
     35   virtual void CancelSparseIO() OVERRIDE;
     36   virtual int ReadyForSparseIO(const CompletionCallback& callback) OVERRIDE;
     37 
     38  private:
     39   friend class base::RefCountedThreadSafe<EntryProxy>;
     40   typedef TracingCacheBackend::Operation Operation;
     41   virtual ~EntryProxy();
     42 
     43   struct RwOpExtra {
     44     int index;
     45     int offset;
     46     int buf_len;
     47     bool truncate;
     48   };
     49 
     50   void RecordEvent(base::TimeTicks start_time, Operation op, RwOpExtra extra,
     51                    int result_to_record);
     52   void EntryOpComplete(base::TimeTicks start_time, Operation op,
     53                        RwOpExtra extra, const CompletionCallback& cb,
     54                        int result);
     55   Entry* entry_;
     56   base::WeakPtr<TracingCacheBackend> backend_;
     57 
     58   DISALLOW_COPY_AND_ASSIGN(EntryProxy);
     59 };
     60 
     61 EntryProxy::EntryProxy(Entry *entry, TracingCacheBackend* backend)
     62   : entry_(entry),
     63     backend_(backend->AsWeakPtr()) {
     64 }
     65 
     66 void EntryProxy::Doom() {
     67   // TODO(pasko): Record the event.
     68   entry_->Doom();
     69 }
     70 
     71 void EntryProxy::Close() {
     72   // TODO(pasko): Record the event.
     73   entry_->Close();
     74   Release();
     75 }
     76 
     77 std::string EntryProxy::GetKey() const {
     78   return entry_->GetKey();
     79 }
     80 
     81 base::Time EntryProxy::GetLastUsed() const {
     82   return entry_->GetLastUsed();
     83 }
     84 
     85 base::Time EntryProxy::GetLastModified() const {
     86   return entry_->GetLastModified();
     87 }
     88 
     89 int32 EntryProxy::GetDataSize(int index) const {
     90   return entry_->GetDataSize(index);
     91 }
     92 
     93 int EntryProxy::ReadData(int index, int offset, IOBuffer* buf, int buf_len,
     94                          const CompletionCallback& callback) {
     95   base::TimeTicks start_time = base::TimeTicks::Now();
     96   RwOpExtra extra;
     97   extra.index = index;
     98   extra.offset = offset;
     99   extra.buf_len = buf_len;
    100   extra.truncate = false;
    101   int rv = entry_->ReadData(
    102       index, offset, buf, buf_len,
    103       base::Bind(&EntryProxy::EntryOpComplete, this, start_time,
    104                  TracingCacheBackend::OP_READ, extra, callback));
    105   if (rv != net::ERR_IO_PENDING) {
    106     RecordEvent(start_time, TracingCacheBackend::OP_READ, extra, rv);
    107   }
    108   return rv;
    109 }
    110 
    111 int EntryProxy::WriteData(int index, int offset, IOBuffer* buf, int buf_len,
    112                       const CompletionCallback& callback,
    113                       bool truncate) {
    114   base::TimeTicks start_time = base::TimeTicks::Now();
    115   RwOpExtra extra;
    116   extra.index = index;
    117   extra.offset = offset;
    118   extra.buf_len = buf_len;
    119   extra.truncate = truncate;
    120   int rv = entry_->WriteData(index, offset, buf, buf_len,
    121       base::Bind(&EntryProxy::EntryOpComplete, this, start_time,
    122                  TracingCacheBackend::OP_WRITE, extra, callback),
    123       truncate);
    124   if (rv != net::ERR_IO_PENDING) {
    125     RecordEvent(start_time, TracingCacheBackend::OP_WRITE, extra, rv);
    126   }
    127   return rv;
    128 }
    129 
    130 int EntryProxy::ReadSparseData(int64 offset, IOBuffer* buf, int buf_len,
    131                            const CompletionCallback& callback) {
    132   // TODO(pasko): Record the event.
    133   return entry_->ReadSparseData(offset, buf, buf_len, callback);
    134 }
    135 
    136 int EntryProxy::WriteSparseData(int64 offset, IOBuffer* buf, int buf_len,
    137                             const CompletionCallback& callback) {
    138   // TODO(pasko): Record the event.
    139   return entry_->WriteSparseData(offset, buf, buf_len, callback);
    140 }
    141 
    142 int EntryProxy::GetAvailableRange(int64 offset, int len, int64* start,
    143                               const CompletionCallback& callback) {
    144   return entry_->GetAvailableRange(offset, len, start, callback);
    145 }
    146 
    147 bool EntryProxy::CouldBeSparse() const {
    148   return entry_->CouldBeSparse();
    149 }
    150 
    151 void EntryProxy::CancelSparseIO() {
    152   return entry_->CancelSparseIO();
    153 }
    154 
    155 int EntryProxy::ReadyForSparseIO(const CompletionCallback& callback) {
    156   return entry_->ReadyForSparseIO(callback);
    157 }
    158 
    159 void EntryProxy::RecordEvent(base::TimeTicks start_time, Operation op,
    160                              RwOpExtra extra, int result_to_record) {
    161   // TODO(pasko): Implement.
    162 }
    163 
    164 void EntryProxy::EntryOpComplete(base::TimeTicks start_time, Operation op,
    165                                  RwOpExtra extra, const CompletionCallback& cb,
    166                                  int result) {
    167   RecordEvent(start_time, op, extra, result);
    168   if (!cb.is_null()) {
    169     cb.Run(result);
    170   }
    171 }
    172 
    173 EntryProxy::~EntryProxy() {
    174   if (backend_.get()) {
    175     backend_->OnDeleteEntry(entry_);
    176   }
    177 }
    178 
    179 TracingCacheBackend::TracingCacheBackend(scoped_ptr<Backend> backend)
    180   : backend_(backend.Pass()) {
    181 }
    182 
    183 TracingCacheBackend::~TracingCacheBackend() {
    184 }
    185 
    186 net::CacheType TracingCacheBackend::GetCacheType() const {
    187   return backend_->GetCacheType();
    188 }
    189 
    190 int32 TracingCacheBackend::GetEntryCount() const {
    191   return backend_->GetEntryCount();
    192 }
    193 
    194 void TracingCacheBackend::RecordEvent(base::TimeTicks start_time, Operation op,
    195                                       std::string key, Entry* entry, int rv) {
    196   // TODO(pasko): Implement.
    197 }
    198 
    199 EntryProxy* TracingCacheBackend::FindOrCreateEntryProxy(Entry* entry) {
    200   EntryProxy* entry_proxy;
    201   EntryToProxyMap::iterator it = open_entries_.find(entry);
    202   if (it != open_entries_.end()) {
    203     entry_proxy = it->second;
    204     entry_proxy->AddRef();
    205     return entry_proxy;
    206   }
    207   entry_proxy = new EntryProxy(entry, this);
    208   entry_proxy->AddRef();
    209   open_entries_[entry] = entry_proxy;
    210   return entry_proxy;
    211 }
    212 
    213 void TracingCacheBackend::OnDeleteEntry(Entry* entry) {
    214   EntryToProxyMap::iterator it = open_entries_.find(entry);
    215   if (it != open_entries_.end()) {
    216     open_entries_.erase(it);
    217   }
    218 }
    219 
    220 void TracingCacheBackend::BackendOpComplete(base::TimeTicks start_time,
    221                                             Operation op,
    222                                             std::string key,
    223                                             Entry** entry,
    224                                             const CompletionCallback& callback,
    225                                             int result) {
    226   RecordEvent(start_time, op, key, *entry, result);
    227   if (*entry) {
    228     *entry = FindOrCreateEntryProxy(*entry);
    229   }
    230   if (!callback.is_null()) {
    231     callback.Run(result);
    232   }
    233 }
    234 
    235 net::CompletionCallback TracingCacheBackend::BindCompletion(
    236     Operation op, base::TimeTicks start_time, const std::string& key,
    237     Entry **entry, const net::CompletionCallback& cb) {
    238   return base::Bind(&TracingCacheBackend::BackendOpComplete,
    239                     AsWeakPtr(), start_time, op, key, entry, cb);
    240 }
    241 
    242 int TracingCacheBackend::OpenEntry(const std::string& key, Entry** entry,
    243                                    const CompletionCallback& callback) {
    244   DCHECK(*entry == NULL);
    245   base::TimeTicks start_time = base::TimeTicks::Now();
    246   int rv = backend_->OpenEntry(key, entry,
    247                                BindCompletion(OP_OPEN, start_time, key, entry,
    248                                               callback));
    249   if (rv != net::ERR_IO_PENDING) {
    250     RecordEvent(start_time, OP_OPEN, key, *entry, rv);
    251     if (*entry) {
    252       *entry = FindOrCreateEntryProxy(*entry);
    253     }
    254   }
    255   return rv;
    256 }
    257 
    258 int TracingCacheBackend::CreateEntry(const std::string& key, Entry** entry,
    259                                      const CompletionCallback& callback) {
    260   base::TimeTicks start_time = base::TimeTicks::Now();
    261   int rv = backend_->CreateEntry(key, entry,
    262                                  BindCompletion(OP_CREATE, start_time, key,
    263                                                 entry, callback));
    264   if (rv != net::ERR_IO_PENDING) {
    265     RecordEvent(start_time, OP_CREATE, key, *entry, rv);
    266     if (*entry) {
    267       *entry = FindOrCreateEntryProxy(*entry);
    268     }
    269   }
    270   return rv;
    271 }
    272 
    273 int TracingCacheBackend::DoomEntry(const std::string& key,
    274                                    const CompletionCallback& callback) {
    275   base::TimeTicks start_time = base::TimeTicks::Now();
    276   int rv = backend_->DoomEntry(key, BindCompletion(OP_DOOM_ENTRY,
    277                                                    start_time, key, NULL,
    278                                                    callback));
    279   if (rv != net::ERR_IO_PENDING) {
    280     RecordEvent(start_time, OP_DOOM_ENTRY, key, NULL, rv);
    281   }
    282   return rv;
    283 }
    284 
    285 int TracingCacheBackend::DoomAllEntries(const CompletionCallback& callback) {
    286   return backend_->DoomAllEntries(callback);
    287 }
    288 
    289 int TracingCacheBackend::DoomEntriesBetween(base::Time initial_time,
    290                                             base::Time end_time,
    291                                             const CompletionCallback& cb) {
    292   return backend_->DoomEntriesBetween(initial_time, end_time, cb);
    293 }
    294 
    295 int TracingCacheBackend::DoomEntriesSince(base::Time initial_time,
    296                                           const CompletionCallback& callback) {
    297   return backend_->DoomEntriesSince(initial_time, callback);
    298 }
    299 
    300 int TracingCacheBackend::OpenNextEntry(void** iter, Entry** next_entry,
    301                                        const CompletionCallback& callback) {
    302   return backend_->OpenNextEntry(iter, next_entry, callback);
    303 }
    304 
    305 void TracingCacheBackend::EndEnumeration(void** iter) {
    306   return backend_->EndEnumeration(iter);
    307 }
    308 
    309 void TracingCacheBackend::GetStats(StatsItems* stats) {
    310   return backend_->GetStats(stats);
    311 }
    312 
    313 void TracingCacheBackend::OnExternalCacheHit(const std::string& key) {
    314   return backend_->OnExternalCacheHit(key);
    315 }
    316 
    317 }  // namespace disk_cache
    318