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

Side by Side Diff: net/disk_cache/backend_impl.cc

Issue 11649028: Add an IO thread index bitmap to disk cache. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: windows build fix Created 7 years, 11 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/backend_impl.h" 5 #include "net/disk_cache/backend_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/file_path.h" 9 #include "base/file_path.h"
10 #include "base/file_util.h" 10 #include "base/file_util.h"
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 // is not there anymore... let's create a new set of files. 242 // is not there anymore... let's create a new set of files.
243 int rv = Run(); 243 int rv = Run();
244 DCHECK_EQ(net::ERR_IO_PENDING, rv); 244 DCHECK_EQ(net::ERR_IO_PENDING, rv);
245 } 245 }
246 246
247 // A callback to perform final cleanup on the background thread. 247 // A callback to perform final cleanup on the background thread.
248 void FinalCleanupCallback(disk_cache::BackendImpl* backend) { 248 void FinalCleanupCallback(disk_cache::BackendImpl* backend) {
249 backend->CleanupCache(); 249 backend->CleanupCache();
250 } 250 }
251 251
252 bool IsPowerOfTwo(size_t number) {
253 return !(number & (number - 1));
254 }
255
256 bool IndexBitmapLookup(const std::vector<bool>& bitmap,
257 const std::string& key) {
258 DCHECK(!bitmap.empty()) << "Call site should provide default behaviour";
259 DCHECK(IsPowerOfTwo(bitmap.size()));
260 const uint32 mask = bitmap.size() - 1;
261 const uint32 hash = base::Hash(key);
262 return bitmap[hash & mask];
263 }
264
265 void IndexBitmapSetValue(std::vector<bool>* bitmap,
266 const std::string& key,
267 bool value) {
268 if (bitmap->empty())
269 return;
270 DCHECK(IsPowerOfTwo(bitmap->size()));
271 const uint32 mask = bitmap->size() - 1;
272 const uint32 hash = base::Hash(key);
273 (*bitmap)[hash & mask] = value;
274 }
275
252 } // namespace 276 } // namespace
253 277
254 // ------------------------------------------------------------------------ 278 // ------------------------------------------------------------------------
255 279
256 namespace disk_cache { 280 namespace disk_cache {
257 281
258 int CreateCacheBackend(net::CacheType type, const FilePath& path, int max_bytes, 282 int CreateCacheBackend(net::CacheType type, const FilePath& path, int max_bytes,
259 bool force, base::MessageLoopProxy* thread, 283 bool force, base::MessageLoopProxy* thread,
260 net::NetLog* net_log, Backend** backend, 284 net::NetLog* net_log, Backend** backend,
261 const net::CompletionCallback& callback) { 285 const net::CompletionCallback& callback) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 uma_report_(0), 338 uma_report_(0),
315 user_flags_(0), 339 user_flags_(0),
316 init_(false), 340 init_(false),
317 restarted_(false), 341 restarted_(false),
318 unit_test_(false), 342 unit_test_(false),
319 read_only_(false), 343 read_only_(false),
320 disabled_(false), 344 disabled_(false),
321 new_eviction_(false), 345 new_eviction_(false),
322 first_timer_(true), 346 first_timer_(true),
323 user_load_(false), 347 user_load_(false),
348 index_bitmap_has_been_set_(false, false),
324 net_log_(net_log), 349 net_log_(net_log),
325 done_(true, false), 350 done_(true, false),
326 ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)) { 351 ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)) {
327 } 352 }
328 353
329 BackendImpl::BackendImpl(const FilePath& path, 354 BackendImpl::BackendImpl(const FilePath& path,
330 uint32 mask, 355 uint32 mask,
331 base::MessageLoopProxy* cache_thread, 356 base::MessageLoopProxy* cache_thread,
332 net::NetLog* net_log) 357 net::NetLog* net_log)
333 : ALLOW_THIS_IN_INITIALIZER_LIST(background_queue_(this, cache_thread)), 358 : ALLOW_THIS_IN_INITIALIZER_LIST(background_queue_(this, cache_thread)),
334 path_(path), 359 path_(path),
335 block_files_(path), 360 block_files_(path),
336 mask_(mask), 361 mask_(mask),
337 max_size_(0), 362 max_size_(0),
338 up_ticks_(0), 363 up_ticks_(0),
339 cache_type_(net::DISK_CACHE), 364 cache_type_(net::DISK_CACHE),
340 uma_report_(0), 365 uma_report_(0),
341 user_flags_(kMask), 366 user_flags_(kMask),
342 init_(false), 367 init_(false),
343 restarted_(false), 368 restarted_(false),
344 unit_test_(false), 369 unit_test_(false),
345 read_only_(false), 370 read_only_(false),
346 disabled_(false), 371 disabled_(false),
347 new_eviction_(false), 372 new_eviction_(false),
348 first_timer_(true), 373 first_timer_(true),
349 user_load_(false), 374 user_load_(false),
375 index_bitmap_has_been_set_(false, false),
350 net_log_(net_log), 376 net_log_(net_log),
351 done_(true, false), 377 done_(true, false),
352 ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)) { 378 ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)) {
353 } 379 }
354 380
355 BackendImpl::~BackendImpl() { 381 BackendImpl::~BackendImpl() {
356 if (user_flags_ & kNoRandom) { 382 if (user_flags_ & kNoRandom) {
357 // This is a unit test, so we want to be strict about not leaking entries 383 // This is a unit test, so we want to be strict about not leaking entries
358 // and completing all the work. 384 // and completing all the work.
359 background_queue_.WaitForPendingIO(); 385 background_queue_.WaitForPendingIO();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 net_log, backend, callback); 422 net_log, backend, callback);
397 // This object will self-destroy when finished. 423 // This object will self-destroy when finished.
398 return creator->Run(); 424 return creator->Run();
399 } 425 }
400 426
401 int BackendImpl::Init(const CompletionCallback& callback) { 427 int BackendImpl::Init(const CompletionCallback& callback) {
402 background_queue_.Init(callback); 428 background_queue_.Init(callback);
403 return net::ERR_IO_PENDING; 429 return net::ERR_IO_PENDING;
404 } 430 }
405 431
406 int BackendImpl::SyncInit() { 432 int BackendImpl::SyncInit(scoped_refptr<base::MessageLoopProxy> async_thread) {
rvargas (doing something else) 2013/01/22 22:31:51 We should be able to do this without sending the m
gavinp 2013/01/22 23:15:47 Can you tell me more?
rvargas (doing something else) 2013/01/22 23:46:14 It seems like this is used for controlling when to
gavinp 2013/02/09 16:46:51 Now removed, since we just initialize the bitmap i
407 #if defined(NET_BUILD_STRESS_CACHE) 433 #if defined(NET_BUILD_STRESS_CACHE)
408 // Start evictions right away. 434 // Start evictions right away.
409 up_ticks_ = kTrimDelay * 2; 435 up_ticks_ = kTrimDelay * 2;
410 #endif 436 #endif
411 DCHECK(!init_); 437 DCHECK(!init_);
412 if (init_) 438 if (init_)
413 return net::ERR_FAILED; 439 return net::ERR_FAILED;
414 440
415 bool create_files = false; 441 bool create_files = false;
416 if (!InitBackingStore(&create_files)) { 442 if (!InitBackingStore(&create_files)) {
(...skipping 26 matching lines...) Expand all
443 if (!(user_flags_ & kNoRandom)) { 469 if (!(user_flags_ & kNoRandom)) {
444 // The unit test controls directly what to test. 470 // The unit test controls directly what to test.
445 new_eviction_ = (cache_type_ == net::DISK_CACHE); 471 new_eviction_ = (cache_type_ == net::DISK_CACHE);
446 } 472 }
447 473
448 if (!CheckIndex()) { 474 if (!CheckIndex()) {
449 ReportError(ERR_INIT_FAILED); 475 ReportError(ERR_INIT_FAILED);
450 return net::ERR_FAILED; 476 return net::ERR_FAILED;
451 } 477 }
452 478
479 if (async_thread) {
rvargas (doing something else) 2013/01/22 22:31:51 restarted_ can be used to avoid doing something mo
gavinp 2013/02/09 16:46:51 Done.
480 std::vector<bool> bitmap;
481 CalculateIndexBitmap(&bitmap);
482 if (async_thread->BelongsToCurrentThread()) {
483 SetIndexBitmap(bitmap);
484 } else {
485 async_thread->PostTask(FROM_HERE, base::Bind(&BackendImpl::SetIndexBitmap,
486 base::Unretained(this),
487 bitmap));
488 index_bitmap_has_been_set_.Wait();
rvargas (doing something else) 2013/01/22 22:31:51 A lock doesn't sound so good. Initialization is p
gavinp 2013/01/22 23:15:47 Yes, I did see that the cache is not used during I
rvargas (doing something else) 2013/01/22 23:46:14 That is correct, assuming that the second thread c
gavinp 2013/02/09 16:46:51 Done.
489 }
490 }
453 if (!restarted_ && (create_files || !data_->header.num_entries)) 491 if (!restarted_ && (create_files || !data_->header.num_entries))
454 ReportError(ERR_CACHE_CREATED); 492 ReportError(ERR_CACHE_CREATED);
455 493
456 if (!(user_flags_ & kNoRandom) && 494 if (!(user_flags_ & kNoRandom) &&
457 cache_type_ == net::DISK_CACHE && !InitExperiment(&data_->header)) 495 cache_type_ == net::DISK_CACHE && !InitExperiment(&data_->header))
458 return net::ERR_FAILED; 496 return net::ERR_FAILED;
459 497
460 // We don't care if the value overflows. The only thing we care about is that 498 // We don't care if the value overflows. The only thing we care about is that
461 // the id cannot be zero, because that value is used as "not dirty". 499 // the id cannot be zero, because that value is used as "not dirty".
462 // Increasing the value once per second gives us many years before we start 500 // Increasing the value once per second gives us many years before we start
(...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after
1271 1309
1272 void BackendImpl::SetNewEviction() { 1310 void BackendImpl::SetNewEviction() {
1273 user_flags_ |= kNewEviction; 1311 user_flags_ |= kNewEviction;
1274 new_eviction_ = true; 1312 new_eviction_ = true;
1275 } 1313 }
1276 1314
1277 void BackendImpl::SetFlags(uint32 flags) { 1315 void BackendImpl::SetFlags(uint32 flags) {
1278 user_flags_ |= flags; 1316 user_flags_ |= flags;
1279 } 1317 }
1280 1318
1319 void BackendImpl::ClearIndexBitmapForTest() {
1320 index_bitmap_.clear();
1321 }
1322
1281 void BackendImpl::ClearRefCountForTest() { 1323 void BackendImpl::ClearRefCountForTest() {
1282 num_refs_ = 0; 1324 num_refs_ = 0;
1283 } 1325 }
1284 1326
1285 int BackendImpl::FlushQueueForTest(const CompletionCallback& callback) { 1327 int BackendImpl::FlushQueueForTest(const CompletionCallback& callback) {
1286 background_queue_.FlushQueue(callback); 1328 background_queue_.FlushQueue(callback);
1287 return net::ERR_IO_PENDING; 1329 return net::ERR_IO_PENDING;
1288 } 1330 }
1289 1331
1290 int BackendImpl::RunTaskForTest(const base::Closure& task, 1332 int BackendImpl::RunTaskForTest(const base::Closure& task,
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1349 NOTREACHED(); 1391 NOTREACHED();
1350 not_deleted = 0; 1392 not_deleted = 0;
1351 } 1393 }
1352 1394
1353 return not_deleted; 1395 return not_deleted;
1354 } 1396 }
1355 1397
1356 int BackendImpl::OpenEntry(const std::string& key, Entry** entry, 1398 int BackendImpl::OpenEntry(const std::string& key, Entry** entry,
1357 const CompletionCallback& callback) { 1399 const CompletionCallback& callback) {
1358 DCHECK(!callback.is_null()); 1400 DCHECK(!callback.is_null());
1401 if (!index_bitmap_.empty() && !IndexBitmapLookup(index_bitmap_, key)) {
1402 VLOG(4) << "BackendImpl::OpenEntry missed on bitmap";
1403 return net::ERR_FAILED;
1404 }
1359 background_queue_.OpenEntry(key, entry, callback); 1405 background_queue_.OpenEntry(key, entry, callback);
1360 return net::ERR_IO_PENDING; 1406 return net::ERR_IO_PENDING;
1361 } 1407 }
1362 1408
1363 int BackendImpl::CreateEntry(const std::string& key, Entry** entry, 1409 int BackendImpl::CreateEntry(const std::string& key, Entry** entry,
1364 const CompletionCallback& callback) { 1410 const CompletionCallback& callback) {
1365 DCHECK(!callback.is_null()); 1411 DCHECK(!callback.is_null());
1412 // TODO(gavinp): Only set index_bitmap_ when CreateEntry succeeds.
1413 IndexBitmapSetValue(&index_bitmap_, key, true);
1366 background_queue_.CreateEntry(key, entry, callback); 1414 background_queue_.CreateEntry(key, entry, callback);
1367 return net::ERR_IO_PENDING; 1415 return net::ERR_IO_PENDING;
1368 } 1416 }
1369 1417
1370 int BackendImpl::DoomEntry(const std::string& key, 1418 int BackendImpl::DoomEntry(const std::string& key,
1371 const CompletionCallback& callback) { 1419 const CompletionCallback& callback) {
1372 DCHECK(!callback.is_null()); 1420 DCHECK(!callback.is_null());
1421 // TODO(gavinp): Clear the index_bitmap_ when appropriate after Doom.
1373 background_queue_.DoomEntry(key, callback); 1422 background_queue_.DoomEntry(key, callback);
1374 return net::ERR_IO_PENDING; 1423 return net::ERR_IO_PENDING;
1375 } 1424 }
1376 1425
1377 int BackendImpl::DoomAllEntries(const CompletionCallback& callback) { 1426 int BackendImpl::DoomAllEntries(const CompletionCallback& callback) {
1378 DCHECK(!callback.is_null()); 1427 DCHECK(!callback.is_null());
1379 background_queue_.DoomAllEntries(callback); 1428 background_queue_.DoomAllEntries(callback);
1380 return net::ERR_IO_PENDING; 1429 return net::ERR_IO_PENDING;
1381 } 1430 }
1382 1431
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1431 1480
1432 stats_.GetItems(stats); 1481 stats_.GetItems(stats);
1433 } 1482 }
1434 1483
1435 void BackendImpl::OnExternalCacheHit(const std::string& key) { 1484 void BackendImpl::OnExternalCacheHit(const std::string& key) {
1436 background_queue_.OnExternalCacheHit(key); 1485 background_queue_.OnExternalCacheHit(key);
1437 } 1486 }
1438 1487
1439 // ------------------------------------------------------------------------ 1488 // ------------------------------------------------------------------------
1440 1489
1490 void BackendImpl::CalculateIndexBitmap(std::vector<bool>* bitmap) const {
1491 DCHECK(bitmap);
1492 const int32 table_size = mask_ + 1;
1493 DCHECK(IsPowerOfTwo(table_size));
1494 bitmap->reserve(table_size);
1495 for (int i = 0; i < table_size; ++i)
1496 bitmap->push_back(data_->table[i] != 0);
1497 }
1498
1499 void BackendImpl::SetIndexBitmap(const std::vector<bool>& index_bitmap) {
1500 index_bitmap_ = index_bitmap;
1501 index_bitmap_has_been_set_.Signal();
1502 }
1503
1441 // We just created a new file so we're going to write the header and set the 1504 // We just created a new file so we're going to write the header and set the
1442 // file length to include the hash table (zero filled). 1505 // file length to include the hash table (zero filled).
1443 bool BackendImpl::CreateBackingStore(disk_cache::File* file) { 1506 bool BackendImpl::CreateBackingStore(disk_cache::File* file) {
1444 AdjustMaxCacheSize(0); 1507 AdjustMaxCacheSize(0);
1445 1508
1446 IndexHeader header; 1509 IndexHeader header;
1447 header.table_len = DesiredIndexTableLen(max_size_); 1510 header.table_len = DesiredIndexTableLen(max_size_);
1448 1511
1449 // We need file version 2.1 for the new eviction algorithm. 1512 // We need file version 2.1 for the new eviction algorithm.
1450 if (new_eviction_) 1513 if (new_eviction_)
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1547 DCHECK(!open_entries_.size()); 1610 DCHECK(!open_entries_.size());
1548 DelayedCacheCleanup(path_); 1611 DelayedCacheCleanup(path_);
1549 } else { 1612 } else {
1550 DeleteCache(path_, false); 1613 DeleteCache(path_, false);
1551 } 1614 }
1552 1615
1553 // Don't call Init() if directed by the unit test: we are simulating a failure 1616 // Don't call Init() if directed by the unit test: we are simulating a failure
1554 // trying to re-enable the cache. 1617 // trying to re-enable the cache.
1555 if (unit_test_) 1618 if (unit_test_)
1556 init_ = true; // Let the destructor do proper cleanup. 1619 init_ = true; // Let the destructor do proper cleanup.
1557 else if (SyncInit() == net::OK) { 1620 else if (SyncInit(NULL) == net::OK) {
1558 stats_.SetCounter(Stats::FATAL_ERROR, errors); 1621 stats_.SetCounter(Stats::FATAL_ERROR, errors);
1559 stats_.SetCounter(Stats::DOOM_CACHE, full_dooms); 1622 stats_.SetCounter(Stats::DOOM_CACHE, full_dooms);
1560 stats_.SetCounter(Stats::DOOM_RECENT, partial_dooms); 1623 stats_.SetCounter(Stats::DOOM_RECENT, partial_dooms);
1561 stats_.SetCounter(Stats::GAJS_EVICTED, ga_evictions); 1624 stats_.SetCounter(Stats::GAJS_EVICTED, ga_evictions);
1562 stats_.SetCounter(Stats::LAST_REPORT, last_report); 1625 stats_.SetCounter(Stats::LAST_REPORT, last_report);
1563 } 1626 }
1564 } 1627 }
1565 1628
1566 void BackendImpl::PrepareForRestart() { 1629 void BackendImpl::PrepareForRestart() {
1567 // Reset the mask_ if it was not given by the user. 1630 // Reset the mask_ if it was not given by the user.
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after
2236 if (total_memory > kMaxBuffersSize || total_memory <= 0) 2299 if (total_memory > kMaxBuffersSize || total_memory <= 0)
2237 total_memory = kMaxBuffersSize; 2300 total_memory = kMaxBuffersSize;
2238 2301
2239 done = true; 2302 done = true;
2240 } 2303 }
2241 2304
2242 return static_cast<int>(total_memory); 2305 return static_cast<int>(total_memory);
2243 } 2306 }
2244 2307
2245 } // namespace disk_cache 2308 } // namespace disk_cache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698