Chromium Code Reviews| 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()) | |
|
brettw
2016/09/14 23:02:13
I don't understand this addition, can you describe
Sam McNally
2016/09/15 04:12:16
Previously, VisitedLinkEventListener received a po
| |
| 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, hash_table.get(), |
| 671 num_entries * sizeof(Fingerprint))) { | 679 num_entries * sizeof(Fingerprint))) { |
| 672 return false; | 680 return false; |
| 673 } | 681 } |
| 674 | 682 |
| 675 *load_from_file_result = | 683 *load_from_file_result = new LoadFromFileResult( |
| 676 new LoadFromFileResult(std::move(file_closer), std::move(shared_memory), | 684 std::move(file_closer), std::move(shared_memory), std::move(hash_table), |
| 677 hash_table, num_entries, used_count, salt); | 685 num_entries, used_count, salt); |
| 678 return true; | 686 return true; |
| 679 } | 687 } |
| 680 | 688 |
| 681 void VisitedLinkMaster::OnTableLoadComplete( | 689 void VisitedLinkMaster::OnTableLoadComplete( |
| 682 bool success, | 690 bool success, |
| 683 scoped_refptr<LoadFromFileResult> load_from_file_result) { | 691 scoped_refptr<LoadFromFileResult> load_from_file_result) { |
| 684 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 692 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 685 DCHECK(persist_to_disk_); | 693 DCHECK(persist_to_disk_); |
| 686 DCHECK(!table_builder_.get()); | 694 DCHECK(!table_builder_.get()); |
| 687 | 695 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 708 return; | 716 return; |
| 709 } | 717 } |
| 710 | 718 |
| 711 // This temporary sets are needed only to rebuild table. | 719 // This temporary sets are needed only to rebuild table. |
| 712 added_since_rebuild_.clear(); | 720 added_since_rebuild_.clear(); |
| 713 deleted_since_rebuild_.clear(); | 721 deleted_since_rebuild_.clear(); |
| 714 | 722 |
| 715 DCHECK(load_from_file_result.get()); | 723 DCHECK(load_from_file_result.get()); |
| 716 | 724 |
| 717 // Delete the previous table. | 725 // Delete the previous table. |
| 718 DCHECK(shared_memory_); | 726 DCHECK(shared_memory_.is_valid()); |
| 719 delete shared_memory_; | 727 shared_memory_.reset(); |
| 720 shared_memory_ = nullptr; | 728 hash_table_mapping_.reset(); |
| 721 | 729 |
| 722 // Assign the open file. | 730 // Assign the open file. |
| 723 DCHECK(!file_); | 731 DCHECK(!file_); |
| 724 DCHECK(load_from_file_result->file.get()); | 732 DCHECK(load_from_file_result->file.get()); |
| 725 file_ = static_cast<FILE**>(malloc(sizeof(*file_))); | 733 file_ = static_cast<FILE**>(malloc(sizeof(*file_))); |
| 726 *file_ = load_from_file_result->file.release(); | 734 *file_ = load_from_file_result->file.release(); |
| 727 | 735 |
| 728 // Assign the loaded table. | 736 // Assign the loaded table. |
| 729 DCHECK(load_from_file_result->shared_memory.get()); | 737 DCHECK(load_from_file_result->shared_memory.is_valid()); |
| 730 DCHECK(load_from_file_result->hash_table); | 738 DCHECK(load_from_file_result->hash_table); |
| 731 memcpy(salt_, load_from_file_result->salt, LINK_SALT_LENGTH); | 739 memcpy(salt_, load_from_file_result->salt, LINK_SALT_LENGTH); |
| 732 shared_memory_ = load_from_file_result->shared_memory.release(); | 740 shared_memory_ = std::move(load_from_file_result->shared_memory); |
| 733 hash_table_ = load_from_file_result->hash_table; | 741 hash_table_mapping_ = std::move(load_from_file_result->hash_table); |
| 742 hash_table_ = static_cast<Fingerprint*>(hash_table_mapping_.get()); | |
| 734 table_length_ = load_from_file_result->num_entries; | 743 table_length_ = load_from_file_result->num_entries; |
| 735 used_items_ = load_from_file_result->used_count; | 744 used_items_ = load_from_file_result->used_count; |
| 736 | 745 |
| 737 #ifndef NDEBUG | 746 #ifndef NDEBUG |
| 738 DebugValidate(); | 747 DebugValidate(); |
| 739 #endif | 748 #endif |
| 740 | 749 |
| 741 // Send an update notification to all child processes. | 750 // Send an update notification to all child processes. |
| 742 listener_->NewTable(shared_memory_); | 751 listener_->NewTable(shared_memory_.get()); |
| 743 | 752 |
| 744 if (!added_since_load_.empty() || !deleted_since_load_.empty()) { | 753 if (!added_since_load_.empty() || !deleted_since_load_.empty()) { |
| 745 // Resize the table if the table doesn't have enough capacity. | 754 // Resize the table if the table doesn't have enough capacity. |
| 746 int new_used_items = | 755 int new_used_items = |
| 747 used_items_ + static_cast<int>(added_since_load_.size()); | 756 used_items_ + static_cast<int>(added_since_load_.size()); |
| 748 if (new_used_items >= table_length_) | 757 if (new_used_items >= table_length_) |
| 749 ResizeTable(NewTableSizeForCount(new_used_items)); | 758 ResizeTable(NewTableSizeForCount(new_used_items)); |
| 750 | 759 |
| 751 // Also add anything that was added while we were asynchronously | 760 // Also add anything that was added while we were asynchronously |
| 752 // loading the table. | 761 // loading the table. |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 852 return false; | 861 return false; |
| 853 | 862 |
| 854 base::FilePath profile_dir = browser_context_->GetPath(); | 863 base::FilePath profile_dir = browser_context_->GetPath(); |
| 855 *filename = profile_dir.Append(FILE_PATH_LITERAL("Visited Links")); | 864 *filename = profile_dir.Append(FILE_PATH_LITERAL("Visited Links")); |
| 856 return true; | 865 return true; |
| 857 } | 866 } |
| 858 | 867 |
| 859 // Initializes the shared memory structure. The salt should already be filled | 868 // Initializes the shared memory structure. The salt should already be filled |
| 860 // in so that it can be written to the shared memory | 869 // in so that it can be written to the shared memory |
| 861 bool VisitedLinkMaster::CreateURLTable(int32_t num_entries) { | 870 bool VisitedLinkMaster::CreateURLTable(int32_t num_entries) { |
| 862 std::unique_ptr<base::SharedMemory> shared_memory; | 871 mojo::ScopedSharedBufferHandle shared_memory; |
| 863 VisitedLinkCommon::Fingerprint* hash_table; | 872 mojo::ScopedSharedBufferMapping hash_table; |
| 864 if (CreateApartURLTable(num_entries, salt_, &shared_memory, &hash_table)) { | 873 if (CreateApartURLTable(num_entries, salt_, &shared_memory, &hash_table)) { |
| 865 shared_memory_ = shared_memory.release(); | 874 shared_memory_ = std::move(shared_memory); |
| 866 hash_table_ = hash_table; | 875 hash_table_mapping_ = std::move(hash_table); |
| 876 hash_table_ = static_cast<Fingerprint*>(hash_table_mapping_.get()); | |
| 867 table_length_ = num_entries; | 877 table_length_ = num_entries; |
| 868 used_items_ = 0; | 878 used_items_ = 0; |
| 869 return true; | 879 return true; |
| 870 } | 880 } |
| 871 | 881 |
| 872 return false; | 882 return false; |
| 873 } | 883 } |
| 874 | 884 |
| 875 // static | 885 // static |
| 876 bool VisitedLinkMaster::CreateApartURLTable( | 886 bool VisitedLinkMaster::CreateApartURLTable( |
| 877 int32_t num_entries, | 887 int32_t num_entries, |
| 878 const uint8_t salt[LINK_SALT_LENGTH], | 888 const uint8_t salt[LINK_SALT_LENGTH], |
| 879 std::unique_ptr<base::SharedMemory>* shared_memory, | 889 mojo::ScopedSharedBufferHandle* shared_memory, |
| 880 VisitedLinkCommon::Fingerprint** hash_table) { | 890 mojo::ScopedSharedBufferMapping* hash_table) { |
| 881 DCHECK(salt); | 891 DCHECK(salt); |
| 882 DCHECK(shared_memory); | 892 DCHECK(shared_memory); |
| 883 DCHECK(hash_table); | 893 DCHECK(hash_table); |
| 884 | 894 |
| 885 // The table is the size of the table followed by the entries. | 895 // The table is the size of the table followed by the entries. |
| 886 uint32_t alloc_size = | 896 uint32_t alloc_size = |
| 887 num_entries * sizeof(Fingerprint) + sizeof(SharedHeader); | 897 num_entries * sizeof(Fingerprint) + sizeof(SharedHeader); |
| 888 | 898 |
| 889 // Create the shared memory object. | 899 // Create the shared memory object. |
| 890 std::unique_ptr<base::SharedMemory> sh_mem(new base::SharedMemory()); | 900 mojo::ScopedSharedBufferHandle shared_buffer = |
| 891 if (!sh_mem) | 901 mojo::SharedBufferHandle::Create(alloc_size); |
| 902 if (!shared_buffer.is_valid()) | |
| 903 return false; | |
| 904 { | |
| 905 mojo::ScopedSharedBufferMapping mapping = shared_buffer->Map(alloc_size); | |
| 906 if (!mapping) | |
| 907 return false; | |
| 908 | |
| 909 memset(mapping.get(), 0, alloc_size); | |
| 910 | |
| 911 // Save the header for other processes to read. | |
| 912 SharedHeader* header = static_cast<SharedHeader*>(mapping.get()); | |
| 913 header->length = num_entries; | |
| 914 memcpy(header->salt, salt, LINK_SALT_LENGTH); | |
| 915 } | |
| 916 | |
| 917 // Our table pointer is just the data immediately following the header. | |
| 918 mojo::ScopedSharedBufferMapping hash_table_mapping = | |
|
brettw
2016/09/14 23:02:13
I kind of preferred the old way. Unmapping and rem
Sam McNally
2016/09/15 04:12:15
I think it makes the code a bit simpler, but addin
| |
| 919 shared_buffer->MapAtOffset(num_entries * sizeof(Fingerprint), | |
| 920 sizeof(SharedHeader)); | |
| 921 if (!hash_table_mapping) | |
| 892 return false; | 922 return false; |
| 893 | 923 |
| 894 base::SharedMemoryCreateOptions options; | 924 *shared_memory = std::move(shared_buffer); |
| 895 options.size = alloc_size; | 925 *hash_table = std::move(hash_table_mapping); |
| 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 | |
| 903 // Save the header for other processes to read. | |
| 904 SharedHeader* header = static_cast<SharedHeader*>(sh_mem->memory()); | |
| 905 header->length = num_entries; | |
| 906 memcpy(header->salt, salt, LINK_SALT_LENGTH); | |
| 907 | |
| 908 // Our table pointer is just the data immediately following the size. | |
| 909 *hash_table = reinterpret_cast<Fingerprint*>( | |
| 910 static_cast<char*>(sh_mem->memory()) + sizeof(SharedHeader)); | |
| 911 | |
| 912 *shared_memory = std::move(sh_mem); | |
| 913 | 926 |
| 914 return true; | 927 return true; |
| 915 } | 928 } |
| 916 | 929 |
| 917 bool VisitedLinkMaster::BeginReplaceURLTable(int32_t num_entries) { | 930 bool VisitedLinkMaster::BeginReplaceURLTable(int32_t num_entries) { |
| 918 base::SharedMemory *old_shared_memory = shared_memory_; | 931 mojo::ScopedSharedBufferHandle old_shared_memory = std::move(shared_memory_); |
| 919 Fingerprint* old_hash_table = hash_table_; | 932 mojo::ScopedSharedBufferMapping old_hash_table_mapping = |
| 933 std::move(hash_table_mapping_); | |
| 920 int32_t old_table_length = table_length_; | 934 int32_t old_table_length = table_length_; |
| 921 if (!CreateURLTable(num_entries)) { | 935 if (!CreateURLTable(num_entries)) { |
| 922 // Try to put back the old state. | 936 // Try to put back the old state. |
| 923 shared_memory_ = old_shared_memory; | 937 shared_memory_ = std::move(old_shared_memory); |
| 924 hash_table_ = old_hash_table; | 938 hash_table_mapping_ = std::move(old_hash_table_mapping); |
| 939 hash_table_ = static_cast<Fingerprint*>(hash_table_mapping_.get()); | |
| 925 table_length_ = old_table_length; | 940 table_length_ = old_table_length; |
| 926 return false; | 941 return false; |
| 927 } | 942 } |
| 928 | 943 |
| 929 #ifndef NDEBUG | 944 #ifndef NDEBUG |
| 930 DebugValidate(); | 945 DebugValidate(); |
| 931 #endif | 946 #endif |
| 932 | 947 |
| 933 return true; | 948 return true; |
| 934 } | 949 } |
| 935 | 950 |
| 936 void VisitedLinkMaster::FreeURLTable() { | 951 void VisitedLinkMaster::FreeURLTable() { |
| 937 if (shared_memory_) { | 952 shared_memory_.reset(); |
| 938 delete shared_memory_; | 953 hash_table_mapping_.reset(); |
| 939 shared_memory_ = NULL; | |
| 940 } | |
| 941 if (!persist_to_disk_ || !file_) | 954 if (!persist_to_disk_ || !file_) |
| 942 return; | 955 return; |
| 943 PostIOTask(FROM_HERE, base::Bind(&AsyncClose, file_)); | 956 PostIOTask(FROM_HERE, base::Bind(&AsyncClose, file_)); |
| 944 // AsyncClose() will close the file and free the memory pointed by |file_|. | 957 // AsyncClose() will close the file and free the memory pointed by |file_|. |
| 945 file_ = NULL; | 958 file_ = NULL; |
| 946 } | 959 } |
| 947 | 960 |
| 948 bool VisitedLinkMaster::ResizeTableIfNecessary() { | 961 bool VisitedLinkMaster::ResizeTableIfNecessary() { |
| 949 DCHECK(table_length_ > 0) << "Must have a table"; | 962 DCHECK(table_length_ > 0) << "Must have a table"; |
| 950 | 963 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 963 | 976 |
| 964 // Table needs to grow or shrink. | 977 // Table needs to grow or shrink. |
| 965 int new_size = NewTableSizeForCount(used_items_); | 978 int new_size = NewTableSizeForCount(used_items_); |
| 966 DCHECK(new_size > used_items_); | 979 DCHECK(new_size > used_items_); |
| 967 DCHECK(load <= min_table_load || new_size > table_length_); | 980 DCHECK(load <= min_table_load || new_size > table_length_); |
| 968 ResizeTable(new_size); | 981 ResizeTable(new_size); |
| 969 return true; | 982 return true; |
| 970 } | 983 } |
| 971 | 984 |
| 972 void VisitedLinkMaster::ResizeTable(int32_t new_size) { | 985 void VisitedLinkMaster::ResizeTable(int32_t new_size) { |
| 973 DCHECK(shared_memory_ && shared_memory_->memory() && hash_table_); | 986 DCHECK(shared_memory_.is_valid() && hash_table_mapping_); |
| 974 shared_memory_serial_++; | 987 shared_memory_serial_++; |
| 975 | 988 |
| 976 #ifndef NDEBUG | 989 #ifndef NDEBUG |
| 977 DebugValidate(); | 990 DebugValidate(); |
| 978 #endif | 991 #endif |
| 979 | 992 |
| 980 base::SharedMemory* old_shared_memory = shared_memory_; | 993 mojo::ScopedSharedBufferMapping old_hash_table_mapping = |
| 981 Fingerprint* old_hash_table = hash_table_; | 994 std::move(hash_table_mapping_); |
| 982 int32_t old_table_length = table_length_; | 995 int32_t old_table_length = table_length_; |
| 983 if (!BeginReplaceURLTable(new_size)) | 996 if (!BeginReplaceURLTable(new_size)) { |
| 997 hash_table_mapping_ = std::move(old_hash_table_mapping); | |
| 998 hash_table_ = static_cast<Fingerprint*>(hash_table_mapping_.get()); | |
| 984 return; | 999 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 } | 1000 } |
| 993 | 1001 |
| 994 // On error unmapping, just forget about it since we can't do anything | 1002 { |
| 995 // else to release it. | 1003 Fingerprint* old_hash_table = |
| 996 delete old_shared_memory; | 1004 static_cast<Fingerprint*>(old_hash_table_mapping.get()); |
| 1005 // Now we have two tables, our local copy which is the old one, and the new | |
| 1006 // one loaded into this object where we need to copy the data. | |
| 1007 for (int32_t i = 0; i < old_table_length; i++) { | |
| 1008 Fingerprint cur = old_hash_table[i]; | |
| 1009 if (cur) | |
| 1010 AddFingerprint(cur, false); | |
| 1011 } | |
| 1012 } | |
| 1013 old_hash_table_mapping.reset(); | |
| 997 | 1014 |
| 998 // Send an update notification to all child processes so they read the new | 1015 // Send an update notification to all child processes so they read the new |
| 999 // table. | 1016 // table. |
| 1000 listener_->NewTable(shared_memory_); | 1017 listener_->NewTable(shared_memory_.get()); |
| 1001 | 1018 |
| 1002 #ifndef NDEBUG | 1019 #ifndef NDEBUG |
| 1003 DebugValidate(); | 1020 DebugValidate(); |
| 1004 #endif | 1021 #endif |
| 1005 | 1022 |
| 1006 // The new table needs to be written to disk. | 1023 // The new table needs to be written to disk. |
| 1007 if (persist_to_disk_) | 1024 if (persist_to_disk_) |
| 1008 WriteFullTable(); | 1025 WriteFullTable(); |
| 1009 } | 1026 } |
| 1010 | 1027 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1058 } | 1075 } |
| 1059 | 1076 |
| 1060 // See the TableBuilder declaration above for how this works. | 1077 // See the TableBuilder declaration above for how this works. |
| 1061 void VisitedLinkMaster::OnTableRebuildComplete( | 1078 void VisitedLinkMaster::OnTableRebuildComplete( |
| 1062 bool success, | 1079 bool success, |
| 1063 const std::vector<Fingerprint>& fingerprints) { | 1080 const std::vector<Fingerprint>& fingerprints) { |
| 1064 if (success) { | 1081 if (success) { |
| 1065 // Replace the old table with a new blank one. | 1082 // Replace the old table with a new blank one. |
| 1066 shared_memory_serial_++; | 1083 shared_memory_serial_++; |
| 1067 | 1084 |
| 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( | 1085 int new_table_size = NewTableSizeForCount( |
| 1073 static_cast<int>(fingerprints.size() + added_since_rebuild_.size())); | 1086 static_cast<int>(fingerprints.size() + added_since_rebuild_.size())); |
| 1074 if (BeginReplaceURLTable(new_table_size)) { | 1087 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. | 1088 // Add the stored fingerprints to the hash table. |
| 1079 for (const auto& fingerprint : fingerprints) | 1089 for (const auto& fingerprint : fingerprints) |
| 1080 AddFingerprint(fingerprint, false); | 1090 AddFingerprint(fingerprint, false); |
| 1081 | 1091 |
| 1082 // Also add anything that was added while we were asynchronously | 1092 // Also add anything that was added while we were asynchronously |
| 1083 // generating the new table. | 1093 // generating the new table. |
| 1084 for (const auto& fingerprint : added_since_rebuild_) | 1094 for (const auto& fingerprint : added_since_rebuild_) |
| 1085 AddFingerprint(fingerprint, false); | 1095 AddFingerprint(fingerprint, false); |
| 1086 added_since_rebuild_.clear(); | 1096 added_since_rebuild_.clear(); |
| 1087 | 1097 |
| 1088 // Now handle deletions. Do not shrink the table now, we'll shrink it when | 1098 // Now handle deletions. Do not shrink the table now, we'll shrink it when |
| 1089 // adding or deleting an url the next time. | 1099 // adding or deleting an url the next time. |
| 1090 for (const auto& fingerprint : deleted_since_rebuild_) | 1100 for (const auto& fingerprint : deleted_since_rebuild_) |
| 1091 DeleteFingerprint(fingerprint, false); | 1101 DeleteFingerprint(fingerprint, false); |
| 1092 deleted_since_rebuild_.clear(); | 1102 deleted_since_rebuild_.clear(); |
| 1093 | 1103 |
| 1094 // Send an update notification to all child processes. | 1104 // Send an update notification to all child processes. |
| 1095 listener_->NewTable(shared_memory_); | 1105 listener_->NewTable(shared_memory_.get()); |
| 1096 // All tabs which was loaded when table was being rebuilt | 1106 // All tabs which was loaded when table was being rebuilt |
| 1097 // invalidate their links again. | 1107 // invalidate their links again. |
| 1098 listener_->Reset(false); | 1108 listener_->Reset(false); |
| 1099 | 1109 |
| 1100 if (persist_to_disk_) | 1110 if (persist_to_disk_) |
| 1101 WriteFullTable(); | 1111 WriteFullTable(); |
| 1102 } | 1112 } |
| 1103 } | 1113 } |
| 1104 table_builder_ = NULL; // Will release our reference to the builder. | 1114 table_builder_ = NULL; // Will release our reference to the builder. |
| 1105 | 1115 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1195 BrowserThread::UI, FROM_HERE, | 1205 BrowserThread::UI, FROM_HERE, |
| 1196 base::Bind(&TableBuilder::OnCompleteMainThread, this)); | 1206 base::Bind(&TableBuilder::OnCompleteMainThread, this)); |
| 1197 } | 1207 } |
| 1198 | 1208 |
| 1199 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { | 1209 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { |
| 1200 if (master_) | 1210 if (master_) |
| 1201 master_->OnTableRebuildComplete(success_, fingerprints_); | 1211 master_->OnTableRebuildComplete(success_, fingerprints_); |
| 1202 } | 1212 } |
| 1203 | 1213 |
| 1204 } // namespace visitedlink | 1214 } // namespace visitedlink |
| OLD | NEW |