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 "net/disk_cache/backend_impl.h" | 5 #include "net/disk_cache/backend_impl.h" |
6 | 6 |
7 #include "base/field_trial.h" | 7 #include "base/field_trial.h" |
8 #include "base/file_path.h" | 8 #include "base/file_path.h" |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/histogram.h" | 10 #include "base/histogram.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 | 22 |
23 // This has to be defined before including histogram_macros.h from this file. | 23 // This has to be defined before including histogram_macros.h from this file. |
24 #define NET_DISK_CACHE_BACKEND_IMPL_CC_ | 24 #define NET_DISK_CACHE_BACKEND_IMPL_CC_ |
25 #include "net/disk_cache/histogram_macros.h" | 25 #include "net/disk_cache/histogram_macros.h" |
26 | 26 |
27 using base::Time; | 27 using base::Time; |
28 using base::TimeDelta; | 28 using base::TimeDelta; |
29 | 29 |
30 namespace { | 30 namespace { |
31 | 31 |
32 const wchar_t* kIndexName = L"index"; | 32 const char* kIndexName = "index"; |
33 const int kMaxOldFolders = 100; | 33 const int kMaxOldFolders = 100; |
34 | 34 |
35 // Seems like ~240 MB correspond to less than 50k entries for 99% of the people. | 35 // Seems like ~240 MB correspond to less than 50k entries for 99% of the people. |
36 const int k64kEntriesStore = 240 * 1000 * 1000; | 36 const int k64kEntriesStore = 240 * 1000 * 1000; |
37 const int kBaseTableLen = 64 * 1024; | 37 const int kBaseTableLen = 64 * 1024; |
38 const int kDefaultCacheSize = 80 * 1024 * 1024; | 38 const int kDefaultCacheSize = 80 * 1024 * 1024; |
39 | 39 |
40 int DesiredIndexTableLen(int32 storage_size) { | 40 int DesiredIndexTableLen(int32 storage_size) { |
41 if (storage_size <= k64kEntriesStore) | 41 if (storage_size <= k64kEntriesStore) |
42 return kBaseTableLen; | 42 return kBaseTableLen; |
(...skipping 15 matching lines...) Expand all Loading... |
58 size_t GetIndexSize(int table_len) { | 58 size_t GetIndexSize(int table_len) { |
59 size_t table_size = sizeof(disk_cache::CacheAddr) * table_len; | 59 size_t table_size = sizeof(disk_cache::CacheAddr) * table_len; |
60 return sizeof(disk_cache::IndexHeader) + table_size; | 60 return sizeof(disk_cache::IndexHeader) + table_size; |
61 } | 61 } |
62 | 62 |
63 // ------------------------------------------------------------------------ | 63 // ------------------------------------------------------------------------ |
64 | 64 |
65 // Returns a fully qualified name from path and name, using a given name prefix | 65 // Returns a fully qualified name from path and name, using a given name prefix |
66 // and index number. For instance, if the arguments are "/foo", "bar" and 5, it | 66 // and index number. For instance, if the arguments are "/foo", "bar" and 5, it |
67 // will return "/foo/old_bar_005". | 67 // will return "/foo/old_bar_005". |
68 std::wstring GetPrefixedName(const std::wstring& path, const std::wstring& name, | 68 FilePath GetPrefixedName(const FilePath& path, const std::string& name, |
69 int index) { | 69 int index) { |
70 std::wstring prefixed(path); | 70 std::string tmp = StringPrintf("%s%s_%03d", "old_", name.c_str(), index); |
71 std::wstring tmp = StringPrintf(L"%ls%ls_%03d", L"old_", name.c_str(), index); | 71 return path.AppendASCII(tmp); |
72 file_util::AppendToPath(&prefixed, tmp); | |
73 return prefixed; | |
74 } | 72 } |
75 | 73 |
76 // This is a simple Task to cleanup old caches. | 74 // This is a simple Task to cleanup old caches. |
77 class CleanupTask : public Task { | 75 class CleanupTask : public Task { |
78 public: | 76 public: |
79 CleanupTask(const std::wstring& path, const std::wstring& name) | 77 CleanupTask(const FilePath& path, const std::string& name) |
80 : path_(path), name_(name) {} | 78 : path_(path), name_(name) {} |
81 | 79 |
82 virtual void Run(); | 80 virtual void Run(); |
83 | 81 |
84 private: | 82 private: |
85 std::wstring path_; | 83 FilePath path_; |
86 std::wstring name_; | 84 std::string name_; |
87 DISALLOW_EVIL_CONSTRUCTORS(CleanupTask); | 85 DISALLOW_EVIL_CONSTRUCTORS(CleanupTask); |
88 }; | 86 }; |
89 | 87 |
90 void CleanupTask::Run() { | 88 void CleanupTask::Run() { |
91 for (int i = 0; i < kMaxOldFolders; i++) { | 89 for (int i = 0; i < kMaxOldFolders; i++) { |
92 std::wstring to_delete = GetPrefixedName(path_, name_, i); | 90 FilePath to_delete = GetPrefixedName(path_, name_, i); |
93 disk_cache::DeleteCache(to_delete, true); | 91 disk_cache::DeleteCache(to_delete, true); |
94 } | 92 } |
95 } | 93 } |
96 | 94 |
97 // Returns a full path to rename the current cache, in order to delete it. path | 95 // Returns a full path to rename the current cache, in order to delete it. path |
98 // is the current folder location, and name is the current folder name. | 96 // is the current folder location, and name is the current folder name. |
99 std::wstring GetTempCacheName(const std::wstring& path, | 97 FilePath GetTempCacheName(const FilePath& path, const std::string& name) { |
100 const std::wstring& name) { | |
101 // We'll attempt to have up to kMaxOldFolders folders for deletion. | 98 // We'll attempt to have up to kMaxOldFolders folders for deletion. |
102 for (int i = 0; i < kMaxOldFolders; i++) { | 99 for (int i = 0; i < kMaxOldFolders; i++) { |
103 std::wstring to_delete = GetPrefixedName(path, name, i); | 100 FilePath to_delete = GetPrefixedName(path, name, i); |
104 if (!file_util::PathExists(to_delete)) | 101 if (!file_util::PathExists(to_delete)) |
105 return to_delete; | 102 return to_delete; |
106 } | 103 } |
107 return std::wstring(); | 104 return FilePath(); |
108 } | 105 } |
109 | 106 |
110 // Moves the cache files to a new folder and creates a task to delete them. | 107 // Moves the cache files to a new folder and creates a task to delete them. |
111 bool DelayedCacheCleanup(const std::wstring& full_path) { | 108 bool DelayedCacheCleanup(const FilePath& full_path) { |
112 FilePath current_path = FilePath::FromWStringHack(full_path); | 109 FilePath current_path = full_path.StripTrailingSeparators(); |
113 current_path = current_path.StripTrailingSeparators(); | |
114 | 110 |
115 std::wstring path = current_path.DirName().ToWStringHack(); | 111 FilePath path = current_path.DirName(); |
116 std::wstring name = current_path.BaseName().ToWStringHack(); | 112 FilePath name = current_path.BaseName(); |
| 113 #if defined(OS_POSIX) |
| 114 std::string name_str = name.value(); |
| 115 #elif defined(OS_WIN) |
| 116 // We created this file so it should only contain ASCII. |
| 117 std::string name_str = WideToASCII(name.value()); |
| 118 #endif |
117 | 119 |
118 std::wstring to_delete = GetTempCacheName(path, name); | 120 FilePath to_delete = GetTempCacheName(path, name_str); |
119 if (to_delete.empty()) { | 121 if (to_delete.empty()) { |
120 LOG(ERROR) << "Unable to get another cache folder"; | 122 LOG(ERROR) << "Unable to get another cache folder"; |
121 return false; | 123 return false; |
122 } | 124 } |
123 | 125 |
124 if (!disk_cache::MoveCache(full_path.c_str(), to_delete.c_str())) { | 126 if (!disk_cache::MoveCache(full_path, to_delete)) { |
125 LOG(ERROR) << "Unable to rename cache folder"; | 127 LOG(ERROR) << "Unable to rename cache folder"; |
126 return false; | 128 return false; |
127 } | 129 } |
128 | 130 |
129 #if defined(OS_WIN) | 131 #if defined(OS_WIN) |
130 WorkerPool::PostTask(FROM_HERE, new CleanupTask(path, name), true); | 132 WorkerPool::PostTask(FROM_HERE, new CleanupTask(path, name_str), true); |
131 #elif defined(OS_POSIX) | 133 #elif defined(OS_POSIX) |
132 // TODO(rvargas): Use the worker pool. | 134 // TODO(rvargas): Use the worker pool. |
133 MessageLoop::current()->PostTask(FROM_HERE, new CleanupTask(path, name)); | 135 MessageLoop::current()->PostTask(FROM_HERE, new CleanupTask(path, name_str)); |
134 #endif | 136 #endif |
135 return true; | 137 return true; |
136 } | 138 } |
137 | 139 |
138 // Sets |current_group| for the current experiment. Returns false if the files | 140 // Sets |current_group| for the current experiment. Returns false if the files |
139 // should be discarded. | 141 // should be discarded. |
140 bool InitExperiment(int* current_group) { | 142 bool InitExperiment(int* current_group) { |
141 if (*current_group == 3 || *current_group == 4) { | 143 if (*current_group == 3 || *current_group == 4) { |
142 // Discard current cache for groups 3 and 4. | 144 // Discard current cache for groups 3 and 4. |
143 return false; | 145 return false; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 // number, (located on the same parent folder), and spawn a worker thread to | 210 // number, (located on the same parent folder), and spawn a worker thread to |
209 // delete all the files on all the stale cache folders. The whole process can | 211 // delete all the files on all the stale cache folders. The whole process can |
210 // still fail if we are not able to rename the cache folder (for instance due to | 212 // still fail if we are not able to rename the cache folder (for instance due to |
211 // a sharing violation), and in that case a cache for this profile (on the | 213 // a sharing violation), and in that case a cache for this profile (on the |
212 // desired path) cannot be created. | 214 // desired path) cannot be created. |
213 // | 215 // |
214 // Static. | 216 // Static. |
215 Backend* BackendImpl::CreateBackend(const std::wstring& full_path, bool force, | 217 Backend* BackendImpl::CreateBackend(const std::wstring& full_path, bool force, |
216 int max_bytes, net::CacheType type, | 218 int max_bytes, net::CacheType type, |
217 BackendFlags flags) { | 219 BackendFlags flags) { |
218 BackendImpl* cache = new BackendImpl(full_path); | 220 FilePath full_cache_path = FilePath::FromWStringHack(full_path); |
| 221 BackendImpl* cache = new BackendImpl(full_cache_path); |
219 cache->SetMaxSize(max_bytes); | 222 cache->SetMaxSize(max_bytes); |
220 cache->SetType(type); | 223 cache->SetType(type); |
221 cache->SetFlags(flags); | 224 cache->SetFlags(flags); |
222 if (cache->Init()) | 225 if (cache->Init()) |
223 return cache; | 226 return cache; |
224 | 227 |
225 delete cache; | 228 delete cache; |
226 if (!force) | 229 if (!force) |
227 return NULL; | 230 return NULL; |
228 | 231 |
229 if (!DelayedCacheCleanup(full_path)) | 232 if (!DelayedCacheCleanup(full_cache_path)) |
230 return NULL; | 233 return NULL; |
231 | 234 |
232 // The worker thread will start deleting files soon, but the original folder | 235 // The worker thread will start deleting files soon, but the original folder |
233 // is not there anymore... let's create a new set of files. | 236 // is not there anymore... let's create a new set of files. |
234 cache = new BackendImpl(full_path); | 237 cache = new BackendImpl(full_cache_path); |
235 cache->SetMaxSize(max_bytes); | 238 cache->SetMaxSize(max_bytes); |
236 cache->SetType(type); | 239 cache->SetType(type); |
237 cache->SetFlags(flags); | 240 cache->SetFlags(flags); |
238 if (cache->Init()) | 241 if (cache->Init()) |
239 return cache; | 242 return cache; |
240 | 243 |
241 delete cache; | 244 delete cache; |
242 LOG(ERROR) << "Unable to create cache"; | 245 LOG(ERROR) << "Unable to create cache"; |
243 return NULL; | 246 return NULL; |
244 } | 247 } |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 // but that triggers strict aliasing problems with gcc. | 474 // but that triggers strict aliasing problems with gcc. |
472 EntryImpl* entry_impl = reinterpret_cast<EntryImpl*>(entry); | 475 EntryImpl* entry_impl = reinterpret_cast<EntryImpl*>(entry); |
473 entry_impl->Doom(); | 476 entry_impl->Doom(); |
474 entry_impl->Release(); | 477 entry_impl->Release(); |
475 return true; | 478 return true; |
476 } | 479 } |
477 | 480 |
478 bool BackendImpl::DoomAllEntries() { | 481 bool BackendImpl::DoomAllEntries() { |
479 if (!num_refs_) { | 482 if (!num_refs_) { |
480 PrepareForRestart(); | 483 PrepareForRestart(); |
481 DeleteCache(path_.c_str(), false); | 484 DeleteCache(path_, false); |
482 return Init(); | 485 return Init(); |
483 } else { | 486 } else { |
484 if (disabled_) | 487 if (disabled_) |
485 return false; | 488 return false; |
486 | 489 |
487 eviction_.TrimCache(true); | 490 eviction_.TrimCache(true); |
488 stats_.OnEvent(Stats::DOOM_CACHE); | 491 stats_.OnEvent(Stats::DOOM_CACHE); |
489 return true; | 492 return true; |
490 } | 493 } |
491 } | 494 } |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 user_flags_ |= kMaxSize; | 606 user_flags_ |= kMaxSize; |
604 max_size_ = max_bytes; | 607 max_size_ = max_bytes; |
605 return true; | 608 return true; |
606 } | 609 } |
607 | 610 |
608 void BackendImpl::SetType(net::CacheType type) { | 611 void BackendImpl::SetType(net::CacheType type) { |
609 DCHECK(type != net::MEMORY_CACHE); | 612 DCHECK(type != net::MEMORY_CACHE); |
610 cache_type_ = type; | 613 cache_type_ = type; |
611 } | 614 } |
612 | 615 |
613 std::wstring BackendImpl::GetFileName(Addr address) const { | 616 FilePath BackendImpl::GetFileName(Addr address) const { |
614 if (!address.is_separate_file() || !address.is_initialized()) { | 617 if (!address.is_separate_file() || !address.is_initialized()) { |
615 NOTREACHED(); | 618 NOTREACHED(); |
616 return std::wstring(); | 619 return FilePath(); |
617 } | 620 } |
618 | 621 |
619 std::wstring name(path_); | 622 std::string tmp = StringPrintf("f_%06x", address.FileNumber()); |
620 std::wstring tmp = StringPrintf(L"f_%06x", address.FileNumber()); | 623 return path_.AppendASCII(tmp); |
621 file_util::AppendToPath(&name, tmp); | |
622 return name; | |
623 } | 624 } |
624 | 625 |
625 MappedFile* BackendImpl::File(Addr address) { | 626 MappedFile* BackendImpl::File(Addr address) { |
626 if (disabled_) | 627 if (disabled_) |
627 return NULL; | 628 return NULL; |
628 return block_files_.GetFile(address); | 629 return block_files_.GetFile(address); |
629 } | 630 } |
630 | 631 |
631 bool BackendImpl::CreateExternalFile(Addr* address) { | 632 bool BackendImpl::CreateExternalFile(Addr* address) { |
632 int file_number = data_->header.last_file + 1; | 633 int file_number = data_->header.last_file + 1; |
633 Addr file_address(0); | 634 Addr file_address(0); |
634 bool success = false; | 635 bool success = false; |
635 for (int i = 0; i < 0x0fffffff; i++, file_number++) { | 636 for (int i = 0; i < 0x0fffffff; i++, file_number++) { |
636 if (!file_address.SetFileNumber(file_number)) { | 637 if (!file_address.SetFileNumber(file_number)) { |
637 file_number = 1; | 638 file_number = 1; |
638 continue; | 639 continue; |
639 } | 640 } |
640 std::wstring name = GetFileName(file_address); | 641 FilePath name = GetFileName(file_address); |
641 int flags = base::PLATFORM_FILE_READ | | 642 int flags = base::PLATFORM_FILE_READ | |
642 base::PLATFORM_FILE_WRITE | | 643 base::PLATFORM_FILE_WRITE | |
643 base::PLATFORM_FILE_CREATE | | 644 base::PLATFORM_FILE_CREATE | |
644 base::PLATFORM_FILE_EXCLUSIVE_WRITE; | 645 base::PLATFORM_FILE_EXCLUSIVE_WRITE; |
645 scoped_refptr<disk_cache::File> file(new disk_cache::File( | 646 scoped_refptr<disk_cache::File> file(new disk_cache::File( |
646 base::CreatePlatformFile(name.c_str(), flags, NULL))); | 647 base::CreatePlatformFile(name.ToWStringHack().c_str(), flags, NULL))); |
647 if (!file->IsValid()) | 648 if (!file->IsValid()) |
648 continue; | 649 continue; |
649 | 650 |
650 success = true; | 651 success = true; |
651 break; | 652 break; |
652 } | 653 } |
653 | 654 |
654 DCHECK(success); | 655 DCHECK(success); |
655 if (!success) | 656 if (!success) |
656 return false; | 657 return false; |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 | 982 |
982 if (!file->Write(&header, sizeof(header), 0)) | 983 if (!file->Write(&header, sizeof(header), 0)) |
983 return false; | 984 return false; |
984 | 985 |
985 return file->SetLength(GetIndexSize(header.table_len)); | 986 return file->SetLength(GetIndexSize(header.table_len)); |
986 } | 987 } |
987 | 988 |
988 bool BackendImpl::InitBackingStore(bool* file_created) { | 989 bool BackendImpl::InitBackingStore(bool* file_created) { |
989 file_util::CreateDirectory(path_); | 990 file_util::CreateDirectory(path_); |
990 | 991 |
991 std::wstring index_name(path_); | 992 FilePath index_name = path_.AppendASCII(kIndexName); |
992 file_util::AppendToPath(&index_name, kIndexName); | |
993 | 993 |
994 int flags = base::PLATFORM_FILE_READ | | 994 int flags = base::PLATFORM_FILE_READ | |
995 base::PLATFORM_FILE_WRITE | | 995 base::PLATFORM_FILE_WRITE | |
996 base::PLATFORM_FILE_OPEN_ALWAYS | | 996 base::PLATFORM_FILE_OPEN_ALWAYS | |
997 base::PLATFORM_FILE_EXCLUSIVE_WRITE; | 997 base::PLATFORM_FILE_EXCLUSIVE_WRITE; |
998 scoped_refptr<disk_cache::File> file(new disk_cache::File( | 998 scoped_refptr<disk_cache::File> file(new disk_cache::File( |
999 base::CreatePlatformFile(index_name.c_str(), flags, file_created))); | 999 base::CreatePlatformFile(index_name.ToWStringHack().c_str(), flags, |
| 1000 file_created))); |
1000 | 1001 |
1001 if (!file->IsValid()) | 1002 if (!file->IsValid()) |
1002 return false; | 1003 return false; |
1003 | 1004 |
1004 bool ret = true; | 1005 bool ret = true; |
1005 if (*file_created) | 1006 if (*file_created) |
1006 ret = CreateBackingStore(file); | 1007 ret = CreateBackingStore(file); |
1007 | 1008 |
1008 file = NULL; | 1009 file = NULL; |
1009 if (!ret) | 1010 if (!ret) |
1010 return false; | 1011 return false; |
1011 | 1012 |
1012 index_ = new MappedFile(); | 1013 index_ = new MappedFile(); |
1013 data_ = reinterpret_cast<Index*>(index_->Init(index_name, 0)); | 1014 data_ = reinterpret_cast<Index*>(index_->Init(index_name.ToWStringHack(), 0)); |
1014 if (!data_) { | 1015 if (!data_) { |
1015 LOG(ERROR) << "Unable to map Index file"; | 1016 LOG(ERROR) << "Unable to map Index file"; |
1016 return false; | 1017 return false; |
1017 } | 1018 } |
1018 return true; | 1019 return true; |
1019 } | 1020 } |
1020 | 1021 |
1021 // The maximum cache size will be either set explicitly by the caller, or | 1022 // The maximum cache size will be either set explicitly by the caller, or |
1022 // calculated by this code. | 1023 // calculated by this code. |
1023 void BackendImpl::AdjustMaxCacheSize(int table_len) { | 1024 void BackendImpl::AdjustMaxCacheSize(int table_len) { |
1024 if (max_size_) | 1025 if (max_size_) |
1025 return; | 1026 return; |
1026 | 1027 |
1027 // If table_len is provided, the index file exists. | 1028 // If table_len is provided, the index file exists. |
1028 DCHECK(!table_len || data_->header.magic); | 1029 DCHECK(!table_len || data_->header.magic); |
1029 | 1030 |
1030 // The user is not setting the size, let's figure it out. | 1031 // The user is not setting the size, let's figure it out. |
1031 int64 available = base::SysInfo::AmountOfFreeDiskSpace(path_); | 1032 int64 available = base::SysInfo::AmountOfFreeDiskSpace(path_.ToWStringHack()); |
1032 if (available < 0) { | 1033 if (available < 0) { |
1033 max_size_ = kDefaultCacheSize; | 1034 max_size_ = kDefaultCacheSize; |
1034 return; | 1035 return; |
1035 } | 1036 } |
1036 | 1037 |
1037 if (table_len) | 1038 if (table_len) |
1038 available += data_->header.num_bytes; | 1039 available += data_->header.num_bytes; |
1039 | 1040 |
1040 max_size_ = PreferedCacheSize(available); | 1041 max_size_ = PreferedCacheSize(available); |
1041 | 1042 |
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1619 | 1620 |
1620 return num_dirty; | 1621 return num_dirty; |
1621 } | 1622 } |
1622 | 1623 |
1623 bool BackendImpl::CheckEntry(EntryImpl* cache_entry) { | 1624 bool BackendImpl::CheckEntry(EntryImpl* cache_entry) { |
1624 RankingsNode* rankings = cache_entry->rankings()->Data(); | 1625 RankingsNode* rankings = cache_entry->rankings()->Data(); |
1625 return !rankings->dummy; | 1626 return !rankings->dummy; |
1626 } | 1627 } |
1627 | 1628 |
1628 } // namespace disk_cache | 1629 } // namespace disk_cache |
OLD | NEW |