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

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

Issue 22859060: Fix race condition for non-open/create operations happening after a doom. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 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 <algorithm> 7 #include <algorithm>
8 #include <cstring> 8 #include <cstring>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
13 #include "base/callback.h" 13 #include "base/callback.h"
14 #include "base/location.h" 14 #include "base/location.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/message_loop/message_loop_proxy.h" 16 #include "base/message_loop/message_loop_proxy.h"
17 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
18 #include "base/task_runner.h" 18 #include "base/task_runner.h"
19 #include "base/task_runner_util.h"
19 #include "base/time/time.h" 20 #include "base/time/time.h"
20 #include "net/base/io_buffer.h" 21 #include "net/base/io_buffer.h"
21 #include "net/base/net_errors.h" 22 #include "net/base/net_errors.h"
22 #include "net/disk_cache/net_log_parameters.h" 23 #include "net/disk_cache/net_log_parameters.h"
23 #include "net/disk_cache/simple/simple_backend_impl.h" 24 #include "net/disk_cache/simple/simple_backend_impl.h"
24 #include "net/disk_cache/simple/simple_index.h" 25 #include "net/disk_cache/simple/simple_index.h"
25 #include "net/disk_cache/simple/simple_net_log_parameters.h" 26 #include "net/disk_cache/simple/simple_net_log_parameters.h"
26 #include "net/disk_cache/simple/simple_synchronous_entry.h" 27 #include "net/disk_cache/simple/simple_synchronous_entry.h"
27 #include "net/disk_cache/simple/simple_util.h" 28 #include "net/disk_cache/simple/simple_util.h"
28 #include "third_party/zlib/zlib.h" 29 #include "third_party/zlib/zlib.h"
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 251
251 RunNextOperationIfNeeded(); 252 RunNextOperationIfNeeded();
252 return ret_value; 253 return ret_value;
253 } 254 }
254 255
255 int SimpleEntryImpl::DoomEntry(const CompletionCallback& callback) { 256 int SimpleEntryImpl::DoomEntry(const CompletionCallback& callback) {
256 net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_DOOM_CALL); 257 net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_DOOM_CALL);
257 net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_DOOM_BEGIN); 258 net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_DOOM_BEGIN);
258 259
259 MarkAsDoomed(); 260 MarkAsDoomed();
260 scoped_ptr<int> result(new int()); 261 pending_operations_.push(SimpleEntryOperation::DoomOperation(this, callback));
261 Closure task = base::Bind(&SimpleSynchronousEntry::DoomEntry, path_, key_, 262 RunNextOperationIfNeeded();
262 entry_hash_, result.get());
263 Closure reply = base::Bind(&CallCompletionCallback,
264 callback, base::Passed(&result));
265 worker_pool_->PostTaskAndReply(FROM_HERE, task, reply);
266 return net::ERR_IO_PENDING; 263 return net::ERR_IO_PENDING;
267 } 264 }
268 265
269 void SimpleEntryImpl::SetKey(const std::string& key) { 266 void SimpleEntryImpl::SetKey(const std::string& key) {
270 key_ = key; 267 key_ = key;
271 net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_SET_KEY, 268 net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_SET_KEY,
272 net::NetLog::StringCallback("key", &key)); 269 net::NetLog::StringCallback("key", &key));
273 } 270 }
274 271
275 void SimpleEntryImpl::Doom() { 272 void SimpleEntryImpl::Doom() {
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 if (!backend_.get()) 527 if (!backend_.get())
531 return; 528 return;
532 backend_->OnDeactivated(this); 529 backend_->OnDeactivated(this);
533 backend_.reset(); 530 backend_.reset();
534 } 531 }
535 532
536 void SimpleEntryImpl::MarkAsDoomed() { 533 void SimpleEntryImpl::MarkAsDoomed() {
537 if (!backend_.get()) 534 if (!backend_.get())
538 return; 535 return;
539 backend_->index()->Remove(entry_hash_); 536 backend_->index()->Remove(entry_hash_);
540 RemoveSelfFromBackend();
gavinp 2013/08/26 20:36:50 There's more to it than this. This was the only c
Philippe 2013/08/27 11:33:30 To be honest I'm a bit confused with this MarkAsDo
gavinp 2013/08/27 15:48:02 There's a member backend_ on SimpleEntryImpl, it's
Philippe 2013/08/27 16:11:21 I see now, thanks :) I hadn't understood that the
541 } 537 }
542 538
543 void SimpleEntryImpl::RunNextOperationIfNeeded() { 539 void SimpleEntryImpl::RunNextOperationIfNeeded() {
544 DCHECK(io_thread_checker_.CalledOnValidThread()); 540 DCHECK(io_thread_checker_.CalledOnValidThread());
545 UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.EntryOperationsPending", 541 UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.EntryOperationsPending",
546 pending_operations_.size(), 0, 100, 20); 542 pending_operations_.size(), 0, 100, 20);
547 if (!pending_operations_.empty() && state_ != STATE_IO_PENDING) { 543 if (!pending_operations_.empty() && state_ != STATE_IO_PENDING) {
548 scoped_ptr<SimpleEntryOperation> operation( 544 scoped_ptr<SimpleEntryOperation> operation(
549 new SimpleEntryOperation(pending_operations_.front())); 545 new SimpleEntryOperation(pending_operations_.front()));
550 pending_operations_.pop(); 546 pending_operations_.pop();
(...skipping 21 matching lines...) Expand all
572 break; 568 break;
573 case SimpleEntryOperation::TYPE_WRITE: 569 case SimpleEntryOperation::TYPE_WRITE:
574 RecordWriteDependencyType(*operation); 570 RecordWriteDependencyType(*operation);
575 WriteDataInternal(operation->index(), 571 WriteDataInternal(operation->index(),
576 operation->offset(), 572 operation->offset(),
577 operation->buf(), 573 operation->buf(),
578 operation->length(), 574 operation->length(),
579 operation->callback(), 575 operation->callback(),
580 operation->truncate()); 576 operation->truncate());
581 break; 577 break;
578 case SimpleEntryOperation::TYPE_DOOM:
579 DoomEntryInternal(operation->callback());
580 break;
582 default: 581 default:
583 NOTREACHED(); 582 NOTREACHED();
584 } 583 }
585 // The operation is kept for histograms. Makes sure it does not leak 584 // The operation is kept for histograms. Makes sure it does not leak
586 // resources. 585 // resources.
587 executing_operation_.swap(operation); 586 executing_operation_.swap(operation);
588 executing_operation_->ReleaseReferences(); 587 executing_operation_->ReleaseReferences();
589 // |this| may have been deleted. 588 // |this| may have been deleted.
590 } 589 }
591 } 590 }
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 result.get()); 882 result.get());
884 Closure reply = base::Bind(&SimpleEntryImpl::WriteOperationComplete, 883 Closure reply = base::Bind(&SimpleEntryImpl::WriteOperationComplete,
885 this, 884 this,
886 stream_index, 885 stream_index,
887 callback, 886 callback,
888 base::Passed(&entry_stat), 887 base::Passed(&entry_stat),
889 base::Passed(&result)); 888 base::Passed(&result));
890 worker_pool_->PostTaskAndReply(FROM_HERE, task, reply); 889 worker_pool_->PostTaskAndReply(FROM_HERE, task, reply);
891 } 890 }
892 891
892 void SimpleEntryImpl::DoomEntryInternal(const CompletionCallback& callback) {
893 PostTaskAndReplyWithResult(
gavinp 2013/08/26 20:36:50 Every one of the other calls has a kind of manual
Philippe 2013/08/27 11:33:30 In my opinion it would be nice to switch to PostTa
894 worker_pool_, FROM_HERE,
895 base::Bind(&SimpleSynchronousEntry::DoomEntry, path_, key_, entry_hash_),
896 base::Bind(&SimpleEntryImpl::DoomOperationComplete, this, state_,
897 callback));
898 state_ = STATE_IO_PENDING;
899 }
900
893 void SimpleEntryImpl::CreationOperationComplete( 901 void SimpleEntryImpl::CreationOperationComplete(
894 const CompletionCallback& completion_callback, 902 const CompletionCallback& completion_callback,
895 const base::TimeTicks& start_time, 903 const base::TimeTicks& start_time,
896 scoped_ptr<SimpleEntryCreationResults> in_results, 904 scoped_ptr<SimpleEntryCreationResults> in_results,
897 Entry** out_entry, 905 Entry** out_entry,
898 net::NetLog::EventType end_event_type) { 906 net::NetLog::EventType end_event_type) {
899 DCHECK(io_thread_checker_.CalledOnValidThread()); 907 DCHECK(io_thread_checker_.CalledOnValidThread());
900 DCHECK_EQ(state_, STATE_IO_PENDING); 908 DCHECK_EQ(state_, STATE_IO_PENDING);
901 DCHECK(in_results); 909 DCHECK(in_results);
902 ScopedOperationRunner operation_runner(this); 910 ScopedOperationRunner operation_runner(this);
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1053 RecordWriteResult(WRITE_RESULT_SYNC_WRITE_FAILURE); 1061 RecordWriteResult(WRITE_RESULT_SYNC_WRITE_FAILURE);
1054 if (net_log_.IsLoggingAllEvents()) { 1062 if (net_log_.IsLoggingAllEvents()) {
1055 net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_WRITE_END, 1063 net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_WRITE_END,
1056 CreateNetLogReadWriteCompleteCallback(*result)); 1064 CreateNetLogReadWriteCompleteCallback(*result));
1057 } 1065 }
1058 1066
1059 EntryOperationComplete( 1067 EntryOperationComplete(
1060 stream_index, completion_callback, *entry_stat, result.Pass()); 1068 stream_index, completion_callback, *entry_stat, result.Pass());
1061 } 1069 }
1062 1070
1071 void SimpleEntryImpl::DoomOperationComplete(State state_to_restore,
1072 const CompletionCallback& callback,
1073 int result) {
1074 state_ = state_to_restore;
1075 if (!callback.is_null())
1076 callback.Run(result);
1077 RunNextOperationIfNeeded();
1078 }
1079
1063 void SimpleEntryImpl::ChecksumOperationComplete( 1080 void SimpleEntryImpl::ChecksumOperationComplete(
1064 int orig_result, 1081 int orig_result,
1065 int stream_index, 1082 int stream_index,
1066 const CompletionCallback& completion_callback, 1083 const CompletionCallback& completion_callback,
1067 scoped_ptr<int> result) { 1084 scoped_ptr<int> result) {
1068 DCHECK(io_thread_checker_.CalledOnValidThread()); 1085 DCHECK(io_thread_checker_.CalledOnValidThread());
1069 DCHECK(synchronous_entry_); 1086 DCHECK(synchronous_entry_);
1070 DCHECK_EQ(STATE_IO_PENDING, state_); 1087 DCHECK_EQ(STATE_IO_PENDING, state_);
1071 DCHECK(result); 1088 DCHECK(result);
1072 1089
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1195 } else { 1212 } else {
1196 type = conflicting ? WRITE_FOLLOWS_CONFLICTING_WRITE 1213 type = conflicting ? WRITE_FOLLOWS_CONFLICTING_WRITE
1197 : WRITE_FOLLOWS_NON_CONFLICTING_WRITE; 1214 : WRITE_FOLLOWS_NON_CONFLICTING_WRITE;
1198 } 1215 }
1199 } 1216 }
1200 UMA_HISTOGRAM_ENUMERATION( 1217 UMA_HISTOGRAM_ENUMERATION(
1201 "SimpleCache.WriteDependencyType", type, WRITE_DEPENDENCY_TYPE_MAX); 1218 "SimpleCache.WriteDependencyType", type, WRITE_DEPENDENCY_TYPE_MAX);
1202 } 1219 }
1203 1220
1204 } // namespace disk_cache 1221 } // namespace disk_cache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698