OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/disk_cache/simple/simple_entry_impl.h" | 5 #include "net/disk_cache/simple/simple_entry_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
81 index->Remove(key); | 81 index->Remove(key); |
82 WorkerPool::PostTask(FROM_HERE, | 82 WorkerPool::PostTask(FROM_HERE, |
83 base::Bind(&SimpleSynchronousEntry::DoomEntry, path, key, | 83 base::Bind(&SimpleSynchronousEntry::DoomEntry, path, key, |
84 MessageLoopProxy::current(), callback), | 84 MessageLoopProxy::current(), callback), |
85 true); | 85 true); |
86 return net::ERR_IO_PENDING; | 86 return net::ERR_IO_PENDING; |
87 } | 87 } |
88 | 88 |
89 void SimpleEntryImpl::Doom() { | 89 void SimpleEntryImpl::Doom() { |
90 DCHECK(io_thread_checker_.CalledOnValidThread()); | 90 DCHECK(io_thread_checker_.CalledOnValidThread()); |
91 DCHECK(!operation_running_); | |
91 #if defined(OS_POSIX) | 92 #if defined(OS_POSIX) |
92 // This call to static SimpleEntryImpl::DoomEntry() will just erase the | 93 // This call to static SimpleEntryImpl::DoomEntry() will just erase the |
93 // underlying files. On POSIX, this is fine; the files are still open on the | 94 // underlying files. On POSIX, this is fine; the files are still open on the |
94 // SimpleSynchronousEntry, and operations can even happen on them. The files | 95 // SimpleSynchronousEntry, and operations can even happen on them. The files |
95 // will be removed from the filesystem when they are closed. | 96 // will be removed from the filesystem when they are closed. |
96 DoomEntry(index_, path_, key_, CompletionCallback()); | 97 DoomEntry(index_, path_, key_, CompletionCallback()); |
97 #else | 98 #else |
98 NOTIMPLEMENTED(); | 99 NOTIMPLEMENTED(); |
99 #endif | 100 #endif |
100 } | 101 } |
101 | 102 |
102 void SimpleEntryImpl::Close() { | 103 void SimpleEntryImpl::Close() { |
103 DCHECK(io_thread_checker_.CalledOnValidThread()); | 104 DCHECK(io_thread_checker_.CalledOnValidThread()); |
104 if (!synchronous_entry_in_use_by_worker_) { | 105 if (operation_running_) { |
gavinp
2013/04/17 11:04:36
I think if you rebase on top of https://codereview
felipeg
2013/04/17 11:51:22
If I am going to land before you, I think I should
gavinp
2013/04/17 13:13:45
Agreed. And whoever wins the race dodges the merge
| |
105 WorkerPool::PostTask(FROM_HERE, | 106 // Postpone close operation. |
106 base::Bind(&SimpleSynchronousEntry::Close, | 107 // Push the close operation to the end of the line. This way we run all |
107 base::Unretained(synchronous_entry_)), | 108 // operations before we are able close. |
108 true); | 109 operations_.push( |
110 base::Bind(&SimpleEntryImpl::Close, | |
111 weak_ptr_factory_.GetWeakPtr())); | |
112 return; | |
109 } | 113 } |
114 DCHECK(operations_.size() == 0); | |
115 DCHECK(!operation_running_); | |
116 | |
117 WorkerPool::PostTask(FROM_HERE, | |
118 base::Bind(&SimpleSynchronousEntry::Close, | |
119 base::Unretained(synchronous_entry_)), | |
120 true); | |
110 // Entry::Close() is expected to release this entry. See disk_cache.h for | 121 // Entry::Close() is expected to release this entry. See disk_cache.h for |
111 // details. | 122 // details. |
112 delete this; | 123 delete this; |
113 } | 124 } |
114 | 125 |
115 std::string SimpleEntryImpl::GetKey() const { | 126 std::string SimpleEntryImpl::GetKey() const { |
116 DCHECK(io_thread_checker_.CalledOnValidThread()); | 127 DCHECK(io_thread_checker_.CalledOnValidThread()); |
117 return key_; | 128 return key_; |
118 } | 129 } |
119 | 130 |
(...skipping 11 matching lines...) Expand all Loading... | |
131 DCHECK(io_thread_checker_.CalledOnValidThread()); | 142 DCHECK(io_thread_checker_.CalledOnValidThread()); |
132 return data_size_[index]; | 143 return data_size_[index]; |
133 } | 144 } |
134 | 145 |
135 int SimpleEntryImpl::ReadData(int index, | 146 int SimpleEntryImpl::ReadData(int index, |
136 int offset, | 147 int offset, |
137 net::IOBuffer* buf, | 148 net::IOBuffer* buf, |
138 int buf_len, | 149 int buf_len, |
139 const CompletionCallback& callback) { | 150 const CompletionCallback& callback) { |
140 DCHECK(io_thread_checker_.CalledOnValidThread()); | 151 DCHECK(io_thread_checker_.CalledOnValidThread()); |
141 // TODO(gavinp): Add support for overlapping reads. The net::HttpCache does | 152 if (index < 0 || index >= kSimpleEntryFileCount || buf_len < 0) |
142 // make overlapping read requests when multiple transactions access the same | 153 return net::ERR_INVALID_ARGUMENT; |
143 // entry as read only. This might make calling SimpleSynchronousEntry::Close() | 154 if (offset >= data_size_[index] || offset < 0 || !buf_len) |
144 // correctly more tricky (see SimpleEntryImpl::EntryOperationComplete). | 155 return 0; |
145 if (synchronous_entry_in_use_by_worker_) { | 156 // TODO(felipeg): Optimization: Add support for truly parallel read |
146 NOTIMPLEMENTED(); | 157 // operations. |
147 CHECK(false); | 158 operations_.push( |
148 } | 159 base::Bind(&SimpleEntryImpl::ReadDataInternal, |
149 synchronous_entry_in_use_by_worker_ = true; | 160 weak_ptr_factory_.GetWeakPtr(), |
161 index, | |
162 offset, | |
163 make_scoped_refptr(buf), | |
164 buf_len, | |
165 callback)); | |
166 RunNextOperationIfNeeded(); | |
167 return net::ERR_IO_PENDING; | |
168 } | |
169 | |
170 void SimpleEntryImpl::ReadDataInternal(int index, | |
gavinp
2013/04/17 11:04:36
Method ordering: this should go to the end of the
felipeg
2013/04/17 11:51:22
Done.
| |
171 int offset, | |
172 scoped_refptr<net::IOBuffer> buf, | |
173 int buf_len, | |
174 const CompletionCallback& callback) { | |
175 DCHECK(io_thread_checker_.CalledOnValidThread()); | |
176 DCHECK(!operation_running_); | |
177 operation_running_ = true; | |
150 if (index_) | 178 if (index_) |
151 index_->UseIfExists(key_); | 179 index_->UseIfExists(key_); |
152 SynchronousOperationCallback sync_operation_callback = | 180 SynchronousOperationCallback sync_operation_callback = |
153 base::Bind(&SimpleEntryImpl::EntryOperationComplete, | 181 base::Bind(&SimpleEntryImpl::EntryOperationComplete, |
154 index_, callback, weak_ptr_factory_.GetWeakPtr(), | 182 index_, callback, weak_ptr_factory_.GetWeakPtr(), |
155 synchronous_entry_); | 183 synchronous_entry_); |
156 WorkerPool::PostTask(FROM_HERE, | 184 WorkerPool::PostTask(FROM_HERE, |
157 base::Bind(&SimpleSynchronousEntry::ReadData, | 185 base::Bind(&SimpleSynchronousEntry::ReadData, |
158 base::Unretained(synchronous_entry_), | 186 base::Unretained(synchronous_entry_), |
159 index, offset, make_scoped_refptr(buf), | 187 index, offset, buf, |
160 buf_len, sync_operation_callback), | 188 buf_len, sync_operation_callback), |
161 true); | 189 true); |
162 return net::ERR_IO_PENDING; | |
163 } | 190 } |
164 | 191 |
165 int SimpleEntryImpl::WriteData(int index, | 192 int SimpleEntryImpl::WriteData(int index, |
166 int offset, | 193 int offset, |
167 net::IOBuffer* buf, | 194 net::IOBuffer* buf, |
168 int buf_len, | 195 int buf_len, |
169 const CompletionCallback& callback, | 196 const CompletionCallback& callback, |
170 bool truncate) { | 197 bool truncate) { |
171 DCHECK(io_thread_checker_.CalledOnValidThread()); | 198 DCHECK(io_thread_checker_.CalledOnValidThread()); |
172 if (synchronous_entry_in_use_by_worker_) { | 199 if (index < 0 || index >= kSimpleEntryFileCount || offset < 0 || buf_len < 0) |
173 NOTIMPLEMENTED(); | 200 return net::ERR_INVALID_ARGUMENT; |
174 CHECK(false); | 201 |
175 } | 202 operations_.push( |
176 synchronous_entry_in_use_by_worker_ = true; | 203 base::Bind(&SimpleEntryImpl::WriteDataInternal, |
204 weak_ptr_factory_.GetWeakPtr(), | |
205 index, | |
206 offset, | |
207 make_scoped_refptr(buf), | |
208 buf_len, | |
209 callback, | |
210 truncate)); | |
211 RunNextOperationIfNeeded(); | |
212 | |
213 // TODO(felipeg): Optimization: Add support for optimistic writes, quickly | |
214 // returning net::OK here. | |
215 return net::ERR_IO_PENDING; | |
216 } | |
217 | |
218 void SimpleEntryImpl::WriteDataInternal(int index, | |
219 int offset, | |
220 scoped_refptr<net::IOBuffer> buf, | |
221 int buf_len, | |
222 const CompletionCallback& callback, | |
223 bool truncate) { | |
224 DCHECK(io_thread_checker_.CalledOnValidThread()); | |
225 DCHECK(!operation_running_); | |
226 operation_running_ = true; | |
177 if (index_) | 227 if (index_) |
178 index_->UseIfExists(key_); | 228 index_->UseIfExists(key_); |
229 | |
230 last_used_ = base::Time::Now(); | |
231 last_modified_ = base::Time::Now(); | |
232 data_size_[index] = buf_len; | |
233 | |
179 SynchronousOperationCallback sync_operation_callback = | 234 SynchronousOperationCallback sync_operation_callback = |
180 base::Bind(&SimpleEntryImpl::EntryOperationComplete, | 235 base::Bind(&SimpleEntryImpl::EntryOperationComplete, |
181 index_, callback, weak_ptr_factory_.GetWeakPtr(), | 236 index_, callback, weak_ptr_factory_.GetWeakPtr(), |
182 synchronous_entry_); | 237 synchronous_entry_); |
183 WorkerPool::PostTask(FROM_HERE, | 238 WorkerPool::PostTask(FROM_HERE, |
184 base::Bind(&SimpleSynchronousEntry::WriteData, | 239 base::Bind(&SimpleSynchronousEntry::WriteData, |
185 base::Unretained(synchronous_entry_), | 240 base::Unretained(synchronous_entry_), |
186 index, offset, make_scoped_refptr(buf), | 241 index, offset, buf, |
187 buf_len, sync_operation_callback, truncate), | 242 buf_len, sync_operation_callback, truncate), |
188 true); | 243 true); |
189 return net::ERR_IO_PENDING; | |
190 } | 244 } |
191 | 245 |
192 int SimpleEntryImpl::ReadSparseData(int64 offset, | 246 int SimpleEntryImpl::ReadSparseData(int64 offset, |
193 net::IOBuffer* buf, | 247 net::IOBuffer* buf, |
194 int buf_len, | 248 int buf_len, |
195 const CompletionCallback& callback) { | 249 const CompletionCallback& callback) { |
196 DCHECK(io_thread_checker_.CalledOnValidThread()); | 250 DCHECK(io_thread_checker_.CalledOnValidThread()); |
197 // TODO(gavinp): Determine if the simple backend should support sparse data. | 251 // TODO(gavinp): Determine if the simple backend should support sparse data. |
198 NOTIMPLEMENTED(); | 252 NOTIMPLEMENTED(); |
199 return net::ERR_FAILED; | 253 return net::ERR_FAILED; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 return net::ERR_FAILED; | 292 return net::ERR_FAILED; |
239 } | 293 } |
240 | 294 |
241 SimpleEntryImpl::SimpleEntryImpl( | 295 SimpleEntryImpl::SimpleEntryImpl( |
242 SimpleSynchronousEntry* synchronous_entry, | 296 SimpleSynchronousEntry* synchronous_entry, |
243 WeakPtr<SimpleIndex> index) | 297 WeakPtr<SimpleIndex> index) |
244 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | 298 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), |
245 path_(synchronous_entry->path()), | 299 path_(synchronous_entry->path()), |
246 key_(synchronous_entry->key()), | 300 key_(synchronous_entry->key()), |
247 synchronous_entry_(synchronous_entry), | 301 synchronous_entry_(synchronous_entry), |
248 synchronous_entry_in_use_by_worker_(false), | 302 operation_running_(false), |
249 index_(index) { | 303 index_(index) { |
250 DCHECK(synchronous_entry); | 304 DCHECK(synchronous_entry); |
251 SetSynchronousData(); | 305 SetSynchronousData(); |
252 } | 306 } |
253 | 307 |
254 SimpleEntryImpl::~SimpleEntryImpl() { | 308 SimpleEntryImpl::~SimpleEntryImpl() { |
255 DCHECK(io_thread_checker_.CalledOnValidThread()); | 309 DCHECK(io_thread_checker_.CalledOnValidThread()); |
256 } | 310 } |
257 | 311 |
258 // static | 312 // static |
(...skipping 25 matching lines...) Expand all Loading... | |
284 int result) { | 338 int result) { |
285 DCHECK(sync_entry); | 339 DCHECK(sync_entry); |
286 if (index) { | 340 if (index) { |
287 if (result >= 0) | 341 if (result >= 0) |
288 index->UpdateEntrySize(sync_entry->key(), sync_entry->GetFileSize()); | 342 index->UpdateEntrySize(sync_entry->key(), sync_entry->GetFileSize()); |
289 else | 343 else |
290 index->Remove(sync_entry->key()); | 344 index->Remove(sync_entry->key()); |
291 } | 345 } |
292 | 346 |
293 if (entry) { | 347 if (entry) { |
294 DCHECK(entry->synchronous_entry_in_use_by_worker_); | 348 DCHECK(entry->operation_running_); |
295 entry->synchronous_entry_in_use_by_worker_ = false; | 349 entry->operation_running_ = false; |
296 entry->SetSynchronousData(); | 350 entry->SetSynchronousData(); |
351 entry->RunNextOperationIfNeeded(); | |
297 } else { | 352 } else { |
298 // |entry| must have had Close() called while this operation was in flight. | 353 // |entry| must have had Close() called while this operation was in flight. |
299 // Since the simple cache now only supports one pending entry operation in | 354 // Since the simple cache now only supports one pending entry operation in |
300 // flight at a time, it's safe to now call Close() on |sync_entry|. | 355 // flight at a time, it's safe to now call Close() on |sync_entry|. |
301 WorkerPool::PostTask(FROM_HERE, | 356 WorkerPool::PostTask(FROM_HERE, |
302 base::Bind(&SimpleSynchronousEntry::Close, | 357 base::Bind(&SimpleSynchronousEntry::Close, |
303 base::Unretained(sync_entry)), | 358 base::Unretained(sync_entry)), |
304 true); | 359 true); |
305 } | 360 } |
306 completion_callback.Run(result); | 361 completion_callback.Run(result); |
307 } | 362 } |
308 | 363 |
364 bool SimpleEntryImpl::RunNextOperationIfNeeded() { | |
365 DCHECK(io_thread_checker_.CalledOnValidThread()); | |
366 if (operations_.size() <= 0 || operation_running_) | |
367 return false; | |
368 base::Closure operation = operations_.front(); | |
369 operations_.pop(); | |
370 operation.Run(); | |
371 return true; | |
372 } | |
373 | |
309 void SimpleEntryImpl::SetSynchronousData() { | 374 void SimpleEntryImpl::SetSynchronousData() { |
310 DCHECK(io_thread_checker_.CalledOnValidThread()); | 375 DCHECK(io_thread_checker_.CalledOnValidThread()); |
311 DCHECK(!synchronous_entry_in_use_by_worker_); | 376 DCHECK(!operation_running_); |
312 // TODO(felipeg): These copies to avoid data races are not optimal. While | 377 // TODO(felipeg): These copies to avoid data races are not optimal. While |
313 // adding an IO thread index (for fast misses etc...), we can store this data | 378 // adding an IO thread index (for fast misses etc...), we can store this data |
314 // in that structure. This also solves problems with last_used() on ext4 | 379 // in that structure. This also solves problems with last_used() on ext4 |
315 // filesystems not being accurate. | 380 // filesystems not being accurate. |
316 last_used_ = synchronous_entry_->last_used(); | 381 last_used_ = synchronous_entry_->last_used(); |
317 last_modified_ = synchronous_entry_->last_modified(); | 382 last_modified_ = synchronous_entry_->last_modified(); |
318 for (int i = 0; i < kSimpleEntryFileCount; ++i) | 383 for (int i = 0; i < kSimpleEntryFileCount; ++i) |
319 data_size_[i] = synchronous_entry_->data_size(i); | 384 data_size_[i] = synchronous_entry_->data_size(i); |
320 } | 385 } |
321 | 386 |
322 } // namespace disk_cache | 387 } // namespace disk_cache |
OLD | NEW |