| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/rankings.h" | 5 #include "net/disk_cache/rankings.h" |
| 6 | 6 |
| 7 #include "base/histogram.h" | 7 #include "base/histogram.h" |
| 8 #include "net/disk_cache/backend_impl.h" | 8 #include "net/disk_cache/backend_impl.h" |
| 9 #include "net/disk_cache/entry_impl.h" | 9 #include "net/disk_cache/entry_impl.h" |
| 10 #include "net/disk_cache/errors.h" | 10 #include "net/disk_cache/errors.h" |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 // | 313 // |
| 314 // D. Remove tail: | 314 // D. Remove tail: |
| 315 // 1. a(x, r), r(a, r), head(x), tail(r) initial state | 315 // 1. a(x, r), r(a, r), head(x), tail(r) initial state |
| 316 // 2. a(x, r), r(a, r), head(x), tail(a) WriteTail() | 316 // 2. a(x, r), r(a, r), head(x), tail(a) WriteTail() |
| 317 // 3. a(x, a), r(a, r), head(x), tail(a) prev.Store() | 317 // 3. a(x, a), r(a, r), head(x), tail(a) prev.Store() |
| 318 // 4. a(x, a), r(0, 0), head(x), tail(a) next.Store() | 318 // 4. a(x, a), r(0, 0), head(x), tail(a) next.Store() |
| 319 void Rankings::Remove(CacheRankingsBlock* node, List list) { | 319 void Rankings::Remove(CacheRankingsBlock* node, List list) { |
| 320 Trace("Remove 0x%x (0x%x 0x%x)", node->address().value(), node->Data()->next, | 320 Trace("Remove 0x%x (0x%x 0x%x)", node->address().value(), node->Data()->next, |
| 321 node->Data()->prev); | 321 node->Data()->prev); |
| 322 DCHECK(node->HasData()); | 322 DCHECK(node->HasData()); |
| 323 InvalidateIterators(node); |
| 323 Addr next_addr(node->Data()->next); | 324 Addr next_addr(node->Data()->next); |
| 324 Addr prev_addr(node->Data()->prev); | 325 Addr prev_addr(node->Data()->prev); |
| 325 if (!next_addr.is_initialized() || next_addr.is_separate_file() || | 326 if (!next_addr.is_initialized() || next_addr.is_separate_file() || |
| 326 !prev_addr.is_initialized() || prev_addr.is_separate_file()) { | 327 !prev_addr.is_initialized() || prev_addr.is_separate_file()) { |
| 327 LOG(WARNING) << "Invalid rankings info."; | 328 LOG(WARNING) << "Invalid rankings info."; |
| 328 return; | 329 return; |
| 329 } | 330 } |
| 330 | 331 |
| 331 CacheRankingsBlock next(backend_->File(next_addr), next_addr); | 332 CacheRankingsBlock next(backend_->File(next_addr), next_addr); |
| 332 CacheRankingsBlock prev(backend_->File(prev_addr), prev_addr); | 333 CacheRankingsBlock prev(backend_->File(prev_addr), prev_addr); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 UpdateIterators(&next); | 388 UpdateIterators(&next); |
| 388 UpdateIterators(&prev); | 389 UpdateIterators(&prev); |
| 389 } | 390 } |
| 390 | 391 |
| 391 // A crash in between Remove and Insert will lead to a dirty entry not on the | 392 // A crash in between Remove and Insert will lead to a dirty entry not on the |
| 392 // list. We want to avoid that case as much as we can (as while waiting for IO), | 393 // list. We want to avoid that case as much as we can (as while waiting for IO), |
| 393 // but the net effect is just an assert on debug when attempting to remove the | 394 // but the net effect is just an assert on debug when attempting to remove the |
| 394 // entry. Otherwise we'll need reentrant transactions, which is an overkill. | 395 // entry. Otherwise we'll need reentrant transactions, which is an overkill. |
| 395 void Rankings::UpdateRank(CacheRankingsBlock* node, bool modified, List list) { | 396 void Rankings::UpdateRank(CacheRankingsBlock* node, bool modified, List list) { |
| 396 Time start = Time::Now(); | 397 Time start = Time::Now(); |
| 397 NotAnIterator(node); | |
| 398 Remove(node, list); | 398 Remove(node, list); |
| 399 Insert(node, modified, list); | 399 Insert(node, modified, list); |
| 400 CACHE_UMA(AGE_MS, "UpdateRank", 0, start); | 400 CACHE_UMA(AGE_MS, "UpdateRank", 0, start); |
| 401 } | 401 } |
| 402 | 402 |
| 403 void Rankings::CompleteTransaction() { | 403 void Rankings::CompleteTransaction() { |
| 404 Addr node_addr(static_cast<CacheAddr>(control_data_->transaction)); | 404 Addr node_addr(static_cast<CacheAddr>(control_data_->transaction)); |
| 405 if (!node_addr.is_initialized() || node_addr.is_separate_file()) { | 405 if (!node_addr.is_initialized() || node_addr.is_separate_file()) { |
| 406 NOTREACHED(); | 406 NOTREACHED(); |
| 407 LOG(ERROR) << "Invalid rankings info."; | 407 LOG(ERROR) << "Invalid rankings info."; |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 if (node && !CheckSingleLink(prev.get(), node)) | 567 if (node && !CheckSingleLink(prev.get(), node)) |
| 568 return NULL; | 568 return NULL; |
| 569 | 569 |
| 570 return prev.release(); | 570 return prev.release(); |
| 571 } | 571 } |
| 572 | 572 |
| 573 void Rankings::FreeRankingsBlock(CacheRankingsBlock* node) { | 573 void Rankings::FreeRankingsBlock(CacheRankingsBlock* node) { |
| 574 TrackRankingsBlock(node, false); | 574 TrackRankingsBlock(node, false); |
| 575 } | 575 } |
| 576 | 576 |
| 577 void Rankings::TrackRankingsBlock(CacheRankingsBlock* node, |
| 578 bool start_tracking) { |
| 579 if (!node) |
| 580 return; |
| 581 |
| 582 IteratorPair current(node->address().value(), node); |
| 583 |
| 584 if (start_tracking) |
| 585 iterators_.push_back(current); |
| 586 else |
| 587 iterators_.remove(current); |
| 588 } |
| 589 |
| 577 int Rankings::SelfCheck() { | 590 int Rankings::SelfCheck() { |
| 578 int total = 0; | 591 int total = 0; |
| 579 for (int i = 0; i < LAST_ELEMENT; i++) { | 592 for (int i = 0; i < LAST_ELEMENT; i++) { |
| 580 int partial = CheckList(static_cast<List>(i)); | 593 int partial = CheckList(static_cast<List>(i)); |
| 581 if (partial < 0) | 594 if (partial < 0) |
| 582 return partial; | 595 return partial; |
| 583 total += partial; | 596 total += partial; |
| 584 } | 597 } |
| 585 return total; | 598 return total; |
| 586 } | 599 } |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 720 return false; | 733 return false; |
| 721 } | 734 } |
| 722 | 735 |
| 723 bool Rankings::IsTail(CacheAddr addr) { | 736 bool Rankings::IsTail(CacheAddr addr) { |
| 724 for (int i = 0; i < LAST_ELEMENT; i++) | 737 for (int i = 0; i < LAST_ELEMENT; i++) |
| 725 if (addr == tails_[i].value()) | 738 if (addr == tails_[i].value()) |
| 726 return true; | 739 return true; |
| 727 return false; | 740 return false; |
| 728 } | 741 } |
| 729 | 742 |
| 730 void Rankings::TrackRankingsBlock(CacheRankingsBlock* node, | |
| 731 bool start_tracking) { | |
| 732 if (!node) | |
| 733 return; | |
| 734 | |
| 735 IteratorPair current(node->address().value(), node); | |
| 736 | |
| 737 if (start_tracking) | |
| 738 iterators_.push_back(current); | |
| 739 else | |
| 740 iterators_.remove(current); | |
| 741 } | |
| 742 | |
| 743 // We expect to have just a few iterators at any given time, maybe two or three, | 743 // We expect to have just a few iterators at any given time, maybe two or three, |
| 744 // But we could have more than one pointing at the same mode. We walk the list | 744 // But we could have more than one pointing at the same mode. We walk the list |
| 745 // of cache iterators and update all that are pointing to the given node. | 745 // of cache iterators and update all that are pointing to the given node. |
| 746 void Rankings::UpdateIterators(CacheRankingsBlock* node) { | 746 void Rankings::UpdateIterators(CacheRankingsBlock* node) { |
| 747 CacheAddr address = node->address().value(); | 747 CacheAddr address = node->address().value(); |
| 748 for (IteratorList::iterator it = iterators_.begin(); it != iterators_.end(); | 748 for (IteratorList::iterator it = iterators_.begin(); it != iterators_.end(); |
| 749 ++it) { | 749 ++it) { |
| 750 if (it->first == address) { | 750 if (it->first == address && it->second->HasData()) { |
| 751 CacheRankingsBlock* other = it->second; | 751 CacheRankingsBlock* other = it->second; |
| 752 other->Data()->next = node->Data()->next; | 752 other->Data()->next = node->Data()->next; |
| 753 other->Data()->prev = node->Data()->prev; | 753 other->Data()->prev = node->Data()->prev; |
| 754 } | 754 } |
| 755 } | 755 } |
| 756 } | 756 } |
| 757 | 757 |
| 758 void Rankings::NotAnIterator(CacheRankingsBlock* node) { | 758 void Rankings::InvalidateIterators(CacheRankingsBlock* node) { |
| 759 #ifdef NDEBUG | |
| 760 // This method is only enabled for debug builds. | |
| 761 return; | |
| 762 #endif | |
| 763 CacheAddr address = node->address().value(); | 759 CacheAddr address = node->address().value(); |
| 764 for (IteratorList::iterator it = iterators_.begin(); it != iterators_.end(); | 760 for (IteratorList::iterator it = iterators_.begin(); it != iterators_.end(); |
| 765 ++it) { | 761 ++it) { |
| 766 if (it->first == address) | 762 if (it->first == address) { |
| 767 NOTREACHED(); | 763 LOG(WARNING) << "Invalidating iterator at 0x" << std::hex << address; |
| 764 it->second->Discard(); |
| 765 } |
| 768 } | 766 } |
| 769 } | 767 } |
| 770 | 768 |
| 771 void Rankings::IncrementCounter(List list) { | 769 void Rankings::IncrementCounter(List list) { |
| 772 if (!count_lists_) | 770 if (!count_lists_) |
| 773 return; | 771 return; |
| 774 | 772 |
| 775 DCHECK(control_data_->sizes[list] < kint32max); | 773 DCHECK(control_data_->sizes[list] < kint32max); |
| 776 if (control_data_->sizes[list] < kint32max) | 774 if (control_data_->sizes[list] < kint32max) |
| 777 control_data_->sizes[list]++; | 775 control_data_->sizes[list]++; |
| 778 } | 776 } |
| 779 | 777 |
| 780 void Rankings::DecrementCounter(List list) { | 778 void Rankings::DecrementCounter(List list) { |
| 781 if (!count_lists_) | 779 if (!count_lists_) |
| 782 return; | 780 return; |
| 783 | 781 |
| 784 DCHECK(control_data_->sizes[list] > 0); | 782 DCHECK(control_data_->sizes[list] > 0); |
| 785 if (control_data_->sizes[list] > 0) | 783 if (control_data_->sizes[list] > 0) |
| 786 control_data_->sizes[list]--; | 784 control_data_->sizes[list]--; |
| 787 } | 785 } |
| 788 | 786 |
| 789 } // namespace disk_cache | 787 } // namespace disk_cache |
| OLD | NEW |