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 9namespace 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. 14class 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 61EntryProxy::EntryProxy(Entry *entry, TracingCacheBackend* backend) 62 : entry_(entry), 63 backend_(backend->AsWeakPtr()) { 64} 65 66void EntryProxy::Doom() { 67 // TODO(pasko): Record the event. 68 entry_->Doom(); 69} 70 71void EntryProxy::Close() { 72 // TODO(pasko): Record the event. 73 entry_->Close(); 74 Release(); 75} 76 77std::string EntryProxy::GetKey() const { 78 return entry_->GetKey(); 79} 80 81base::Time EntryProxy::GetLastUsed() const { 82 return entry_->GetLastUsed(); 83} 84 85base::Time EntryProxy::GetLastModified() const { 86 return entry_->GetLastModified(); 87} 88 89int32 EntryProxy::GetDataSize(int index) const { 90 return entry_->GetDataSize(index); 91} 92 93int 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 111int 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 130int 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 136int 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 142int EntryProxy::GetAvailableRange(int64 offset, int len, int64* start, 143 const CompletionCallback& callback) { 144 return entry_->GetAvailableRange(offset, len, start, callback); 145} 146 147bool EntryProxy::CouldBeSparse() const { 148 return entry_->CouldBeSparse(); 149} 150 151void EntryProxy::CancelSparseIO() { 152 return entry_->CancelSparseIO(); 153} 154 155int EntryProxy::ReadyForSparseIO(const CompletionCallback& callback) { 156 return entry_->ReadyForSparseIO(callback); 157} 158 159void EntryProxy::RecordEvent(base::TimeTicks start_time, Operation op, 160 RwOpExtra extra, int result_to_record) { 161 // TODO(pasko): Implement. 162} 163 164void 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 173EntryProxy::~EntryProxy() { 174 if (backend_.get()) { 175 backend_->OnDeleteEntry(entry_); 176 } 177} 178 179TracingCacheBackend::TracingCacheBackend(scoped_ptr<Backend> backend) 180 : backend_(backend.Pass()) { 181} 182 183TracingCacheBackend::~TracingCacheBackend() { 184} 185 186net::CacheType TracingCacheBackend::GetCacheType() const { 187 return backend_->GetCacheType(); 188} 189 190int32 TracingCacheBackend::GetEntryCount() const { 191 return backend_->GetEntryCount(); 192} 193 194void TracingCacheBackend::RecordEvent(base::TimeTicks start_time, Operation op, 195 std::string key, Entry* entry, int rv) { 196 // TODO(pasko): Implement. 197} 198 199EntryProxy* 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 213void 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 220void 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 235net::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 242int 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 258int 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 273int 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 285int TracingCacheBackend::DoomAllEntries(const CompletionCallback& callback) { 286 return backend_->DoomAllEntries(callback); 287} 288 289int 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 295int TracingCacheBackend::DoomEntriesSince(base::Time initial_time, 296 const CompletionCallback& callback) { 297 return backend_->DoomEntriesSince(initial_time, callback); 298} 299 300int TracingCacheBackend::OpenNextEntry(void** iter, Entry** next_entry, 301 const CompletionCallback& callback) { 302 return backend_->OpenNextEntry(iter, next_entry, callback); 303} 304 305void TracingCacheBackend::EndEnumeration(void** iter) { 306 return backend_->EndEnumeration(iter); 307} 308 309void TracingCacheBackend::GetStats(StatsItems* stats) { 310 return backend_->GetStats(stats); 311} 312 313void TracingCacheBackend::OnExternalCacheHit(const std::string& key) { 314 return backend_->OnExternalCacheHit(key); 315} 316 317} // namespace disk_cache 318