Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |