OLD | NEW |
---|---|
(Empty) | |
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/simple/simple_entry_impl.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/bind_helpers.h" | |
9 #include "base/callback.h" | |
10 #include "base/location.h" | |
11 #include "base/message_loop_proxy.h" | |
12 #include "base/threading/worker_pool.h" | |
13 #include "net/base/io_buffer.h" | |
14 #include "net/base/net_errors.h" | |
15 #include "net/disk_cache/simple/simple_synchronous_entry.h" | |
16 | |
17 | |
18 namespace { | |
19 | |
20 typedef disk_cache::Entry::CompletionCallback CompletionCallback; | |
21 typedef disk_cache::SimpleSynchronousEntry::SynchronousEntryCallback | |
22 SynchronousEntryCallback; | |
23 | |
24 } // namespace | |
25 | |
26 namespace disk_cache { | |
27 | |
28 using base::FilePath; | |
29 using base::MessageLoopProxy; | |
30 using base::Time; | |
31 using base::WeakPtr; | |
32 using base::WorkerPool; | |
33 | |
34 // A PendingOperation represents an operation on a SynchronousEntry while it is | |
35 // in flight. It informs the owning SimpleEntryImpl of IO completion if | |
36 // necessary, as well as calling the IO completion callback. | |
37 class SimpleEntryImpl::PendingOperation { | |
pasko-google - do not use
2013/02/11 13:59:25
maybe a PendingEntryOperation would be a better na
gavinp
2013/02/11 17:55:50
Done.
| |
38 public: | |
39 static SynchronousEntryCallback Create( | |
40 const WeakPtr<SimpleEntryImpl>& entry, | |
41 const CompletionCallback& completion_callback); | |
42 | |
43 private: | |
44 PendingOperation(const WeakPtr<SimpleEntryImpl>& entry, | |
45 const CompletionCallback& completion_callback); | |
46 | |
47 void OnIOComplete(SimpleSynchronousEntry* sync_entry, int result); | |
48 | |
49 WeakPtr<SimpleEntryImpl> entry_; | |
50 CompletionCallback completion_callback_; | |
51 }; | |
52 | |
53 // A PendingCreationOperation represents a pending operation that is creating a | |
54 // new SimpleSynchronousEntry, such as OpenEntry() or CreateEntry(). It ensures | |
55 // that a SimpleEntryImpl is only created after the underlying synchronous | |
56 // operation has succeeded. | |
57 class SimpleEntryImpl::PendingCreationOperation { | |
58 public: | |
59 static SynchronousEntryCallback Create( | |
60 const CompletionCallback& completion_callback, | |
61 Entry** out_entry); | |
62 | |
63 private: | |
64 PendingCreationOperation(const CompletionCallback& completion_callback, | |
65 Entry** out_entry); | |
66 | |
67 void OnIOComplete(SimpleSynchronousEntry* sync_entry, int result); | |
68 | |
69 CompletionCallback completion_callback_; | |
70 Entry** out_entry_; | |
71 }; | |
72 | |
73 // static | |
74 SynchronousEntryCallback SimpleEntryImpl::PendingOperation::Create( | |
75 const WeakPtr<SimpleEntryImpl>& entry, | |
76 const CompletionCallback& completion_callback) { | |
77 PendingOperation* operation = new PendingOperation(entry, | |
78 completion_callback); | |
79 DCHECK(operation); | |
80 return base::Bind(&PendingOperation::OnIOComplete, base::Owned(operation)); | |
81 } | |
82 | |
83 SimpleEntryImpl::PendingOperation::PendingOperation( | |
84 const WeakPtr<SimpleEntryImpl>& entry, | |
85 const CompletionCallback& completion_callback) | |
86 : entry_(entry), | |
87 completion_callback_(completion_callback) { | |
88 } | |
89 | |
90 void SimpleEntryImpl::PendingOperation::OnIOComplete( | |
91 SimpleSynchronousEntry* sync_entry, | |
92 int result) { | |
93 DCHECK(sync_entry); | |
94 if (entry_) | |
95 entry_->SetSynchronousEntry(sync_entry); | |
96 completion_callback_.Run(result); | |
97 } | |
98 | |
99 // static | |
100 SynchronousEntryCallback SimpleEntryImpl::PendingCreationOperation::Create( | |
101 const CompletionCallback& completion_callback, | |
102 Entry** out_entry) { | |
103 PendingCreationOperation* operation = | |
104 new PendingCreationOperation(completion_callback, out_entry); | |
105 DCHECK(operation); | |
106 return base::Bind(&PendingCreationOperation::OnIOComplete, | |
107 base::Owned(operation)); | |
108 } | |
109 | |
110 SimpleEntryImpl::PendingCreationOperation::PendingCreationOperation( | |
111 const CompletionCallback& completion_callback, | |
112 Entry** out_entry) : completion_callback_(completion_callback), | |
113 out_entry_(out_entry) { | |
114 } | |
115 | |
116 void SimpleEntryImpl::PendingCreationOperation::OnIOComplete( | |
117 SimpleSynchronousEntry* sync_entry, | |
118 int result) { | |
119 DCHECK_NE(net::ERR_IO_PENDING, result); | |
120 | |
121 if (result != net::OK) { | |
122 DCHECK(!sync_entry) << "sync_entry = " << sync_entry; | |
123 completion_callback_.Run(result); | |
124 return; | |
125 } | |
126 DCHECK(sync_entry); | |
127 *out_entry_ = new SimpleEntryImpl(sync_entry); | |
128 DCHECK(*out_entry_); | |
129 completion_callback_.Run(net::OK); | |
130 } | |
131 | |
132 // static | |
133 int SimpleEntryImpl::OpenEntry(const FilePath& path, | |
134 const std::string& key, | |
135 Entry** entry, | |
136 const CompletionCallback& callback) { | |
137 SynchronousEntryCallback sync_entry_callback = | |
138 PendingCreationOperation::Create(callback, entry); | |
139 | |
140 WorkerPool::PostTask(FROM_HERE, | |
141 base::Bind(&SimpleSynchronousEntry::OpenEntry, path, key, | |
142 MessageLoopProxy::current(), | |
143 sync_entry_callback), | |
144 true); | |
145 return net::ERR_IO_PENDING; | |
146 } | |
147 | |
148 // static | |
149 int SimpleEntryImpl::CreateEntry(const FilePath& path, | |
150 const std::string& key, | |
151 Entry** entry, | |
152 const CompletionCallback& callback) { | |
153 SynchronousEntryCallback sync_entry_callback = | |
154 PendingCreationOperation::Create(callback, entry); | |
155 WorkerPool::PostTask(FROM_HERE, | |
156 base::Bind(&SimpleSynchronousEntry::CreateEntry, path, | |
157 key, MessageLoopProxy::current(), | |
158 sync_entry_callback), | |
159 true); | |
160 return net::ERR_IO_PENDING; | |
161 } | |
162 | |
163 // static | |
164 int SimpleEntryImpl::DoomEntry(const FilePath& path, | |
165 const std::string& key, | |
166 const CompletionCallback& callback) { | |
167 WorkerPool::PostTask(FROM_HERE, | |
168 base::Bind(&SimpleSynchronousEntry::DoomEntry, path, key, | |
169 MessageLoopProxy::current(), callback), | |
170 true); | |
171 return net::ERR_IO_PENDING; | |
172 } | |
173 | |
174 void SimpleEntryImpl::Doom() { | |
175 DCHECK(thread_checker_.CalledOnValidThread()); | |
176 WorkerPool::PostTask(FROM_HERE, | |
177 base::Bind(&SimpleSynchronousEntry::DoomAndClose, | |
178 base::Unretained(ReleaseSynchronousEntry())), | |
179 true); | |
180 has_been_doomed_ = true; | |
181 } | |
182 | |
183 void SimpleEntryImpl::Close() { | |
184 DCHECK(thread_checker_.CalledOnValidThread()); | |
185 if (!has_been_doomed_) { | |
186 WorkerPool::PostTask(FROM_HERE, | |
187 base::Bind(&SimpleSynchronousEntry::Close, | |
188 base::Unretained( | |
189 ReleaseSynchronousEntry())), | |
190 true); | |
191 } | |
192 // Entry::Close() is expected to release this entry. See disk_cache.h for | |
193 // details. | |
194 delete this; | |
195 } | |
196 | |
197 std::string SimpleEntryImpl::GetKey() const { | |
198 DCHECK(thread_checker_.CalledOnValidThread()); | |
199 return key_; | |
200 } | |
201 | |
202 Time SimpleEntryImpl::GetLastUsed() const { | |
203 DCHECK(thread_checker_.CalledOnValidThread()); | |
204 DCHECK(synchronous_entry_); | |
205 return synchronous_entry_->last_used(); | |
pasko-google - do not use
2013/02/11 13:59:25
is there a hidden assumption that last used cannot
gavinp
2013/02/11 17:55:50
Hopefully. The reads will change a bit once checks
| |
206 } | |
207 | |
208 Time SimpleEntryImpl::GetLastModified() const { | |
209 DCHECK(thread_checker_.CalledOnValidThread()); | |
210 DCHECK(synchronous_entry_); | |
211 return synchronous_entry_->last_modified(); | |
212 } | |
213 | |
214 int32 SimpleEntryImpl::GetDataSize(int index) const { | |
215 DCHECK(thread_checker_.CalledOnValidThread()); | |
216 DCHECK(synchronous_entry_); | |
217 return synchronous_entry_->data_size(index); | |
218 } | |
219 | |
220 int SimpleEntryImpl::ReadData(int index, | |
221 int offset, | |
222 net::IOBuffer* buf, | |
223 int buf_len, | |
224 const CompletionCallback& callback) { | |
225 DCHECK(thread_checker_.CalledOnValidThread()); | |
226 // TODO(gavinp): Add support for overlapping reads. The net::HttpCache does | |
227 // make overlapping read requests when multiple transactions access the same | |
228 // entry as read only. | |
pasko-google - do not use
2013/02/11 13:59:25
does it happen often? on what occasion?
gavinp
2013/02/11 17:55:50
Yes, if for instance a page uses google served jQu
| |
229 DCHECK(synchronous_entry_); | |
230 SynchronousEntryCallback sync_entry_callback = | |
231 PendingOperation::Create(weak_ptr_factory_.GetWeakPtr(), callback); | |
232 WorkerPool::PostTask(FROM_HERE, | |
233 base::Bind(&SimpleSynchronousEntry::ReadData, | |
234 base::Unretained(ReleaseSynchronousEntry()), | |
235 index, offset, scoped_refptr<IOBuffer>(buf), | |
236 buf_len, sync_entry_callback), | |
237 true); | |
238 return net::ERR_IO_PENDING; | |
239 } | |
240 | |
241 int SimpleEntryImpl::WriteData(int index, | |
242 int offset, | |
243 net::IOBuffer* buf, | |
244 int buf_len, | |
245 const CompletionCallback& callback, | |
246 bool truncate) { | |
247 for (int i = 0; i < buf_len; ++i) { | |
248 char c ALLOW_UNUSED = buf->data()[i]; | |
pasko-google - do not use
2013/02/11 13:59:25
It is hard to believe that this will be optimized
gavinp
2013/02/11 17:55:50
That is debugging code that made it into this uplo
| |
249 } | |
250 DCHECK(thread_checker_.CalledOnValidThread()); | |
251 DCHECK(synchronous_entry_); | |
252 SynchronousEntryCallback sync_entry_callback = | |
253 PendingOperation::Create(weak_ptr_factory_.GetWeakPtr(), callback); | |
254 WorkerPool::PostTask(FROM_HERE, | |
255 base::Bind(&SimpleSynchronousEntry::WriteData, | |
256 base::Unretained(ReleaseSynchronousEntry()), | |
257 index, offset, scoped_refptr<IOBuffer>(buf), | |
258 buf_len, sync_entry_callback, truncate), | |
259 true); | |
260 return net::ERR_IO_PENDING; | |
261 } | |
262 | |
263 int SimpleEntryImpl::ReadSparseData(int64 offset, | |
264 net::IOBuffer* buf, | |
265 int buf_len, | |
266 const CompletionCallback& callback) { | |
267 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
268 DCHECK(thread_checker_.CalledOnValidThread()); | |
269 return net::ERR_FAILED; | |
270 } | |
271 | |
272 int SimpleEntryImpl::WriteSparseData(int64 offset, | |
273 net::IOBuffer* buf, | |
274 int buf_len, | |
275 const CompletionCallback& callback) { | |
276 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
277 DCHECK(thread_checker_.CalledOnValidThread()); | |
278 return net::ERR_FAILED; | |
279 } | |
280 | |
281 int SimpleEntryImpl::GetAvailableRange(int64 offset, | |
282 int len, | |
283 int64* start, | |
284 const CompletionCallback& callback) { | |
285 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
286 DCHECK(thread_checker_.CalledOnValidThread()); | |
287 return net::ERR_FAILED; | |
288 } | |
289 | |
290 bool SimpleEntryImpl::CouldBeSparse() const { | |
291 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
292 DCHECK(thread_checker_.CalledOnValidThread()); | |
293 return false; | |
294 } | |
295 | |
296 void SimpleEntryImpl::CancelSparseIO() { | |
297 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
298 DCHECK(thread_checker_.CalledOnValidThread()); | |
299 } | |
300 | |
301 int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { | |
302 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
303 DCHECK(thread_checker_.CalledOnValidThread()); | |
304 return net::ERR_FAILED; | |
305 } | |
306 | |
307 SimpleEntryImpl::SimpleEntryImpl( | |
308 SimpleSynchronousEntry* synchronous_entry) | |
309 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | |
310 key_(synchronous_entry->key()), | |
311 synchronous_entry_(synchronous_entry), | |
312 has_been_doomed_(false) { | |
313 DCHECK(synchronous_entry); | |
314 } | |
315 | |
316 SimpleEntryImpl::~SimpleEntryImpl() { | |
317 DCHECK(thread_checker_.CalledOnValidThread()); | |
318 DCHECK(!synchronous_entry_) << "synchronous_entry_ = " << synchronous_entry_; | |
319 } | |
320 | |
321 SimpleSynchronousEntry* SimpleEntryImpl::ReleaseSynchronousEntry() { | |
322 DCHECK(synchronous_entry_); | |
323 SimpleSynchronousEntry* retval = synchronous_entry_; | |
324 synchronous_entry_ = NULL; | |
325 return retval; | |
326 } | |
327 | |
328 void SimpleEntryImpl::SetSynchronousEntry( | |
329 SimpleSynchronousEntry* synchronous_entry) { | |
330 DCHECK(!synchronous_entry_) << "synchronous_entry_ = " << synchronous_entry_; | |
331 synchronous_entry_ = synchronous_entry; | |
332 } | |
333 | |
334 } // namespace disk_cache | |
OLD | NEW |