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 |