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

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: Address Gavin's and Thomas' comments 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
« no previous file with comments | « net/disk_cache/entry_unittest.cc ('k') | net/disk_cache/simple/simple_entry_impl.h » ('j') | 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_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 class DoomEntrySetContext : public base::RefCounted<DoomEntrySetContext> {
63 public:
64 DoomEntrySetContext() : entries_left(0), error_happened(false) {}
65
66 int entries_left; // Number of entries that remain to be doomed.
67 bool error_happened;
68
69 private:
70 friend class base::RefCounted<DoomEntrySetContext>;
71
72 ~DoomEntrySetContext() {}
73 };
74
62 void MaybeCreateSequencedWorkerPool() { 75 void MaybeCreateSequencedWorkerPool() {
63 if (!g_sequenced_worker_pool) { 76 if (!g_sequenced_worker_pool) {
64 int max_worker_threads = kDefaultMaxWorkerThreads; 77 int max_worker_threads = kDefaultMaxWorkerThreads;
65 78
66 const std::string thread_count_field_trial = 79 const std::string thread_count_field_trial =
67 base::FieldTrialList::FindFullName("SimpleCacheMaxThreads"); 80 base::FieldTrialList::FindFullName("SimpleCacheMaxThreads");
68 if (!thread_count_field_trial.empty()) { 81 if (!thread_count_field_trial.empty()) {
69 max_worker_threads = 82 max_worker_threads =
70 std::max(1, std::atoi(thread_count_field_trial.c_str())); 83 std::max(1, std::atoi(thread_count_field_trial.c_str()));
71 } 84 }
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 211
199 void RecordIndexLoad(base::TimeTicks constructed_since, int result) { 212 void RecordIndexLoad(base::TimeTicks constructed_since, int result) {
200 const base::TimeDelta creation_to_index = base::TimeTicks::Now() - 213 const base::TimeDelta creation_to_index = base::TimeTicks::Now() -
201 constructed_since; 214 constructed_since;
202 if (result == net::OK) 215 if (result == net::OK)
203 UMA_HISTOGRAM_TIMES("SimpleCache.CreationToIndex", creation_to_index); 216 UMA_HISTOGRAM_TIMES("SimpleCache.CreationToIndex", creation_to_index);
204 else 217 else
205 UMA_HISTOGRAM_TIMES("SimpleCache.CreationToIndexFail", creation_to_index); 218 UMA_HISTOGRAM_TIMES("SimpleCache.CreationToIndexFail", creation_to_index);
206 } 219 }
207 220
221 // Used only by mass dooming to execute the client-provided callback once all
222 // the entries are doomed. Note that this is called multiple times during a mass
223 // doom operation (until the number of left entries in the context reaches 0).
224 void OnDoomEntriesCompleted(
225 DoomEntrySetContext* context,
226 const net::CompletionCallback& all_entries_doomed_callback,
227 int doomed_entries_count,
228 int net_error) {
229 context->entries_left -= doomed_entries_count;
230 if (net_error == net::ERR_FAILED)
231 context->error_happened = true;
232 if (context->entries_left == 0 && !all_entries_doomed_callback.is_null()) {
233 all_entries_doomed_callback.Run(
234 context->error_happened ? net::ERR_FAILED : net::OK);
235 }
236 }
237
208 } // namespace 238 } // namespace
209 239
210 namespace disk_cache { 240 namespace disk_cache {
211 241
212 SimpleBackendImpl::SimpleBackendImpl(const FilePath& path, 242 SimpleBackendImpl::SimpleBackendImpl(const FilePath& path,
213 int max_bytes, 243 int max_bytes,
214 net::CacheType type, 244 net::CacheType type,
215 base::SingleThreadTaskRunner* cache_thread, 245 base::SingleThreadTaskRunner* cache_thread,
216 net::NetLog* net_log) 246 net::NetLog* net_log)
217 : path_(path), 247 : path_(path),
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 void SimpleBackendImpl::IndexReadyForDoom(Time initial_time, 340 void SimpleBackendImpl::IndexReadyForDoom(Time initial_time,
311 Time end_time, 341 Time end_time,
312 const CompletionCallback& callback, 342 const CompletionCallback& callback,
313 int result) { 343 int result) {
314 if (result != net::OK) { 344 if (result != net::OK) {
315 callback.Run(result); 345 callback.Run(result);
316 return; 346 return;
317 } 347 }
318 scoped_ptr<std::vector<uint64> > removed_key_hashes( 348 scoped_ptr<std::vector<uint64> > removed_key_hashes(
319 index_->RemoveEntriesBetween(initial_time, end_time).release()); 349 index_->RemoveEntriesBetween(initial_time, end_time).release());
320 350 const scoped_refptr<DoomEntrySetContext> context(new DoomEntrySetContext());
351 const CompletionCallback on_entry_doomed_callback = base::Bind(
352 &OnDoomEntriesCompleted, context, callback, 1 /* entry count */);
353 int doomed_active_entries_count = 0;
321 // If any of the entries we are dooming are currently open, we need to remove 354 // 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 355 // them from |active_entries_|, so that attempts to create new entries will
323 // succeed and attempts to open them will fail. 356 // succeed and attempts to open them will fail.
324 for (int i = removed_key_hashes->size() - 1; i >= 0; --i) { 357 for (int i = removed_key_hashes->size() - 1; i >= 0; --i) {
325 const uint64 entry_hash = (*removed_key_hashes)[i]; 358 const uint64 entry_hash = (*removed_key_hashes)[i];
326 EntryMap::iterator it = active_entries_.find(entry_hash); 359 EntryMap::iterator it = active_entries_.find(entry_hash);
327 if (it == active_entries_.end()) 360 if (it == active_entries_.end())
328 continue; 361 continue;
362 ++doomed_active_entries_count;
329 SimpleEntryImpl* entry = it->second.get(); 363 SimpleEntryImpl* entry = it->second.get();
330 entry->Doom(); 364 entry->DoomEntry(on_entry_doomed_callback);
331 365
332 (*removed_key_hashes)[i] = removed_key_hashes->back(); 366 (*removed_key_hashes)[i] = removed_key_hashes->back();
333 removed_key_hashes->resize(removed_key_hashes->size() - 1); 367 removed_key_hashes->resize(removed_key_hashes->size() - 1);
334 } 368 }
369 context->entries_left += doomed_active_entries_count;
370 context->entries_left += removed_key_hashes->size();
335 371
336 PostTaskAndReplyWithResult( 372 PostTaskAndReplyWithResult(
337 worker_pool_, FROM_HERE, 373 worker_pool_, FROM_HERE,
338 base::Bind(&SimpleSynchronousEntry::DoomEntrySet, 374 base::Bind(&SimpleSynchronousEntry::DoomEntrySet,
339 base::Passed(&removed_key_hashes), path_), 375 base::Passed(&removed_key_hashes), path_),
340 base::Bind(&CallCompletionCallback, callback)); 376 base::Bind(&OnDoomEntriesCompleted, context, callback,
377 removed_key_hashes->size()));
gavinp 2013/08/27 15:48:02 What was the undefined behaviour?
Deprecated (see juliatuttle) 2013/08/27 16:44:37 +1; this looked fine to me.
Philippe 2013/08/27 16:58:56 Ah thanks Thomas for reminding me this :) So base:
341 } 378 }
342 379
343 int SimpleBackendImpl::DoomEntriesBetween( 380 int SimpleBackendImpl::DoomEntriesBetween(
344 const Time initial_time, 381 const Time initial_time,
345 const Time end_time, 382 const Time end_time,
346 const CompletionCallback& callback) { 383 const CompletionCallback& callback) {
347 return index_->ExecuteWhenReady( 384 return index_->ExecuteWhenReady(
348 base::Bind(&SimpleBackendImpl::IndexReadyForDoom, AsWeakPtr(), 385 base::Bind(&SimpleBackendImpl::IndexReadyForDoom, AsWeakPtr(),
349 initial_time, end_time, callback)); 386 initial_time, end_time, callback));
350 } 387 }
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 const CompletionCallback& callback, 598 const CompletionCallback& callback,
562 int error_code) { 599 int error_code) {
563 if (error_code == net::ERR_FAILED) { 600 if (error_code == net::ERR_FAILED) {
564 OpenNextEntry(iter, entry, callback); 601 OpenNextEntry(iter, entry, callback);
565 return; 602 return;
566 } 603 }
567 CallCompletionCallback(callback, error_code); 604 CallCompletionCallback(callback, error_code);
568 } 605 }
569 606
570 } // namespace disk_cache 607 } // namespace disk_cache
OLDNEW
« no previous file with comments | « net/disk_cache/entry_unittest.cc ('k') | net/disk_cache/simple/simple_entry_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698