Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: net/disk_cache/simple/simple_entry_impl.cc

Issue 13880016: Make SimpleEntryImpl ref counted. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remove flaky dchecks Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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"
11 #include "base/logging.h"
11 #include "base/message_loop_proxy.h" 12 #include "base/message_loop_proxy.h"
12 #include "base/threading/worker_pool.h" 13 #include "base/threading/worker_pool.h"
13 #include "net/base/io_buffer.h" 14 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h" 15 #include "net/base/net_errors.h"
15 #include "net/disk_cache/simple/simple_index.h" 16 #include "net/disk_cache/simple/simple_index.h"
16 #include "net/disk_cache/simple/simple_synchronous_entry.h" 17 #include "net/disk_cache/simple/simple_synchronous_entry.h"
17 18
18 namespace { 19 namespace {
19 20
20 typedef disk_cache::Entry::CompletionCallback CompletionCallback; 21 typedef disk_cache::Entry::CompletionCallback CompletionCallback;
21 typedef disk_cache::SimpleSynchronousEntry::SynchronousCreationCallback 22 typedef disk_cache::SimpleSynchronousEntry::SynchronousCreationCallback
22 SynchronousCreationCallback; 23 SynchronousCreationCallback;
23 typedef disk_cache::SimpleSynchronousEntry::SynchronousOperationCallback 24 typedef disk_cache::SimpleSynchronousEntry::SynchronousOperationCallback
24 SynchronousOperationCallback; 25 SynchronousOperationCallback;
25 26
26 } // namespace 27 } // namespace
27 28
28 namespace disk_cache { 29 namespace disk_cache {
29 30
30 using base::FilePath; 31 using base::FilePath;
31 using base::MessageLoopProxy; 32 using base::MessageLoopProxy;
32 using base::Time; 33 using base::Time;
33 using base::WeakPtr;
34 using base::WorkerPool; 34 using base::WorkerPool;
35 35
36 // static 36 // static
37 int SimpleEntryImpl::OpenEntry(WeakPtr<SimpleIndex> index, 37 int SimpleEntryImpl::OpenEntry(const scoped_refptr<SimpleIndex>& index,
38 const FilePath& path, 38 const FilePath& path,
39 const std::string& key, 39 const std::string& key,
40 Entry** entry, 40 Entry** entry,
41 const CompletionCallback& callback) { 41 const CompletionCallback& callback) {
42 // TODO(gavinp): More closely unify the last_used_ in the 42 // TODO(gavinp): More closely unify the last_used_ in the
43 // SimpleSynchronousEntry and the SimpleIndex. 43 // SimpleSynchronousEntry and the SimpleIndex.
44 if (!index || index->UseIfExists(key)) { 44 if (!index || index->UseIfExists(key)) {
45 scoped_refptr<SimpleEntryImpl> new_entry =
46 new SimpleEntryImpl(index, path, key);
45 SynchronousCreationCallback sync_creation_callback = 47 SynchronousCreationCallback sync_creation_callback =
46 base::Bind(&SimpleEntryImpl::CreationOperationComplete, 48 base::Bind(&SimpleEntryImpl::CreationOperationComplete,
47 index, callback, key, entry); 49 new_entry, entry, callback);
48 WorkerPool::PostTask(FROM_HERE, 50 WorkerPool::PostTask(FROM_HERE,
49 base::Bind(&SimpleSynchronousEntry::OpenEntry, path, 51 base::Bind(&SimpleSynchronousEntry::OpenEntry, path,
50 key, MessageLoopProxy::current(), 52 key, MessageLoopProxy::current(),
51 sync_creation_callback), 53 sync_creation_callback),
52 true); 54 true);
53 return net::ERR_IO_PENDING; 55 return net::ERR_IO_PENDING;
54 } 56 }
55 return net::ERR_FAILED; 57 return net::ERR_FAILED;
56 } 58 }
57 59
58 // static 60 // static
59 int SimpleEntryImpl::CreateEntry(WeakPtr<SimpleIndex> index, 61 int SimpleEntryImpl::CreateEntry(const scoped_refptr<SimpleIndex>& index,
60 const FilePath& path, 62 const FilePath& path,
61 const std::string& key, 63 const std::string& key,
62 Entry** entry, 64 Entry** entry,
63 const CompletionCallback& callback) { 65 const CompletionCallback& callback) {
66 scoped_refptr<SimpleEntryImpl> new_entry =
67 new SimpleEntryImpl(index, path, key);
64 SynchronousCreationCallback sync_creation_callback = 68 SynchronousCreationCallback sync_creation_callback =
65 base::Bind(&SimpleEntryImpl::CreationOperationComplete, 69 base::Bind(&SimpleEntryImpl::CreationOperationComplete,
66 index, callback, key, entry); 70 new_entry, entry, callback);
67 WorkerPool::PostTask(FROM_HERE, 71 WorkerPool::PostTask(FROM_HERE,
68 base::Bind(&SimpleSynchronousEntry::CreateEntry, path, 72 base::Bind(&SimpleSynchronousEntry::CreateEntry, path,
69 key, MessageLoopProxy::current(), 73 key, MessageLoopProxy::current(),
70 sync_creation_callback), 74 sync_creation_callback),
71 true); 75 true);
72 return net::ERR_IO_PENDING; 76 return net::ERR_IO_PENDING;
73 } 77 }
74 78
75 // static 79 // static
76 int SimpleEntryImpl::DoomEntry(WeakPtr<SimpleIndex> index, 80 int SimpleEntryImpl::DoomEntry(const scoped_refptr<SimpleIndex>& index,
77 const FilePath& path, 81 const FilePath& path,
78 const std::string& key, 82 const std::string& key,
79 const CompletionCallback& callback) { 83 const CompletionCallback& callback) {
80 if (index) 84 index->Remove(key);
81 index->Remove(key);
82 WorkerPool::PostTask(FROM_HERE, 85 WorkerPool::PostTask(FROM_HERE,
83 base::Bind(&SimpleSynchronousEntry::DoomEntry, path, key, 86 base::Bind(&SimpleSynchronousEntry::DoomEntry, path, key,
84 MessageLoopProxy::current(), callback), 87 MessageLoopProxy::current(), callback),
85 true); 88 true);
86 return net::ERR_IO_PENDING; 89 return net::ERR_IO_PENDING;
87 } 90 }
88 91
89 void SimpleEntryImpl::Doom() { 92 void SimpleEntryImpl::Doom() {
90 DCHECK(io_thread_checker_.CalledOnValidThread()); 93 DCHECK(io_thread_checker_.CalledOnValidThread());
94 DCHECK(synchronous_entry_);
91 #if defined(OS_POSIX) 95 #if defined(OS_POSIX)
92 // This call to static SimpleEntryImpl::DoomEntry() will just erase the 96 // 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 97 // 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 98 // SimpleSynchronousEntry, and operations can even happen on them. The files
95 // will be removed from the filesystem when they are closed. 99 // will be removed from the filesystem when they are closed.
96 DoomEntry(index_, path_, key_, CompletionCallback()); 100 DoomEntry(index_, path_, key_, CompletionCallback());
97 #else 101 #else
98 NOTIMPLEMENTED(); 102 NOTIMPLEMENTED();
99 #endif 103 #endif
100 } 104 }
101 105
102 void SimpleEntryImpl::Close() { 106 void SimpleEntryImpl::Close() {
gavinp 2013/04/20 07:28:33 ***THREE*** In response to the callback from ***TW
103 DCHECK(io_thread_checker_.CalledOnValidThread()); 107 DCHECK(io_thread_checker_.CalledOnValidThread());
104 if (!synchronous_entry_in_use_by_worker_) { 108 Release(); // Balanced in CreationOperationCompleted().
gavinp 2013/04/20 07:28:33 ***FOUR*** Close releases one ref on SimpleEntryIm
105 WorkerPool::PostTask(FROM_HERE,
106 base::Bind(&SimpleSynchronousEntry::Close,
107 base::Unretained(synchronous_entry_)),
108 true);
109 }
110 // Entry::Close() is expected to release this entry. See disk_cache.h for
111 // details.
112 delete this;
113 } 109 }
114 110
115 std::string SimpleEntryImpl::GetKey() const { 111 std::string SimpleEntryImpl::GetKey() const {
116 DCHECK(io_thread_checker_.CalledOnValidThread()); 112 DCHECK(io_thread_checker_.CalledOnValidThread());
117 return key_; 113 return key_;
118 } 114 }
119 115
120 Time SimpleEntryImpl::GetLastUsed() const { 116 Time SimpleEntryImpl::GetLastUsed() const {
121 DCHECK(io_thread_checker_.CalledOnValidThread()); 117 DCHECK(io_thread_checker_.CalledOnValidThread());
122 return last_used_; 118 return last_used_;
(...skipping 17 matching lines...) Expand all
140 DCHECK(io_thread_checker_.CalledOnValidThread()); 136 DCHECK(io_thread_checker_.CalledOnValidThread());
141 // TODO(gavinp): Add support for overlapping reads. The net::HttpCache does 137 // TODO(gavinp): Add support for overlapping reads. The net::HttpCache does
142 // make overlapping read requests when multiple transactions access the same 138 // make overlapping read requests when multiple transactions access the same
143 // entry as read only. This might make calling SimpleSynchronousEntry::Close() 139 // entry as read only. This might make calling SimpleSynchronousEntry::Close()
144 // correctly more tricky (see SimpleEntryImpl::EntryOperationComplete). 140 // correctly more tricky (see SimpleEntryImpl::EntryOperationComplete).
145 if (synchronous_entry_in_use_by_worker_) { 141 if (synchronous_entry_in_use_by_worker_) {
146 NOTIMPLEMENTED(); 142 NOTIMPLEMENTED();
147 CHECK(false); 143 CHECK(false);
148 } 144 }
149 synchronous_entry_in_use_by_worker_ = true; 145 synchronous_entry_in_use_by_worker_ = true;
150 if (index_) 146 index_->UseIfExists(key_);
151 index_->UseIfExists(key_);
152 SynchronousOperationCallback sync_operation_callback = 147 SynchronousOperationCallback sync_operation_callback =
153 base::Bind(&SimpleEntryImpl::EntryOperationComplete, 148 base::Bind(&SimpleEntryImpl::EntryOperationComplete,
154 index_, callback, weak_ptr_factory_.GetWeakPtr(), 149 this, callback);
155 synchronous_entry_);
156 WorkerPool::PostTask(FROM_HERE, 150 WorkerPool::PostTask(FROM_HERE,
157 base::Bind(&SimpleSynchronousEntry::ReadData, 151 base::Bind(&SimpleSynchronousEntry::ReadData,
158 base::Unretained(synchronous_entry_), 152 base::Unretained(synchronous_entry_),
159 index, offset, make_scoped_refptr(buf), 153 index, offset, make_scoped_refptr(buf),
160 buf_len, sync_operation_callback), 154 buf_len, sync_operation_callback),
161 true); 155 true);
162 return net::ERR_IO_PENDING; 156 return net::ERR_IO_PENDING;
163 } 157 }
164 158
165 int SimpleEntryImpl::WriteData(int index, 159 int SimpleEntryImpl::WriteData(int index,
166 int offset, 160 int offset,
167 net::IOBuffer* buf, 161 net::IOBuffer* buf,
168 int buf_len, 162 int buf_len,
169 const CompletionCallback& callback, 163 const CompletionCallback& callback,
170 bool truncate) { 164 bool truncate) {
171 DCHECK(io_thread_checker_.CalledOnValidThread()); 165 DCHECK(io_thread_checker_.CalledOnValidThread());
172 if (synchronous_entry_in_use_by_worker_) { 166 if (synchronous_entry_in_use_by_worker_) {
173 NOTIMPLEMENTED(); 167 NOTIMPLEMENTED();
174 CHECK(false); 168 CHECK(false);
175 } 169 }
176 synchronous_entry_in_use_by_worker_ = true; 170 synchronous_entry_in_use_by_worker_ = true;
177 if (index_) 171 index_->UseIfExists(key_);
178 index_->UseIfExists(key_);
179 SynchronousOperationCallback sync_operation_callback = 172 SynchronousOperationCallback sync_operation_callback =
180 base::Bind(&SimpleEntryImpl::EntryOperationComplete, 173 base::Bind(&SimpleEntryImpl::EntryOperationComplete,
181 index_, callback, weak_ptr_factory_.GetWeakPtr(), 174 this, callback);
182 synchronous_entry_);
183 WorkerPool::PostTask(FROM_HERE, 175 WorkerPool::PostTask(FROM_HERE,
184 base::Bind(&SimpleSynchronousEntry::WriteData, 176 base::Bind(&SimpleSynchronousEntry::WriteData,
185 base::Unretained(synchronous_entry_), 177 base::Unretained(synchronous_entry_),
186 index, offset, make_scoped_refptr(buf), 178 index, offset, make_scoped_refptr(buf),
187 buf_len, sync_operation_callback, truncate), 179 buf_len, sync_operation_callback, truncate),
188 true); 180 true);
189 return net::ERR_IO_PENDING; 181 return net::ERR_IO_PENDING;
190 } 182 }
191 183
192 int SimpleEntryImpl::ReadSparseData(int64 offset, 184 int SimpleEntryImpl::ReadSparseData(int64 offset,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 NOTIMPLEMENTED(); 223 NOTIMPLEMENTED();
232 } 224 }
233 225
234 int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { 226 int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) {
235 DCHECK(io_thread_checker_.CalledOnValidThread()); 227 DCHECK(io_thread_checker_.CalledOnValidThread());
236 // TODO(gavinp): Determine if the simple backend should support sparse data. 228 // TODO(gavinp): Determine if the simple backend should support sparse data.
237 NOTIMPLEMENTED(); 229 NOTIMPLEMENTED();
238 return net::ERR_FAILED; 230 return net::ERR_FAILED;
239 } 231 }
240 232
241 SimpleEntryImpl::SimpleEntryImpl( 233 SimpleEntryImpl::SimpleEntryImpl(const scoped_refptr<SimpleIndex>& index,
242 SimpleSynchronousEntry* synchronous_entry, 234 const base::FilePath& path,
243 WeakPtr<SimpleIndex> index) 235 const std::string& key)
244 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), 236 : constructor_thread_(base::MessageLoopProxy::current()),
245 path_(synchronous_entry->path()), 237 index_(index),
246 key_(synchronous_entry->key()), 238 path_(path),
247 synchronous_entry_(synchronous_entry), 239 key_(key),
248 synchronous_entry_in_use_by_worker_(false), 240 synchronous_entry_(NULL),
249 index_(index) { 241 synchronous_entry_in_use_by_worker_(false) {
250 DCHECK(synchronous_entry);
251 SetSynchronousData();
252 } 242 }
253 243
254 SimpleEntryImpl::~SimpleEntryImpl() { 244 SimpleEntryImpl::~SimpleEntryImpl() {
255 DCHECK(io_thread_checker_.CalledOnValidThread()); 245 if (synchronous_entry_) {
246 base::Closure close_sync_entry =
247 base::Bind(&SimpleSynchronousEntry::Close,
248 base::Unretained(synchronous_entry_));
249 // We aren't guaranteed to be able to run IO on our constructor thread, but
250 // we are also not guaranteed to be allowed to run WorkerPool::PostTask on
251 // our other threads.
252 if (constructor_thread_->BelongsToCurrentThread())
253 WorkerPool::PostTask(FROM_HERE, close_sync_entry, true);
254 else
255 close_sync_entry.Run();
256 }
256 } 257 }
257 258
258 // static
259 void SimpleEntryImpl::CreationOperationComplete( 259 void SimpleEntryImpl::CreationOperationComplete(
260 WeakPtr<SimpleIndex> index, 260 Entry** out_entry,
261 const CompletionCallback& completion_callback, 261 const CompletionCallback& completion_callback,
262 const std::string& key,
263 Entry** out_entry,
264 SimpleSynchronousEntry* sync_entry) { 262 SimpleSynchronousEntry* sync_entry) {
263 DCHECK(io_thread_checker_.CalledOnValidThread());
265 if (!sync_entry) { 264 if (!sync_entry) {
266 completion_callback.Run(net::ERR_FAILED); 265 completion_callback.Run(net::ERR_FAILED);
267 // If OpenEntry failed, we must remove it from our index. 266 // If OpenEntry failed, we must remove it from our index.
268 if (index) 267 index_->Remove(key_);
269 index->Remove(key); 268 // The reference held by the Callback calling us will go out of scope and
269 // delete |this| on leaving this scope.
270 return; 270 return;
271 } 271 }
272 if (index) 272 // Adding a reference to self will keep |this| alive after the scope of our
rvargas (doing something else) 2013/04/17 19:56:38 nit: "our callback calling us" -> the callback
gavinp 2013/04/18 09:12:41 Done.
273 index->Insert(sync_entry->key()); 273 // Callback calling us is destroyed.
274 *out_entry = new SimpleEntryImpl(sync_entry, index); 274 AddRef(); // Balanced in Close().
275 synchronous_entry_ = sync_entry;
276 SetSynchronousData();
277 index_->Insert(key_);
278 *out_entry = this;
rvargas (doing something else) 2013/04/17 19:56:38 nit: I believe the "real" reason for Addref is tha
gavinp 2013/04/18 09:12:41 Done.
275 completion_callback.Run(net::OK); 279 completion_callback.Run(net::OK);
276 } 280 }
277 281
278 // static
279 void SimpleEntryImpl::EntryOperationComplete( 282 void SimpleEntryImpl::EntryOperationComplete(
280 base::WeakPtr<SimpleIndex> index,
281 const CompletionCallback& completion_callback, 283 const CompletionCallback& completion_callback,
282 base::WeakPtr<SimpleEntryImpl> entry,
283 SimpleSynchronousEntry* sync_entry,
284 int result) { 284 int result) {
285 DCHECK(sync_entry); 285 DCHECK(io_thread_checker_.CalledOnValidThread());
286 if (index) { 286 DCHECK(synchronous_entry_);
287 if (result >= 0) 287 DCHECK(synchronous_entry_in_use_by_worker_);
288 index->UpdateEntrySize(sync_entry->key(), sync_entry->GetFileSize()); 288 synchronous_entry_in_use_by_worker_ = false;
289 else 289 SetSynchronousData();
290 index->Remove(sync_entry->key()); 290 if (result >= 0) {
291 } 291 index_->UpdateEntrySize(synchronous_entry_->key(),
292 292 synchronous_entry_->GetFileSize());
293 if (entry) {
294 DCHECK(entry->synchronous_entry_in_use_by_worker_);
295 entry->synchronous_entry_in_use_by_worker_ = false;
296 entry->SetSynchronousData();
297 } else { 293 } else {
298 // |entry| must have had Close() called while this operation was in flight. 294 index_->Remove(synchronous_entry_->key());
299 // 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|.
301 WorkerPool::PostTask(FROM_HERE,
302 base::Bind(&SimpleSynchronousEntry::Close,
303 base::Unretained(sync_entry)),
304 true);
305 } 295 }
306 completion_callback.Run(result); 296 completion_callback.Run(result);
gavinp 2013/04/20 07:28:33 ***TWO*** The IO thread runs the task posted just
307 } 297 }
308 298
309 void SimpleEntryImpl::SetSynchronousData() { 299 void SimpleEntryImpl::SetSynchronousData() {
310 DCHECK(io_thread_checker_.CalledOnValidThread()); 300 DCHECK(io_thread_checker_.CalledOnValidThread());
311 DCHECK(!synchronous_entry_in_use_by_worker_); 301 DCHECK(!synchronous_entry_in_use_by_worker_);
312 // TODO(felipeg): These copies to avoid data races are not optimal. While 302 // 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 303 // 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 304 // in that structure. This also solves problems with last_used() on ext4
315 // filesystems not being accurate. 305 // filesystems not being accurate.
316 last_used_ = synchronous_entry_->last_used(); 306 last_used_ = synchronous_entry_->last_used();
317 last_modified_ = synchronous_entry_->last_modified(); 307 last_modified_ = synchronous_entry_->last_modified();
318 for (int i = 0; i < kSimpleEntryFileCount; ++i) 308 for (int i = 0; i < kSimpleEntryFileCount; ++i)
319 data_size_[i] = synchronous_entry_->data_size(i); 309 data_size_[i] = synchronous_entry_->data_size(i);
320 } 310 }
321 311
322 } // namespace disk_cache 312 } // namespace disk_cache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698