• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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