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

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: Only make doom operations use the pending operations queue 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));
gavinp 2013/08/29 19:31:40 There's two things about this that might be unnece
Philippe 2013/08/30 13:43:02 IMO, it would be a little subtle/risky to re-order
gavinp 2013/08/30 14:58:18 You're right. This kind of subtle perf change does
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 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 break; 569 break;
573 case SimpleEntryOperation::TYPE_WRITE: 570 case SimpleEntryOperation::TYPE_WRITE:
574 RecordWriteDependencyType(*operation); 571 RecordWriteDependencyType(*operation);
575 WriteDataInternal(operation->index(), 572 WriteDataInternal(operation->index(),
576 operation->offset(), 573 operation->offset(),
577 operation->buf(), 574 operation->buf(),
578 operation->length(), 575 operation->length(),
579 operation->callback(), 576 operation->callback(),
580 operation->truncate()); 577 operation->truncate());
581 break; 578 break;
579 case SimpleEntryOperation::TYPE_DOOM:
580 DoomEntryInternal(operation->callback());
581 break;
582 default: 582 default:
583 NOTREACHED(); 583 NOTREACHED();
584 } 584 }
585 // The operation is kept for histograms. Makes sure it does not leak 585 // The operation is kept for histograms. Makes sure it does not leak
586 // resources. 586 // resources.
587 executing_operation_.swap(operation); 587 executing_operation_.swap(operation);
588 executing_operation_->ReleaseReferences(); 588 executing_operation_->ReleaseReferences();
589 // |this| may have been deleted. 589 // |this| may have been deleted.
590 } 590 }
591 } 591 }
592 592
593 void SimpleEntryImpl::OpenEntryInternal(bool have_index, 593 void SimpleEntryImpl::OpenEntryInternal(bool have_index,
594 const CompletionCallback& callback, 594 const CompletionCallback& callback,
595 Entry** out_entry) { 595 Entry** out_entry) {
596 ScopedOperationRunner operation_runner(this); 596 ScopedOperationRunner operation_runner(this);
597 597
598 net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_OPEN_BEGIN); 598 net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_OPEN_BEGIN);
599 599
600 if (state_ == STATE_READY) { 600 if (state_ == STATE_READY) {
601 ReturnEntryToCaller(out_entry); 601 ReturnEntryToCaller(out_entry);
602 MessageLoopProxy::current()->PostTask(FROM_HERE, base::Bind(callback, 602 MessageLoopProxy::current()->PostTask(FROM_HERE, base::Bind(callback,
603 net::OK)); 603 net::OK));
604 net_log_.AddEvent( 604 net_log_.AddEvent(
605 net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_OPEN_END, 605 net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_OPEN_END,
606 CreateNetLogSimpleEntryCreationCallback(this, net::OK)); 606 CreateNetLogSimpleEntryCreationCallback(this, net::OK));
607 return; 607 return;
608 } else if (state_ == STATE_FAILURE) { 608 }
609 if (state_ == STATE_FAILURE) {
609 if (!callback.is_null()) { 610 if (!callback.is_null()) {
610 MessageLoopProxy::current()->PostTask(FROM_HERE, base::Bind( 611 MessageLoopProxy::current()->PostTask(FROM_HERE, base::Bind(
611 callback, net::ERR_FAILED)); 612 callback, net::ERR_FAILED));
612 } 613 }
613 net_log_.AddEvent( 614 net_log_.AddEvent(
614 net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_OPEN_END, 615 net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_OPEN_END,
615 CreateNetLogSimpleEntryCreationCallback(this, net::ERR_FAILED)); 616 CreateNetLogSimpleEntryCreationCallback(this, net::ERR_FAILED));
616 return; 617 return;
617 } 618 }
618 619
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 synchronous_entry_ = NULL; 726 synchronous_entry_ = NULL;
726 worker_pool_->PostTaskAndReply(FROM_HERE, task, reply); 727 worker_pool_->PostTaskAndReply(FROM_HERE, task, reply);
727 728
728 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 729 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
729 if (!have_written_[i]) { 730 if (!have_written_[i]) {
730 UMA_HISTOGRAM_ENUMERATION("SimpleCache.CheckCRCResult", 731 UMA_HISTOGRAM_ENUMERATION("SimpleCache.CheckCRCResult",
731 crc_check_state_[i], CRC_CHECK_MAX); 732 crc_check_state_[i], CRC_CHECK_MAX);
732 } 733 }
733 } 734 }
734 } else { 735 } else {
735 synchronous_entry_ = NULL;
736 CloseOperationComplete(); 736 CloseOperationComplete();
737 } 737 }
738 } 738 }
739 739
740 void SimpleEntryImpl::ReadDataInternal(int stream_index, 740 void SimpleEntryImpl::ReadDataInternal(int stream_index,
741 int offset, 741 int offset,
742 net::IOBuffer* buf, 742 net::IOBuffer* buf,
743 int buf_len, 743 int buf_len,
744 const CompletionCallback& callback) { 744 const CompletionCallback& callback) {
745 DCHECK(io_thread_checker_.CalledOnValidThread()); 745 DCHECK(io_thread_checker_.CalledOnValidThread());
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 result.get()); 883 result.get());
884 Closure reply = base::Bind(&SimpleEntryImpl::WriteOperationComplete, 884 Closure reply = base::Bind(&SimpleEntryImpl::WriteOperationComplete,
885 this, 885 this,
886 stream_index, 886 stream_index,
887 callback, 887 callback,
888 base::Passed(&entry_stat), 888 base::Passed(&entry_stat),
889 base::Passed(&result)); 889 base::Passed(&result));
890 worker_pool_->PostTaskAndReply(FROM_HERE, task, reply); 890 worker_pool_->PostTaskAndReply(FROM_HERE, task, reply);
891 } 891 }
892 892
893 void SimpleEntryImpl::DoomEntryInternal(const CompletionCallback& callback) {
894 PostTaskAndReplyWithResult(
gavinp 2013/08/29 19:31:40 I think there's a bug here, although it's pre-exis
Philippe 2013/08/30 13:43:02 That's your last CL, right?
gavinp 2013/08/30 14:58:18 Yes.
895 worker_pool_, FROM_HERE,
896 base::Bind(&SimpleSynchronousEntry::DoomEntry, path_, key_, entry_hash_),
897 base::Bind(&SimpleEntryImpl::DoomOperationComplete, this, callback,
898 state_));
899 state_ = STATE_IO_PENDING;
900 }
901
893 void SimpleEntryImpl::CreationOperationComplete( 902 void SimpleEntryImpl::CreationOperationComplete(
894 const CompletionCallback& completion_callback, 903 const CompletionCallback& completion_callback,
895 const base::TimeTicks& start_time, 904 const base::TimeTicks& start_time,
896 scoped_ptr<SimpleEntryCreationResults> in_results, 905 scoped_ptr<SimpleEntryCreationResults> in_results,
897 Entry** out_entry, 906 Entry** out_entry,
898 net::NetLog::EventType end_event_type) { 907 net::NetLog::EventType end_event_type) {
899 DCHECK(io_thread_checker_.CalledOnValidThread()); 908 DCHECK(io_thread_checker_.CalledOnValidThread());
900 DCHECK_EQ(state_, STATE_IO_PENDING); 909 DCHECK_EQ(state_, STATE_IO_PENDING);
901 DCHECK(in_results); 910 DCHECK(in_results);
902 ScopedOperationRunner operation_runner(this); 911 ScopedOperationRunner operation_runner(this);
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1053 RecordWriteResult(WRITE_RESULT_SYNC_WRITE_FAILURE); 1062 RecordWriteResult(WRITE_RESULT_SYNC_WRITE_FAILURE);
1054 if (net_log_.IsLoggingAllEvents()) { 1063 if (net_log_.IsLoggingAllEvents()) {
1055 net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_WRITE_END, 1064 net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_WRITE_END,
1056 CreateNetLogReadWriteCompleteCallback(*result)); 1065 CreateNetLogReadWriteCompleteCallback(*result));
1057 } 1066 }
1058 1067
1059 EntryOperationComplete( 1068 EntryOperationComplete(
1060 stream_index, completion_callback, *entry_stat, result.Pass()); 1069 stream_index, completion_callback, *entry_stat, result.Pass());
1061 } 1070 }
1062 1071
1072 void SimpleEntryImpl::DoomOperationComplete(const CompletionCallback& callback,
1073 State state_to_restore,
1074 int result) {
1075 state_ = state_to_restore;
1076 if (!callback.is_null())
1077 callback.Run(result);
1078 RunNextOperationIfNeeded();
1079 }
1080
1063 void SimpleEntryImpl::ChecksumOperationComplete( 1081 void SimpleEntryImpl::ChecksumOperationComplete(
1064 int orig_result, 1082 int orig_result,
1065 int stream_index, 1083 int stream_index,
1066 const CompletionCallback& completion_callback, 1084 const CompletionCallback& completion_callback,
1067 scoped_ptr<int> result) { 1085 scoped_ptr<int> result) {
1068 DCHECK(io_thread_checker_.CalledOnValidThread()); 1086 DCHECK(io_thread_checker_.CalledOnValidThread());
1069 DCHECK(synchronous_entry_); 1087 DCHECK(synchronous_entry_);
1070 DCHECK_EQ(STATE_IO_PENDING, state_); 1088 DCHECK_EQ(STATE_IO_PENDING, state_);
1071 DCHECK(result); 1089 DCHECK(result);
1072 1090
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1195 } else { 1213 } else {
1196 type = conflicting ? WRITE_FOLLOWS_CONFLICTING_WRITE 1214 type = conflicting ? WRITE_FOLLOWS_CONFLICTING_WRITE
1197 : WRITE_FOLLOWS_NON_CONFLICTING_WRITE; 1215 : WRITE_FOLLOWS_NON_CONFLICTING_WRITE;
1198 } 1216 }
1199 } 1217 }
1200 UMA_HISTOGRAM_ENUMERATION( 1218 UMA_HISTOGRAM_ENUMERATION(
1201 "SimpleCache.WriteDependencyType", type, WRITE_DEPENDENCY_TYPE_MAX); 1219 "SimpleCache.WriteDependencyType", type, WRITE_DEPENDENCY_TYPE_MAX);
1202 } 1220 }
1203 1221
1204 } // namespace disk_cache 1222 } // namespace disk_cache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698