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