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

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

Issue 14130015: Support overlapping operations on the SimpleEntryImpl. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix a bug in GetDataSize() 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
« no previous file with comments | « net/disk_cache/simple/simple_entry_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 const CompletionCallback& callback) { 79 const CompletionCallback& callback) {
80 if (index) 80 if (index)
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() {
gavinp 2013/04/17 08:12:35 I think doom is one of the only operations that al
felipeg 2013/04/17 10:06:43 Done.
90 LOG(INFO) << " DOOM " << key_;
90 DCHECK(io_thread_checker_.CalledOnValidThread()); 91 DCHECK(io_thread_checker_.CalledOnValidThread());
92 if (synchronous_entry_in_use_by_worker_) {
93 // Postpone doom operation.
94 operations_.push(
95 base::Bind(&SimpleEntryImpl::DoomInternal,
96 weak_ptr_factory_.GetWeakPtr()));
97 return;
98 }
99 DCHECK(operations_.size() == 0);
100 DCHECK(!synchronous_entry_in_use_by_worker_);
101
102 DoomInternal();
103 // TODO(felipeg): Maybe we should have a flag is_doomed_ and do some DCHECKS
104 // around the code, to see if we dont call read in a doomed entry.
gavinp 2013/04/17 08:12:35 I believe it's correct and valid to Read/Write in
felipeg 2013/04/17 10:06:43 Done.
105 RunNextOperationIfNeeded();
106 }
107
108 void SimpleEntryImpl::DoomInternal() {
109 LOG(INFO) << " DOOM " << key_;
110 DCHECK(io_thread_checker_.CalledOnValidThread());
111 DCHECK(!synchronous_entry_in_use_by_worker_);
91 #if defined(OS_POSIX) 112 #if defined(OS_POSIX)
92 // This call to static SimpleEntryImpl::DoomEntry() will just erase the 113 // 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 114 // 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 115 // SimpleSynchronousEntry, and operations can even happen on them. The files
95 // will be removed from the filesystem when they are closed. 116 // will be removed from the filesystem when they are closed.
96 DoomEntry(index_, path_, key_, CompletionCallback()); 117 DoomEntry(index_, path_, key_, CompletionCallback());
97 #else 118 #else
98 NOTIMPLEMENTED(); 119 NOTIMPLEMENTED();
99 #endif 120 #endif
100 } 121 }
101 122
102 void SimpleEntryImpl::Close() { 123 void SimpleEntryImpl::Close() {
124 LOG(INFO) << " CLOSE " << key_;
103 DCHECK(io_thread_checker_.CalledOnValidThread()); 125 DCHECK(io_thread_checker_.CalledOnValidThread());
104 if (!synchronous_entry_in_use_by_worker_) { 126 if (synchronous_entry_in_use_by_worker_) {
105 WorkerPool::PostTask(FROM_HERE, 127 LOG(INFO) << " CLOSE " << key_;
106 base::Bind(&SimpleSynchronousEntry::Close, 128 // Postpone close operation.
107 base::Unretained(synchronous_entry_)), 129 // Push the close operation to the end of the line. This way we run all
108 true); 130 // operations before we are able close.
131 operations_.push(
132 base::Bind(&SimpleEntryImpl::Close,
133 weak_ptr_factory_.GetWeakPtr()));
134 return;
109 } 135 }
136 LOG(INFO) << " CLOSE " << key_;
137 DCHECK(operations_.size() == 0);
138 DCHECK(!synchronous_entry_in_use_by_worker_);
139
140 WorkerPool::PostTask(FROM_HERE,
141 base::Bind(&SimpleSynchronousEntry::Close,
142 base::Unretained(synchronous_entry_)),
143 true);
110 // Entry::Close() is expected to release this entry. See disk_cache.h for 144 // Entry::Close() is expected to release this entry. See disk_cache.h for
111 // details. 145 // details.
112 delete this; 146 delete this;
113 } 147 }
114 148
115 std::string SimpleEntryImpl::GetKey() const { 149 std::string SimpleEntryImpl::GetKey() const {
116 DCHECK(io_thread_checker_.CalledOnValidThread()); 150 DCHECK(io_thread_checker_.CalledOnValidThread());
117 return key_; 151 return key_;
118 } 152 }
119 153
120 Time SimpleEntryImpl::GetLastUsed() const { 154 Time SimpleEntryImpl::GetLastUsed() const {
121 DCHECK(io_thread_checker_.CalledOnValidThread()); 155 DCHECK(io_thread_checker_.CalledOnValidThread());
122 return last_used_; 156 return last_used_;
123 } 157 }
124 158
125 Time SimpleEntryImpl::GetLastModified() const { 159 Time SimpleEntryImpl::GetLastModified() const {
126 DCHECK(io_thread_checker_.CalledOnValidThread()); 160 DCHECK(io_thread_checker_.CalledOnValidThread());
127 return last_modified_; 161 return last_modified_;
128 } 162 }
129 163
130 int32 SimpleEntryImpl::GetDataSize(int index) const { 164 int32 SimpleEntryImpl::GetDataSize(int index) const {
131 DCHECK(io_thread_checker_.CalledOnValidThread()); 165 DCHECK(io_thread_checker_.CalledOnValidThread());
132 return data_size_[index]; 166 return data_size_[index];
133 } 167 }
134 168
169
170
135 int SimpleEntryImpl::ReadData(int index, 171 int SimpleEntryImpl::ReadData(int index,
136 int offset, 172 int offset,
137 net::IOBuffer* buf, 173 net::IOBuffer* buf,
138 int buf_len, 174 int buf_len,
139 const CompletionCallback& callback) { 175 const CompletionCallback& callback) {
176 LOG(INFO) << " READ " << key_;
140 DCHECK(io_thread_checker_.CalledOnValidThread()); 177 DCHECK(io_thread_checker_.CalledOnValidThread());
141 // TODO(gavinp): Add support for overlapping reads. The net::HttpCache does 178 // TODO(gavinp): Add support for overlapping reads. The net::HttpCache does
142 // make overlapping read requests when multiple transactions access the same 179 // make overlapping read requests when multiple transactions access the same
143 // entry as read only. This might make calling SimpleSynchronousEntry::Close() 180 // entry as read only. This might make calling SimpleSynchronousEntry::Close()
144 // correctly more tricky (see SimpleEntryImpl::EntryOperationComplete). 181 // correctly more tricky (see SimpleEntryImpl::EntryOperationComplete).
145 if (synchronous_entry_in_use_by_worker_) { 182 if (synchronous_entry_in_use_by_worker_ && !read_only_operation_) {
146 NOTIMPLEMENTED(); 183 // Postpone read operation.
147 CHECK(false); 184 operations_.push(
185 base::Bind(&SimpleEntryImpl::ReadDataInternal,
186 weak_ptr_factory_.GetWeakPtr(),
187 index,
188 offset,
189 make_scoped_refptr(buf),
190 buf_len,
191 callback));
192 return net::ERR_IO_PENDING;
148 } 193 }
194 DCHECK(operations_.size() == 0);
195 ReadDataInternal(index,
196 offset,
197 make_scoped_refptr(buf),
198 buf_len,
199 callback);
200 return net::ERR_IO_PENDING;
201 }
202
203 void SimpleEntryImpl::ReadDataInternal(int index,
204 int offset,
205 scoped_refptr<net::IOBuffer> buf,
206 int buf_len,
207 const CompletionCallback& callback) {
208 LOG(INFO) << " READ " << key_;
209 DCHECK(io_thread_checker_.CalledOnValidThread());
210 DCHECK(!synchronous_entry_in_use_by_worker_);
211 read_only_operation_ = true;
149 synchronous_entry_in_use_by_worker_ = true; 212 synchronous_entry_in_use_by_worker_ = true;
150 if (index_) 213 if (index_)
151 index_->UseIfExists(key_); 214 index_->UseIfExists(key_);
152 SynchronousOperationCallback sync_operation_callback = 215 SynchronousOperationCallback sync_operation_callback =
153 base::Bind(&SimpleEntryImpl::EntryOperationComplete, 216 base::Bind(&SimpleEntryImpl::EntryOperationComplete,
154 index_, callback, weak_ptr_factory_.GetWeakPtr(), 217 index_, callback, weak_ptr_factory_.GetWeakPtr(),
155 synchronous_entry_); 218 synchronous_entry_);
156 WorkerPool::PostTask(FROM_HERE, 219 WorkerPool::PostTask(FROM_HERE,
157 base::Bind(&SimpleSynchronousEntry::ReadData, 220 base::Bind(&SimpleSynchronousEntry::ReadData,
158 base::Unretained(synchronous_entry_), 221 base::Unretained(synchronous_entry_),
159 index, offset, make_scoped_refptr(buf), 222 index, offset, buf,
gavinp 2013/04/17 08:17:14 This is really dangerous, calling with the naked b
gavinp 2013/04/17 09:40:16 Boy this stuff is subtle. I was wrong: I failed t
160 buf_len, sync_operation_callback), 223 buf_len, sync_operation_callback),
161 true); 224 true);
162 return net::ERR_IO_PENDING; 225 }
226
227 // TODO(felipeg): Maybe in case of failure from a write operation, we could try
228 // to invalidate all operations in the queue of the current entry.
229 static void WriteDataNoOp(int noop) {
163 } 230 }
164 231
165 int SimpleEntryImpl::WriteData(int index, 232 int SimpleEntryImpl::WriteData(int index,
gavinp 2013/04/17 09:23:56 I think ReadData / WriteData can be made a lot sim
felipeg 2013/04/17 10:06:43 Done.
166 int offset, 233 int offset,
167 net::IOBuffer* buf, 234 net::IOBuffer* buf,
168 int buf_len, 235 int buf_len,
169 const CompletionCallback& callback, 236 const CompletionCallback& callback,
170 bool truncate) { 237 bool truncate) {
238 LOG(INFO) << " WRITE " << key_ << " buf " << buf << " buf_len " << buf_len << " truncate " << truncate;
171 DCHECK(io_thread_checker_.CalledOnValidThread()); 239 DCHECK(io_thread_checker_.CalledOnValidThread());
240
172 if (synchronous_entry_in_use_by_worker_) { 241 if (synchronous_entry_in_use_by_worker_) {
173 NOTIMPLEMENTED(); 242 LOG(INFO) << " WRITE " << key_;
174 CHECK(false); 243 // Postpone write operation.
244 operations_.push(
245 base::Bind(&SimpleEntryImpl::WriteDataInternal,
246 weak_ptr_factory_.GetWeakPtr(),
247 index,
248 offset,
249 make_scoped_refptr(buf),
250 buf_len,
251 callback,
252 truncate));
253 // When writting, if there is already a pending operation, we have to return
254 // pending.
255 return net::ERR_IO_PENDING;
175 } 256 }
257 LOG(INFO) << " WRITE " << key_;
258 DCHECK(operations_.size() == 0);
259 WriteDataInternal(index,
260 offset,
261 make_scoped_refptr(buf),
262 buf_len,
263 //callback,
264 base::Bind(&WriteDataNoOp),
265 truncate);
266 //return net::ERR_IO_PENDING;
267 // Pretend everything goes fine, and make HTTP Cache Transaction happy.
268 return buf_len;
269 }
270
271 void SimpleEntryImpl::WriteDataInternal(int index,
272 int offset,
273 scoped_refptr<net::IOBuffer> buf,
274 int buf_len,
275 const CompletionCallback& callback,
276 bool truncate) {
277 DCHECK(io_thread_checker_.CalledOnValidThread());
278 DCHECK(!synchronous_entry_in_use_by_worker_);
279 read_only_operation_ = false;
176 synchronous_entry_in_use_by_worker_ = true; 280 synchronous_entry_in_use_by_worker_ = true;
177 if (index_) 281 if (index_)
178 index_->UseIfExists(key_); 282 index_->UseIfExists(key_);
283
284 // TODO(felipeg): last_used_ last_modified_
285
286 data_size_[index] = buf_len;
287
179 SynchronousOperationCallback sync_operation_callback = 288 SynchronousOperationCallback sync_operation_callback =
180 base::Bind(&SimpleEntryImpl::EntryOperationComplete, 289 base::Bind(&SimpleEntryImpl::EntryOperationComplete,
181 index_, callback, weak_ptr_factory_.GetWeakPtr(), 290 index_, callback, weak_ptr_factory_.GetWeakPtr(),
182 synchronous_entry_); 291 synchronous_entry_);
183 WorkerPool::PostTask(FROM_HERE, 292 WorkerPool::PostTask(FROM_HERE,
184 base::Bind(&SimpleSynchronousEntry::WriteData, 293 base::Bind(&SimpleSynchronousEntry::WriteData,
185 base::Unretained(synchronous_entry_), 294 base::Unretained(synchronous_entry_),
186 index, offset, make_scoped_refptr(buf), 295 index, offset, buf,
187 buf_len, sync_operation_callback, truncate), 296 buf_len, sync_operation_callback, truncate),
188 true); 297 true);
189 return net::ERR_IO_PENDING; 298 LOG(INFO) << " WRITE " << key_;
190 } 299 }
191 300
192 int SimpleEntryImpl::ReadSparseData(int64 offset, 301 int SimpleEntryImpl::ReadSparseData(int64 offset,
193 net::IOBuffer* buf, 302 net::IOBuffer* buf,
194 int buf_len, 303 int buf_len,
195 const CompletionCallback& callback) { 304 const CompletionCallback& callback) {
196 DCHECK(io_thread_checker_.CalledOnValidThread()); 305 DCHECK(io_thread_checker_.CalledOnValidThread());
197 // TODO(gavinp): Determine if the simple backend should support sparse data. 306 // TODO(gavinp): Determine if the simple backend should support sparse data.
198 NOTIMPLEMENTED(); 307 NOTIMPLEMENTED();
199 return net::ERR_FAILED; 308 return net::ERR_FAILED;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 } 348 }
240 349
241 SimpleEntryImpl::SimpleEntryImpl( 350 SimpleEntryImpl::SimpleEntryImpl(
242 SimpleSynchronousEntry* synchronous_entry, 351 SimpleSynchronousEntry* synchronous_entry,
243 WeakPtr<SimpleIndex> index) 352 WeakPtr<SimpleIndex> index)
244 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), 353 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
245 path_(synchronous_entry->path()), 354 path_(synchronous_entry->path()),
246 key_(synchronous_entry->key()), 355 key_(synchronous_entry->key()),
247 synchronous_entry_(synchronous_entry), 356 synchronous_entry_(synchronous_entry),
248 synchronous_entry_in_use_by_worker_(false), 357 synchronous_entry_in_use_by_worker_(false),
358 read_only_operation_(false),
249 index_(index) { 359 index_(index) {
250 DCHECK(synchronous_entry); 360 DCHECK(synchronous_entry);
251 SetSynchronousData(); 361 SetSynchronousData();
252 } 362 }
253 363
254 SimpleEntryImpl::~SimpleEntryImpl() { 364 SimpleEntryImpl::~SimpleEntryImpl() {
255 DCHECK(io_thread_checker_.CalledOnValidThread()); 365 DCHECK(io_thread_checker_.CalledOnValidThread());
256 } 366 }
257 367
258 // static 368 // static
(...skipping 25 matching lines...) Expand all
284 int result) { 394 int result) {
285 DCHECK(sync_entry); 395 DCHECK(sync_entry);
286 if (index) { 396 if (index) {
287 if (result >= 0) 397 if (result >= 0)
288 index->UpdateEntrySize(sync_entry->key(), sync_entry->GetFileSize()); 398 index->UpdateEntrySize(sync_entry->key(), sync_entry->GetFileSize());
289 else 399 else
290 index->Remove(sync_entry->key()); 400 index->Remove(sync_entry->key());
291 } 401 }
292 402
293 if (entry) { 403 if (entry) {
404 if (entry->read_only_operation_)
405 LOG(INFO) << " READ EntryOperationComplete " << entry->key();
406 else
407 LOG(INFO) << " WRITE EntryOperationComplete " << entry->key();
294 DCHECK(entry->synchronous_entry_in_use_by_worker_); 408 DCHECK(entry->synchronous_entry_in_use_by_worker_);
409 entry->read_only_operation_ = false;
295 entry->synchronous_entry_in_use_by_worker_ = false; 410 entry->synchronous_entry_in_use_by_worker_ = false;
296 entry->SetSynchronousData(); 411 entry->SetSynchronousData();
412
413 entry->RunNextOperationIfNeeded();
414
415 completion_callback.Run(result);
297 } else { 416 } else {
417
418 LOG(INFO) << " EntryOperationComplete " << entry->key();
298 // |entry| must have had Close() called while this operation was in flight. 419 // |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 420 // 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|. 421 // flight at a time, it's safe to now call Close() on |sync_entry|.
301 WorkerPool::PostTask(FROM_HERE, 422 WorkerPool::PostTask(FROM_HERE,
302 base::Bind(&SimpleSynchronousEntry::Close, 423 base::Bind(&SimpleSynchronousEntry::Close,
303 base::Unretained(sync_entry)), 424 base::Unretained(sync_entry)),
304 true); 425 true);
426
427 completion_callback.Run(result);
305 } 428 }
306 completion_callback.Run(result); 429 }
430
431 void SimpleEntryImpl::RunNextOperationIfNeeded() {
432 LOG(INFO) << " RunNextOperationIfNeeded " << key_;
433 DCHECK(io_thread_checker_.CalledOnValidThread());
434 if (operations_.size() <= 0)
435 return;
436 base::Closure operation = operations_.front();
437 operations_.pop();
438
439 LOG(INFO) << " operation.Run " << key_;
440 // TODO(felipeg): maybe we should post task. But it could shuffle even more
441 // the order of new operations in this entry.
gavinp 2013/04/17 08:17:14 The callers should be totally insensitive to the o
felipeg 2013/04/17 10:06:43 No post is better because when debugging our minds
442 operation.Run();
307 } 443 }
308 444
309 void SimpleEntryImpl::SetSynchronousData() { 445 void SimpleEntryImpl::SetSynchronousData() {
310 DCHECK(io_thread_checker_.CalledOnValidThread()); 446 DCHECK(io_thread_checker_.CalledOnValidThread());
311 DCHECK(!synchronous_entry_in_use_by_worker_); 447 DCHECK(!synchronous_entry_in_use_by_worker_);
312 // TODO(felipeg): These copies to avoid data races are not optimal. While 448 // 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 449 // 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 450 // in that structure. This also solves problems with last_used() on ext4
315 // filesystems not being accurate. 451 // filesystems not being accurate.
316 last_used_ = synchronous_entry_->last_used(); 452 last_used_ = synchronous_entry_->last_used();
317 last_modified_ = synchronous_entry_->last_modified(); 453 last_modified_ = synchronous_entry_->last_modified();
318 for (int i = 0; i < kSimpleEntryFileCount; ++i) 454 for (int i = 0; i < kSimpleEntryFileCount; ++i)
319 data_size_[i] = synchronous_entry_->data_size(i); 455 data_size_[i] = synchronous_entry_->data_size(i);
320 } 456 }
321 457
322 } // namespace disk_cache 458 } // namespace disk_cache
OLDNEW
« no previous file with comments | « 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