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

Side by Side Diff: net/disk_cache/simple/simple_backend_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_backend_impl.h" 5 #include "net/disk_cache/simple/simple_backend_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cstdlib> 8 #include <cstdlib>
9 9
10 #if defined(OS_POSIX) 10 #if defined(OS_POSIX)
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 52
53 // Cache size when all other size heuristics failed. 53 // Cache size when all other size heuristics failed.
54 const uint64 kDefaultCacheSize = 80 * 1024 * 1024; 54 const uint64 kDefaultCacheSize = 80 * 1024 * 1024;
55 55
56 // Maximum fraction of the cache that one entry can consume. 56 // Maximum fraction of the cache that one entry can consume.
57 const int kMaxFileRatio = 8; 57 const int kMaxFileRatio = 8;
58 58
59 // A global sequenced worker pool to use for launching all tasks. 59 // A global sequenced worker pool to use for launching all tasks.
60 SequencedWorkerPool* g_sequenced_worker_pool = NULL; 60 SequencedWorkerPool* g_sequenced_worker_pool = NULL;
61 61
62 struct DoomEntrySetContext : public base::RefCounted<DoomEntrySetContext> {
gavinp 2013/08/26 20:41:37 This probably should be a class, since it inherits
Philippe 2013/08/27 11:33:30 Yes. In general I use structs when I only use publ
63 DoomEntrySetContext() : entries_left(0), error_happened(false) {}
64
65 int entries_left; // Number of entries that remain to be doomed.
66 bool error_happened;
67 };
68
62 void MaybeCreateSequencedWorkerPool() { 69 void MaybeCreateSequencedWorkerPool() {
63 if (!g_sequenced_worker_pool) { 70 if (!g_sequenced_worker_pool) {
64 int max_worker_threads = kDefaultMaxWorkerThreads; 71 int max_worker_threads = kDefaultMaxWorkerThreads;
65 72
66 const std::string thread_count_field_trial = 73 const std::string thread_count_field_trial =
67 base::FieldTrialList::FindFullName("SimpleCacheMaxThreads"); 74 base::FieldTrialList::FindFullName("SimpleCacheMaxThreads");
68 if (!thread_count_field_trial.empty()) { 75 if (!thread_count_field_trial.empty()) {
69 max_worker_threads = 76 max_worker_threads =
70 std::max(1, std::atoi(thread_count_field_trial.c_str())); 77 std::max(1, std::atoi(thread_count_field_trial.c_str()));
71 } 78 }
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 205
199 void RecordIndexLoad(base::TimeTicks constructed_since, int result) { 206 void RecordIndexLoad(base::TimeTicks constructed_since, int result) {
200 const base::TimeDelta creation_to_index = base::TimeTicks::Now() - 207 const base::TimeDelta creation_to_index = base::TimeTicks::Now() -
201 constructed_since; 208 constructed_since;
202 if (result == net::OK) 209 if (result == net::OK)
203 UMA_HISTOGRAM_TIMES("SimpleCache.CreationToIndex", creation_to_index); 210 UMA_HISTOGRAM_TIMES("SimpleCache.CreationToIndex", creation_to_index);
204 else 211 else
205 UMA_HISTOGRAM_TIMES("SimpleCache.CreationToIndexFail", creation_to_index); 212 UMA_HISTOGRAM_TIMES("SimpleCache.CreationToIndexFail", creation_to_index);
206 } 213 }
207 214
215 // Used only by mass dooming to execute the client-provided callback only once
Deprecated (see juliatuttle) 2013/08/26 21:34:18 It is clever that you reuse it as the "single entr
Philippe 2013/08/27 11:33:30 Yes, good point. Thanks.
216 // all the entries are doomed.
217 void OnDoomEntriesCompleted(
218 DoomEntrySetContext* context,
219 const net::CompletionCallback& all_entries_doomed_callback,
220 int doomed_entries_count,
221 int net_error) {
222 context->entries_left -= doomed_entries_count;
223 if (net_error == net::ERR_FAILED)
224 context->error_happened = true;
225 if (context->entries_left == 0 && !all_entries_doomed_callback.is_null()) {
226 all_entries_doomed_callback.Run(
227 context->error_happened ? net::ERR_FAILED : net::OK);
228 }
229 }
230
208 } // namespace 231 } // namespace
209 232
210 namespace disk_cache { 233 namespace disk_cache {
211 234
212 SimpleBackendImpl::SimpleBackendImpl(const FilePath& path, 235 SimpleBackendImpl::SimpleBackendImpl(const FilePath& path,
213 int max_bytes, 236 int max_bytes,
214 net::CacheType type, 237 net::CacheType type,
215 base::SingleThreadTaskRunner* cache_thread, 238 base::SingleThreadTaskRunner* cache_thread,
216 net::NetLog* net_log) 239 net::NetLog* net_log)
217 : path_(path), 240 : path_(path),
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 void SimpleBackendImpl::IndexReadyForDoom(Time initial_time, 333 void SimpleBackendImpl::IndexReadyForDoom(Time initial_time,
311 Time end_time, 334 Time end_time,
312 const CompletionCallback& callback, 335 const CompletionCallback& callback,
313 int result) { 336 int result) {
314 if (result != net::OK) { 337 if (result != net::OK) {
315 callback.Run(result); 338 callback.Run(result);
316 return; 339 return;
317 } 340 }
318 scoped_ptr<std::vector<uint64> > removed_key_hashes( 341 scoped_ptr<std::vector<uint64> > removed_key_hashes(
319 index_->RemoveEntriesBetween(initial_time, end_time).release()); 342 index_->RemoveEntriesBetween(initial_time, end_time).release());
320 343 const scoped_refptr<DoomEntrySetContext> context(new DoomEntrySetContext());
344 const CompletionCallback on_entry_doomed_callback = base::Bind(
345 &OnDoomEntriesCompleted, context, callback, 1 /* entry count */);
346 int doomed_active_entries_count = 0;
321 // If any of the entries we are dooming are currently open, we need to remove 347 // If any of the entries we are dooming are currently open, we need to remove
322 // them from |active_entries_|, so that attempts to create new entries will 348 // them from |active_entries_|, so that attempts to create new entries will
323 // succeed and attempts to open them will fail. 349 // succeed and attempts to open them will fail.
324 for (int i = removed_key_hashes->size() - 1; i >= 0; --i) { 350 for (int i = removed_key_hashes->size() - 1; i >= 0; --i) {
325 const uint64 entry_hash = (*removed_key_hashes)[i]; 351 const uint64 entry_hash = (*removed_key_hashes)[i];
326 EntryMap::iterator it = active_entries_.find(entry_hash); 352 EntryMap::iterator it = active_entries_.find(entry_hash);
327 if (it == active_entries_.end()) 353 if (it == active_entries_.end())
328 continue; 354 continue;
355 ++doomed_active_entries_count;
329 SimpleEntryImpl* entry = it->second.get(); 356 SimpleEntryImpl* entry = it->second.get();
330 entry->Doom(); 357 entry->DoomEntry(on_entry_doomed_callback);
331 358
332 (*removed_key_hashes)[i] = removed_key_hashes->back(); 359 (*removed_key_hashes)[i] = removed_key_hashes->back();
333 removed_key_hashes->resize(removed_key_hashes->size() - 1); 360 removed_key_hashes->resize(removed_key_hashes->size() - 1);
334 } 361 }
362 context->entries_left += doomed_active_entries_count;
363 context->entries_left += removed_key_hashes->size();
335 364
336 PostTaskAndReplyWithResult( 365 PostTaskAndReplyWithResult(
337 worker_pool_, FROM_HERE, 366 worker_pool_, FROM_HERE,
338 base::Bind(&SimpleSynchronousEntry::DoomEntrySet, 367 base::Bind(&SimpleSynchronousEntry::DoomEntrySet,
339 base::Passed(&removed_key_hashes), path_), 368 base::Passed(&removed_key_hashes), path_),
340 base::Bind(&CallCompletionCallback, callback)); 369 base::Bind(&OnDoomEntriesCompleted, context, callback,
370 removed_key_hashes->size()));
341 } 371 }
342 372
343 int SimpleBackendImpl::DoomEntriesBetween( 373 int SimpleBackendImpl::DoomEntriesBetween(
344 const Time initial_time, 374 const Time initial_time,
345 const Time end_time, 375 const Time end_time,
346 const CompletionCallback& callback) { 376 const CompletionCallback& callback) {
347 return index_->ExecuteWhenReady( 377 return index_->ExecuteWhenReady(
348 base::Bind(&SimpleBackendImpl::IndexReadyForDoom, AsWeakPtr(), 378 base::Bind(&SimpleBackendImpl::IndexReadyForDoom, AsWeakPtr(),
349 initial_time, end_time, callback)); 379 initial_time, end_time, callback));
350 } 380 }
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 const CompletionCallback& callback, 591 const CompletionCallback& callback,
562 int error_code) { 592 int error_code) {
563 if (error_code == net::ERR_FAILED) { 593 if (error_code == net::ERR_FAILED) {
564 OpenNextEntry(iter, entry, callback); 594 OpenNextEntry(iter, entry, callback);
565 return; 595 return;
566 } 596 }
567 CallCompletionCallback(callback, error_code); 597 CallCompletionCallback(callback, error_code);
568 } 598 }
569 599
570 } // namespace disk_cache 600 } // namespace disk_cache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698