Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/metrics/histogram.h" | 7 #include "base/metrics/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 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 293 // 1. r(r, b), b(r, y), head(r), tail(y) initial state | 293 // 1. r(r, b), b(r, y), head(r), tail(y) initial state |
| 294 // 2. r(r, b), b(r, y), head(b), tail(y) WriteHead() | 294 // 2. r(r, b), b(r, y), head(b), tail(y) WriteHead() |
| 295 // 3. r(r, b), b(b, y), head(b), tail(y) next.Store() | 295 // 3. r(r, b), b(b, y), head(b), tail(y) next.Store() |
| 296 // 4. r(0, 0), b(b, y), head(b), tail(y) prev.Store() | 296 // 4. r(0, 0), b(b, y), head(b), tail(y) prev.Store() |
| 297 // | 297 // |
| 298 // D. Remove tail: | 298 // D. Remove tail: |
| 299 // 1. a(x, r), r(a, r), head(x), tail(r) initial state | 299 // 1. a(x, r), r(a, r), head(x), tail(r) initial state |
| 300 // 2. a(x, r), r(a, r), head(x), tail(a) WriteTail() | 300 // 2. a(x, r), r(a, r), head(x), tail(a) WriteTail() |
| 301 // 3. a(x, a), r(a, r), head(x), tail(a) prev.Store() | 301 // 3. a(x, a), r(a, r), head(x), tail(a) prev.Store() |
| 302 // 4. a(x, a), r(0, 0), head(x), tail(a) next.Store() | 302 // 4. a(x, a), r(0, 0), head(x), tail(a) next.Store() |
| 303 void Rankings::Remove(CacheRankingsBlock* node, List list) { | 303 void Rankings::Remove(CacheRankingsBlock* node, List list, bool strict) { |
| 304 Trace("Remove 0x%x (0x%x 0x%x) l %d", node->address().value(), | 304 Trace("Remove 0x%x (0x%x 0x%x) l %d", node->address().value(), |
| 305 node->Data()->next, node->Data()->prev, list); | 305 node->Data()->next, node->Data()->prev, list); |
| 306 DCHECK(node->HasData()); | 306 DCHECK(node->HasData()); |
| 307 InvalidateIterators(node); | 307 if (strict) |
| 308 InvalidateIterators(node); | |
| 309 | |
| 308 Addr next_addr(node->Data()->next); | 310 Addr next_addr(node->Data()->next); |
| 309 Addr prev_addr(node->Data()->prev); | 311 Addr prev_addr(node->Data()->prev); |
| 310 if (!next_addr.is_initialized() || next_addr.is_separate_file() || | 312 if (!next_addr.is_initialized() || next_addr.is_separate_file() || |
| 311 !prev_addr.is_initialized() || prev_addr.is_separate_file()) { | 313 !prev_addr.is_initialized() || prev_addr.is_separate_file()) { |
| 312 if (next_addr.is_initialized() || prev_addr.is_initialized()) { | 314 if (next_addr.is_initialized() || prev_addr.is_initialized()) { |
| 313 LOG(ERROR) << "Invalid rankings info."; | 315 LOG(ERROR) << "Invalid rankings info."; |
| 314 } | 316 } |
| 315 return; | 317 return; |
| 316 } | 318 } |
| 317 | 319 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 381 // entry. Otherwise we'll need reentrant transactions, which is an overkill. | 383 // entry. Otherwise we'll need reentrant transactions, which is an overkill. |
| 382 void Rankings::UpdateRank(CacheRankingsBlock* node, bool modified, List list) { | 384 void Rankings::UpdateRank(CacheRankingsBlock* node, bool modified, List list) { |
| 383 Addr& my_head = heads_[list]; | 385 Addr& my_head = heads_[list]; |
| 384 if (my_head.value() == node->address().value()) { | 386 if (my_head.value() == node->address().value()) { |
| 385 UpdateTimes(node, modified); | 387 UpdateTimes(node, modified); |
| 386 node->set_modified(); | 388 node->set_modified(); |
| 387 return; | 389 return; |
| 388 } | 390 } |
| 389 | 391 |
| 390 TimeTicks start = TimeTicks::Now(); | 392 TimeTicks start = TimeTicks::Now(); |
| 391 Remove(node, list); | 393 Remove(node, list, true); |
| 392 Insert(node, modified, list); | 394 Insert(node, modified, list); |
| 393 CACHE_UMA(AGE_MS, "UpdateRank", 0, start); | 395 CACHE_UMA(AGE_MS, "UpdateRank", 0, start); |
| 394 } | 396 } |
| 395 | 397 |
| 396 CacheRankingsBlock* Rankings::GetNext(CacheRankingsBlock* node, List list) { | 398 CacheRankingsBlock* Rankings::GetNext(CacheRankingsBlock* node, List list) { |
| 397 ScopedRankingsBlock next(this); | 399 ScopedRankingsBlock next(this); |
| 398 if (!node) { | 400 if (!node) { |
| 399 Addr& my_head = heads_[list]; | 401 Addr& my_head = heads_[list]; |
| 400 if (!my_head.is_initialized()) | 402 if (!my_head.is_initialized()) |
| 401 return NULL; | 403 return NULL; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 480 int total = 0; | 482 int total = 0; |
| 481 for (int i = 0; i < LAST_ELEMENT; i++) { | 483 for (int i = 0; i < LAST_ELEMENT; i++) { |
| 482 int partial = CheckList(static_cast<List>(i)); | 484 int partial = CheckList(static_cast<List>(i)); |
| 483 if (partial < 0) | 485 if (partial < 0) |
| 484 return partial; | 486 return partial; |
| 485 total += partial; | 487 total += partial; |
| 486 } | 488 } |
| 487 return total; | 489 return total; |
| 488 } | 490 } |
| 489 | 491 |
| 490 bool Rankings::SanityCheck(CacheRankingsBlock* node, bool from_list) { | 492 bool Rankings::SanityCheck(CacheRankingsBlock* node, bool from_list) const { |
| 491 const RankingsNode* data = node->Data(); | 493 const RankingsNode* data = node->Data(); |
| 492 if (!data->contents) | |
| 493 return false; | |
| 494 | |
| 495 // It may have never been inserted. | |
| 496 if (from_list && (!data->last_used || !data->last_modified)) | |
| 497 return false; | |
| 498 | 494 |
| 499 if ((!data->next && data->prev) || (data->next && !data->prev)) | 495 if ((!data->next && data->prev) || (data->next && !data->prev)) |
| 500 return false; | 496 return false; |
| 501 | 497 |
| 502 // Both pointers on zero is a node out of the list. | 498 // Both pointers on zero is a node out of the list. |
| 503 if (!data->next && !data->prev && from_list) | 499 if (!data->next && !data->prev && from_list) |
| 504 return false; | 500 return false; |
| 505 | 501 |
| 506 List list = NO_USE; // Initialize it to something. | 502 List list = NO_USE; // Initialize it to something. |
| 507 if ((node->address().value() == data->prev) && !IsHead(data->prev, &list)) | 503 if ((node->address().value() == data->prev) && !IsHead(data->prev, &list)) |
| 508 return false; | 504 return false; |
| 509 | 505 |
| 510 if ((node->address().value() == data->next) && !IsTail(data->next, &list)) | 506 if ((node->address().value() == data->next) && !IsTail(data->next, &list)) |
| 511 return false; | 507 return false; |
| 512 | 508 |
| 513 if (!data->next && !data->prev) | 509 if (!data->next && !data->prev) |
| 514 return true; | 510 return true; |
| 515 | 511 |
| 516 Addr next_addr(data->next); | 512 Addr next_addr(data->next); |
| 517 Addr prev_addr(data->prev); | 513 Addr prev_addr(data->prev); |
| 518 if (!next_addr.SanityCheck() || next_addr.file_type() != RANKINGS || | 514 if (!next_addr.SanityCheck() || next_addr.file_type() != RANKINGS || |
| 519 !prev_addr.SanityCheck() || prev_addr.file_type() != RANKINGS) | 515 !prev_addr.SanityCheck() || prev_addr.file_type() != RANKINGS) |
| 520 return false; | 516 return false; |
| 521 | 517 |
| 522 return true; | 518 return true; |
| 523 } | 519 } |
| 524 | 520 |
| 521 bool Rankings::DataSanityCheck(CacheRankingsBlock* node, bool from_list) const { | |
| 522 const RankingsNode* data = node->Data(); | |
| 523 if (!data->contents) | |
| 524 return false; | |
| 525 | |
| 526 // It may have never been inserted. | |
| 527 if (from_list && (!data->last_used || !data->last_modified)) | |
| 528 return false; | |
| 529 | |
| 530 return true; | |
| 531 } | |
| 532 | |
| 533 void Rankings::SetContents(CacheRankingsBlock* node, CacheAddr address) { | |
| 534 node->Data()->contents = address; | |
| 535 node->Store(); | |
| 536 } | |
| 537 | |
| 525 void Rankings::ReadHeads() { | 538 void Rankings::ReadHeads() { |
| 526 for (int i = 0; i < LAST_ELEMENT; i++) | 539 for (int i = 0; i < LAST_ELEMENT; i++) |
| 527 heads_[i] = Addr(control_data_->heads[i]); | 540 heads_[i] = Addr(control_data_->heads[i]); |
| 528 } | 541 } |
| 529 | 542 |
| 530 void Rankings::ReadTails() { | 543 void Rankings::ReadTails() { |
| 531 for (int i = 0; i < LAST_ELEMENT; i++) | 544 for (int i = 0; i < LAST_ELEMENT; i++) |
| 532 tails_[i] = Addr(control_data_->tails[i]); | 545 tails_[i] = Addr(control_data_->tails[i]); |
| 533 } | 546 } |
| 534 | 547 |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 796 prev.set_value(address.value()); | 809 prev.set_value(address.value()); |
| 797 address.set_value(node->Data()->next); | 810 address.set_value(node->Data()->next); |
| 798 if (!address.is_initialized() || address.is_separate_file()) | 811 if (!address.is_initialized() || address.is_separate_file()) |
| 799 return ERR_INVALID_NEXT; | 812 return ERR_INVALID_NEXT; |
| 800 | 813 |
| 801 num_items++; | 814 num_items++; |
| 802 } while (node->address().value() != address.value()); | 815 } while (node->address().value() != address.value()); |
| 803 return num_items; | 816 return num_items; |
| 804 } | 817 } |
| 805 | 818 |
| 806 bool Rankings::IsHead(CacheAddr addr, List* list) { | 819 bool Rankings::IsHead(CacheAddr addr, List* list) const { |
|
gavinp
2011/09/29 13:25:34
Good catch.
| |
| 807 for (int i = 0; i < LAST_ELEMENT; i++) { | 820 for (int i = 0; i < LAST_ELEMENT; i++) { |
| 808 if (addr == heads_[i].value()) { | 821 if (addr == heads_[i].value()) { |
| 809 if (*list != i) | 822 if (*list != i) |
| 810 Trace("Changing list %d to %d", *list, i); | 823 Trace("Changing list %d to %d", *list, i); |
| 811 *list = static_cast<List>(i); | 824 *list = static_cast<List>(i); |
| 812 return true; | 825 return true; |
| 813 } | 826 } |
| 814 } | 827 } |
| 815 return false; | 828 return false; |
| 816 } | 829 } |
| 817 | 830 |
| 818 bool Rankings::IsTail(CacheAddr addr, List* list) { | 831 bool Rankings::IsTail(CacheAddr addr, List* list) const { |
| 819 for (int i = 0; i < LAST_ELEMENT; i++) { | 832 for (int i = 0; i < LAST_ELEMENT; i++) { |
| 820 if (addr == tails_[i].value()) { | 833 if (addr == tails_[i].value()) { |
| 821 if (*list != i) | 834 if (*list != i) |
| 822 Trace("Changing list %d to %d", *list, i); | 835 Trace("Changing list %d to %d", *list, i); |
| 823 *list = static_cast<List>(i); | 836 *list = static_cast<List>(i); |
| 824 return true; | 837 return true; |
| 825 } | 838 } |
| 826 } | 839 } |
| 827 return false; | 840 return false; |
| 828 } | 841 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 864 void Rankings::DecrementCounter(List list) { | 877 void Rankings::DecrementCounter(List list) { |
| 865 if (!count_lists_) | 878 if (!count_lists_) |
| 866 return; | 879 return; |
| 867 | 880 |
| 868 DCHECK(control_data_->sizes[list] > 0); | 881 DCHECK(control_data_->sizes[list] > 0); |
| 869 if (control_data_->sizes[list] > 0) | 882 if (control_data_->sizes[list] > 0) |
| 870 control_data_->sizes[list]--; | 883 control_data_->sizes[list]--; |
| 871 } | 884 } |
| 872 | 885 |
| 873 } // namespace disk_cache | 886 } // namespace disk_cache |
| OLD | NEW |