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/entry_impl.h" | 5 #include "net/disk_cache/entry_impl.h" |
6 | 6 |
7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
10 #include "net/base/io_buffer.h" | 10 #include "net/base/io_buffer.h" |
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 DeleteData(address, index); | 489 DeleteData(address, index); |
490 } | 490 } |
491 } | 491 } |
492 | 492 |
493 if (!everything) | 493 if (!everything) |
494 return; | 494 return; |
495 | 495 |
496 // Remove all traces of this entry. | 496 // Remove all traces of this entry. |
497 backend_->RemoveEntry(this); | 497 backend_->RemoveEntry(this); |
498 | 498 |
| 499 // Note that at this point node_ and entry_ are just two blocks of data, and |
| 500 // even if they reference each other, nobody should be referencing them. |
| 501 |
499 Addr address(entry_.Data()->long_key); | 502 Addr address(entry_.Data()->long_key); |
500 DeleteData(address, kKeyFileIndex); | 503 DeleteData(address, kKeyFileIndex); |
501 backend_->ModifyStorageSize(entry_.Data()->key_len, 0); | 504 backend_->ModifyStorageSize(entry_.Data()->key_len, 0); |
502 | 505 |
503 memset(node_.buffer(), 0, node_.size()); | 506 backend_->DeleteBlock(entry_.address(), true); |
504 memset(entry_.buffer(), 0, entry_.size()); | |
505 node_.Store(); | |
506 entry_.Store(); | |
507 | 507 |
508 backend_->DeleteBlock(node_.address(), false); | 508 if (!LeaveRankingsBehind()) |
509 backend_->DeleteBlock(entry_.address(), false); | 509 backend_->DeleteBlock(node_.address(), true); |
510 } | 510 } |
511 | 511 |
512 CacheAddr EntryImpl::GetNextAddress() { | 512 CacheAddr EntryImpl::GetNextAddress() { |
513 return entry_.Data()->next; | 513 return entry_.Data()->next; |
514 } | 514 } |
515 | 515 |
516 void EntryImpl::SetNextAddress(Addr address) { | 516 void EntryImpl::SetNextAddress(Addr address) { |
517 DCHECK_NE(address.value(), entry_.address().value()); | 517 DCHECK_NE(address.value(), entry_.address().value()); |
518 entry_.Data()->next = address.value(); | 518 entry_.Data()->next = address.value(); |
519 bool success = entry_.Store(); | 519 bool success = entry_.Store(); |
(...skipping 24 matching lines...) Expand all Loading... |
544 | 544 |
545 void EntryImpl::SetDirtyFlag(int32 current_id) { | 545 void EntryImpl::SetDirtyFlag(int32 current_id) { |
546 DCHECK(node_.HasData()); | 546 DCHECK(node_.HasData()); |
547 // We are checking if the entry is valid or not. If there is a pointer here, | 547 // We are checking if the entry is valid or not. If there is a pointer here, |
548 // we should not be checking the entry. | 548 // we should not be checking the entry. |
549 if (node_.Data()->dummy) | 549 if (node_.Data()->dummy) |
550 dirty_ = true; | 550 dirty_ = true; |
551 | 551 |
552 if (node_.Data()->dirty && current_id != node_.Data()->dirty) | 552 if (node_.Data()->dirty && current_id != node_.Data()->dirty) |
553 dirty_ = true; | 553 dirty_ = true; |
| 554 |
| 555 if (!current_id) |
| 556 dirty_ = true; |
554 } | 557 } |
555 | 558 |
556 void EntryImpl::SetPointerForInvalidEntry(int32 new_id) { | 559 void EntryImpl::SetPointerForInvalidEntry(int32 new_id) { |
557 node_.Data()->dirty = new_id; | 560 node_.Data()->dirty = new_id; |
558 node_.Data()->dummy = 0; | 561 node_.Data()->dummy = 0; |
559 node_.Store(); | 562 node_.Store(); |
560 } | 563 } |
561 | 564 |
| 565 bool EntryImpl::LeaveRankingsBehind() { |
| 566 return !node_.Data()->contents; |
| 567 } |
| 568 |
| 569 // This only includes checks that relate to the first block of the entry (the |
| 570 // first 256 bytes), and values that should be set from the entry creation. |
| 571 // Basically, even if there is something wrong with this entry, we want to see |
| 572 // if it is possible to load the rankings node and delete them together. |
562 bool EntryImpl::SanityCheck() { | 573 bool EntryImpl::SanityCheck() { |
563 EntryStore* stored = entry_.Data(); | 574 EntryStore* stored = entry_.Data(); |
564 if (!stored->rankings_node || stored->key_len <= 0) | 575 if (!stored->rankings_node || stored->key_len <= 0) |
565 return false; | 576 return false; |
566 | 577 |
567 if (stored->reuse_count < 0 || stored->refetch_count < 0) | 578 if (stored->reuse_count < 0 || stored->refetch_count < 0) |
568 return false; | 579 return false; |
569 | 580 |
570 Addr rankings_addr(stored->rankings_node); | 581 Addr rankings_addr(stored->rankings_node); |
571 if (!rankings_addr.is_initialized() || rankings_addr.is_separate_file() || | 582 if (!rankings_addr.is_initialized() || rankings_addr.is_separate_file() || |
572 rankings_addr.file_type() != RANKINGS) | 583 rankings_addr.file_type() != RANKINGS || rankings_addr.num_blocks() != 1) |
573 return false; | 584 return false; |
574 | 585 |
575 Addr next_addr(stored->next); | 586 Addr next_addr(stored->next); |
576 if (next_addr.is_initialized() && | 587 if (next_addr.is_initialized() && |
577 (next_addr.is_separate_file() || next_addr.file_type() != BLOCK_256)) | 588 (next_addr.is_separate_file() || next_addr.file_type() != BLOCK_256)) |
578 return false; | 589 return false; |
579 | 590 |
580 if (!rankings_addr.SanityCheck() || !next_addr.SanityCheck()) | 591 if (!rankings_addr.SanityCheck() || !next_addr.SanityCheck()) |
581 return false; | 592 return false; |
582 | 593 |
(...skipping 10 matching lines...) Expand all Loading... |
593 | 604 |
594 if (key_addr.is_initialized() && | 605 if (key_addr.is_initialized() && |
595 ((stored->key_len <= kMaxBlockSize && key_addr.is_separate_file()) || | 606 ((stored->key_len <= kMaxBlockSize && key_addr.is_separate_file()) || |
596 (stored->key_len > kMaxBlockSize && key_addr.is_block_file()))) | 607 (stored->key_len > kMaxBlockSize && key_addr.is_block_file()))) |
597 return false; | 608 return false; |
598 | 609 |
599 int num_blocks = NumBlocksForEntry(stored->key_len); | 610 int num_blocks = NumBlocksForEntry(stored->key_len); |
600 if (entry_.address().num_blocks() != num_blocks) | 611 if (entry_.address().num_blocks() != num_blocks) |
601 return false; | 612 return false; |
602 | 613 |
| 614 return true; |
| 615 } |
| 616 |
| 617 bool EntryImpl::DataSanityCheck() { |
| 618 EntryStore* stored = entry_.Data(); |
| 619 Addr key_addr(stored->long_key); |
| 620 |
603 // The key must be NULL terminated. | 621 // The key must be NULL terminated. |
604 if (!key_addr.is_initialized() && stored->key[stored->key_len]) | 622 if (!key_addr.is_initialized() && stored->key[stored->key_len]) |
605 return false; | 623 return false; |
606 | 624 |
607 if (stored->hash != Hash(GetKey())) | 625 if (stored->hash != Hash(GetKey())) |
608 return false; | 626 return false; |
609 | 627 |
610 for (int i = 0; i < kNumStreams; i++) { | 628 for (int i = 0; i < kNumStreams; i++) { |
611 Addr data_addr(stored->data_addr[i]); | 629 Addr data_addr(stored->data_addr[i]); |
612 int data_size = stored->data_size[i]; | 630 int data_size = stored->data_size[i]; |
613 if (data_size < 0) | 631 if (data_size < 0) |
614 return false; | 632 return false; |
615 if (!data_size && data_addr.is_initialized()) | 633 if (!data_size && data_addr.is_initialized()) |
616 return false; | 634 return false; |
617 if (!data_addr.SanityCheck()) | 635 if (!data_addr.SanityCheck()) |
618 return false; | 636 return false; |
619 if (!data_size) | 637 if (!data_size) |
620 continue; | 638 continue; |
621 if (data_size <= kMaxBlockSize && data_addr.is_separate_file()) | 639 if (data_size <= kMaxBlockSize && data_addr.is_separate_file()) |
622 return false; | 640 return false; |
623 if (data_size > kMaxBlockSize && data_addr.is_block_file()) | 641 if (data_size > kMaxBlockSize && data_addr.is_block_file()) |
624 return false; | 642 return false; |
625 } | 643 } |
| 644 return true; |
| 645 } |
626 | 646 |
627 return true; | 647 void EntryImpl::FixForDelete() { |
| 648 EntryStore* stored = entry_.Data(); |
| 649 Addr key_addr(stored->long_key); |
| 650 |
| 651 if (!key_addr.is_initialized()) |
| 652 stored->key[stored->key_len] = '\0'; |
| 653 |
| 654 for (int i = 0; i < kNumStreams; i++) { |
| 655 Addr data_addr(stored->data_addr[i]); |
| 656 int data_size = stored->data_size[i]; |
| 657 if (data_addr.is_initialized()) { |
| 658 if ((data_size <= kMaxBlockSize && data_addr.is_separate_file()) || |
| 659 (data_size > kMaxBlockSize && data_addr.is_block_file()) || |
| 660 !data_addr.SanityCheck()) { |
| 661 // The address is weird so don't attempt to delete it. |
| 662 stored->data_addr[i] = 0; |
| 663 // In general, trust the stored size as it should be in sync with the |
| 664 // total size tracked by the backend. |
| 665 } |
| 666 } |
| 667 if (data_size < 0) |
| 668 stored->data_size[i] = 0; |
| 669 } |
| 670 entry_.Store(); |
628 } | 671 } |
629 | 672 |
630 void EntryImpl::IncrementIoCount() { | 673 void EntryImpl::IncrementIoCount() { |
631 backend_->IncrementIoCount(); | 674 backend_->IncrementIoCount(); |
632 } | 675 } |
633 | 676 |
634 void EntryImpl::DecrementIoCount() { | 677 void EntryImpl::DecrementIoCount() { |
635 backend_->DecrementIoCount(); | 678 backend_->DecrementIoCount(); |
636 } | 679 } |
637 | 680 |
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1426 Trace("%s 0x%p 0x%x 0x%x", msg, reinterpret_cast<void*>(this), | 1469 Trace("%s 0x%p 0x%x 0x%x", msg, reinterpret_cast<void*>(this), |
1427 entry_.address().value(), node_.address().value()); | 1470 entry_.address().value(), node_.address().value()); |
1428 | 1471 |
1429 Trace(" data: 0x%x 0x%x 0x%x", entry_.Data()->data_addr[0], | 1472 Trace(" data: 0x%x 0x%x 0x%x", entry_.Data()->data_addr[0], |
1430 entry_.Data()->data_addr[1], entry_.Data()->long_key); | 1473 entry_.Data()->data_addr[1], entry_.Data()->long_key); |
1431 | 1474 |
1432 Trace(" doomed: %d 0x%x", doomed_, dirty); | 1475 Trace(" doomed: %d 0x%x", doomed_, dirty); |
1433 } | 1476 } |
1434 | 1477 |
1435 } // namespace disk_cache | 1478 } // namespace disk_cache |
OLD | NEW |