Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(508)

Side by Side Diff: chrome/browser/visitedlink_master.cc

Issue 19024: Reverting 8722,8721. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/visitedlink_master.h ('k') | chrome/browser/visitedlink_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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)
8 #include <windows.h> 7 #include <windows.h>
9 #include <io.h>
10 #include <shlobj.h> 8 #include <shlobj.h>
11 #endif // defined(OS_WIN)
12 #include <stdio.h>
13
14 #include <algorithm> 9 #include <algorithm>
15 10
16 #include "base/file_util.h"
17 #include "base/logging.h" 11 #include "base/logging.h"
18 #include "base/message_loop.h" 12 #include "base/message_loop.h"
19 #include "base/path_service.h" 13 #include "base/path_service.h"
20 #include "base/process_util.h"
21 #include "base/rand_util.h" 14 #include "base/rand_util.h"
22 #include "base/stack_container.h" 15 #include "base/stack_container.h"
23 #include "base/string_util.h" 16 #include "base/string_util.h"
24 #include "base/thread.h"
25 #include "chrome/browser/browser_process.h" 17 #include "chrome/browser/browser_process.h"
26 #if defined(OS_WIN)
27 #include "chrome/browser/history/history.h" 18 #include "chrome/browser/history/history.h"
28 #include "chrome/browser/profile.h" 19 #include "chrome/browser/profile.h"
29 #else
30 // TODO(port): We should be using history.h & profile.h, remove scaffolding
31 // when those are ported.
32 #include "chrome/common/temp_scaffolding_stubs.h"
33 #endif // !defined(OS_WIN)
34 #if defined(OS_WIN)
35 #include "chrome/common/win_util.h" 20 #include "chrome/common/win_util.h"
36 #endif
37
38 using file_util::ScopedFILE;
39 using file_util::OpenFile;
40 using file_util::TruncateFile;
41 21
42 const int32 VisitedLinkMaster::kFileHeaderSignatureOffset = 0; 22 const int32 VisitedLinkMaster::kFileHeaderSignatureOffset = 0;
43 const int32 VisitedLinkMaster::kFileHeaderVersionOffset = 4; 23 const int32 VisitedLinkMaster::kFileHeaderVersionOffset = 4;
44 const int32 VisitedLinkMaster::kFileHeaderLengthOffset = 8; 24 const int32 VisitedLinkMaster::kFileHeaderLengthOffset = 8;
45 const int32 VisitedLinkMaster::kFileHeaderUsedOffset = 12; 25 const int32 VisitedLinkMaster::kFileHeaderUsedOffset = 12;
46 const int32 VisitedLinkMaster::kFileHeaderSaltOffset = 16; 26 const int32 VisitedLinkMaster::kFileHeaderSaltOffset = 16;
47 27
48 const int32 VisitedLinkMaster::kFileCurrentVersion = 2; 28 const int32 VisitedLinkMaster::kFileCurrentVersion = 2;
49 29
50 // the signature at the beginning of the URL table = "VLnk" (visited links) 30 // the signature at the beginning of the URL table = "VLnk" (visited links)
51 const int32 VisitedLinkMaster::kFileSignature = 0x6b6e4c56; 31 const int32 VisitedLinkMaster::kFileSignature = 0x6b6e4c56;
52 const size_t VisitedLinkMaster::kFileHeaderSize = 32 const size_t VisitedLinkMaster::kFileHeaderSize =
53 kFileHeaderSaltOffset + LINK_SALT_LENGTH; 33 kFileHeaderSaltOffset + LINK_SALT_LENGTH;
54 34
55 // This value should also be the same as the smallest size in the lookup 35 // This value should also be the same as the smallest size in the lookup
56 // table in NewTableSizeForCount (prime number). 36 // table in NewTableSizeForCount (prime number).
57 const unsigned VisitedLinkMaster::kDefaultTableSize = 16381; 37 const unsigned VisitedLinkMaster::kDefaultTableSize = 16381;
58 38
59 const size_t VisitedLinkMaster::kBigDeleteThreshold = 64; 39 const int32 VisitedLinkMaster::kBigDeleteThreshold = 64;
60 40
61 namespace { 41 namespace {
62 42
63 // Fills the given salt structure with some quasi-random values 43 // Fills the given salt structure with some quasi-random values
64 // It is not necessary to generate a cryptographically strong random string, 44 // It is not necessary to generate a cryptographically strong random string,
65 // only that it be reasonably different for different users. 45 // only that it be reasonably different for different users.
66 void GenerateSalt(uint8 salt[LINK_SALT_LENGTH]) { 46 void GenerateSalt(uint8 salt[LINK_SALT_LENGTH]) {
67 DCHECK_EQ(LINK_SALT_LENGTH, 8) << "This code assumes the length of the salt"; 47 DCHECK_EQ(LINK_SALT_LENGTH, 8) << "This code assumes the length of the salt";
68 uint64 randval = base::RandUint64(); 48 uint64 randval = base::RandUint64();
69 memcpy(salt, &randval, 8); 49 memcpy(salt, &randval, 8);
70 } 50 }
71
72 // AsyncWriter ---------------------------------------------------------------- 51 // AsyncWriter ----------------------------------------------------------------
73 52
74 // This task executes on a background thread and executes a write. This 53 // This task executes on a background thread and executes a write. This
75 // prevents us from blocking the UI thread doing I/O. 54 // prevents us from blocking the UI thread doing I/O.
76 class AsyncWriter : public Task { 55 class AsyncWriter : public Task {
77 public: 56 public:
78 AsyncWriter(FILE* file, int32 offset, const void* data, size_t data_len) 57 AsyncWriter(HANDLE hfile, int32 offset, const void* data, int32 data_len)
79 : file_(file), 58 : hfile_(hfile),
80 offset_(offset) { 59 offset_(offset) {
81 data_->resize(data_len); 60 data_->resize(data_len);
82 memcpy(&*data_->begin(), data, data_len); 61 memcpy(&*data_->begin(), data, data_len);
83 } 62 }
84 63
85 virtual void Run() { 64 virtual void Run() {
86 WriteToFile(file_, offset_, 65 WriteToFile(hfile_, offset_,
87 &*data_->begin(), static_cast<int32>(data_->size())); 66 &*data_->begin(), static_cast<int32>(data_->size()));
88 } 67 }
89 68
90 // Exposed as a static so it can be called directly from the Master to 69 // Exposed as a static so it can be called directly from the Master to
91 // reduce the number of platform-specific I/O sites we have. Returns true if 70 // reduce the number of platform-specific I/O sites we have. Returns true if
92 // the write was complete. 71 // the write was complete.
93 static bool WriteToFile(FILE* file, 72 static bool WriteToFile(HANDLE hfile,
94 off_t offset, 73 int32 offset,
95 const void* data, 74 const void* data,
96 size_t data_len) { 75 int32 data_len) {
97 if (fseek(file, offset, SEEK_SET) != 0) 76 if (SetFilePointer(hfile, offset, NULL, FILE_BEGIN) ==
77 INVALID_SET_FILE_POINTER)
98 return false; // Don't write to an invalid part of the file. 78 return false; // Don't write to an invalid part of the file.
99 79
100 size_t num_written = fwrite(data, 1, data_len, file); 80 DWORD num_written;
101 return num_written == data_len; 81 return WriteFile(hfile, data, data_len, &num_written, NULL) &&
82 (num_written == data_len);
102 } 83 }
103 84
104 private: 85 private:
105 // The data to write and where to write it. 86 // The data to write and where to write it.
106 FILE* file_; 87 HANDLE hfile_;
107 int32 offset_; // Offset from the beginning of the file. 88 int32 offset_; // Offset from the beginning of the file.
108 89
109 // Most writes are just a single fingerprint, so we reserve that much in this 90 // Most writes are just a single fingerprint, so we reserve that much in this
110 // object to avoid mallocs in that case. 91 // object to avoid mallocs in that case.
111 StackVector<char, sizeof(VisitedLinkCommon::Fingerprint)> data_; 92 StackVector<char, sizeof(VisitedLinkCommon::Fingerprint)> data_;
112 93
113 DISALLOW_EVIL_CONSTRUCTORS(AsyncWriter); 94 DISALLOW_EVIL_CONSTRUCTORS(AsyncWriter);
114 }; 95 };
115 96
116 // Used to asynchronously set the end of the file. This must be done on the 97 // Used to asynchronously set the end of the file. This must be done on the
117 // same thread as the writing to keep things synchronized. 98 // same thread as the writing to keep things synchronized.
118 class AsyncSetEndOfFile : public Task { 99 class AsyncSetEndOfFile : public Task {
119 public: 100 public:
120 explicit AsyncSetEndOfFile(FILE* file) : file_(file) {} 101 explicit AsyncSetEndOfFile(HANDLE hfile) : hfile_(hfile) {}
121 102
122 virtual void Run() { 103 virtual void Run() {
123 TruncateFile(file_); 104 SetEndOfFile(hfile_);
124 } 105 }
125 106
126 private: 107 private:
127 FILE* file_; 108 HANDLE hfile_;
128 DISALLOW_EVIL_CONSTRUCTORS(AsyncSetEndOfFile); 109 DISALLOW_EVIL_CONSTRUCTORS(AsyncSetEndOfFile);
129 }; 110 };
130 111
131 // Used to asynchronously close a file. This must be done on the same thread as 112 // Used to asynchronously close a file. This must be done on the same thread as
132 // the writing to keep things synchronized. 113 // the writing to keep things synchronized.
133 class AsyncCloseHandle : public Task { 114 class AsyncCloseHandle : public Task {
134 public: 115 public:
135 explicit AsyncCloseHandle(FILE* file) : file_(file) {} 116 explicit AsyncCloseHandle(HANDLE hfile) : hfile_(hfile) {}
136 117
137 virtual void Run() { 118 virtual void Run() {
138 fclose(file_); 119 CloseHandle(hfile_);
139 } 120 }
140 121
141 private: 122 private:
142 FILE* file_; 123 HANDLE hfile_;
143 DISALLOW_EVIL_CONSTRUCTORS(AsyncCloseHandle); 124 DISALLOW_EVIL_CONSTRUCTORS(AsyncCloseHandle);
144 }; 125 };
145 126
146 } // namespace 127 } // namespace
147 128
148 // TableBuilder --------------------------------------------------------------- 129 // TableBuilder ---------------------------------------------------------------
149 130
150 // How rebuilding from history works 131 // How rebuilding from history works
151 // --------------------------------- 132 // ---------------------------------
152 // 133 //
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 VisitedLinkMaster::VisitedLinkMaster(base::Thread* file_thread, 187 VisitedLinkMaster::VisitedLinkMaster(base::Thread* file_thread,
207 PostNewTableEvent* poster, 188 PostNewTableEvent* poster,
208 Profile* profile) { 189 Profile* profile) {
209 InitMembers(file_thread, poster, profile); 190 InitMembers(file_thread, poster, profile);
210 } 191 }
211 192
212 VisitedLinkMaster::VisitedLinkMaster(base::Thread* file_thread, 193 VisitedLinkMaster::VisitedLinkMaster(base::Thread* file_thread,
213 PostNewTableEvent* poster, 194 PostNewTableEvent* poster,
214 HistoryService* history_service, 195 HistoryService* history_service,
215 bool suppress_rebuild, 196 bool suppress_rebuild,
216 const FilePath& filename, 197 const std::wstring& filename,
217 int32 default_table_size) { 198 int32 default_table_size) {
218 InitMembers(file_thread, poster, NULL); 199 InitMembers(file_thread, poster, NULL);
219 200
220 database_name_override_ = filename; 201 database_name_override_.assign(filename);
221 table_size_override_ = default_table_size; 202 table_size_override_ = default_table_size;
222 history_service_override_ = history_service; 203 history_service_override_ = history_service;
223 suppress_rebuild_ = suppress_rebuild; 204 suppress_rebuild_ = suppress_rebuild;
224 } 205 }
225 206
226 VisitedLinkMaster::~VisitedLinkMaster() { 207 VisitedLinkMaster::~VisitedLinkMaster() {
227 if (table_builder_.get()) { 208 if (table_builder_.get()) {
228 // Prevent the table builder from calling us back now that we're being 209 // Prevent the table builder from calling us back now that we're being
229 // destroyed. Note that we DON'T delete the object, since the history 210 // destroyed. Note that we DON'T delete the object, since the history
230 // system is still writing into it. When that is complete, the table 211 // system is still writing into it. When that is complete, the table
(...skipping 29 matching lines...) Expand all
260 // The shared memory name should be unique on the system and also needs to 241 // The shared memory name should be unique on the system and also needs to
261 // change when we create a new table. The scheme we use includes the process 242 // change when we create a new table. The scheme we use includes the process
262 // ID, an increasing serial number, and the profile ID. 243 // ID, an increasing serial number, and the profile ID.
263 std::wstring VisitedLinkMaster::GetSharedMemoryName() const { 244 std::wstring VisitedLinkMaster::GetSharedMemoryName() const {
264 // When unit testing, there's no profile, so use an empty ID string. 245 // When unit testing, there's no profile, so use an empty ID string.
265 std::wstring profile_id; 246 std::wstring profile_id;
266 if (profile_) 247 if (profile_)
267 profile_id = profile_->GetID().c_str(); 248 profile_id = profile_->GetID().c_str();
268 249
269 return StringPrintf(L"GVisitedLinks_%lu_%lu_%ls", 250 return StringPrintf(L"GVisitedLinks_%lu_%lu_%ls",
270 base::GetCurrentProcId(), shared_memory_serial_, 251 GetCurrentProcessId(), shared_memory_serial_,
271 profile_id.c_str()); 252 profile_id.c_str());
272 } 253 }
273 254
274 bool VisitedLinkMaster::Init() { 255 bool VisitedLinkMaster::Init() {
275 if (!InitFromFile()) 256 if (!InitFromFile())
276 return InitFromScratch(suppress_rebuild_); 257 return InitFromScratch(suppress_rebuild_);
277 return true; 258 return true;
278 } 259 }
279 260
280 bool VisitedLinkMaster::ShareToProcess(base::ProcessHandle process, 261 bool VisitedLinkMaster::ShareToProcess(base::ProcessHandle process,
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 // since there may be write operations pending on the file I/O thread. 505 // since there may be write operations pending on the file I/O thread.
525 // 506 //
526 // Note that once we start writing, we do not delete on error. This means 507 // Note that once we start writing, we do not delete on error. This means
527 // there can be a partial file, but the short file will be detected next time 508 // there can be a partial file, but the short file will be detected next time
528 // we start, and will be replaced. 509 // we start, and will be replaced.
529 // 510 //
530 // This might possibly get corrupted if we crash in the middle of writing. 511 // This might possibly get corrupted if we crash in the middle of writing.
531 // We should pick up the most common types of these failures when we notice 512 // We should pick up the most common types of these failures when we notice
532 // that the file size is different when we load it back in, and then we will 513 // that the file size is different when we load it back in, and then we will
533 // regenerate the table. 514 // regenerate the table.
534 ScopedFILE file_closer; // Valid only when not open already. 515 win_util::ScopedHandle hfile_closer; // Valid only when not open already.
535 FILE* file; // Always valid. 516 HANDLE hfile; // Always valid.
536 if (file_) { 517 if (file_) {
537 file = file_; 518 hfile = file_;
538 } else { 519 } else {
539 FilePath filename; 520 std::wstring filename;
540 GetDatabaseFileName(&filename); 521 GetDatabaseFileName(&filename);
541 file_closer.reset(OpenFile(filename, "wb+")); 522 hfile_closer.Set(
542 if (!file_closer.get()) { 523 CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL,
543 DLOG(ERROR) << "Failed to open file " << filename.value(); 524 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL));
525 if (!hfile_closer.IsValid())
544 return false; 526 return false;
545 } 527 hfile = hfile_closer;
546 file = file_closer.get();
547 } 528 }
548 529
549 // Write the new header. 530 // Write the new header.
550 int32 header[4]; 531 int32 header[4];
551 header[0] = kFileSignature; 532 header[0] = kFileSignature;
552 header[1] = kFileCurrentVersion; 533 header[1] = kFileCurrentVersion;
553 header[2] = table_length_; 534 header[2] = table_length_;
554 header[3] = used_items_; 535 header[3] = used_items_;
555 WriteToFile(file, 0, header, sizeof(header)); 536 WriteToFile(hfile, 0, header, sizeof(header));
556 WriteToFile(file, sizeof(header), salt_, LINK_SALT_LENGTH); 537 WriteToFile(hfile, sizeof(header), salt_, LINK_SALT_LENGTH);
557 538
558 // Write the hash data. 539 // Write the hash data.
559 WriteToFile(file, kFileHeaderSize, 540 WriteToFile(hfile, kFileHeaderSize,
560 hash_table_, table_length_ * sizeof(Fingerprint)); 541 hash_table_, table_length_ * sizeof(Fingerprint));
561 542
562 // The hash table may have shrunk, so make sure this is the end. 543 // The hash table may have shrunk, so make sure this is the end.
563 if (file_thread_) { 544 if (file_thread_) {
564 AsyncSetEndOfFile* setter = new AsyncSetEndOfFile(file); 545 AsyncSetEndOfFile* setter = new AsyncSetEndOfFile(hfile);
565 file_thread_->PostTask(FROM_HERE, setter); 546 file_thread_->PostTask(FROM_HERE, setter);
566 } else { 547 } else {
567 TruncateFile(file); 548 SetEndOfFile(hfile);
568 } 549 }
569 550
570 // Keep the file open so we can dynamically write changes to it. When the 551 // Keep the file open so we can dynamically write changes to it. When the
571 // file was already open, the file_closer is NULL, and file_ is already good. 552 // file was alrady open, the hfile_closer is NULL, and file_ is already good.
572 if (file_closer.get()) 553 if (hfile_closer.IsValid())
573 file_ = file_closer.release(); 554 file_ = hfile_closer.Take();
574 return true; 555 return true;
575 } 556 }
576 557
577 bool VisitedLinkMaster::InitFromFile() { 558 bool VisitedLinkMaster::InitFromFile() {
578 DCHECK(file_ == NULL); 559 DCHECK(file_ == NULL);
579 560
580 FilePath filename; 561 std::wstring filename;
581 GetDatabaseFileName(&filename); 562 GetDatabaseFileName(&filename);
582 ScopedFILE file_closer(OpenFile(filename, "rb+")); 563 win_util::ScopedHandle hfile(
583 if (!file_closer.get()) { 564 CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL,
584 DLOG(ERROR) << "Failed to open file " << filename.value(); 565 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL));
566 if (!hfile.IsValid())
585 return false; 567 return false;
586 }
587 568
588 int32 num_entries, used_count; 569 int32 num_entries, used_count;
589 if (!ReadFileHeader(file_closer.get(), &num_entries, &used_count, salt_)) 570 if (!ReadFileHeader(hfile, &num_entries, &used_count, salt_))
590 return false; // Header isn't valid. 571 return false; // Header isn't valid.
591 572
592 // Allocate and read the table. 573 // Allocate and read the table.
593 if (!CreateURLTable(num_entries, false)) 574 if (!CreateURLTable(num_entries, false))
594 return false; 575 return false;
595 if (!ReadFromFile(file_closer.get(), kFileHeaderSize, 576 if (!ReadFromFile(hfile, kFileHeaderSize,
596 hash_table_, num_entries * sizeof(Fingerprint))) { 577 hash_table_, num_entries * sizeof(Fingerprint))) {
597 FreeURLTable(); 578 FreeURLTable();
598 return false; 579 return false;
599 } 580 }
600 used_items_ = used_count; 581 used_items_ = used_count;
601 582
602 file_ = file_closer.release(); 583 file_ = hfile.Take();
603 return true; 584 return true;
604 } 585 }
605 586
606 bool VisitedLinkMaster::InitFromScratch(bool suppress_rebuild) { 587 bool VisitedLinkMaster::InitFromScratch(bool suppress_rebuild) {
607 int32 table_size = kDefaultTableSize; 588 int32 table_size = kDefaultTableSize;
608 if (table_size_override_) 589 if (table_size_override_)
609 table_size = table_size_override_; 590 table_size = table_size_override_;
610 591
611 // The salt must be generated before the table so that it can be copied to 592 // The salt must be generated before the table so that it can be copied to
612 // the shared memory. 593 // the shared memory.
613 GenerateSalt(salt_); 594 GenerateSalt(salt_);
614 if (!CreateURLTable(table_size, true)) 595 if (!CreateURLTable(table_size, true))
615 return false; 596 return false;
616 597
617 if (suppress_rebuild) { 598 if (suppress_rebuild) {
618 // When we disallow rebuilds (normally just unit tests), just use the 599 // When we disallow rebuilds (normally just unit tests), just use the
619 // current empty table. 600 // current empty table.
620 return WriteFullTable(); 601 return WriteFullTable();
621 } 602 }
622 603
623 // This will build the table from history. On the first run, history will 604 // This will build the table from history. On the first run, history will
624 // be empty, so this will be correct. This will also write the new table 605 // be empty, so this will be correct. This will also write the new table
625 // to disk. We don't want to save explicitly here, since the rebuild may 606 // to disk. We don't want to save explicitly here, since the rebuild may
626 // not complete, leaving us with an empty but valid visited link database. 607 // not complete, leaving us with an empty but valid visited link database.
627 // In the future, we won't know we need to try rebuilding again. 608 // In the future, we won't know we need to try rebuilding again.
628 return RebuildTableFromHistory(); 609 return RebuildTableFromHistory();
629 } 610 }
630 611
631 bool VisitedLinkMaster::ReadFileHeader(FILE* file, 612 bool VisitedLinkMaster::ReadFileHeader(HANDLE hfile,
632 int32* num_entries, 613 int32* num_entries,
633 int32* used_count, 614 int32* used_count,
634 uint8 salt[LINK_SALT_LENGTH]) { 615 uint8 salt[LINK_SALT_LENGTH]) {
635 // Get file size. 616 int32 file_size = GetFileSize(hfile, NULL);
636 // Note that there is no need to seek back to the original location in the
637 // file since ReadFromFile() [which is the next call accessing the file]
638 // seeks before reading.
639 if (fseek(file, 0, SEEK_END) == -1)
640 return false;
641 size_t file_size = ftell(file);
642
643 if (file_size <= kFileHeaderSize) 617 if (file_size <= kFileHeaderSize)
644 return false; 618 return false;
645 619
646 uint8 header[kFileHeaderSize]; 620 uint8 header[kFileHeaderSize];
647 if (!ReadFromFile(file, 0, &header, kFileHeaderSize)) 621 if (!ReadFromFile(hfile, 0, &header, kFileHeaderSize))
648 return false; 622 return false;
649 623
650 // Verify the signature. 624 // Verify the signature.
651 int32 signature; 625 uint32 signature;
652 memcpy(&signature, &header[kFileHeaderSignatureOffset], sizeof(signature)); 626 memcpy(&signature, &header[kFileHeaderSignatureOffset], sizeof(signature));
653 if (signature != kFileSignature) 627 if (signature != kFileSignature)
654 return false; 628 return false;
655 629
656 // Verify the version is up-to-date. As with other read errors, a version 630 // Verify the version is up-to-date. As with other read errors, a version
657 // mistmatch will trigger a rebuild of the database from history, which will 631 // mistmatch will trigger a rebuild of the database from history, which will
658 // have the effect of migrating the database. 632 // have the effect of migrating the database.
659 int32 version; 633 int32 version;
660 memcpy(&version, &header[kFileHeaderVersionOffset], sizeof(version)); 634 memcpy(&version, &header[kFileHeaderVersionOffset], sizeof(version));
661 if (version != kFileCurrentVersion) 635 if (version != kFileCurrentVersion)
662 return false; // Bad version. 636 return false; // Bad version.
663 637
664 // Read the table size and make sure it matches the file size. 638 // Read the table size and make sure it matches the file size.
665 memcpy(num_entries, &header[kFileHeaderLengthOffset], sizeof(*num_entries)); 639 memcpy(num_entries, &header[kFileHeaderLengthOffset], sizeof(*num_entries));
666 if (*num_entries * sizeof(Fingerprint) + kFileHeaderSize != file_size) 640 if (*num_entries * sizeof(Fingerprint) + kFileHeaderSize != file_size)
667 return false; // Bad size. 641 return false; // Bad size.
668 642
669 // Read the used item count. 643 // Read the used item count.
670 memcpy(used_count, &header[kFileHeaderUsedOffset], sizeof(*used_count)); 644 memcpy(used_count, &header[kFileHeaderUsedOffset], sizeof(*used_count));
671 if (*used_count > *num_entries) 645 if (*used_count > *num_entries)
672 return false; // Bad used item count; 646 return false; // Bad used item count;
673 647
674 // Read the salt. 648 // Read the salt.
675 memcpy(salt, &header[kFileHeaderSaltOffset], LINK_SALT_LENGTH); 649 memcpy(salt, &header[kFileHeaderSaltOffset], LINK_SALT_LENGTH);
676 650
677 // This file looks OK from the header's perspective. 651 // This file looks OK from the header's perspective.
678 return true; 652 return true;
679 } 653 }
680 654
681 bool VisitedLinkMaster::GetDatabaseFileName(FilePath* filename) { 655 bool VisitedLinkMaster::GetDatabaseFileName(std::wstring* filename) {
682 if (!database_name_override_.empty()) { 656 if (!database_name_override_.empty()) {
683 // use this filename, the directory must exist 657 // use this filename, the directory must exist
684 *filename = database_name_override_; 658 *filename = database_name_override_;
685 return true; 659 return true;
686 } 660 }
687 661
688 if (!profile_ || profile_->GetPath().empty()) 662 if (!profile_ || profile_->GetPath().empty())
689 return false; 663 return false;
690 664
691 FilePath profile_dir = FilePath::FromWStringHack(profile_->GetPath()); 665 *filename = profile_->GetPath();
692 *filename = profile_dir.Append(FILE_PATH_LITERAL("Visited Links")); 666 filename->append(L"\\Visited Links");
693 return true; 667 return true;
694 } 668 }
695 669
696 // Initializes the shared memory structure. The salt should already be filled 670 // Initializes the shared memory structure. The salt should already be filled
697 // in so that it can be written to the shared memory 671 // in so that it can be written to the shared memory
698 bool VisitedLinkMaster::CreateURLTable(int32 num_entries, bool init_to_empty) { 672 bool VisitedLinkMaster::CreateURLTable(int32 num_entries, bool init_to_empty) {
699 // The table is the size of the table followed by the entries. 673 // The table is the size of the table followed by the entries.
700 int32 alloc_size = num_entries * sizeof(Fingerprint) + sizeof(SharedHeader); 674 int32 alloc_size = num_entries * sizeof(Fingerprint) + sizeof(SharedHeader);
701 675
702 // Create the shared memory object. 676 // Create the shared memory object.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 void VisitedLinkMaster::FreeURLTable() { 728 void VisitedLinkMaster::FreeURLTable() {
755 if (shared_memory_) { 729 if (shared_memory_) {
756 delete shared_memory_; 730 delete shared_memory_;
757 shared_memory_ = NULL; 731 shared_memory_ = NULL;
758 } 732 }
759 if (file_) { 733 if (file_) {
760 if (file_thread_) { 734 if (file_thread_) {
761 AsyncCloseHandle* closer = new AsyncCloseHandle(file_); 735 AsyncCloseHandle* closer = new AsyncCloseHandle(file_);
762 file_thread_->PostTask(FROM_HERE, closer); 736 file_thread_->PostTask(FROM_HERE, closer);
763 } else { 737 } else {
764 fclose(file_); 738 CloseHandle(file_);
765 } 739 }
766 } 740 }
767 } 741 }
768 742
769 bool VisitedLinkMaster::ResizeTableIfNecessary() { 743 bool VisitedLinkMaster::ResizeTableIfNecessary() {
770 DCHECK(table_length_ > 0) << "Must have a table"; 744 DCHECK(table_length_ > 0) << "Must have a table";
771 745
772 // Load limits for good performance/space. We are pretty conservative about 746 // Load limits for good performance/space. We are pretty conservative about
773 // keeping the table not very full. This is because we use linear probing 747 // keeping the table not very full. This is because we use linear probing
774 // which increases the likelihood of clumps of entries which will reduce 748 // which increases the likelihood of clumps of entries which will reduce
775 // performance. 749 // performance.
776 const float max_table_load = 0.5f; // Grow when we're > this full. 750 const float max_table_load = 0.5f; // Grow when we're > this full.
777 const float min_table_load = 0.2f; // Shrink when we're < this full. 751 const float min_table_load = 0.2f; // Shrink when we're < this full.
778 752
779 float load = ComputeTableLoad(); 753 float load = ComputeTableLoad();
780 if (load < max_table_load && 754 if (load < max_table_load &&
781 (table_length_ <= static_cast<float>(kDefaultTableSize) || 755 (table_length_ <= kDefaultTableSize || load > min_table_load))
782 load > min_table_load))
783 return false; 756 return false;
784 757
785 // Table needs to grow or shrink. 758 // Table needs to grow or shrink.
786 int new_size = NewTableSizeForCount(used_items_); 759 int new_size = NewTableSizeForCount(used_items_);
787 DCHECK(new_size > used_items_); 760 DCHECK(new_size > used_items_);
788 DCHECK(load <= min_table_load || new_size > table_length_); 761 DCHECK(load <= min_table_load || new_size > table_length_);
789 ResizeTable(new_size); 762 ResizeTable(new_size);
790 return true; 763 return true;
791 } 764 }
792 765
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 2097143, // 2M = 2097152 816 2097143, // 2M = 2097152
844 4194301, // 4M = 4194304 817 4194301, // 4M = 4194304
845 8388571, // 8M = 8388608 818 8388571, // 8M = 8388608
846 16777199, // 16M = 16777216 819 16777199, // 16M = 16777216
847 33554347}; // 32M = 33554432 820 33554347}; // 32M = 33554432
848 821
849 // Try to leave the table 33% full. 822 // Try to leave the table 33% full.
850 int desired = item_count * 3; 823 int desired = item_count * 3;
851 824
852 // Find the closest prime. 825 // Find the closest prime.
853 for (size_t i = 0; i < arraysize(table_sizes); i ++) { 826 for (int i = 0; i < arraysize(table_sizes); i ++) {
854 if (table_sizes[i] > desired) 827 if (table_sizes[i] > desired)
855 return table_sizes[i]; 828 return table_sizes[i];
856 } 829 }
857 830
858 // Growing very big, just approximate a "good" number, not growing as much 831 // Growing very big, just approximate a "good" number, not growing as much
859 // as normal. 832 // as normal.
860 return item_count * 2 - 1; 833 return item_count * 2 - 1;
861 } 834 }
862 835
863 // See the TableBuilder definition in the header file for how this works. 836 // See the TableBuilder definition in the header file for how this works.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
928 } 901 }
929 table_builder_ = NULL; // Will release our reference to the builder. 902 table_builder_ = NULL; // Will release our reference to the builder.
930 903
931 // Notify the unit test that the rebuild is complete (will be NULL in prod.) 904 // Notify the unit test that the rebuild is complete (will be NULL in prod.)
932 if (rebuild_complete_task_.get()) { 905 if (rebuild_complete_task_.get()) {
933 rebuild_complete_task_->Run(); 906 rebuild_complete_task_->Run();
934 rebuild_complete_task_.reset(NULL); 907 rebuild_complete_task_.reset(NULL);
935 } 908 }
936 } 909 }
937 910
938 void VisitedLinkMaster::WriteToFile(FILE* file, 911 void VisitedLinkMaster::WriteToFile(HANDLE hfile,
939 off_t offset, 912 int32 offset,
940 void* data, 913 void* data,
941 int32 data_size) { 914 int32 data_size) {
942 #ifndef NDEBUG 915 #ifndef NDEBUG
943 posted_asynchronous_operation_ = true; 916 posted_asynchronous_operation_ = true;
944 #endif 917 #endif
945 918
946 if (file_thread_) { 919 if (file_thread_) {
947 // Send the write to the other thread for execution to avoid blocking. 920 // Send the write to the other thread for execution to avoid blocking.
948 AsyncWriter* writer = new AsyncWriter(file, offset, data, data_size); 921 AsyncWriter* writer = new AsyncWriter(hfile, offset, data, data_size);
949 file_thread_->PostTask(FROM_HERE, writer); 922 file_thread_->PostTask(FROM_HERE, writer);
950 } else { 923 } else {
951 // When there is no I/O thread, we are probably running in unit test mode, 924 // When there is no I/O thread, we are probably running in unit test mode,
952 // just do the write synchronously. 925 // just do the write synchronously.
953 AsyncWriter::WriteToFile(file, offset, data, data_size); 926 AsyncWriter::WriteToFile(hfile, offset, data, data_size);
954 } 927 }
955 } 928 }
956 929
957 void VisitedLinkMaster::WriteUsedItemCountToFile() { 930 void VisitedLinkMaster::WriteUsedItemCountToFile() {
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 (last_hash < first_hash) { 935 if (last_hash < first_hash) {
963 // Handle wraparound at 0. This first write is first_hash->EOF 936 // Handle wraparound at 0. This first write is first_hash->EOF
964 WriteToFile(file_, first_hash * sizeof(Fingerprint) + kFileHeaderSize, 937 WriteToFile(file_, first_hash * sizeof(Fingerprint) + kFileHeaderSize,
965 &hash_table_[first_hash], 938 &hash_table_[first_hash],
966 (table_length_ - first_hash + 1) * sizeof(Fingerprint)); 939 (table_length_ - first_hash + 1) * sizeof(Fingerprint));
967 940
968 // Now do 0->last_lash. 941 // Now do 0->last_lash.
969 WriteToFile(file_, kFileHeaderSize, hash_table_, 942 WriteToFile(file_, kFileHeaderSize, hash_table_,
970 (last_hash + 1) * sizeof(Fingerprint)); 943 (last_hash + 1) * sizeof(Fingerprint));
971 } else { 944 } else {
972 // Normal case, just write the range. 945 // Normal case, just write the range.
973 WriteToFile(file_, first_hash * sizeof(Fingerprint) + kFileHeaderSize, 946 WriteToFile(file_, first_hash * sizeof(Fingerprint) + kFileHeaderSize,
974 &hash_table_[first_hash], 947 &hash_table_[first_hash],
975 (last_hash - first_hash + 1) * sizeof(Fingerprint)); 948 (last_hash - first_hash + 1) * sizeof(Fingerprint));
976 } 949 }
977 } 950 }
978 951
979 bool VisitedLinkMaster::ReadFromFile(FILE* file, 952 bool VisitedLinkMaster::ReadFromFile(HANDLE hfile,
980 off_t offset, 953 int32 offset,
981 void* data, 954 void* data,
982 size_t data_size) { 955 int32 data_size) {
983 #ifndef NDEBUG 956 #ifndef NDEBUG
984 // Since this function is synchronous, we require that no asynchronous 957 // Since this function is synchronous, we require that no asynchronous
985 // operations could possibly be pending. 958 // operations could possibly be pending.
986 DCHECK(!posted_asynchronous_operation_); 959 DCHECK(!posted_asynchronous_operation_);
987 #endif 960 #endif
988 961
989 fseek(file, offset, SEEK_SET); 962 SetFilePointer(hfile, offset, NULL, FILE_BEGIN);
990 963
991 size_t num_read = fread(data, 1, data_size, file); 964 DWORD num_read;
992 return num_read == data_size; 965 return ReadFile(hfile, data, data_size, &num_read, NULL) &&
966 num_read == data_size;
993 } 967 }
994 968
995 // VisitedLinkTableBuilder ---------------------------------------------------- 969 // VisitedLinkTableBuilder ----------------------------------------------------
996 970
997 VisitedLinkMaster::TableBuilder::TableBuilder( 971 VisitedLinkMaster::TableBuilder::TableBuilder(
998 VisitedLinkMaster* master, 972 VisitedLinkMaster* master,
999 const uint8 salt[LINK_SALT_LENGTH]) 973 const uint8 salt[LINK_SALT_LENGTH])
1000 : master_(master), 974 : master_(master),
1001 main_message_loop_(MessageLoop::current()), 975 success_(true),
1002 success_(true) { 976 main_message_loop_(MessageLoop::current()) {
1003 fingerprints_.reserve(4096); 977 fingerprints_.reserve(4096);
1004 memcpy(salt_, salt, sizeof(salt)); 978 memcpy(salt_, salt, sizeof(salt));
1005 } 979 }
1006 980
1007 // 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
1008 // could delay shutdown if there are a lot of URLs. 982 // could delay shutdown if there are a lot of URLs.
1009 void VisitedLinkMaster::TableBuilder::DisownMaster() { 983 void VisitedLinkMaster::TableBuilder::DisownMaster() {
1010 master_ = NULL; 984 master_ = NULL;
1011 } 985 }
1012 986
(...skipping 15 matching lines...) Expand all
1028 } 1002 }
1029 1003
1030 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { 1004 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() {
1031 if (master_) 1005 if (master_)
1032 master_->OnTableRebuildComplete(success_, fingerprints_); 1006 master_->OnTableRebuildComplete(success_, fingerprints_);
1033 1007
1034 // WILL (generally) DELETE THIS! This balances the AddRef in 1008 // WILL (generally) DELETE THIS! This balances the AddRef in
1035 // VisitedLinkMaster::RebuildTableFromHistory. 1009 // VisitedLinkMaster::RebuildTableFromHistory.
1036 Release(); 1010 Release();
1037 } 1011 }
OLDNEW
« no previous file with comments | « chrome/browser/visitedlink_master.h ('k') | chrome/browser/visitedlink_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698