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 |