| 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 "components/visitedlink/browser/visitedlink_master.h" | 5 #include "components/visitedlink/browser/visitedlink_master.h" |
| 6 | 6 |
| 7 #include <stdio.h> | 7 #include <stdio.h> |
| 8 #include <string.h> | 8 #include <string.h> |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
| 14 #include "base/containers/stack_container.h" | 14 #include "base/containers/stack_container.h" |
| 15 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
| 16 #include "base/files/scoped_file.h" | 16 #include "base/files/scoped_file.h" |
| 17 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/macros.h" | 18 #include "base/macros.h" |
| 19 #include "base/memory/ptr_util.h" |
| 19 #include "base/message_loop/message_loop.h" | 20 #include "base/message_loop/message_loop.h" |
| 20 #include "base/rand_util.h" | 21 #include "base/rand_util.h" |
| 21 #include "base/strings/string_util.h" | 22 #include "base/strings/string_util.h" |
| 22 #include "base/threading/thread_restrictions.h" | 23 #include "base/threading/thread_restrictions.h" |
| 23 #include "build/build_config.h" | 24 #include "build/build_config.h" |
| 24 #include "components/visitedlink/browser/visitedlink_delegate.h" | 25 #include "components/visitedlink/browser/visitedlink_delegate.h" |
| 25 #include "components/visitedlink/browser/visitedlink_event_listener.h" | 26 #include "components/visitedlink/browser/visitedlink_event_listener.h" |
| 26 #include "content/public/browser/browser_context.h" | 27 #include "content/public/browser/browser_context.h" |
| 27 #include "content/public/browser/browser_thread.h" | 28 #include "content/public/browser/browser_thread.h" |
| 28 #include "url/gurl.h" | 29 #include "url/gurl.h" |
| (...skipping 26 matching lines...) Expand all Loading... |
| 55 const unsigned VisitedLinkMaster::kDefaultTableSize = 16381; | 56 const unsigned VisitedLinkMaster::kDefaultTableSize = 16381; |
| 56 | 57 |
| 57 const size_t VisitedLinkMaster::kBigDeleteThreshold = 64; | 58 const size_t VisitedLinkMaster::kBigDeleteThreshold = 64; |
| 58 | 59 |
| 59 namespace { | 60 namespace { |
| 60 | 61 |
| 61 // Fills the given salt structure with some quasi-random values | 62 // Fills the given salt structure with some quasi-random values |
| 62 // It is not necessary to generate a cryptographically strong random string, | 63 // It is not necessary to generate a cryptographically strong random string, |
| 63 // only that it be reasonably different for different users. | 64 // only that it be reasonably different for different users. |
| 64 void GenerateSalt(uint8_t salt[LINK_SALT_LENGTH]) { | 65 void GenerateSalt(uint8_t salt[LINK_SALT_LENGTH]) { |
| 65 DCHECK_EQ(LINK_SALT_LENGTH, 8) << "This code assumes the length of the salt"; | 66 static_assert(LINK_SALT_LENGTH == 8, |
| 67 "This code assumes the length of the salt"); |
| 66 uint64_t randval = base::RandUint64(); | 68 uint64_t randval = base::RandUint64(); |
| 67 memcpy(salt, &randval, 8); | 69 memcpy(salt, &randval, 8); |
| 68 } | 70 } |
| 69 | 71 |
| 70 // Opens file on a background thread to not block UI thread. | 72 // Opens file on a background thread to not block UI thread. |
| 71 void AsyncOpen(FILE** file, const base::FilePath& filename) { | 73 void AsyncOpen(FILE** file, const base::FilePath& filename) { |
| 72 *file = base::OpenFile(filename, "wb+"); | 74 *file = base::OpenFile(filename, "wb+"); |
| 73 DLOG_IF(ERROR, !(*file)) << "Failed to open file " << filename.value(); | 75 DLOG_IF(ERROR, !(*file)) << "Failed to open file " << filename.value(); |
| 74 } | 76 } |
| 75 | 77 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 if (*file) | 118 if (*file) |
| 117 base::IgnoreResult(fclose(*file)); | 119 base::IgnoreResult(fclose(*file)); |
| 118 free(file); | 120 free(file); |
| 119 } | 121 } |
| 120 | 122 |
| 121 } // namespace | 123 } // namespace |
| 122 | 124 |
| 123 struct VisitedLinkMaster::LoadFromFileResult | 125 struct VisitedLinkMaster::LoadFromFileResult |
| 124 : public base::RefCountedThreadSafe<LoadFromFileResult> { | 126 : public base::RefCountedThreadSafe<LoadFromFileResult> { |
| 125 LoadFromFileResult(base::ScopedFILE file, | 127 LoadFromFileResult(base::ScopedFILE file, |
| 126 std::unique_ptr<base::SharedMemory> shared_memory, | 128 mojo::ScopedSharedBufferHandle shared_memory, |
| 127 Fingerprint* hash_table, | 129 mojo::ScopedSharedBufferMapping hash_table, |
| 128 int32_t num_entries, | 130 int32_t num_entries, |
| 129 int32_t used_count, | 131 int32_t used_count, |
| 130 uint8_t salt[LINK_SALT_LENGTH]); | 132 uint8_t salt[LINK_SALT_LENGTH]); |
| 131 | 133 |
| 132 base::ScopedFILE file; | 134 base::ScopedFILE file; |
| 133 std::unique_ptr<base::SharedMemory> shared_memory; | 135 mojo::ScopedSharedBufferHandle shared_memory; |
| 134 Fingerprint* hash_table; | 136 mojo::ScopedSharedBufferMapping hash_table; |
| 135 int32_t num_entries; | 137 int32_t num_entries; |
| 136 int32_t used_count; | 138 int32_t used_count; |
| 137 uint8_t salt[LINK_SALT_LENGTH]; | 139 uint8_t salt[LINK_SALT_LENGTH]; |
| 138 | 140 |
| 139 private: | 141 private: |
| 140 friend class base::RefCountedThreadSafe<LoadFromFileResult>; | 142 friend class base::RefCountedThreadSafe<LoadFromFileResult>; |
| 141 virtual ~LoadFromFileResult(); | 143 virtual ~LoadFromFileResult(); |
| 142 | 144 |
| 143 DISALLOW_COPY_AND_ASSIGN(LoadFromFileResult); | 145 DISALLOW_COPY_AND_ASSIGN(LoadFromFileResult); |
| 144 }; | 146 }; |
| 145 | 147 |
| 146 VisitedLinkMaster::LoadFromFileResult::LoadFromFileResult( | 148 VisitedLinkMaster::LoadFromFileResult::LoadFromFileResult( |
| 147 base::ScopedFILE file, | 149 base::ScopedFILE file, |
| 148 std::unique_ptr<base::SharedMemory> shared_memory, | 150 mojo::ScopedSharedBufferHandle shared_memory, |
| 149 Fingerprint* hash_table, | 151 mojo::ScopedSharedBufferMapping hash_table, |
| 150 int32_t num_entries, | 152 int32_t num_entries, |
| 151 int32_t used_count, | 153 int32_t used_count, |
| 152 uint8_t salt[LINK_SALT_LENGTH]) | 154 uint8_t salt[LINK_SALT_LENGTH]) |
| 153 : file(std::move(file)), | 155 : file(std::move(file)), |
| 154 shared_memory(std::move(shared_memory)), | 156 shared_memory(std::move(shared_memory)), |
| 155 hash_table(hash_table), | 157 hash_table(std::move(hash_table)), |
| 156 num_entries(num_entries), | 158 num_entries(num_entries), |
| 157 used_count(used_count) { | 159 used_count(used_count) { |
| 158 memcpy(this->salt, salt, LINK_SALT_LENGTH); | 160 memcpy(this->salt, salt, LINK_SALT_LENGTH); |
| 159 } | 161 } |
| 160 | 162 |
| 161 VisitedLinkMaster::LoadFromFileResult::~LoadFromFileResult() { | 163 VisitedLinkMaster::LoadFromFileResult::~LoadFromFileResult() { |
| 162 } | 164 } |
| 163 | 165 |
| 164 // TableBuilder --------------------------------------------------------------- | 166 // TableBuilder --------------------------------------------------------------- |
| 165 | 167 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 DISALLOW_COPY_AND_ASSIGN(TableBuilder); | 219 DISALLOW_COPY_AND_ASSIGN(TableBuilder); |
| 218 }; | 220 }; |
| 219 | 221 |
| 220 // VisitedLinkMaster ---------------------------------------------------------- | 222 // VisitedLinkMaster ---------------------------------------------------------- |
| 221 | 223 |
| 222 VisitedLinkMaster::VisitedLinkMaster(content::BrowserContext* browser_context, | 224 VisitedLinkMaster::VisitedLinkMaster(content::BrowserContext* browser_context, |
| 223 VisitedLinkDelegate* delegate, | 225 VisitedLinkDelegate* delegate, |
| 224 bool persist_to_disk) | 226 bool persist_to_disk) |
| 225 : browser_context_(browser_context), | 227 : browser_context_(browser_context), |
| 226 delegate_(delegate), | 228 delegate_(delegate), |
| 227 listener_(new VisitedLinkEventListener(this, browser_context)), | 229 listener_(base::MakeUnique<VisitedLinkEventListener>(browser_context)), |
| 228 persist_to_disk_(persist_to_disk), | 230 persist_to_disk_(persist_to_disk), |
| 229 table_is_loading_from_file_(false), | 231 table_is_loading_from_file_(false), |
| 230 weak_ptr_factory_(this) { | 232 weak_ptr_factory_(this) { |
| 231 InitMembers(); | 233 InitMembers(); |
| 232 } | 234 } |
| 233 | 235 |
| 234 VisitedLinkMaster::VisitedLinkMaster(Listener* listener, | 236 VisitedLinkMaster::VisitedLinkMaster(Listener* listener, |
| 235 VisitedLinkDelegate* delegate, | 237 VisitedLinkDelegate* delegate, |
| 236 bool persist_to_disk, | 238 bool persist_to_disk, |
| 237 bool suppress_rebuild, | 239 bool suppress_rebuild, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 // state. On the next start table will be rebuilt. | 272 // state. On the next start table will be rebuilt. |
| 271 base::FilePath filename; | 273 base::FilePath filename; |
| 272 GetDatabaseFileName(&filename); | 274 GetDatabaseFileName(&filename); |
| 273 PostIOTask(FROM_HERE, | 275 PostIOTask(FROM_HERE, |
| 274 base::Bind(IgnoreResult(&base::DeleteFile), filename, false)); | 276 base::Bind(IgnoreResult(&base::DeleteFile), filename, false)); |
| 275 } | 277 } |
| 276 } | 278 } |
| 277 | 279 |
| 278 void VisitedLinkMaster::InitMembers() { | 280 void VisitedLinkMaster::InitMembers() { |
| 279 file_ = NULL; | 281 file_ = NULL; |
| 280 shared_memory_ = NULL; | |
| 281 shared_memory_serial_ = 0; | 282 shared_memory_serial_ = 0; |
| 282 used_items_ = 0; | 283 used_items_ = 0; |
| 283 table_size_override_ = 0; | 284 table_size_override_ = 0; |
| 284 suppress_rebuild_ = false; | 285 suppress_rebuild_ = false; |
| 285 sequence_token_ = base::SequencedWorkerPool::GetSequenceToken(); | 286 sequence_token_ = base::SequencedWorkerPool::GetSequenceToken(); |
| 286 } | 287 } |
| 287 | 288 |
| 288 bool VisitedLinkMaster::Init() { | 289 bool VisitedLinkMaster::Init() { |
| 289 // Create the temporary table. If the table is rebuilt that temporary table | 290 // Create the temporary table. If the table is rebuilt that temporary table |
| 290 // will be became the main table. | 291 // will be became the main table. |
| 291 // The salt must be generated before the table so that it can be copied to | 292 // The salt must be generated before the table so that it can be copied to |
| 292 // the shared memory. | 293 // the shared memory. |
| 293 GenerateSalt(salt_); | 294 GenerateSalt(salt_); |
| 294 if (!CreateURLTable(DefaultTableSize())) | 295 if (!CreateURLTable(DefaultTableSize())) |
| 295 return false; | 296 return false; |
| 296 | 297 |
| 298 if (shared_memory_.is_valid()) |
| 299 listener_->NewTable(shared_memory_.get()); |
| 300 |
| 297 #ifndef NDEBUG | 301 #ifndef NDEBUG |
| 298 DebugValidate(); | 302 DebugValidate(); |
| 299 #endif | 303 #endif |
| 300 | 304 |
| 301 if (persist_to_disk_) { | 305 if (persist_to_disk_) { |
| 302 if (InitFromFile()) | 306 if (InitFromFile()) |
| 303 return true; | 307 return true; |
| 304 } | 308 } |
| 305 return InitFromScratch(suppress_rebuild_); | 309 return InitFromScratch(suppress_rebuild_); |
| 306 } | 310 } |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 base::ScopedFILE file_closer(base::OpenFile(filename, "rb+")); | 659 base::ScopedFILE file_closer(base::OpenFile(filename, "rb+")); |
| 656 if (!file_closer.get()) | 660 if (!file_closer.get()) |
| 657 return false; | 661 return false; |
| 658 | 662 |
| 659 int32_t num_entries, used_count; | 663 int32_t num_entries, used_count; |
| 660 uint8_t salt[LINK_SALT_LENGTH]; | 664 uint8_t salt[LINK_SALT_LENGTH]; |
| 661 if (!ReadFileHeader(file_closer.get(), &num_entries, &used_count, salt)) | 665 if (!ReadFileHeader(file_closer.get(), &num_entries, &used_count, salt)) |
| 662 return false; // Header isn't valid. | 666 return false; // Header isn't valid. |
| 663 | 667 |
| 664 // Allocate and read the table. | 668 // Allocate and read the table. |
| 665 std::unique_ptr<base::SharedMemory> shared_memory; | 669 mojo::ScopedSharedBufferHandle shared_memory; |
| 666 VisitedLinkCommon::Fingerprint* hash_table; | 670 mojo::ScopedSharedBufferMapping hash_table; |
| 667 if (!CreateApartURLTable(num_entries, salt, &shared_memory, &hash_table)) | 671 if (!CreateApartURLTable(num_entries, salt, &shared_memory, &hash_table)) |
| 668 return false; | 672 return false; |
| 669 | 673 |
| 670 if (!ReadFromFile(file_closer.get(), kFileHeaderSize, hash_table, | 674 if (!ReadFromFile(file_closer.get(), kFileHeaderSize, |
| 675 GetHashTableFromMapping(hash_table), |
| 671 num_entries * sizeof(Fingerprint))) { | 676 num_entries * sizeof(Fingerprint))) { |
| 672 return false; | 677 return false; |
| 673 } | 678 } |
| 674 | 679 |
| 675 *load_from_file_result = | 680 *load_from_file_result = new LoadFromFileResult( |
| 676 new LoadFromFileResult(std::move(file_closer), std::move(shared_memory), | 681 std::move(file_closer), std::move(shared_memory), std::move(hash_table), |
| 677 hash_table, num_entries, used_count, salt); | 682 num_entries, used_count, salt); |
| 678 return true; | 683 return true; |
| 679 } | 684 } |
| 680 | 685 |
| 681 void VisitedLinkMaster::OnTableLoadComplete( | 686 void VisitedLinkMaster::OnTableLoadComplete( |
| 682 bool success, | 687 bool success, |
| 683 scoped_refptr<LoadFromFileResult> load_from_file_result) { | 688 scoped_refptr<LoadFromFileResult> load_from_file_result) { |
| 684 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 689 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 685 DCHECK(persist_to_disk_); | 690 DCHECK(persist_to_disk_); |
| 686 DCHECK(!table_builder_.get()); | 691 DCHECK(!table_builder_.get()); |
| 687 | 692 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 708 return; | 713 return; |
| 709 } | 714 } |
| 710 | 715 |
| 711 // This temporary sets are needed only to rebuild table. | 716 // This temporary sets are needed only to rebuild table. |
| 712 added_since_rebuild_.clear(); | 717 added_since_rebuild_.clear(); |
| 713 deleted_since_rebuild_.clear(); | 718 deleted_since_rebuild_.clear(); |
| 714 | 719 |
| 715 DCHECK(load_from_file_result.get()); | 720 DCHECK(load_from_file_result.get()); |
| 716 | 721 |
| 717 // Delete the previous table. | 722 // Delete the previous table. |
| 718 DCHECK(shared_memory_); | 723 DCHECK(shared_memory_.is_valid()); |
| 719 delete shared_memory_; | 724 shared_memory_.reset(); |
| 720 shared_memory_ = nullptr; | 725 hash_table_mapping_.reset(); |
| 721 | 726 |
| 722 // Assign the open file. | 727 // Assign the open file. |
| 723 DCHECK(!file_); | 728 DCHECK(!file_); |
| 724 DCHECK(load_from_file_result->file.get()); | 729 DCHECK(load_from_file_result->file.get()); |
| 725 file_ = static_cast<FILE**>(malloc(sizeof(*file_))); | 730 file_ = static_cast<FILE**>(malloc(sizeof(*file_))); |
| 726 *file_ = load_from_file_result->file.release(); | 731 *file_ = load_from_file_result->file.release(); |
| 727 | 732 |
| 728 // Assign the loaded table. | 733 // Assign the loaded table. |
| 729 DCHECK(load_from_file_result->shared_memory.get()); | 734 DCHECK(load_from_file_result->shared_memory.is_valid()); |
| 730 DCHECK(load_from_file_result->hash_table); | 735 DCHECK(load_from_file_result->hash_table); |
| 731 memcpy(salt_, load_from_file_result->salt, LINK_SALT_LENGTH); | 736 memcpy(salt_, load_from_file_result->salt, LINK_SALT_LENGTH); |
| 732 shared_memory_ = load_from_file_result->shared_memory.release(); | 737 shared_memory_ = std::move(load_from_file_result->shared_memory); |
| 733 hash_table_ = load_from_file_result->hash_table; | 738 hash_table_mapping_ = std::move(load_from_file_result->hash_table); |
| 739 hash_table_ = GetHashTableFromMapping(hash_table_mapping_); |
| 734 table_length_ = load_from_file_result->num_entries; | 740 table_length_ = load_from_file_result->num_entries; |
| 735 used_items_ = load_from_file_result->used_count; | 741 used_items_ = load_from_file_result->used_count; |
| 736 | 742 |
| 737 #ifndef NDEBUG | 743 #ifndef NDEBUG |
| 738 DebugValidate(); | 744 DebugValidate(); |
| 739 #endif | 745 #endif |
| 740 | 746 |
| 741 // Send an update notification to all child processes. | 747 // Send an update notification to all child processes. |
| 742 listener_->NewTable(shared_memory_); | 748 listener_->NewTable(shared_memory_.get()); |
| 743 | 749 |
| 744 if (!added_since_load_.empty() || !deleted_since_load_.empty()) { | 750 if (!added_since_load_.empty() || !deleted_since_load_.empty()) { |
| 745 // Resize the table if the table doesn't have enough capacity. | 751 // Resize the table if the table doesn't have enough capacity. |
| 746 int new_used_items = | 752 int new_used_items = |
| 747 used_items_ + static_cast<int>(added_since_load_.size()); | 753 used_items_ + static_cast<int>(added_since_load_.size()); |
| 748 if (new_used_items >= table_length_) | 754 if (new_used_items >= table_length_) |
| 749 ResizeTable(NewTableSizeForCount(new_used_items)); | 755 ResizeTable(NewTableSizeForCount(new_used_items)); |
| 750 | 756 |
| 751 // Also add anything that was added while we were asynchronously | 757 // Also add anything that was added while we were asynchronously |
| 752 // loading the table. | 758 // loading the table. |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 return false; | 858 return false; |
| 853 | 859 |
| 854 base::FilePath profile_dir = browser_context_->GetPath(); | 860 base::FilePath profile_dir = browser_context_->GetPath(); |
| 855 *filename = profile_dir.Append(FILE_PATH_LITERAL("Visited Links")); | 861 *filename = profile_dir.Append(FILE_PATH_LITERAL("Visited Links")); |
| 856 return true; | 862 return true; |
| 857 } | 863 } |
| 858 | 864 |
| 859 // Initializes the shared memory structure. The salt should already be filled | 865 // Initializes the shared memory structure. The salt should already be filled |
| 860 // in so that it can be written to the shared memory | 866 // in so that it can be written to the shared memory |
| 861 bool VisitedLinkMaster::CreateURLTable(int32_t num_entries) { | 867 bool VisitedLinkMaster::CreateURLTable(int32_t num_entries) { |
| 862 std::unique_ptr<base::SharedMemory> shared_memory; | 868 mojo::ScopedSharedBufferHandle shared_memory; |
| 863 VisitedLinkCommon::Fingerprint* hash_table; | 869 mojo::ScopedSharedBufferMapping hash_table; |
| 864 if (CreateApartURLTable(num_entries, salt_, &shared_memory, &hash_table)) { | 870 if (CreateApartURLTable(num_entries, salt_, &shared_memory, &hash_table)) { |
| 865 shared_memory_ = shared_memory.release(); | 871 shared_memory_ = std::move(shared_memory); |
| 866 hash_table_ = hash_table; | 872 hash_table_mapping_ = std::move(hash_table); |
| 873 hash_table_ = GetHashTableFromMapping(hash_table_mapping_); |
| 867 table_length_ = num_entries; | 874 table_length_ = num_entries; |
| 868 used_items_ = 0; | 875 used_items_ = 0; |
| 869 return true; | 876 return true; |
| 870 } | 877 } |
| 871 | 878 |
| 872 return false; | 879 return false; |
| 873 } | 880 } |
| 874 | 881 |
| 875 // static | 882 // static |
| 876 bool VisitedLinkMaster::CreateApartURLTable( | 883 bool VisitedLinkMaster::CreateApartURLTable( |
| 877 int32_t num_entries, | 884 int32_t num_entries, |
| 878 const uint8_t salt[LINK_SALT_LENGTH], | 885 const uint8_t salt[LINK_SALT_LENGTH], |
| 879 std::unique_ptr<base::SharedMemory>* shared_memory, | 886 mojo::ScopedSharedBufferHandle* shared_memory, |
| 880 VisitedLinkCommon::Fingerprint** hash_table) { | 887 mojo::ScopedSharedBufferMapping* hash_table) { |
| 881 DCHECK(salt); | 888 DCHECK(salt); |
| 882 DCHECK(shared_memory); | 889 DCHECK(shared_memory); |
| 883 DCHECK(hash_table); | 890 DCHECK(hash_table); |
| 884 | 891 |
| 885 // The table is the size of the table followed by the entries. | 892 // The table is the size of the table followed by the entries. |
| 886 uint32_t alloc_size = | 893 uint32_t alloc_size = |
| 887 num_entries * sizeof(Fingerprint) + sizeof(SharedHeader); | 894 num_entries * sizeof(Fingerprint) + sizeof(SharedHeader); |
| 888 | 895 |
| 889 // Create the shared memory object. | 896 // Create the shared memory object. |
| 890 std::unique_ptr<base::SharedMemory> sh_mem(new base::SharedMemory()); | 897 mojo::ScopedSharedBufferHandle shared_buffer = |
| 891 if (!sh_mem) | 898 mojo::SharedBufferHandle::Create(alloc_size); |
| 899 if (!shared_buffer.is_valid()) |
| 900 return false; |
| 901 mojo::ScopedSharedBufferMapping hash_table_mapping = |
| 902 shared_buffer->Map(alloc_size); |
| 903 if (!hash_table_mapping) |
| 892 return false; | 904 return false; |
| 893 | 905 |
| 894 base::SharedMemoryCreateOptions options; | 906 memset(hash_table_mapping.get(), 0, alloc_size); |
| 895 options.size = alloc_size; | |
| 896 options.share_read_only = true; | |
| 897 | |
| 898 if (!sh_mem->Create(options) || !sh_mem->Map(alloc_size)) | |
| 899 return false; | |
| 900 | |
| 901 memset(sh_mem->memory(), 0, alloc_size); | |
| 902 | 907 |
| 903 // Save the header for other processes to read. | 908 // Save the header for other processes to read. |
| 904 SharedHeader* header = static_cast<SharedHeader*>(sh_mem->memory()); | 909 SharedHeader* header = static_cast<SharedHeader*>(hash_table_mapping.get()); |
| 905 header->length = num_entries; | 910 header->length = num_entries; |
| 906 memcpy(header->salt, salt, LINK_SALT_LENGTH); | 911 memcpy(header->salt, salt, LINK_SALT_LENGTH); |
| 907 | 912 |
| 908 // Our table pointer is just the data immediately following the size. | 913 *shared_memory = std::move(shared_buffer); |
| 909 *hash_table = reinterpret_cast<Fingerprint*>( | 914 *hash_table = std::move(hash_table_mapping); |
| 910 static_cast<char*>(sh_mem->memory()) + sizeof(SharedHeader)); | |
| 911 | |
| 912 *shared_memory = std::move(sh_mem); | |
| 913 | 915 |
| 914 return true; | 916 return true; |
| 915 } | 917 } |
| 916 | 918 |
| 917 bool VisitedLinkMaster::BeginReplaceURLTable(int32_t num_entries) { | 919 bool VisitedLinkMaster::BeginReplaceURLTable(int32_t num_entries) { |
| 918 base::SharedMemory *old_shared_memory = shared_memory_; | 920 mojo::ScopedSharedBufferHandle old_shared_memory = std::move(shared_memory_); |
| 919 Fingerprint* old_hash_table = hash_table_; | 921 mojo::ScopedSharedBufferMapping old_hash_table_mapping = |
| 922 std::move(hash_table_mapping_); |
| 920 int32_t old_table_length = table_length_; | 923 int32_t old_table_length = table_length_; |
| 921 if (!CreateURLTable(num_entries)) { | 924 if (!CreateURLTable(num_entries)) { |
| 922 // Try to put back the old state. | 925 // Try to put back the old state. |
| 923 shared_memory_ = old_shared_memory; | 926 shared_memory_ = std::move(old_shared_memory); |
| 924 hash_table_ = old_hash_table; | 927 hash_table_mapping_ = std::move(old_hash_table_mapping); |
| 928 hash_table_ = GetHashTableFromMapping(hash_table_mapping_); |
| 925 table_length_ = old_table_length; | 929 table_length_ = old_table_length; |
| 926 return false; | 930 return false; |
| 927 } | 931 } |
| 928 | 932 |
| 929 #ifndef NDEBUG | 933 #ifndef NDEBUG |
| 930 DebugValidate(); | 934 DebugValidate(); |
| 931 #endif | 935 #endif |
| 932 | 936 |
| 933 return true; | 937 return true; |
| 934 } | 938 } |
| 935 | 939 |
| 936 void VisitedLinkMaster::FreeURLTable() { | 940 void VisitedLinkMaster::FreeURLTable() { |
| 937 if (shared_memory_) { | 941 shared_memory_.reset(); |
| 938 delete shared_memory_; | 942 hash_table_mapping_.reset(); |
| 939 shared_memory_ = NULL; | |
| 940 } | |
| 941 if (!persist_to_disk_ || !file_) | 943 if (!persist_to_disk_ || !file_) |
| 942 return; | 944 return; |
| 943 PostIOTask(FROM_HERE, base::Bind(&AsyncClose, file_)); | 945 PostIOTask(FROM_HERE, base::Bind(&AsyncClose, file_)); |
| 944 // AsyncClose() will close the file and free the memory pointed by |file_|. | 946 // AsyncClose() will close the file and free the memory pointed by |file_|. |
| 945 file_ = NULL; | 947 file_ = NULL; |
| 946 } | 948 } |
| 947 | 949 |
| 948 bool VisitedLinkMaster::ResizeTableIfNecessary() { | 950 bool VisitedLinkMaster::ResizeTableIfNecessary() { |
| 949 DCHECK(table_length_ > 0) << "Must have a table"; | 951 DCHECK(table_length_ > 0) << "Must have a table"; |
| 950 | 952 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 963 | 965 |
| 964 // Table needs to grow or shrink. | 966 // Table needs to grow or shrink. |
| 965 int new_size = NewTableSizeForCount(used_items_); | 967 int new_size = NewTableSizeForCount(used_items_); |
| 966 DCHECK(new_size > used_items_); | 968 DCHECK(new_size > used_items_); |
| 967 DCHECK(load <= min_table_load || new_size > table_length_); | 969 DCHECK(load <= min_table_load || new_size > table_length_); |
| 968 ResizeTable(new_size); | 970 ResizeTable(new_size); |
| 969 return true; | 971 return true; |
| 970 } | 972 } |
| 971 | 973 |
| 972 void VisitedLinkMaster::ResizeTable(int32_t new_size) { | 974 void VisitedLinkMaster::ResizeTable(int32_t new_size) { |
| 973 DCHECK(shared_memory_ && shared_memory_->memory() && hash_table_); | 975 DCHECK(shared_memory_.is_valid() && hash_table_mapping_); |
| 974 shared_memory_serial_++; | 976 shared_memory_serial_++; |
| 975 | 977 |
| 976 #ifndef NDEBUG | 978 #ifndef NDEBUG |
| 977 DebugValidate(); | 979 DebugValidate(); |
| 978 #endif | 980 #endif |
| 979 | 981 |
| 980 base::SharedMemory* old_shared_memory = shared_memory_; | 982 mojo::ScopedSharedBufferMapping old_hash_table_mapping = |
| 981 Fingerprint* old_hash_table = hash_table_; | 983 std::move(hash_table_mapping_); |
| 982 int32_t old_table_length = table_length_; | 984 int32_t old_table_length = table_length_; |
| 983 if (!BeginReplaceURLTable(new_size)) | 985 if (!BeginReplaceURLTable(new_size)) { |
| 986 hash_table_mapping_ = std::move(old_hash_table_mapping); |
| 987 hash_table_ = GetHashTableFromMapping(hash_table_mapping_); |
| 984 return; | 988 return; |
| 985 | |
| 986 // Now we have two tables, our local copy which is the old one, and the new | |
| 987 // one loaded into this object where we need to copy the data. | |
| 988 for (int32_t i = 0; i < old_table_length; i++) { | |
| 989 Fingerprint cur = old_hash_table[i]; | |
| 990 if (cur) | |
| 991 AddFingerprint(cur, false); | |
| 992 } | 989 } |
| 993 | 990 { |
| 994 // On error unmapping, just forget about it since we can't do anything | 991 Fingerprint* old_hash_table = |
| 995 // else to release it. | 992 GetHashTableFromMapping(old_hash_table_mapping); |
| 996 delete old_shared_memory; | 993 // Now we have two tables, our local copy which is the old one, and the new |
| 994 // one loaded into this object where we need to copy the data. |
| 995 for (int32_t i = 0; i < old_table_length; i++) { |
| 996 Fingerprint cur = old_hash_table[i]; |
| 997 if (cur) |
| 998 AddFingerprint(cur, false); |
| 999 } |
| 1000 } |
| 1001 old_hash_table_mapping.reset(); |
| 997 | 1002 |
| 998 // Send an update notification to all child processes so they read the new | 1003 // Send an update notification to all child processes so they read the new |
| 999 // table. | 1004 // table. |
| 1000 listener_->NewTable(shared_memory_); | 1005 listener_->NewTable(shared_memory_.get()); |
| 1001 | 1006 |
| 1002 #ifndef NDEBUG | 1007 #ifndef NDEBUG |
| 1003 DebugValidate(); | 1008 DebugValidate(); |
| 1004 #endif | 1009 #endif |
| 1005 | 1010 |
| 1006 // The new table needs to be written to disk. | 1011 // The new table needs to be written to disk. |
| 1007 if (persist_to_disk_) | 1012 if (persist_to_disk_) |
| 1008 WriteFullTable(); | 1013 WriteFullTable(); |
| 1009 } | 1014 } |
| 1010 | 1015 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1058 } | 1063 } |
| 1059 | 1064 |
| 1060 // See the TableBuilder declaration above for how this works. | 1065 // See the TableBuilder declaration above for how this works. |
| 1061 void VisitedLinkMaster::OnTableRebuildComplete( | 1066 void VisitedLinkMaster::OnTableRebuildComplete( |
| 1062 bool success, | 1067 bool success, |
| 1063 const std::vector<Fingerprint>& fingerprints) { | 1068 const std::vector<Fingerprint>& fingerprints) { |
| 1064 if (success) { | 1069 if (success) { |
| 1065 // Replace the old table with a new blank one. | 1070 // Replace the old table with a new blank one. |
| 1066 shared_memory_serial_++; | 1071 shared_memory_serial_++; |
| 1067 | 1072 |
| 1068 // We are responsible for freeing it AFTER it has been replaced if | |
| 1069 // replacement succeeds. | |
| 1070 base::SharedMemory* old_shared_memory = shared_memory_; | |
| 1071 | |
| 1072 int new_table_size = NewTableSizeForCount( | 1073 int new_table_size = NewTableSizeForCount( |
| 1073 static_cast<int>(fingerprints.size() + added_since_rebuild_.size())); | 1074 static_cast<int>(fingerprints.size() + added_since_rebuild_.size())); |
| 1074 if (BeginReplaceURLTable(new_table_size)) { | 1075 if (BeginReplaceURLTable(new_table_size)) { |
| 1075 // Free the old table. | |
| 1076 delete old_shared_memory; | |
| 1077 | |
| 1078 // Add the stored fingerprints to the hash table. | 1076 // Add the stored fingerprints to the hash table. |
| 1079 for (const auto& fingerprint : fingerprints) | 1077 for (const auto& fingerprint : fingerprints) |
| 1080 AddFingerprint(fingerprint, false); | 1078 AddFingerprint(fingerprint, false); |
| 1081 | 1079 |
| 1082 // Also add anything that was added while we were asynchronously | 1080 // Also add anything that was added while we were asynchronously |
| 1083 // generating the new table. | 1081 // generating the new table. |
| 1084 for (const auto& fingerprint : added_since_rebuild_) | 1082 for (const auto& fingerprint : added_since_rebuild_) |
| 1085 AddFingerprint(fingerprint, false); | 1083 AddFingerprint(fingerprint, false); |
| 1086 added_since_rebuild_.clear(); | 1084 added_since_rebuild_.clear(); |
| 1087 | 1085 |
| 1088 // Now handle deletions. Do not shrink the table now, we'll shrink it when | 1086 // Now handle deletions. Do not shrink the table now, we'll shrink it when |
| 1089 // adding or deleting an url the next time. | 1087 // adding or deleting an url the next time. |
| 1090 for (const auto& fingerprint : deleted_since_rebuild_) | 1088 for (const auto& fingerprint : deleted_since_rebuild_) |
| 1091 DeleteFingerprint(fingerprint, false); | 1089 DeleteFingerprint(fingerprint, false); |
| 1092 deleted_since_rebuild_.clear(); | 1090 deleted_since_rebuild_.clear(); |
| 1093 | 1091 |
| 1094 // Send an update notification to all child processes. | 1092 // Send an update notification to all child processes. |
| 1095 listener_->NewTable(shared_memory_); | 1093 listener_->NewTable(shared_memory_.get()); |
| 1096 // All tabs which was loaded when table was being rebuilt | 1094 // All tabs which was loaded when table was being rebuilt |
| 1097 // invalidate their links again. | 1095 // invalidate their links again. |
| 1098 listener_->Reset(false); | 1096 listener_->Reset(false); |
| 1099 | 1097 |
| 1100 if (persist_to_disk_) | 1098 if (persist_to_disk_) |
| 1101 WriteFullTable(); | 1099 WriteFullTable(); |
| 1102 } | 1100 } |
| 1103 } | 1101 } |
| 1104 table_builder_ = NULL; // Will release our reference to the builder. | 1102 table_builder_ = NULL; // Will release our reference to the builder. |
| 1105 | 1103 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1194 BrowserThread::PostTask( | 1192 BrowserThread::PostTask( |
| 1195 BrowserThread::UI, FROM_HERE, | 1193 BrowserThread::UI, FROM_HERE, |
| 1196 base::Bind(&TableBuilder::OnCompleteMainThread, this)); | 1194 base::Bind(&TableBuilder::OnCompleteMainThread, this)); |
| 1197 } | 1195 } |
| 1198 | 1196 |
| 1199 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { | 1197 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { |
| 1200 if (master_) | 1198 if (master_) |
| 1201 master_->OnTableRebuildComplete(success_, fingerprints_); | 1199 master_->OnTableRebuildComplete(success_, fingerprints_); |
| 1202 } | 1200 } |
| 1203 | 1201 |
| 1202 // static |
| 1203 VisitedLinkCommon::Fingerprint* VisitedLinkMaster::GetHashTableFromMapping( |
| 1204 const mojo::ScopedSharedBufferMapping& hash_table_mapping) { |
| 1205 DCHECK(hash_table_mapping); |
| 1206 // Our table pointer is just the data immediately following the header. |
| 1207 return reinterpret_cast<Fingerprint*>( |
| 1208 static_cast<char*>(hash_table_mapping.get()) + sizeof(SharedHeader)); |
| 1209 } |
| 1210 |
| 1204 } // namespace visitedlink | 1211 } // namespace visitedlink |
| OLD | NEW |