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

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: fix comments 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"
Philippe 2013/04/17 10:19:22 Nit: "base/logging.h" is missing.
gavinp 2013/04/17 10:56:28 Done.
11 #include "base/message_loop_proxy.h" 11 #include "base/message_loop_proxy.h"
12 #include "base/threading/worker_pool.h" 12 #include "base/threading/worker_pool.h"
13 #include "net/base/io_buffer.h" 13 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h" 14 #include "net/base/net_errors.h"
15 #include "net/disk_cache/simple/simple_index.h" 15 #include "net/disk_cache/simple/simple_index.h"
16 #include "net/disk_cache/simple/simple_synchronous_entry.h" 16 #include "net/disk_cache/simple/simple_synchronous_entry.h"
17 17
18 namespace { 18 namespace {
19 19
20 typedef disk_cache::Entry::CompletionCallback CompletionCallback; 20 typedef disk_cache::Entry::CompletionCallback CompletionCallback;
(...skipping 14 matching lines...) Expand all
35 35
36 // static 36 // static
37 int SimpleEntryImpl::OpenEntry(WeakPtr<SimpleIndex> index, 37 int SimpleEntryImpl::OpenEntry(WeakPtr<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,
digit 2013/04/16 10:21:32 This callback will be destroyed in the WorkerPool
gavinp 2013/04/17 09:52:46 Great catch. For moving forward, I went with RefC
felipeg 2013/04/19 18:12:08 I think this is not true sync_creation_callback on
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(WeakPtr<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,
digit 2013/04/16 10:21:32 exact same issue here.
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(WeakPtr<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 if (index)
81 index->Remove(key); 85 index->Remove(key);
82 WorkerPool::PostTask(FROM_HERE, 86 WorkerPool::PostTask(FROM_HERE,
83 base::Bind(&SimpleSynchronousEntry::DoomEntry, path, key, 87 base::Bind(&SimpleSynchronousEntry::DoomEntry, path, key,
84 MessageLoopProxy::current(), callback), 88 MessageLoopProxy::current(), callback),
85 true); 89 true);
86 return net::ERR_IO_PENDING; 90 return net::ERR_IO_PENDING;
87 } 91 }
88 92
89 void SimpleEntryImpl::Doom() { 93 void SimpleEntryImpl::Doom() {
90 DCHECK(io_thread_checker_.CalledOnValidThread()); 94 DCHECK(io_thread_checker_.CalledOnValidThread());
95 DCHECK(synchronous_entry_);
91 #if defined(OS_POSIX) 96 #if defined(OS_POSIX)
92 // This call to static SimpleEntryImpl::DoomEntry() will just erase the 97 // 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 98 // 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 99 // SimpleSynchronousEntry, and operations can even happen on them. The files
95 // will be removed from the filesystem when they are closed. 100 // will be removed from the filesystem when they are closed.
96 DoomEntry(index_, path_, key_, CompletionCallback()); 101 DoomEntry(index_, path_, key_, CompletionCallback());
97 #else 102 #else
98 NOTIMPLEMENTED(); 103 NOTIMPLEMENTED();
99 #endif 104 #endif
100 } 105 }
101 106
102 void SimpleEntryImpl::Close() { 107 void SimpleEntryImpl::Close() {
103 DCHECK(io_thread_checker_.CalledOnValidThread()); 108 DCHECK(io_thread_checker_.CalledOnValidThread());
104 if (!synchronous_entry_in_use_by_worker_) { 109 bool in_use = synchronous_entry_in_use_by_worker_;
105 WorkerPool::PostTask(FROM_HERE, 110 DCHECK((in_use && !HasOneRef()) || (!in_use && HasOneRef()));
106 base::Bind(&SimpleSynchronousEntry::Close, 111 Release(); // Balanced in CreationOperationCompleted().
107 base::Unretained(synchronous_entry_)), 112 // At most one worker can be operating on our |synchronous_entry_| at a time,
108 true); 113 // and so if we were in use when we cleared |self_|, we should expect a single
109 } 114 // reference from that operation now.
110 // Entry::Close() is expected to release this entry. See disk_cache.h for 115 if (in_use)
111 // details. 116 DCHECK(HasOneRef());
112 delete this;
113 } 117 }
114 118
115 std::string SimpleEntryImpl::GetKey() const { 119 std::string SimpleEntryImpl::GetKey() const {
116 DCHECK(io_thread_checker_.CalledOnValidThread()); 120 DCHECK(io_thread_checker_.CalledOnValidThread());
117 return key_; 121 return key_;
118 } 122 }
119 123
120 Time SimpleEntryImpl::GetLastUsed() const { 124 Time SimpleEntryImpl::GetLastUsed() const {
121 DCHECK(io_thread_checker_.CalledOnValidThread()); 125 DCHECK(io_thread_checker_.CalledOnValidThread());
122 return last_used_; 126 return last_used_;
(...skipping 20 matching lines...) Expand all
143 // entry as read only. This might make calling SimpleSynchronousEntry::Close() 147 // entry as read only. This might make calling SimpleSynchronousEntry::Close()
144 // correctly more tricky (see SimpleEntryImpl::EntryOperationComplete). 148 // correctly more tricky (see SimpleEntryImpl::EntryOperationComplete).
145 if (synchronous_entry_in_use_by_worker_) { 149 if (synchronous_entry_in_use_by_worker_) {
146 NOTIMPLEMENTED(); 150 NOTIMPLEMENTED();
147 CHECK(false); 151 CHECK(false);
148 } 152 }
149 synchronous_entry_in_use_by_worker_ = true; 153 synchronous_entry_in_use_by_worker_ = true;
150 index_->UseIfExists(key_); 154 index_->UseIfExists(key_);
151 SynchronousOperationCallback sync_operation_callback = 155 SynchronousOperationCallback sync_operation_callback =
152 base::Bind(&SimpleEntryImpl::EntryOperationComplete, 156 base::Bind(&SimpleEntryImpl::EntryOperationComplete,
153 index_, callback, weak_ptr_factory_.GetWeakPtr(), 157 this, callback);
154 synchronous_entry_);
155 WorkerPool::PostTask(FROM_HERE, 158 WorkerPool::PostTask(FROM_HERE,
156 base::Bind(&SimpleSynchronousEntry::ReadData, 159 base::Bind(&SimpleSynchronousEntry::ReadData,
157 base::Unretained(synchronous_entry_), 160 base::Unretained(synchronous_entry_),
158 index, offset, make_scoped_refptr(buf), 161 index, offset, make_scoped_refptr(buf),
159 buf_len, sync_operation_callback), 162 buf_len, sync_operation_callback),
160 true); 163 true);
161 return net::ERR_IO_PENDING; 164 return net::ERR_IO_PENDING;
162 } 165 }
163 166
164 int SimpleEntryImpl::WriteData(int index, 167 int SimpleEntryImpl::WriteData(int index,
165 int offset, 168 int offset,
166 net::IOBuffer* buf, 169 net::IOBuffer* buf,
167 int buf_len, 170 int buf_len,
168 const CompletionCallback& callback, 171 const CompletionCallback& callback,
169 bool truncate) { 172 bool truncate) {
170 DCHECK(io_thread_checker_.CalledOnValidThread()); 173 DCHECK(io_thread_checker_.CalledOnValidThread());
171 if (synchronous_entry_in_use_by_worker_) { 174 if (synchronous_entry_in_use_by_worker_) {
172 NOTIMPLEMENTED(); 175 NOTIMPLEMENTED();
173 CHECK(false); 176 CHECK(false);
174 } 177 }
175 synchronous_entry_in_use_by_worker_ = true; 178 synchronous_entry_in_use_by_worker_ = true;
176 index_->UseIfExists(key_); 179 index_->UseIfExists(key_);
177 SynchronousOperationCallback sync_operation_callback = 180 SynchronousOperationCallback sync_operation_callback =
178 base::Bind(&SimpleEntryImpl::EntryOperationComplete, 181 base::Bind(&SimpleEntryImpl::EntryOperationComplete,
179 index_, callback, weak_ptr_factory_.GetWeakPtr(), 182 this, callback);
180 synchronous_entry_);
181 WorkerPool::PostTask(FROM_HERE, 183 WorkerPool::PostTask(FROM_HERE,
182 base::Bind(&SimpleSynchronousEntry::WriteData, 184 base::Bind(&SimpleSynchronousEntry::WriteData,
183 base::Unretained(synchronous_entry_), 185 base::Unretained(synchronous_entry_),
184 index, offset, make_scoped_refptr(buf), 186 index, offset, make_scoped_refptr(buf),
185 buf_len, sync_operation_callback, truncate), 187 buf_len, sync_operation_callback, truncate),
186 true); 188 true);
187 return net::ERR_IO_PENDING; 189 return net::ERR_IO_PENDING;
188 } 190 }
189 191
190 int SimpleEntryImpl::ReadSparseData(int64 offset, 192 int SimpleEntryImpl::ReadSparseData(int64 offset,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 NOTIMPLEMENTED(); 231 NOTIMPLEMENTED();
230 } 232 }
231 233
232 int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { 234 int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) {
233 DCHECK(io_thread_checker_.CalledOnValidThread()); 235 DCHECK(io_thread_checker_.CalledOnValidThread());
234 // TODO(gavinp): Determine if the simple backend should support sparse data. 236 // TODO(gavinp): Determine if the simple backend should support sparse data.
235 NOTIMPLEMENTED(); 237 NOTIMPLEMENTED();
236 return net::ERR_FAILED; 238 return net::ERR_FAILED;
237 } 239 }
238 240
239 SimpleEntryImpl::SimpleEntryImpl( 241 SimpleEntryImpl::SimpleEntryImpl(WeakPtr<SimpleIndex> index,
240 SimpleSynchronousEntry* synchronous_entry, 242 const base::FilePath& path,
241 WeakPtr<SimpleIndex> index) 243 const std::string& key)
242 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), 244 : index_(index),
243 path_(synchronous_entry->path()), 245 path_(path),
244 key_(synchronous_entry->key()), 246 key_(key),
245 synchronous_entry_(synchronous_entry), 247 synchronous_entry_(NULL),
246 synchronous_entry_in_use_by_worker_(false), 248 synchronous_entry_in_use_by_worker_(false) {
247 index_(index) {
248 DCHECK(synchronous_entry);
249 SetSynchronousData();
250 } 249 }
251 250
252 SimpleEntryImpl::~SimpleEntryImpl() { 251 SimpleEntryImpl::~SimpleEntryImpl() {
253 DCHECK(io_thread_checker_.CalledOnValidThread()); 252 DCHECK(io_thread_checker_.CalledOnValidThread());
253 if (synchronous_entry_) {
254 WorkerPool::PostTask(FROM_HERE,
255 base::Bind(&SimpleSynchronousEntry::Close,
256 base::Unretained(synchronous_entry_)),
257 true);
258 }
254 } 259 }
255 260
256 // static
257 void SimpleEntryImpl::CreationOperationComplete( 261 void SimpleEntryImpl::CreationOperationComplete(
258 WeakPtr<SimpleIndex> index, 262 Entry** entry,
259 const CompletionCallback& completion_callback, 263 const CompletionCallback& completion_callback,
260 const std::string& key,
261 Entry** out_entry,
262 SimpleSynchronousEntry* sync_entry) { 264 SimpleSynchronousEntry* sync_entry) {
265 DCHECK(io_thread_checker_.CalledOnValidThread());
263 if (!sync_entry) { 266 if (!sync_entry) {
264 completion_callback.Run(net::ERR_FAILED); 267 completion_callback.Run(net::ERR_FAILED);
265 // If OpenEntry failed, we must remove it from our index. 268 // If OpenEntry failed, we must remove it from our index.
266 if (index) 269 if (index_)
267 index->Remove(key); 270 index_->Remove(key_);
271 // The reference held by the Callback calling us will go out of scope and
272 // delete |this| on leaving this scope.
268 return; 273 return;
269 } 274 }
270 if (index) 275 // Adding a reference to self will keep |this| alive after the scope of our
271 index->Insert(sync_entry->key()); 276 // Callback calling us is destroyed.
272 *out_entry = new SimpleEntryImpl(sync_entry, index); 277 AddRef(); // Balanced in Close().
278 synchronous_entry_ = sync_entry;
279 SetSynchronousData();
280 if (index_)
281 index_->Insert(key_);
282 *entry = this;
273 completion_callback.Run(net::OK); 283 completion_callback.Run(net::OK);
274 } 284 }
275 285
276 // static
277 void SimpleEntryImpl::EntryOperationComplete( 286 void SimpleEntryImpl::EntryOperationComplete(
278 base::WeakPtr<SimpleIndex> index,
279 const CompletionCallback& completion_callback, 287 const CompletionCallback& completion_callback,
280 base::WeakPtr<SimpleEntryImpl> entry,
281 SimpleSynchronousEntry* sync_entry,
282 int result) { 288 int result) {
283 DCHECK(sync_entry); 289 DCHECK(io_thread_checker_.CalledOnValidThread());
284 if (index) { 290 DCHECK(synchronous_entry_);
285 if (result >= 0) 291 DCHECK(synchronous_entry_in_use_by_worker_);
286 index->UpdateEntrySize(sync_entry->key(), sync_entry->GetFileSize()); 292 synchronous_entry_in_use_by_worker_ = false;
287 else 293 SetSynchronousData();
288 index->Remove(sync_entry->key()); 294 if (index_) {
289 } 295 if (result >= 0) {
290 296 index_->UpdateEntrySize(synchronous_entry_->key(),
291 if (entry) { 297 synchronous_entry_->GetFileSize());
292 DCHECK(entry->synchronous_entry_in_use_by_worker_); 298 } else {
293 entry->synchronous_entry_in_use_by_worker_ = false; 299 index_->Remove(synchronous_entry_->key());
294 entry->SetSynchronousData(); 300 }
295 } else {
296 // |entry| must have had Close() called while this operation was in flight.
297 // Since the simple cache now only supports one pending entry operation in
298 // flight at a time, it's safe to now call Close() on |sync_entry|.
299 WorkerPool::PostTask(FROM_HERE,
300 base::Bind(&SimpleSynchronousEntry::Close,
301 base::Unretained(sync_entry)),
302 true);
303 } 301 }
304 completion_callback.Run(result); 302 completion_callback.Run(result);
305 } 303 }
306 304
307 void SimpleEntryImpl::SetSynchronousData() { 305 void SimpleEntryImpl::SetSynchronousData() {
308 DCHECK(io_thread_checker_.CalledOnValidThread()); 306 DCHECK(io_thread_checker_.CalledOnValidThread());
309 DCHECK(!synchronous_entry_in_use_by_worker_); 307 DCHECK(!synchronous_entry_in_use_by_worker_);
310 // TODO(felipeg): These copies to avoid data races are not optimal. While 308 // TODO(felipeg): These copies to avoid data races are not optimal. While
311 // adding an IO thread index (for fast misses etc...), we can store this data 309 // adding an IO thread index (for fast misses etc...), we can store this data
312 // in that structure. This also solves problems with last_used() on ext4 310 // in that structure. This also solves problems with last_used() on ext4
313 // filesystems not being accurate. 311 // filesystems not being accurate.
314 last_used_ = synchronous_entry_->last_used(); 312 last_used_ = synchronous_entry_->last_used();
315 last_modified_ = synchronous_entry_->last_modified(); 313 last_modified_ = synchronous_entry_->last_modified();
316 for (int i = 0; i < kSimpleEntryFileCount; ++i) 314 for (int i = 0; i < kSimpleEntryFileCount; ++i)
317 data_size_[i] = synchronous_entry_->data_size(i); 315 data_size_[i] = synchronous_entry_->data_size(i);
318 } 316 }
319 317
320 } // namespace disk_cache 318 } // namespace disk_cache
OLDNEW
« net/disk_cache/simple/simple_entry_impl.h ('K') | « net/disk_cache/simple/simple_entry_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698