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