| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "chrome/browser/visitedlink_master.h" | 5 #include "chrome/browser/visitedlink_master.h" |
| 6 | 6 |
| 7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 #include <windows.h> | 8 #include <windows.h> |
| 9 #include <io.h> | 9 #include <io.h> |
| 10 #include <shlobj.h> | 10 #include <shlobj.h> |
| 11 #endif // defined(OS_WIN) | 11 #endif // defined(OS_WIN) |
| 12 #include <stdio.h> | 12 #include <stdio.h> |
| 13 | 13 |
| 14 #include <algorithm> | 14 #include <algorithm> |
| 15 | 15 |
| 16 #if defined(OS_WIN) | 16 #if defined(OS_WIN) |
| 17 #include "app/win_util.h" | 17 #include "app/win_util.h" |
| 18 #endif | 18 #endif |
| 19 #include "base/file_util.h" | 19 #include "base/file_util.h" |
| 20 #include "base/logging.h" | 20 #include "base/logging.h" |
| 21 #include "base/message_loop.h" | 21 #include "base/message_loop.h" |
| 22 #include "base/path_service.h" | 22 #include "base/path_service.h" |
| 23 #include "base/process_util.h" | 23 #include "base/process_util.h" |
| 24 #include "base/rand_util.h" | 24 #include "base/rand_util.h" |
| 25 #include "base/stack_container.h" | 25 #include "base/stack_container.h" |
| 26 #include "base/string_util.h" | 26 #include "base/string_util.h" |
| 27 #include "base/thread.h" | |
| 28 #include "chrome/browser/browser_process.h" | 27 #include "chrome/browser/browser_process.h" |
| 29 #include "chrome/browser/history/history.h" | 28 #include "chrome/browser/history/history.h" |
| 30 #include "chrome/browser/profile.h" | 29 #include "chrome/browser/profile.h" |
| 31 | 30 |
| 32 using file_util::ScopedFILE; | 31 using file_util::ScopedFILE; |
| 33 using file_util::OpenFile; | 32 using file_util::OpenFile; |
| 34 using file_util::TruncateFile; | 33 using file_util::TruncateFile; |
| 35 | 34 |
| 36 const int32 VisitedLinkMaster::kFileHeaderSignatureOffset = 0; | 35 const int32 VisitedLinkMaster::kFileHeaderSignatureOffset = 0; |
| 37 const int32 VisitedLinkMaster::kFileHeaderVersionOffset = 4; | 36 const int32 VisitedLinkMaster::kFileHeaderVersionOffset = 4; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 virtual void OnComplete(bool succeed); | 182 virtual void OnComplete(bool succeed); |
| 184 | 183 |
| 185 private: | 184 private: |
| 186 // OnComplete mashals to this function on the main thread to do the | 185 // OnComplete mashals to this function on the main thread to do the |
| 187 // notification. | 186 // notification. |
| 188 void OnCompleteMainThread(); | 187 void OnCompleteMainThread(); |
| 189 | 188 |
| 190 // Owner of this object. MAY ONLY BE ACCESSED ON THE MAIN THREAD! | 189 // Owner of this object. MAY ONLY BE ACCESSED ON THE MAIN THREAD! |
| 191 VisitedLinkMaster* master_; | 190 VisitedLinkMaster* master_; |
| 192 | 191 |
| 193 // The thread the visited link master is on where we will notify it. | |
| 194 MessageLoop* main_message_loop_; | |
| 195 | |
| 196 // Indicates whether the operation has failed or not. | 192 // Indicates whether the operation has failed or not. |
| 197 bool success_; | 193 bool success_; |
| 198 | 194 |
| 199 // Salt for this new table. | 195 // Salt for this new table. |
| 200 uint8 salt_[LINK_SALT_LENGTH]; | 196 uint8 salt_[LINK_SALT_LENGTH]; |
| 201 | 197 |
| 202 // Stores the fingerprints we computed on the background thread. | 198 // Stores the fingerprints we computed on the background thread. |
| 203 VisitedLinkCommon::Fingerprints fingerprints_; | 199 VisitedLinkCommon::Fingerprints fingerprints_; |
| 204 }; | 200 }; |
| 205 | 201 |
| 206 // VisitedLinkMaster ---------------------------------------------------------- | 202 // VisitedLinkMaster ---------------------------------------------------------- |
| 207 | 203 |
| 208 VisitedLinkMaster::VisitedLinkMaster(base::Thread* file_thread, | 204 VisitedLinkMaster::VisitedLinkMaster(Listener* listener, |
| 209 Listener* listener, | |
| 210 Profile* profile) { | 205 Profile* profile) { |
| 211 InitMembers(file_thread, listener, profile); | 206 InitMembers(listener, profile); |
| 212 } | 207 } |
| 213 | 208 |
| 214 VisitedLinkMaster::VisitedLinkMaster(base::Thread* file_thread, | 209 VisitedLinkMaster::VisitedLinkMaster(Listener* listener, |
| 215 Listener* listener, | |
| 216 HistoryService* history_service, | 210 HistoryService* history_service, |
| 217 bool suppress_rebuild, | 211 bool suppress_rebuild, |
| 218 const FilePath& filename, | 212 const FilePath& filename, |
| 219 int32 default_table_size) { | 213 int32 default_table_size) { |
| 220 InitMembers(file_thread, listener, NULL); | 214 InitMembers(listener, NULL); |
| 221 | 215 |
| 222 database_name_override_ = filename; | 216 database_name_override_ = filename; |
| 223 table_size_override_ = default_table_size; | 217 table_size_override_ = default_table_size; |
| 224 history_service_override_ = history_service; | 218 history_service_override_ = history_service; |
| 225 suppress_rebuild_ = suppress_rebuild; | 219 suppress_rebuild_ = suppress_rebuild; |
| 226 } | 220 } |
| 227 | 221 |
| 228 VisitedLinkMaster::~VisitedLinkMaster() { | 222 VisitedLinkMaster::~VisitedLinkMaster() { |
| 229 if (table_builder_.get()) { | 223 if (table_builder_.get()) { |
| 230 // Prevent the table builder from calling us back now that we're being | 224 // Prevent the table builder from calling us back now that we're being |
| 231 // destroyed. Note that we DON'T delete the object, since the history | 225 // destroyed. Note that we DON'T delete the object, since the history |
| 232 // system is still writing into it. When that is complete, the table | 226 // system is still writing into it. When that is complete, the table |
| 233 // builder will destroy itself when it finds we are gone. | 227 // builder will destroy itself when it finds we are gone. |
| 234 table_builder_->DisownMaster(); | 228 table_builder_->DisownMaster(); |
| 235 } | 229 } |
| 236 FreeURLTable(); | 230 FreeURLTable(); |
| 237 } | 231 } |
| 238 | 232 |
| 239 void VisitedLinkMaster::InitMembers(base::Thread* file_thread, | 233 void VisitedLinkMaster::InitMembers(Listener* listener, Profile* profile) { |
| 240 Listener* listener, | |
| 241 Profile* profile) { | |
| 242 DCHECK(listener); | 234 DCHECK(listener); |
| 243 | 235 |
| 244 if (file_thread) | |
| 245 file_thread_ = file_thread->message_loop(); | |
| 246 else | |
| 247 file_thread_ = NULL; | |
| 248 | |
| 249 listener_ = listener; | 236 listener_ = listener; |
| 250 file_ = NULL; | 237 file_ = NULL; |
| 251 shared_memory_ = NULL; | 238 shared_memory_ = NULL; |
| 252 shared_memory_serial_ = 0; | 239 shared_memory_serial_ = 0; |
| 253 used_items_ = 0; | 240 used_items_ = 0; |
| 254 table_size_override_ = 0; | 241 table_size_override_ = 0; |
| 255 history_service_override_ = NULL; | 242 history_service_override_ = NULL; |
| 256 suppress_rebuild_ = false; | 243 suppress_rebuild_ = false; |
| 257 profile_ = profile; | 244 profile_ = profile; |
| 258 | 245 |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 header[2] = table_length_; | 533 header[2] = table_length_; |
| 547 header[3] = used_items_; | 534 header[3] = used_items_; |
| 548 WriteToFile(file_, 0, header, sizeof(header)); | 535 WriteToFile(file_, 0, header, sizeof(header)); |
| 549 WriteToFile(file_, sizeof(header), salt_, LINK_SALT_LENGTH); | 536 WriteToFile(file_, sizeof(header), salt_, LINK_SALT_LENGTH); |
| 550 | 537 |
| 551 // Write the hash data. | 538 // Write the hash data. |
| 552 WriteToFile(file_, kFileHeaderSize, | 539 WriteToFile(file_, kFileHeaderSize, |
| 553 hash_table_, table_length_ * sizeof(Fingerprint)); | 540 hash_table_, table_length_ * sizeof(Fingerprint)); |
| 554 | 541 |
| 555 // The hash table may have shrunk, so make sure this is the end. | 542 // The hash table may have shrunk, so make sure this is the end. |
| 556 if (file_thread_) { | 543 ChromeThread::PostTask( |
| 557 AsyncSetEndOfFile* setter = new AsyncSetEndOfFile(file_); | 544 ChromeThread::FILE, FROM_HERE, new AsyncSetEndOfFile(file_)); |
| 558 file_thread_->PostTask(FROM_HERE, setter); | |
| 559 } else { | |
| 560 TruncateFile(file_); | |
| 561 } | |
| 562 | |
| 563 return true; | 545 return true; |
| 564 } | 546 } |
| 565 | 547 |
| 566 bool VisitedLinkMaster::InitFromFile() { | 548 bool VisitedLinkMaster::InitFromFile() { |
| 567 DCHECK(file_ == NULL); | 549 DCHECK(file_ == NULL); |
| 568 | 550 |
| 569 FilePath filename; | 551 FilePath filename; |
| 570 GetDatabaseFileName(&filename); | 552 GetDatabaseFileName(&filename); |
| 571 ScopedFILE file_closer(OpenFile(filename, "rb+")); | 553 ScopedFILE file_closer(OpenFile(filename, "rb+")); |
| 572 if (!file_closer.get()) | 554 if (!file_closer.get()) |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 #endif | 729 #endif |
| 748 | 730 |
| 749 return true; | 731 return true; |
| 750 } | 732 } |
| 751 | 733 |
| 752 void VisitedLinkMaster::FreeURLTable() { | 734 void VisitedLinkMaster::FreeURLTable() { |
| 753 if (shared_memory_) { | 735 if (shared_memory_) { |
| 754 delete shared_memory_; | 736 delete shared_memory_; |
| 755 shared_memory_ = NULL; | 737 shared_memory_ = NULL; |
| 756 } | 738 } |
| 757 if (file_) { | 739 if (!file_) |
| 758 if (file_thread_) { | 740 return; |
| 759 AsyncCloseHandle* closer = new AsyncCloseHandle(file_); | 741 |
| 760 file_thread_->PostTask(FROM_HERE, closer); | 742 ChromeThread::PostTask( |
| 761 } else { | 743 ChromeThread::FILE, FROM_HERE, new AsyncCloseHandle(file_)); |
| 762 fclose(file_); | |
| 763 } | |
| 764 } | |
| 765 } | 744 } |
| 766 | 745 |
| 767 bool VisitedLinkMaster::ResizeTableIfNecessary() { | 746 bool VisitedLinkMaster::ResizeTableIfNecessary() { |
| 768 DCHECK(table_length_ > 0) << "Must have a table"; | 747 DCHECK(table_length_ > 0) << "Must have a table"; |
| 769 | 748 |
| 770 // Load limits for good performance/space. We are pretty conservative about | 749 // Load limits for good performance/space. We are pretty conservative about |
| 771 // keeping the table not very full. This is because we use linear probing | 750 // keeping the table not very full. This is because we use linear probing |
| 772 // which increases the likelihood of clumps of entries which will reduce | 751 // which increases the likelihood of clumps of entries which will reduce |
| 773 // performance. | 752 // performance. |
| 774 const float max_table_load = 0.5f; // Grow when we're > this full. | 753 const float max_table_load = 0.5f; // Grow when we're > this full. |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 934 } | 913 } |
| 935 | 914 |
| 936 void VisitedLinkMaster::WriteToFile(FILE* file, | 915 void VisitedLinkMaster::WriteToFile(FILE* file, |
| 937 off_t offset, | 916 off_t offset, |
| 938 void* data, | 917 void* data, |
| 939 int32 data_size) { | 918 int32 data_size) { |
| 940 #ifndef NDEBUG | 919 #ifndef NDEBUG |
| 941 posted_asynchronous_operation_ = true; | 920 posted_asynchronous_operation_ = true; |
| 942 #endif | 921 #endif |
| 943 | 922 |
| 944 if (file_thread_) { | 923 ChromeThread::PostTask( |
| 945 // Send the write to the other thread for execution to avoid blocking. | 924 ChromeThread::FILE, FROM_HERE, |
| 946 AsyncWriter* writer = new AsyncWriter(file, offset, data, data_size); | 925 new AsyncWriter(file, offset, data, data_size)); |
| 947 file_thread_->PostTask(FROM_HERE, writer); | |
| 948 } else { | |
| 949 // When there is no I/O thread, we are probably running in unit test mode, | |
| 950 // just do the write synchronously. | |
| 951 AsyncWriter::WriteToFile(file, offset, data, data_size); | |
| 952 } | |
| 953 } | 926 } |
| 954 | 927 |
| 955 void VisitedLinkMaster::WriteUsedItemCountToFile() { | 928 void VisitedLinkMaster::WriteUsedItemCountToFile() { |
| 956 if (!file_) | 929 if (!file_) |
| 957 return; // See comment on the file_ variable for why this might happen. | 930 return; // See comment on the file_ variable for why this might happen. |
| 958 WriteToFile(file_, kFileHeaderUsedOffset, &used_items_, sizeof(used_items_)); | 931 WriteToFile(file_, kFileHeaderUsedOffset, &used_items_, sizeof(used_items_)); |
| 959 } | 932 } |
| 960 | 933 |
| 961 void VisitedLinkMaster::WriteHashRangeToFile(Hash first_hash, Hash last_hash) { | 934 void VisitedLinkMaster::WriteHashRangeToFile(Hash first_hash, Hash last_hash) { |
| 962 if (!file_) | 935 if (!file_) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 993 size_t num_read = fread(data, 1, data_size, file); | 966 size_t num_read = fread(data, 1, data_size, file); |
| 994 return num_read == data_size; | 967 return num_read == data_size; |
| 995 } | 968 } |
| 996 | 969 |
| 997 // VisitedLinkTableBuilder ---------------------------------------------------- | 970 // VisitedLinkTableBuilder ---------------------------------------------------- |
| 998 | 971 |
| 999 VisitedLinkMaster::TableBuilder::TableBuilder( | 972 VisitedLinkMaster::TableBuilder::TableBuilder( |
| 1000 VisitedLinkMaster* master, | 973 VisitedLinkMaster* master, |
| 1001 const uint8 salt[LINK_SALT_LENGTH]) | 974 const uint8 salt[LINK_SALT_LENGTH]) |
| 1002 : master_(master), | 975 : master_(master), |
| 1003 main_message_loop_(MessageLoop::current()), | |
| 1004 success_(true) { | 976 success_(true) { |
| 1005 fingerprints_.reserve(4096); | 977 fingerprints_.reserve(4096); |
| 1006 memcpy(salt_, salt, sizeof(salt)); | 978 memcpy(salt_, salt, sizeof(salt)); |
| 1007 } | 979 } |
| 1008 | 980 |
| 1009 // TODO(brettw): Do we want to try to cancel the request if this happens? It | 981 // TODO(brettw): Do we want to try to cancel the request if this happens? It |
| 1010 // could delay shutdown if there are a lot of URLs. | 982 // could delay shutdown if there are a lot of URLs. |
| 1011 void VisitedLinkMaster::TableBuilder::DisownMaster() { | 983 void VisitedLinkMaster::TableBuilder::DisownMaster() { |
| 1012 master_ = NULL; | 984 master_ = NULL; |
| 1013 } | 985 } |
| 1014 | 986 |
| 1015 void VisitedLinkMaster::TableBuilder::OnURL(const GURL& url) { | 987 void VisitedLinkMaster::TableBuilder::OnURL(const GURL& url) { |
| 1016 if (!url.is_empty()) { | 988 if (!url.is_empty()) { |
| 1017 fingerprints_.push_back(VisitedLinkMaster::ComputeURLFingerprint( | 989 fingerprints_.push_back(VisitedLinkMaster::ComputeURLFingerprint( |
| 1018 url.spec().data(), url.spec().length(), salt_)); | 990 url.spec().data(), url.spec().length(), salt_)); |
| 1019 } | 991 } |
| 1020 } | 992 } |
| 1021 | 993 |
| 1022 void VisitedLinkMaster::TableBuilder::OnComplete(bool success) { | 994 void VisitedLinkMaster::TableBuilder::OnComplete(bool success) { |
| 1023 success_ = success; | 995 success_ = success; |
| 1024 DLOG_IF(WARNING, !success) << "Unable to rebuild visited links"; | 996 DLOG_IF(WARNING, !success) << "Unable to rebuild visited links"; |
| 1025 | 997 |
| 1026 // Marshal to the main thread to notify the VisitedLinkMaster that the | 998 // Marshal to the main thread to notify the VisitedLinkMaster that the |
| 1027 // rebuild is complete. | 999 // rebuild is complete. |
| 1028 main_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 1000 ChromeThread::PostTask( |
| 1029 &TableBuilder::OnCompleteMainThread)); | 1001 ChromeThread::UI, FROM_HERE, |
| 1002 NewRunnableMethod(this, &TableBuilder::OnCompleteMainThread)); |
| 1030 } | 1003 } |
| 1031 | 1004 |
| 1032 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { | 1005 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { |
| 1033 if (master_) | 1006 if (master_) |
| 1034 master_->OnTableRebuildComplete(success_, fingerprints_); | 1007 master_->OnTableRebuildComplete(success_, fingerprints_); |
| 1035 | 1008 |
| 1036 // WILL (generally) DELETE THIS! This balances the AddRef in | 1009 // WILL (generally) DELETE THIS! This balances the AddRef in |
| 1037 // VisitedLinkMaster::RebuildTableFromHistory. | 1010 // VisitedLinkMaster::RebuildTableFromHistory. |
| 1038 Release(); | 1011 Release(); |
| 1039 } | 1012 } |
| OLD | NEW |