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/very_simple/very_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/net_errors.h" | |
14 #include "net/disk_cache/very_simple/very_simple_synchronous_entry.h" | |
15 | |
16 namespace disk_cache { | |
17 | |
18 using base::Bind; | |
19 using base::Callback; | |
20 using base::FilePath; | |
21 using base::MessageLoopProxy; | |
22 using base::Owned; | |
23 using base::Time; | |
24 using base::Unretained; | |
25 using base::WorkerPool; | |
26 | |
27 namespace { | |
rvargas (doing something else)
2013/02/06 03:28:40
nit: can this be out of disk_cache?
gavinp
2013/02/08 23:17:51
Done.
| |
28 | |
29 typedef Entry::CompletionCallback CompletionCallback; | |
30 typedef VerySimpleSynchronousEntry::SynchronousEntryCallback | |
31 SynchronousEntryCallback; | |
32 typedef Callback<VerySimpleEntryImpl*(VerySimpleSynchronousEntry*)> | |
33 EntryFactoryCallback; | |
34 typedef Callback<void(VerySimpleSynchronousEntry*)> SetSyncCallback; | |
35 | |
36 // PendingCreationOperation represents a pending operation that is creating a | |
37 // new VerySimpleSynchronousEntry, such as OpenEntry() or CreateEntry(). After | |
38 // the new synchronous entry has been created, it uses its factory to create | |
39 // a VerySimpleEntryImpl and pass it back to the original caller. | |
40 class PendingCreationOperation { | |
41 public: | |
42 static SynchronousEntryCallback Create( | |
43 const EntryFactoryCallback& entry_factory_callback, | |
44 const CompletionCallback& completion_callback, | |
45 Entry** out_entry) { | |
46 PendingCreationOperation* operation = | |
rvargas (doing something else)
2013/02/06 03:28:40
Could you separate the implementation from the dec
gavinp
2013/02/08 23:17:51
Done.
| |
47 new PendingCreationOperation(entry_factory_callback, | |
48 completion_callback, | |
49 out_entry); | |
50 DCHECK(operation); | |
51 return Bind(&PendingCreationOperation::OnIOComplete, | |
52 Owned(operation)); | |
53 } | |
54 | |
55 private: | |
56 PendingCreationOperation(const EntryFactoryCallback& entry_factory_callback, | |
57 const CompletionCallback& completion_callback, | |
58 Entry** out_entry) | |
59 : entry_factory_callback_(entry_factory_callback), | |
60 completion_callback_(completion_callback), | |
61 out_entry_(out_entry) { | |
62 } | |
63 | |
64 void OnIOComplete(VerySimpleSynchronousEntry* sync_entry, int result) { | |
65 DCHECK_NE(net::ERR_IO_PENDING, result); | |
66 | |
67 if (result != net::OK) { | |
68 DCHECK_EQ(static_cast<VerySimpleSynchronousEntry*>(NULL), sync_entry); | |
rvargas (doing something else)
2013/02/06 03:28:40
nit: DCHECK(!sync_entry)
gavinp
2013/02/08 23:17:51
Done. I had to add some printing cruft, since othe
| |
69 completion_callback_.Run(result); | |
70 return; | |
71 } | |
72 DCHECK(sync_entry); | |
73 *out_entry_ = entry_factory_callback_.Run(sync_entry); | |
rvargas (doing something else)
2013/02/06 03:28:40
I'm not so happy with this pattern of run a task a
gavinp
2013/02/08 23:17:51
I'm sorry to hear you're unhappy with this pattern
| |
74 DCHECK(*out_entry_); | |
75 completion_callback_.Run(net::OK); | |
76 } | |
77 | |
78 EntryFactoryCallback entry_factory_callback_; | |
79 CompletionCallback completion_callback_; | |
80 Entry** out_entry_; | |
81 }; | |
82 | |
83 class PendingOperation { | |
rvargas (doing something else)
2013/02/06 03:28:40
nit: class description
gavinp
2013/02/08 23:17:51
Done.
| |
84 public: | |
85 static SynchronousEntryCallback Create( | |
86 const SetSyncCallback& set_sync_callback, | |
87 const CompletionCallback& completion_callback) { | |
88 PendingOperation* operation = new PendingOperation(set_sync_callback, | |
rvargas (doing something else)
2013/02/06 03:28:40
ditto (implementation vs declaration)
gavinp
2013/02/08 23:17:51
Done.
| |
89 completion_callback); | |
90 DCHECK(operation); | |
91 return Bind(&PendingOperation::OnIOComplete, Owned(operation)); | |
92 } | |
93 | |
94 private: | |
95 PendingOperation(const SetSyncCallback& set_sync_callback, | |
96 const CompletionCallback& completion_callback) | |
97 : set_sync_callback_(set_sync_callback), | |
98 completion_callback_(completion_callback) { | |
99 } | |
100 | |
101 void OnIOComplete(VerySimpleSynchronousEntry* sync_entry, int result) { | |
102 set_sync_callback_.Run(sync_entry); | |
rvargas (doing something else)
2013/02/06 03:28:40
ditto
| |
103 completion_callback_.Run(result); | |
104 } | |
105 | |
106 SetSyncCallback set_sync_callback_; | |
107 CompletionCallback completion_callback_; | |
108 }; | |
109 | |
110 } // namespace | |
111 | |
112 // static | |
113 int VerySimpleEntryImpl::OpenEntry(const FilePath& path, | |
114 const std::string& key, | |
115 Entry** entry, | |
116 const CompletionCallback& callback) { | |
117 SynchronousEntryCallback sync_entry_callback = | |
118 PendingCreationOperation::Create( | |
119 Bind(&VerySimpleEntryImpl::Create), callback, entry); | |
120 WorkerPool::PostTask(FROM_HERE, | |
rvargas (doing something else)
2013/02/06 03:28:40
You know that in general we don't like the worker
gavinp
2013/02/08 23:17:51
I don't know this. Can you expand on this?
rvargas (doing something else)
2013/02/13 01:48:46
That is documented on the header of worker pool.
| |
121 Bind(&VerySimpleSynchronousEntry::OpenEntry, path, key, | |
122 MessageLoopProxy::current(), | |
123 sync_entry_callback), | |
124 true); | |
125 return net::ERR_IO_PENDING; | |
126 } | |
127 | |
128 // static | |
129 int VerySimpleEntryImpl::CreateEntry(const FilePath& path, | |
130 const std::string& key, | |
131 Entry** entry, | |
132 const CompletionCallback& callback) { | |
133 SynchronousEntryCallback sync_entry_callback = | |
134 PendingCreationOperation::Create( | |
135 Bind(&VerySimpleEntryImpl::Create), callback, entry); | |
136 WorkerPool::PostTask(FROM_HERE, | |
137 Bind(&VerySimpleSynchronousEntry::CreateEntry, path, key, | |
138 MessageLoopProxy::current(), | |
139 sync_entry_callback), | |
140 true); | |
141 return net::ERR_IO_PENDING; | |
142 } | |
143 | |
144 // static | |
145 int VerySimpleEntryImpl::DoomEntry(const FilePath& path, | |
146 const std::string& key, | |
147 const CompletionCallback& callback) { | |
148 WorkerPool::PostTask(FROM_HERE, | |
149 Bind(&VerySimpleSynchronousEntry::DoomEntry, path, key, | |
150 MessageLoopProxy::current(), callback), | |
151 true); | |
152 return net::ERR_IO_PENDING; | |
153 } | |
154 | |
155 void VerySimpleEntryImpl::Doom() { | |
156 DCHECK(thread_checker_.CalledOnValidThread()); | |
157 WorkerPool::PostTask(FROM_HERE, | |
158 Bind(&VerySimpleSynchronousEntry::DoomAndClose, | |
rvargas (doing something else)
2013/02/06 03:28:40
DoomAndClose?
gavinp
2013/02/08 23:17:51
DoomAndClose!
rvargas (doing something else)
2013/02/13 01:48:46
I meant it was surprising behavior. As far as I ca
| |
159 Unretained(ReleaseSynchronousEntry())), | |
160 true); | |
161 has_been_doomed_ = true; | |
162 } | |
163 | |
164 void VerySimpleEntryImpl::Close() { | |
165 DCHECK(thread_checker_.CalledOnValidThread()); | |
166 if (!has_been_doomed_) { | |
167 WorkerPool::PostTask(FROM_HERE, | |
168 Bind(&VerySimpleSynchronousEntry::Close, | |
169 Unretained(ReleaseSynchronousEntry())), | |
170 true); | |
171 } | |
172 // Entry::Close() is expected to release this entry. See disk_cache.h for | |
173 // details. | |
174 delete this; | |
175 } | |
176 | |
177 std::string VerySimpleEntryImpl::GetKey() const { | |
178 DCHECK(thread_checker_.CalledOnValidThread()); | |
179 return key_; | |
180 } | |
181 | |
182 Time VerySimpleEntryImpl::GetLastUsed() const { | |
183 DCHECK(thread_checker_.CalledOnValidThread()); | |
184 DCHECK(synchronous_entry_); | |
185 return synchronous_entry_->last_used(); | |
186 } | |
187 | |
188 Time VerySimpleEntryImpl::GetLastModified() const { | |
189 DCHECK(thread_checker_.CalledOnValidThread()); | |
190 DCHECK(synchronous_entry_); | |
191 return synchronous_entry_->last_modified(); | |
192 } | |
193 | |
194 int32 VerySimpleEntryImpl::GetDataSize(int index) const { | |
195 DCHECK(thread_checker_.CalledOnValidThread()); | |
196 DCHECK(synchronous_entry_); | |
197 return synchronous_entry_->data_size(index); | |
198 } | |
199 | |
200 int VerySimpleEntryImpl::ReadData(int index, | |
201 int offset, | |
202 net::IOBuffer* buf, | |
203 int buf_len, | |
204 const CompletionCallback& callback) { | |
205 DCHECK(thread_checker_.CalledOnValidThread()); | |
206 DCHECK(synchronous_entry_); | |
207 SynchronousEntryCallback sync_entry_callback = | |
208 PendingOperation::Create(Bind(&VerySimpleEntryImpl::SetSynchronousEntry, | |
209 weak_ptr_factory_.GetWeakPtr()), | |
210 callback); | |
211 WorkerPool::PostTask(FROM_HERE, | |
212 Bind(&VerySimpleSynchronousEntry::ReadData, | |
213 Unretained(ReleaseSynchronousEntry()), index, | |
rvargas (doing something else)
2013/02/06 03:28:40
is this intended to enforce exclusive access to si
gavinp
2013/02/08 23:17:51
This is intended to enforce thread safety, and the
| |
214 offset, Unretained(buf), buf_len, | |
rvargas (doing something else)
2013/02/06 03:28:40
cannot be unretained
gavinp
2013/02/08 23:17:51
Tell me more?
rvargas (doing something else)
2013/02/13 01:48:46
that would mean keeping the buffer without grabbin
| |
215 sync_entry_callback), | |
216 true); | |
217 return net::ERR_IO_PENDING; | |
218 } | |
219 | |
220 int VerySimpleEntryImpl::WriteData(int index, | |
221 int offset, | |
222 net::IOBuffer* buf, | |
223 int buf_len, | |
224 const CompletionCallback& callback, | |
225 bool truncate) { | |
226 DCHECK(thread_checker_.CalledOnValidThread()); | |
227 DCHECK(synchronous_entry_); | |
228 SynchronousEntryCallback sync_entry_callback = | |
229 PendingOperation::Create(Bind(&VerySimpleEntryImpl::SetSynchronousEntry, | |
230 weak_ptr_factory_.GetWeakPtr()), | |
231 callback); | |
232 WorkerPool::PostTask(FROM_HERE, | |
233 Bind(&VerySimpleSynchronousEntry::WriteData, | |
234 Unretained(ReleaseSynchronousEntry()), index, | |
235 offset, Unretained(buf), buf_len, | |
236 sync_entry_callback, truncate), | |
237 true); | |
238 return net::ERR_IO_PENDING; | |
239 } | |
240 | |
241 int VerySimpleEntryImpl::ReadSparseData(int64 offset, | |
242 net::IOBuffer* buf, | |
243 int buf_len, | |
244 const CompletionCallback& callback) { | |
245 DCHECK(thread_checker_.CalledOnValidThread()); | |
246 return net::ERR_FAILED; | |
247 } | |
248 | |
249 int VerySimpleEntryImpl::WriteSparseData(int64 offset, | |
250 net::IOBuffer* buf, | |
251 int buf_len, | |
252 const CompletionCallback& callback) { | |
253 DCHECK(thread_checker_.CalledOnValidThread()); | |
254 return net::ERR_FAILED; | |
255 } | |
256 | |
257 int VerySimpleEntryImpl::GetAvailableRange(int64 offset, | |
258 int len, | |
259 int64* start, | |
260 const CompletionCallback& callback) { | |
261 DCHECK(thread_checker_.CalledOnValidThread()); | |
262 return net::ERR_FAILED; | |
263 } | |
264 | |
265 bool VerySimpleEntryImpl::CouldBeSparse() const { | |
266 DCHECK(thread_checker_.CalledOnValidThread()); | |
267 return false; | |
268 } | |
269 | |
270 void VerySimpleEntryImpl::CancelSparseIO() { | |
271 DCHECK(thread_checker_.CalledOnValidThread()); | |
272 } | |
273 | |
274 int VerySimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { | |
275 DCHECK(thread_checker_.CalledOnValidThread()); | |
276 return net::ERR_FAILED; | |
277 } | |
278 | |
279 VerySimpleEntryImpl::VerySimpleEntryImpl( | |
280 VerySimpleSynchronousEntry* synchronous_entry) | |
281 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | |
282 key_(synchronous_entry->key()), | |
rvargas (doing something else)
2013/02/06 03:28:40
why duplicate the key?
gavinp
2013/02/08 23:17:51
Thread safe access. In practice, if SimpleSynchron
rvargas (doing something else)
2013/02/13 01:48:46
The code is happy to reach into access times and s
| |
283 synchronous_entry_(synchronous_entry), | |
284 has_been_doomed_(false) { | |
285 DCHECK(synchronous_entry); | |
286 } | |
287 | |
288 VerySimpleEntryImpl::~VerySimpleEntryImpl() { | |
289 DCHECK(thread_checker_.CalledOnValidThread()); | |
290 DCHECK_EQ(static_cast<VerySimpleSynchronousEntry*>(NULL), synchronous_entry_); | |
rvargas (doing something else)
2013/02/06 03:28:40
!sync_entry_
gavinp
2013/02/08 23:17:51
Done.
| |
291 } | |
292 | |
293 // static | |
294 VerySimpleEntryImpl* VerySimpleEntryImpl::Create( | |
295 VerySimpleSynchronousEntry* synchronous_entry) { | |
296 return new VerySimpleEntryImpl(synchronous_entry); | |
297 } | |
298 | |
299 VerySimpleSynchronousEntry* VerySimpleEntryImpl::ReleaseSynchronousEntry() { | |
300 DCHECK(synchronous_entry_); | |
301 VerySimpleSynchronousEntry* retval = synchronous_entry_; | |
302 synchronous_entry_ = NULL; | |
303 return retval; | |
304 } | |
305 | |
306 void VerySimpleEntryImpl::SetSynchronousEntry( | |
307 VerySimpleSynchronousEntry* synchronous_entry) { | |
308 DCHECK_EQ(static_cast<VerySimpleSynchronousEntry*>(NULL), synchronous_entry_); | |
309 synchronous_entry_ = synchronous_entry; | |
310 } | |
311 | |
312 } // namespace disk_cache | |
OLD | NEW |