| 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 // Stores the fingerprints we computed on the background thread. | 216 // Stores the fingerprints we computed on the background thread. |
| 215 VisitedLinkCommon::Fingerprints fingerprints_; | 217 VisitedLinkCommon::Fingerprints fingerprints_; |
| 216 | 218 |
| 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, |
| 227 std::unique_ptr<Listener> listener) |
| 225 : browser_context_(browser_context), | 228 : browser_context_(browser_context), |
| 226 delegate_(delegate), | 229 delegate_(delegate), |
| 227 listener_(new VisitedLinkEventListener(this, browser_context)), | 230 listener_( |
| 231 listener ? std::move(listener) |
| 232 : base::MakeUnique<VisitedLinkEventListener>(browser_context, |
| 233 nullptr)), |
| 228 persist_to_disk_(persist_to_disk), | 234 persist_to_disk_(persist_to_disk), |
| 229 table_is_loading_from_file_(false), | 235 table_is_loading_from_file_(false), |
| 230 weak_ptr_factory_(this) { | 236 weak_ptr_factory_(this) { |
| 231 InitMembers(); | 237 InitMembers(); |
| 232 } | 238 } |
| 233 | 239 |
| 234 VisitedLinkMaster::VisitedLinkMaster(Listener* listener, | 240 VisitedLinkMaster::VisitedLinkMaster(Listener* listener, |
| 235 VisitedLinkDelegate* delegate, | 241 VisitedLinkDelegate* delegate, |
| 236 bool persist_to_disk, | 242 bool persist_to_disk, |
| 237 bool suppress_rebuild, | 243 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. | 276 // state. On the next start table will be rebuilt. |
| 271 base::FilePath filename; | 277 base::FilePath filename; |
| 272 GetDatabaseFileName(&filename); | 278 GetDatabaseFileName(&filename); |
| 273 PostIOTask(FROM_HERE, | 279 PostIOTask(FROM_HERE, |
| 274 base::Bind(IgnoreResult(&base::DeleteFile), filename, false)); | 280 base::Bind(IgnoreResult(&base::DeleteFile), filename, false)); |
| 275 } | 281 } |
| 276 } | 282 } |
| 277 | 283 |
| 278 void VisitedLinkMaster::InitMembers() { | 284 void VisitedLinkMaster::InitMembers() { |
| 279 file_ = NULL; | 285 file_ = NULL; |
| 280 shared_memory_ = NULL; | |
| 281 shared_memory_serial_ = 0; | 286 shared_memory_serial_ = 0; |
| 282 used_items_ = 0; | 287 used_items_ = 0; |
| 283 table_size_override_ = 0; | 288 table_size_override_ = 0; |
| 284 suppress_rebuild_ = false; | 289 suppress_rebuild_ = false; |
| 285 sequence_token_ = base::SequencedWorkerPool::GetSequenceToken(); | 290 sequence_token_ = base::SequencedWorkerPool::GetSequenceToken(); |
| 286 } | 291 } |
| 287 | 292 |
| 288 bool VisitedLinkMaster::Init() { | 293 bool VisitedLinkMaster::Init() { |
| 289 // Create the temporary table. If the table is rebuilt that temporary table | 294 // Create the temporary table. If the table is rebuilt that temporary table |
| 290 // will be became the main table. | 295 // will be became the main table. |
| 291 // The salt must be generated before the table so that it can be copied to | 296 // The salt must be generated before the table so that it can be copied to |
| 292 // the shared memory. | 297 // the shared memory. |
| 293 GenerateSalt(salt_); | 298 GenerateSalt(salt_); |
| 294 if (!CreateURLTable(DefaultTableSize())) | 299 if (!CreateURLTable(DefaultTableSize())) |
| 295 return false; | 300 return false; |
| 296 | 301 |
| 302 if (shared_memory_.is_valid()) |
| 303 listener_->NewTable(shared_memory_.get()); |
| 304 |
| 297 #ifndef NDEBUG | 305 #ifndef NDEBUG |
| 298 DebugValidate(); | 306 DebugValidate(); |
| 299 #endif | 307 #endif |
| 300 | 308 |
| 301 if (persist_to_disk_) { | 309 if (persist_to_disk_) { |
| 302 if (InitFromFile()) | 310 if (InitFromFile()) |
| 303 return true; | 311 return true; |
| 304 } | 312 } |
| 305 return InitFromScratch(suppress_rebuild_); | 313 return InitFromScratch(suppress_rebuild_); |
| 306 } | 314 } |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 base::ScopedFILE file_closer(base::OpenFile(filename, "rb+")); | 663 base::ScopedFILE file_closer(base::OpenFile(filename, "rb+")); |
| 656 if (!file_closer.get()) | 664 if (!file_closer.get()) |
| 657 return false; | 665 return false; |
| 658 | 666 |
| 659 int32_t num_entries, used_count; | 667 int32_t num_entries, used_count; |
| 660 uint8_t salt[LINK_SALT_LENGTH]; | 668 uint8_t salt[LINK_SALT_LENGTH]; |
| 661 if (!ReadFileHeader(file_closer.get(), &num_entries, &used_count, salt)) | 669 if (!ReadFileHeader(file_closer.get(), &num_entries, &used_count, salt)) |
| 662 return false; // Header isn't valid. | 670 return false; // Header isn't valid. |
| 663 | 671 |
| 664 // Allocate and read the table. | 672 // Allocate and read the table. |
| 665 std::unique_ptr<base::SharedMemory> shared_memory; | 673 mojo::ScopedSharedBufferHandle shared_memory; |
| 666 VisitedLinkCommon::Fingerprint* hash_table; | 674 mojo::ScopedSharedBufferMapping hash_table; |
| 667 if (!CreateApartURLTable(num_entries, salt, &shared_memory, &hash_table)) | 675 if (!CreateApartURLTable(num_entries, salt, &shared_memory, &hash_table)) |
| 668 return false; | 676 return false; |
| 669 | 677 |
| 670 if (!ReadFromFile(file_closer.get(), kFileHeaderSize, hash_table, | 678 if (!ReadFromFile(file_closer.get(), kFileHeaderSize, |
| 679 GetHashTableFromMapping(hash_table), |
| 671 num_entries * sizeof(Fingerprint))) { | 680 num_entries * sizeof(Fingerprint))) { |
| 672 return false; | 681 return false; |
| 673 } | 682 } |
| 674 | 683 |
| 675 *load_from_file_result = | 684 *load_from_file_result = new LoadFromFileResult( |
| 676 new LoadFromFileResult(std::move(file_closer), std::move(shared_memory), | 685 std::move(file_closer), std::move(shared_memory), std::move(hash_table), |
| 677 hash_table, num_entries, used_count, salt); | 686 num_entries, used_count, salt); |
| 678 return true; | 687 return true; |
| 679 } | 688 } |
| 680 | 689 |
| 681 void VisitedLinkMaster::OnTableLoadComplete( | 690 void VisitedLinkMaster::OnTableLoadComplete( |
| 682 bool success, | 691 bool success, |
| 683 scoped_refptr<LoadFromFileResult> load_from_file_result) { | 692 scoped_refptr<LoadFromFileResult> load_from_file_result) { |
| 684 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 693 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 685 DCHECK(persist_to_disk_); | 694 DCHECK(persist_to_disk_); |
| 686 DCHECK(!table_builder_.get()); | 695 DCHECK(!table_builder_.get()); |
| 687 | 696 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 708 return; | 717 return; |
| 709 } | 718 } |
| 710 | 719 |
| 711 // This temporary sets are needed only to rebuild table. | 720 // This temporary sets are needed only to rebuild table. |
| 712 added_since_rebuild_.clear(); | 721 added_since_rebuild_.clear(); |
| 713 deleted_since_rebuild_.clear(); | 722 deleted_since_rebuild_.clear(); |
| 714 | 723 |
| 715 DCHECK(load_from_file_result.get()); | 724 DCHECK(load_from_file_result.get()); |
| 716 | 725 |
| 717 // Delete the previous table. | 726 // Delete the previous table. |
| 718 DCHECK(shared_memory_); | 727 DCHECK(shared_memory_.is_valid()); |
| 719 delete shared_memory_; | 728 shared_memory_.reset(); |
| 720 shared_memory_ = nullptr; | 729 hash_table_mapping_.reset(); |
| 721 | 730 |
| 722 // Assign the open file. | 731 // Assign the open file. |
| 723 DCHECK(!file_); | 732 DCHECK(!file_); |
| 724 DCHECK(load_from_file_result->file.get()); | 733 DCHECK(load_from_file_result->file.get()); |
| 725 file_ = static_cast<FILE**>(malloc(sizeof(*file_))); | 734 file_ = static_cast<FILE**>(malloc(sizeof(*file_))); |
| 726 *file_ = load_from_file_result->file.release(); | 735 *file_ = load_from_file_result->file.release(); |
| 727 | 736 |
| 728 // Assign the loaded table. | 737 // Assign the loaded table. |
| 729 DCHECK(load_from_file_result->shared_memory.get()); | 738 DCHECK(load_from_file_result->shared_memory.is_valid()); |
| 730 DCHECK(load_from_file_result->hash_table); | 739 DCHECK(load_from_file_result->hash_table); |
| 731 memcpy(salt_, load_from_file_result->salt, LINK_SALT_LENGTH); | 740 memcpy(salt_, load_from_file_result->salt, LINK_SALT_LENGTH); |
| 732 shared_memory_ = load_from_file_result->shared_memory.release(); | 741 shared_memory_ = std::move(load_from_file_result->shared_memory); |
| 733 hash_table_ = load_from_file_result->hash_table; | 742 hash_table_mapping_ = std::move(load_from_file_result->hash_table); |
| 743 hash_table_ = GetHashTableFromMapping(hash_table_mapping_); |
| 734 table_length_ = load_from_file_result->num_entries; | 744 table_length_ = load_from_file_result->num_entries; |
| 735 used_items_ = load_from_file_result->used_count; | 745 used_items_ = load_from_file_result->used_count; |
| 736 | 746 |
| 737 #ifndef NDEBUG | 747 #ifndef NDEBUG |
| 738 DebugValidate(); | 748 DebugValidate(); |
| 739 #endif | 749 #endif |
| 740 | 750 |
| 741 // Send an update notification to all child processes. | 751 // Send an update notification to all child processes. |
| 742 listener_->NewTable(shared_memory_); | 752 listener_->NewTable(shared_memory_.get()); |
| 743 | 753 |
| 744 if (!added_since_load_.empty() || !deleted_since_load_.empty()) { | 754 if (!added_since_load_.empty() || !deleted_since_load_.empty()) { |
| 745 // Resize the table if the table doesn't have enough capacity. | 755 // Resize the table if the table doesn't have enough capacity. |
| 746 int new_used_items = | 756 int new_used_items = |
| 747 used_items_ + static_cast<int>(added_since_load_.size()); | 757 used_items_ + static_cast<int>(added_since_load_.size()); |
| 748 if (new_used_items >= table_length_) | 758 if (new_used_items >= table_length_) |
| 749 ResizeTable(NewTableSizeForCount(new_used_items)); | 759 ResizeTable(NewTableSizeForCount(new_used_items)); |
| 750 | 760 |
| 751 // Also add anything that was added while we were asynchronously | 761 // Also add anything that was added while we were asynchronously |
| 752 // loading the table. | 762 // loading the table. |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 return false; | 862 return false; |
| 853 | 863 |
| 854 base::FilePath profile_dir = browser_context_->GetPath(); | 864 base::FilePath profile_dir = browser_context_->GetPath(); |
| 855 *filename = profile_dir.Append(FILE_PATH_LITERAL("Visited Links")); | 865 *filename = profile_dir.Append(FILE_PATH_LITERAL("Visited Links")); |
| 856 return true; | 866 return true; |
| 857 } | 867 } |
| 858 | 868 |
| 859 // Initializes the shared memory structure. The salt should already be filled | 869 // Initializes the shared memory structure. The salt should already be filled |
| 860 // in so that it can be written to the shared memory | 870 // in so that it can be written to the shared memory |
| 861 bool VisitedLinkMaster::CreateURLTable(int32_t num_entries) { | 871 bool VisitedLinkMaster::CreateURLTable(int32_t num_entries) { |
| 862 std::unique_ptr<base::SharedMemory> shared_memory; | 872 mojo::ScopedSharedBufferHandle shared_memory; |
| 863 VisitedLinkCommon::Fingerprint* hash_table; | 873 mojo::ScopedSharedBufferMapping hash_table; |
| 864 if (CreateApartURLTable(num_entries, salt_, &shared_memory, &hash_table)) { | 874 if (CreateApartURLTable(num_entries, salt_, &shared_memory, &hash_table)) { |
| 865 shared_memory_ = shared_memory.release(); | 875 shared_memory_ = std::move(shared_memory); |
| 866 hash_table_ = hash_table; | 876 hash_table_mapping_ = std::move(hash_table); |
| 877 hash_table_ = GetHashTableFromMapping(hash_table_mapping_); |
| 867 table_length_ = num_entries; | 878 table_length_ = num_entries; |
| 868 used_items_ = 0; | 879 used_items_ = 0; |
| 869 return true; | 880 return true; |
| 870 } | 881 } |
| 871 | 882 |
| 872 return false; | 883 return false; |
| 873 } | 884 } |
| 874 | 885 |
| 875 // static | 886 // static |
| 876 bool VisitedLinkMaster::CreateApartURLTable( | 887 bool VisitedLinkMaster::CreateApartURLTable( |
| 877 int32_t num_entries, | 888 int32_t num_entries, |
| 878 const uint8_t salt[LINK_SALT_LENGTH], | 889 const uint8_t salt[LINK_SALT_LENGTH], |
| 879 std::unique_ptr<base::SharedMemory>* shared_memory, | 890 mojo::ScopedSharedBufferHandle* shared_memory, |
| 880 VisitedLinkCommon::Fingerprint** hash_table) { | 891 mojo::ScopedSharedBufferMapping* hash_table) { |
| 881 DCHECK(salt); | 892 DCHECK(salt); |
| 882 DCHECK(shared_memory); | 893 DCHECK(shared_memory); |
| 883 DCHECK(hash_table); | 894 DCHECK(hash_table); |
| 884 | 895 |
| 885 // The table is the size of the table followed by the entries. | 896 // The table is the size of the table followed by the entries. |
| 886 uint32_t alloc_size = | 897 uint32_t alloc_size = |
| 887 num_entries * sizeof(Fingerprint) + sizeof(SharedHeader); | 898 num_entries * sizeof(Fingerprint) + sizeof(SharedHeader); |
| 888 | 899 |
| 889 // Create the shared memory object. | 900 // Create the shared memory object. |
| 890 std::unique_ptr<base::SharedMemory> sh_mem(new base::SharedMemory()); | 901 mojo::ScopedSharedBufferHandle shared_buffer = |
| 891 if (!sh_mem) | 902 mojo::SharedBufferHandle::Create(alloc_size); |
| 903 if (!shared_buffer.is_valid()) |
| 904 return false; |
| 905 mojo::ScopedSharedBufferMapping hash_table_mapping = |
| 906 shared_buffer->Map(alloc_size); |
| 907 if (!hash_table_mapping) |
| 892 return false; | 908 return false; |
| 893 | 909 |
| 894 base::SharedMemoryCreateOptions options; | 910 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 | 911 |
| 903 // Save the header for other processes to read. | 912 // Save the header for other processes to read. |
| 904 SharedHeader* header = static_cast<SharedHeader*>(sh_mem->memory()); | 913 SharedHeader* header = static_cast<SharedHeader*>(hash_table_mapping.get()); |
| 905 header->length = num_entries; | 914 header->length = num_entries; |
| 906 memcpy(header->salt, salt, LINK_SALT_LENGTH); | 915 memcpy(header->salt, salt, LINK_SALT_LENGTH); |
| 907 | 916 |
| 908 // Our table pointer is just the data immediately following the size. | 917 *shared_memory = std::move(shared_buffer); |
| 909 *hash_table = reinterpret_cast<Fingerprint*>( | 918 *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 | 919 |
| 914 return true; | 920 return true; |
| 915 } | 921 } |
| 916 | 922 |
| 917 bool VisitedLinkMaster::BeginReplaceURLTable(int32_t num_entries) { | 923 bool VisitedLinkMaster::BeginReplaceURLTable(int32_t num_entries) { |
| 918 base::SharedMemory *old_shared_memory = shared_memory_; | 924 mojo::ScopedSharedBufferHandle old_shared_memory = std::move(shared_memory_); |
| 919 Fingerprint* old_hash_table = hash_table_; | 925 mojo::ScopedSharedBufferMapping old_hash_table_mapping = |
| 926 std::move(hash_table_mapping_); |
| 920 int32_t old_table_length = table_length_; | 927 int32_t old_table_length = table_length_; |
| 921 if (!CreateURLTable(num_entries)) { | 928 if (!CreateURLTable(num_entries)) { |
| 922 // Try to put back the old state. | 929 // Try to put back the old state. |
| 923 shared_memory_ = old_shared_memory; | 930 shared_memory_ = std::move(old_shared_memory); |
| 924 hash_table_ = old_hash_table; | 931 hash_table_mapping_ = std::move(old_hash_table_mapping); |
| 932 hash_table_ = GetHashTableFromMapping(hash_table_mapping_); |
| 925 table_length_ = old_table_length; | 933 table_length_ = old_table_length; |
| 926 return false; | 934 return false; |
| 927 } | 935 } |
| 928 | 936 |
| 929 #ifndef NDEBUG | 937 #ifndef NDEBUG |
| 930 DebugValidate(); | 938 DebugValidate(); |
| 931 #endif | 939 #endif |
| 932 | 940 |
| 933 return true; | 941 return true; |
| 934 } | 942 } |
| 935 | 943 |
| 936 void VisitedLinkMaster::FreeURLTable() { | 944 void VisitedLinkMaster::FreeURLTable() { |
| 937 if (shared_memory_) { | 945 shared_memory_.reset(); |
| 938 delete shared_memory_; | 946 hash_table_mapping_.reset(); |
| 939 shared_memory_ = NULL; | |
| 940 } | |
| 941 if (!persist_to_disk_ || !file_) | 947 if (!persist_to_disk_ || !file_) |
| 942 return; | 948 return; |
| 943 PostIOTask(FROM_HERE, base::Bind(&AsyncClose, file_)); | 949 PostIOTask(FROM_HERE, base::Bind(&AsyncClose, file_)); |
| 944 // AsyncClose() will close the file and free the memory pointed by |file_|. | 950 // AsyncClose() will close the file and free the memory pointed by |file_|. |
| 945 file_ = NULL; | 951 file_ = NULL; |
| 946 } | 952 } |
| 947 | 953 |
| 948 bool VisitedLinkMaster::ResizeTableIfNecessary() { | 954 bool VisitedLinkMaster::ResizeTableIfNecessary() { |
| 949 DCHECK(table_length_ > 0) << "Must have a table"; | 955 DCHECK(table_length_ > 0) << "Must have a table"; |
| 950 | 956 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 963 | 969 |
| 964 // Table needs to grow or shrink. | 970 // Table needs to grow or shrink. |
| 965 int new_size = NewTableSizeForCount(used_items_); | 971 int new_size = NewTableSizeForCount(used_items_); |
| 966 DCHECK(new_size > used_items_); | 972 DCHECK(new_size > used_items_); |
| 967 DCHECK(load <= min_table_load || new_size > table_length_); | 973 DCHECK(load <= min_table_load || new_size > table_length_); |
| 968 ResizeTable(new_size); | 974 ResizeTable(new_size); |
| 969 return true; | 975 return true; |
| 970 } | 976 } |
| 971 | 977 |
| 972 void VisitedLinkMaster::ResizeTable(int32_t new_size) { | 978 void VisitedLinkMaster::ResizeTable(int32_t new_size) { |
| 973 DCHECK(shared_memory_ && shared_memory_->memory() && hash_table_); | 979 DCHECK(shared_memory_.is_valid() && hash_table_mapping_); |
| 974 shared_memory_serial_++; | 980 shared_memory_serial_++; |
| 975 | 981 |
| 976 #ifndef NDEBUG | 982 #ifndef NDEBUG |
| 977 DebugValidate(); | 983 DebugValidate(); |
| 978 #endif | 984 #endif |
| 979 | 985 |
| 980 base::SharedMemory* old_shared_memory = shared_memory_; | 986 mojo::ScopedSharedBufferMapping old_hash_table_mapping = |
| 981 Fingerprint* old_hash_table = hash_table_; | 987 std::move(hash_table_mapping_); |
| 982 int32_t old_table_length = table_length_; | 988 int32_t old_table_length = table_length_; |
| 983 if (!BeginReplaceURLTable(new_size)) | 989 if (!BeginReplaceURLTable(new_size)) { |
| 990 hash_table_mapping_ = std::move(old_hash_table_mapping); |
| 991 hash_table_ = GetHashTableFromMapping(hash_table_mapping_); |
| 984 return; | 992 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 } | 993 } |
| 993 | 994 { |
| 994 // On error unmapping, just forget about it since we can't do anything | 995 Fingerprint* old_hash_table = |
| 995 // else to release it. | 996 GetHashTableFromMapping(old_hash_table_mapping); |
| 996 delete old_shared_memory; | 997 // Now we have two tables, our local copy which is the old one, and the new |
| 998 // one loaded into this object where we need to copy the data. |
| 999 for (int32_t i = 0; i < old_table_length; i++) { |
| 1000 Fingerprint cur = old_hash_table[i]; |
| 1001 if (cur) |
| 1002 AddFingerprint(cur, false); |
| 1003 } |
| 1004 } |
| 1005 old_hash_table_mapping.reset(); |
| 997 | 1006 |
| 998 // Send an update notification to all child processes so they read the new | 1007 // Send an update notification to all child processes so they read the new |
| 999 // table. | 1008 // table. |
| 1000 listener_->NewTable(shared_memory_); | 1009 listener_->NewTable(shared_memory_.get()); |
| 1001 | 1010 |
| 1002 #ifndef NDEBUG | 1011 #ifndef NDEBUG |
| 1003 DebugValidate(); | 1012 DebugValidate(); |
| 1004 #endif | 1013 #endif |
| 1005 | 1014 |
| 1006 // The new table needs to be written to disk. | 1015 // The new table needs to be written to disk. |
| 1007 if (persist_to_disk_) | 1016 if (persist_to_disk_) |
| 1008 WriteFullTable(); | 1017 WriteFullTable(); |
| 1009 } | 1018 } |
| 1010 | 1019 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1058 } | 1067 } |
| 1059 | 1068 |
| 1060 // See the TableBuilder declaration above for how this works. | 1069 // See the TableBuilder declaration above for how this works. |
| 1061 void VisitedLinkMaster::OnTableRebuildComplete( | 1070 void VisitedLinkMaster::OnTableRebuildComplete( |
| 1062 bool success, | 1071 bool success, |
| 1063 const std::vector<Fingerprint>& fingerprints) { | 1072 const std::vector<Fingerprint>& fingerprints) { |
| 1064 if (success) { | 1073 if (success) { |
| 1065 // Replace the old table with a new blank one. | 1074 // Replace the old table with a new blank one. |
| 1066 shared_memory_serial_++; | 1075 shared_memory_serial_++; |
| 1067 | 1076 |
| 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( | 1077 int new_table_size = NewTableSizeForCount( |
| 1073 static_cast<int>(fingerprints.size() + added_since_rebuild_.size())); | 1078 static_cast<int>(fingerprints.size() + added_since_rebuild_.size())); |
| 1074 if (BeginReplaceURLTable(new_table_size)) { | 1079 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. | 1080 // Add the stored fingerprints to the hash table. |
| 1079 for (const auto& fingerprint : fingerprints) | 1081 for (const auto& fingerprint : fingerprints) |
| 1080 AddFingerprint(fingerprint, false); | 1082 AddFingerprint(fingerprint, false); |
| 1081 | 1083 |
| 1082 // Also add anything that was added while we were asynchronously | 1084 // Also add anything that was added while we were asynchronously |
| 1083 // generating the new table. | 1085 // generating the new table. |
| 1084 for (const auto& fingerprint : added_since_rebuild_) | 1086 for (const auto& fingerprint : added_since_rebuild_) |
| 1085 AddFingerprint(fingerprint, false); | 1087 AddFingerprint(fingerprint, false); |
| 1086 added_since_rebuild_.clear(); | 1088 added_since_rebuild_.clear(); |
| 1087 | 1089 |
| 1088 // Now handle deletions. Do not shrink the table now, we'll shrink it when | 1090 // Now handle deletions. Do not shrink the table now, we'll shrink it when |
| 1089 // adding or deleting an url the next time. | 1091 // adding or deleting an url the next time. |
| 1090 for (const auto& fingerprint : deleted_since_rebuild_) | 1092 for (const auto& fingerprint : deleted_since_rebuild_) |
| 1091 DeleteFingerprint(fingerprint, false); | 1093 DeleteFingerprint(fingerprint, false); |
| 1092 deleted_since_rebuild_.clear(); | 1094 deleted_since_rebuild_.clear(); |
| 1093 | 1095 |
| 1094 // Send an update notification to all child processes. | 1096 // Send an update notification to all child processes. |
| 1095 listener_->NewTable(shared_memory_); | 1097 listener_->NewTable(shared_memory_.get()); |
| 1096 // All tabs which was loaded when table was being rebuilt | 1098 // All tabs which was loaded when table was being rebuilt |
| 1097 // invalidate their links again. | 1099 // invalidate their links again. |
| 1098 listener_->Reset(false); | 1100 listener_->Reset(false); |
| 1099 | 1101 |
| 1100 if (persist_to_disk_) | 1102 if (persist_to_disk_) |
| 1101 WriteFullTable(); | 1103 WriteFullTable(); |
| 1102 } | 1104 } |
| 1103 } | 1105 } |
| 1104 table_builder_ = NULL; // Will release our reference to the builder. | 1106 table_builder_ = NULL; // Will release our reference to the builder. |
| 1105 | 1107 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1194 BrowserThread::PostTask( | 1196 BrowserThread::PostTask( |
| 1195 BrowserThread::UI, FROM_HERE, | 1197 BrowserThread::UI, FROM_HERE, |
| 1196 base::Bind(&TableBuilder::OnCompleteMainThread, this)); | 1198 base::Bind(&TableBuilder::OnCompleteMainThread, this)); |
| 1197 } | 1199 } |
| 1198 | 1200 |
| 1199 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { | 1201 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { |
| 1200 if (master_) | 1202 if (master_) |
| 1201 master_->OnTableRebuildComplete(success_, fingerprints_); | 1203 master_->OnTableRebuildComplete(success_, fingerprints_); |
| 1202 } | 1204 } |
| 1203 | 1205 |
| 1206 // static |
| 1207 VisitedLinkCommon::Fingerprint* VisitedLinkMaster::GetHashTableFromMapping( |
| 1208 const mojo::ScopedSharedBufferMapping& hash_table_mapping) { |
| 1209 DCHECK(hash_table_mapping); |
| 1210 // Our table pointer is just the data immediately following the header. |
| 1211 return reinterpret_cast<Fingerprint*>( |
| 1212 static_cast<char*>(hash_table_mapping.get()) + sizeof(SharedHeader)); |
| 1213 } |
| 1214 |
| 1204 } // namespace visitedlink | 1215 } // namespace visitedlink |
| OLD | NEW |