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 PendingCreationOperation represents a pending operation that is creating a | |
35 // new SimpleSynchronousEntry, such as OpenEntry() or CreateEntry(). It ensures | |
36 // that a SimpleEntryImpl is only created after the underlying synchronous | |
37 // operation has succeeded. | |
38 class SimpleEntryImpl::PendingCreationOperation { | |
39 public: | |
40 static SynchronousEntryCallback Create( | |
41 const CompletionCallback& completion_callback, | |
42 Entry** out_entry); | |
43 | |
44 private: | |
45 PendingCreationOperation(const CompletionCallback& completion_callback, | |
46 Entry** out_entry); | |
47 | |
48 void OnIOComplete(SimpleSynchronousEntry* sync_entry, int result); | |
49 | |
50 CompletionCallback completion_callback_; | |
51 Entry** out_entry_; | |
52 }; | |
53 | |
54 // A PendingEntryOperation represents an operation on a SynchronousEntry while | |
55 // it is in flight. It informs the owning SimpleEntryImpl of IO completion if | |
56 // necessary, as well as calling the IO completion callback. | |
57 class SimpleEntryImpl::PendingEntryOperation { | |
58 public: | |
59 static SynchronousEntryCallback Create( | |
60 const WeakPtr<SimpleEntryImpl>& entry, | |
61 const CompletionCallback& completion_callback); | |
62 | |
63 private: | |
64 PendingEntryOperation(const WeakPtr<SimpleEntryImpl>& entry, | |
65 const CompletionCallback& completion_callback); | |
66 | |
67 void OnIOComplete(SimpleSynchronousEntry* sync_entry, int result); | |
68 | |
69 WeakPtr<SimpleEntryImpl> entry_; | |
70 CompletionCallback completion_callback_; | |
71 }; | |
72 | |
73 // static | |
74 SynchronousEntryCallback SimpleEntryImpl::PendingCreationOperation::Create( | |
75 const CompletionCallback& completion_callback, | |
76 Entry** out_entry) { | |
77 PendingCreationOperation* operation = | |
78 new PendingCreationOperation(completion_callback, out_entry); | |
79 DCHECK(operation); | |
80 return base::Bind(&PendingCreationOperation::OnIOComplete, | |
81 base::Owned(operation)); | |
82 } | |
83 | |
84 SimpleEntryImpl::PendingCreationOperation::PendingCreationOperation( | |
85 const CompletionCallback& completion_callback, | |
86 Entry** out_entry) : completion_callback_(completion_callback), | |
87 out_entry_(out_entry) { | |
88 } | |
89 | |
90 void SimpleEntryImpl::PendingCreationOperation::OnIOComplete( | |
91 SimpleSynchronousEntry* sync_entry, | |
92 int result) { | |
93 DCHECK_NE(net::ERR_IO_PENDING, result); | |
94 | |
95 if (result != net::OK) { | |
96 DCHECK(!sync_entry) << "sync_entry = " << sync_entry; | |
97 completion_callback_.Run(result); | |
98 return; | |
99 } | |
100 DCHECK(sync_entry); | |
101 *out_entry_ = new SimpleEntryImpl(sync_entry); | |
102 DCHECK(*out_entry_); | |
103 completion_callback_.Run(net::OK); | |
104 } | |
105 | |
106 // static | |
107 SynchronousEntryCallback SimpleEntryImpl::PendingEntryOperation::Create( | |
108 const WeakPtr<SimpleEntryImpl>& entry, | |
109 const CompletionCallback& completion_callback) { | |
110 PendingEntryOperation* operation = new PendingEntryOperation(entry, | |
111 completion_callback); | |
112 DCHECK(operation); | |
113 return base::Bind(&PendingEntryOperation::OnIOComplete, | |
114 base::Owned(operation)); | |
115 } | |
116 | |
117 SimpleEntryImpl::PendingEntryOperation::PendingEntryOperation( | |
118 const WeakPtr<SimpleEntryImpl>& entry, | |
119 const CompletionCallback& completion_callback) | |
120 : entry_(entry), | |
121 completion_callback_(completion_callback) { | |
122 } | |
123 | |
124 void SimpleEntryImpl::PendingEntryOperation::OnIOComplete( | |
125 SimpleSynchronousEntry* sync_entry, | |
126 int result) { | |
127 DCHECK(sync_entry); | |
128 if (entry_) | |
129 entry_->SetSynchronousEntry(sync_entry); | |
130 completion_callback_.Run(result); | |
131 } | |
132 | |
133 // static | |
134 int SimpleEntryImpl::OpenEntry(const FilePath& path, | |
135 const std::string& key, | |
136 Entry** entry, | |
137 const CompletionCallback& callback) { | |
138 SynchronousEntryCallback sync_entry_callback = | |
139 PendingCreationOperation::Create(callback, entry); | |
140 | |
141 WorkerPool::PostTask(FROM_HERE, | |
142 base::Bind(&SimpleSynchronousEntry::OpenEntry, path, key, | |
143 MessageLoopProxy::current(), | |
144 sync_entry_callback), | |
145 true); | |
146 return net::ERR_IO_PENDING; | |
147 } | |
148 | |
149 // static | |
150 int SimpleEntryImpl::CreateEntry(const FilePath& path, | |
151 const std::string& key, | |
152 Entry** entry, | |
153 const CompletionCallback& callback) { | |
154 SynchronousEntryCallback sync_entry_callback = | |
155 PendingCreationOperation::Create(callback, entry); | |
156 WorkerPool::PostTask(FROM_HERE, | |
157 base::Bind(&SimpleSynchronousEntry::CreateEntry, path, | |
158 key, MessageLoopProxy::current(), | |
159 sync_entry_callback), | |
160 true); | |
161 return net::ERR_IO_PENDING; | |
162 } | |
163 | |
164 // static | |
165 int SimpleEntryImpl::DoomEntry(const FilePath& path, | |
166 const std::string& key, | |
167 const CompletionCallback& callback) { | |
168 WorkerPool::PostTask(FROM_HERE, | |
169 base::Bind(&SimpleSynchronousEntry::DoomEntry, path, key, | |
170 MessageLoopProxy::current(), callback), | |
171 true); | |
172 return net::ERR_IO_PENDING; | |
173 } | |
174 | |
175 void SimpleEntryImpl::Doom() { | |
176 DCHECK(thread_checker_.CalledOnValidThread()); | |
177 if (!synchronous_entry_) { | |
felipeg
2013/02/12 14:50:22
as discussed,
instead of checking the synchronous_
gavinp
2013/02/12 15:45:57
Done.
| |
178 NOTIMPLEMENTED() << ": Overlapping an asynchronous operation."; | |
179 return; | |
180 } | |
181 WorkerPool::PostTask(FROM_HERE, | |
182 base::Bind(&SimpleSynchronousEntry::DoomAndClose, | |
183 base::Unretained(ReleaseSynchronousEntry())), | |
184 true); | |
185 has_been_doomed_ = true; | |
186 } | |
187 | |
188 void SimpleEntryImpl::Close() { | |
189 DCHECK(thread_checker_.CalledOnValidThread()); | |
190 if (!synchronous_entry_) { | |
191 NOTIMPLEMENTED() << ": Overlapping an asynchronous operation."; | |
192 delete this; | |
193 return; | |
194 } | |
195 if (!has_been_doomed_) { | |
196 WorkerPool::PostTask(FROM_HERE, | |
197 base::Bind(&SimpleSynchronousEntry::Close, | |
198 base::Unretained( | |
199 ReleaseSynchronousEntry())), | |
200 true); | |
201 } | |
202 // Entry::Close() is expected to release this entry. See disk_cache.h for | |
203 // details. | |
204 delete this; | |
205 } | |
206 | |
207 std::string SimpleEntryImpl::GetKey() const { | |
208 DCHECK(thread_checker_.CalledOnValidThread()); | |
209 return key_; | |
210 } | |
211 | |
212 Time SimpleEntryImpl::GetLastUsed() const { | |
213 DCHECK(thread_checker_.CalledOnValidThread()); | |
214 if (!synchronous_entry_) { | |
215 NOTIMPLEMENTED() << ": Synchronous operations overlapping an asynchronous " | |
216 << "operation."; | |
217 NOTREACHED(); | |
218 } | |
219 return synchronous_entry_->last_used(); | |
220 } | |
221 | |
222 Time SimpleEntryImpl::GetLastModified() const { | |
223 DCHECK(thread_checker_.CalledOnValidThread()); | |
224 if (!synchronous_entry_) { | |
225 NOTIMPLEMENTED() << ": Synchronous operations overlapping an asynchronous " | |
226 << "operation."; | |
227 NOTREACHED(); | |
228 } | |
229 return synchronous_entry_->last_modified(); | |
230 } | |
231 | |
232 int32 SimpleEntryImpl::GetDataSize(int index) const { | |
233 DCHECK(thread_checker_.CalledOnValidThread()); | |
234 if (!synchronous_entry_) { | |
235 NOTIMPLEMENTED() << ": Synchronous operations overlapping an asynchronous " | |
236 << "operation."; | |
237 NOTREACHED(); | |
238 } | |
239 return synchronous_entry_->data_size(index); | |
240 } | |
241 | |
242 int SimpleEntryImpl::ReadData(int index, | |
243 int offset, | |
244 net::IOBuffer* buf, | |
245 int buf_len, | |
246 const CompletionCallback& callback) { | |
247 DCHECK(thread_checker_.CalledOnValidThread()); | |
248 // TODO(gavinp): Add support for overlapping reads. The net::HttpCache does | |
249 // make overlapping read requests when multiple transactions access the same | |
250 // entry as read only. | |
251 if (!synchronous_entry_) { | |
252 NOTIMPLEMENTED() << ": Overlapping calls to ReadData."; | |
253 NOTREACHED(); | |
254 } | |
255 SynchronousEntryCallback sync_entry_callback = | |
256 PendingEntryOperation::Create(weak_ptr_factory_.GetWeakPtr(), callback); | |
257 WorkerPool::PostTask(FROM_HERE, | |
258 base::Bind(&SimpleSynchronousEntry::ReadData, | |
259 base::Unretained(ReleaseSynchronousEntry()), | |
260 index, offset, scoped_refptr<IOBuffer>(buf), | |
261 buf_len, sync_entry_callback), | |
262 true); | |
263 return net::ERR_IO_PENDING; | |
264 } | |
265 | |
266 int SimpleEntryImpl::WriteData(int index, | |
267 int offset, | |
268 net::IOBuffer* buf, | |
269 int buf_len, | |
270 const CompletionCallback& callback, | |
271 bool truncate) { | |
272 DCHECK(thread_checker_.CalledOnValidThread()); | |
273 if (!synchronous_entry_) { | |
274 NOTIMPLEMENTED() << ": Overlapping calls to WriteData."; | |
275 NOTREACHED(); | |
276 } | |
277 SynchronousEntryCallback sync_entry_callback = | |
278 PendingEntryOperation::Create(weak_ptr_factory_.GetWeakPtr(), callback); | |
279 WorkerPool::PostTask(FROM_HERE, | |
280 base::Bind(&SimpleSynchronousEntry::WriteData, | |
281 base::Unretained(ReleaseSynchronousEntry()), | |
282 index, offset, scoped_refptr<IOBuffer>(buf), | |
283 buf_len, sync_entry_callback, truncate), | |
284 true); | |
285 return net::ERR_IO_PENDING; | |
286 } | |
287 | |
288 int SimpleEntryImpl::ReadSparseData(int64 offset, | |
289 net::IOBuffer* buf, | |
290 int buf_len, | |
291 const CompletionCallback& callback) { | |
292 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
293 DCHECK(thread_checker_.CalledOnValidThread()); | |
294 NOTIMPLEMENTED(); | |
295 return net::ERR_FAILED; | |
296 } | |
297 | |
298 int SimpleEntryImpl::WriteSparseData(int64 offset, | |
299 net::IOBuffer* buf, | |
300 int buf_len, | |
301 const CompletionCallback& callback) { | |
302 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
303 DCHECK(thread_checker_.CalledOnValidThread()); | |
304 NOTIMPLEMENTED(); | |
305 return net::ERR_FAILED; | |
306 } | |
307 | |
308 int SimpleEntryImpl::GetAvailableRange(int64 offset, | |
309 int len, | |
310 int64* start, | |
311 const CompletionCallback& callback) { | |
312 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
313 DCHECK(thread_checker_.CalledOnValidThread()); | |
314 NOTIMPLEMENTED(); | |
315 return net::ERR_FAILED; | |
316 } | |
317 | |
318 bool SimpleEntryImpl::CouldBeSparse() const { | |
319 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
320 DCHECK(thread_checker_.CalledOnValidThread()); | |
321 return false; | |
322 } | |
323 | |
324 void SimpleEntryImpl::CancelSparseIO() { | |
325 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
326 DCHECK(thread_checker_.CalledOnValidThread()); | |
327 NOTIMPLEMENTED(); | |
328 } | |
329 | |
330 int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { | |
331 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
332 DCHECK(thread_checker_.CalledOnValidThread()); | |
333 NOTIMPLEMENTED(); | |
334 return net::ERR_FAILED; | |
335 } | |
336 | |
337 SimpleEntryImpl::SimpleEntryImpl( | |
338 SimpleSynchronousEntry* synchronous_entry) | |
339 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | |
340 key_(synchronous_entry->key()), | |
341 synchronous_entry_(synchronous_entry), | |
342 has_been_doomed_(false) { | |
343 DCHECK(synchronous_entry); | |
344 } | |
345 | |
346 SimpleEntryImpl::~SimpleEntryImpl() { | |
347 DCHECK(thread_checker_.CalledOnValidThread()); | |
348 DCHECK(!synchronous_entry_) << "synchronous_entry_ = " << synchronous_entry_; | |
349 } | |
350 | |
351 SimpleSynchronousEntry* SimpleEntryImpl::ReleaseSynchronousEntry() { | |
352 DCHECK(synchronous_entry_); | |
353 SimpleSynchronousEntry* retval = synchronous_entry_; | |
354 synchronous_entry_ = NULL; | |
355 return retval; | |
356 } | |
357 | |
358 void SimpleEntryImpl::SetSynchronousEntry( | |
359 SimpleSynchronousEntry* synchronous_entry) { | |
360 DCHECK(!synchronous_entry_) << "synchronous_entry_ = " << synchronous_entry_; | |
361 synchronous_entry_ = synchronous_entry; | |
362 } | |
363 | |
364 } // namespace disk_cache | |
OLD | NEW |