| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/disk_cache/cache_util.h" | |
| 6 | |
| 7 #include "base/files/file_enumerator.h" | |
| 8 #include "base/files/file_util.h" | |
| 9 #include "base/location.h" | |
| 10 #include "base/strings/string_util.h" | |
| 11 #include "base/strings/stringprintf.h" | |
| 12 #include "base/strings/utf_string_conversions.h" | |
| 13 #include "base/threading/thread_restrictions.h" | |
| 14 #include "base/threading/worker_pool.h" | |
| 15 | |
| 16 namespace { | |
| 17 | |
| 18 const int kMaxOldFolders = 100; | |
| 19 | |
| 20 // Returns a fully qualified name from path and name, using a given name prefix | |
| 21 // and index number. For instance, if the arguments are "/foo", "bar" and 5, it | |
| 22 // will return "/foo/old_bar_005". | |
| 23 base::FilePath GetPrefixedName(const base::FilePath& path, | |
| 24 const std::string& name, | |
| 25 int index) { | |
| 26 std::string tmp = base::StringPrintf("%s%s_%03d", "old_", | |
| 27 name.c_str(), index); | |
| 28 return path.AppendASCII(tmp); | |
| 29 } | |
| 30 | |
| 31 // This is a simple callback to cleanup old caches. | |
| 32 void CleanupCallback(const base::FilePath& path, const std::string& name) { | |
| 33 for (int i = 0; i < kMaxOldFolders; i++) { | |
| 34 base::FilePath to_delete = GetPrefixedName(path, name, i); | |
| 35 disk_cache::DeleteCache(to_delete, true); | |
| 36 } | |
| 37 } | |
| 38 | |
| 39 // Returns a full path to rename the current cache, in order to delete it. path | |
| 40 // is the current folder location, and name is the current folder name. | |
| 41 base::FilePath GetTempCacheName(const base::FilePath& path, | |
| 42 const std::string& name) { | |
| 43 // We'll attempt to have up to kMaxOldFolders folders for deletion. | |
| 44 for (int i = 0; i < kMaxOldFolders; i++) { | |
| 45 base::FilePath to_delete = GetPrefixedName(path, name, i); | |
| 46 if (!base::PathExists(to_delete)) | |
| 47 return to_delete; | |
| 48 } | |
| 49 return base::FilePath(); | |
| 50 } | |
| 51 | |
| 52 int64 PreferredCacheSizeInternal(int64 available) { | |
| 53 using disk_cache::kDefaultCacheSize; | |
| 54 // Return 80% of the available space if there is not enough space to use | |
| 55 // kDefaultCacheSize. | |
| 56 if (available < kDefaultCacheSize * 10 / 8) | |
| 57 return available * 8 / 10; | |
| 58 | |
| 59 // Return kDefaultCacheSize if it uses 10% to 80% of the available space. | |
| 60 if (available < kDefaultCacheSize * 10) | |
| 61 return kDefaultCacheSize; | |
| 62 | |
| 63 // Return 10% of the available space if the target size | |
| 64 // (2.5 * kDefaultCacheSize) is more than 10%. | |
| 65 if (available < static_cast<int64>(kDefaultCacheSize) * 25) | |
| 66 return available / 10; | |
| 67 | |
| 68 // Return the target size (2.5 * kDefaultCacheSize) if it uses 10% to 1% | |
| 69 // of the available space. | |
| 70 if (available < static_cast<int64>(kDefaultCacheSize) * 250) | |
| 71 return kDefaultCacheSize * 5 / 2; | |
| 72 | |
| 73 // Return 1% of the available space. | |
| 74 return available / 100; | |
| 75 } | |
| 76 | |
| 77 } // namespace | |
| 78 | |
| 79 namespace disk_cache { | |
| 80 | |
| 81 const int kDefaultCacheSize = 80 * 1024 * 1024; | |
| 82 | |
| 83 void DeleteCache(const base::FilePath& path, bool remove_folder) { | |
| 84 if (remove_folder) { | |
| 85 if (!base::DeleteFile(path, /* recursive */ true)) | |
| 86 LOG(WARNING) << "Unable to delete cache folder."; | |
| 87 return; | |
| 88 } | |
| 89 | |
| 90 base::FileEnumerator iter( | |
| 91 path, | |
| 92 /* recursive */ false, | |
| 93 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); | |
| 94 for (base::FilePath file = iter.Next(); !file.value().empty(); | |
| 95 file = iter.Next()) { | |
| 96 if (!base::DeleteFile(file, /* recursive */ true)) { | |
| 97 LOG(WARNING) << "Unable to delete cache."; | |
| 98 return; | |
| 99 } | |
| 100 } | |
| 101 } | |
| 102 | |
| 103 // In order to process a potentially large number of files, we'll rename the | |
| 104 // cache directory to old_ + original_name + number, (located on the same parent | |
| 105 // directory), and use a worker thread to delete all the files on all the stale | |
| 106 // cache directories. The whole process can still fail if we are not able to | |
| 107 // rename the cache directory (for instance due to a sharing violation), and in | |
| 108 // that case a cache for this profile (on the desired path) cannot be created. | |
| 109 bool DelayedCacheCleanup(const base::FilePath& full_path) { | |
| 110 // GetTempCacheName() and MoveCache() use synchronous file | |
| 111 // operations. | |
| 112 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
| 113 | |
| 114 base::FilePath current_path = full_path.StripTrailingSeparators(); | |
| 115 | |
| 116 base::FilePath path = current_path.DirName(); | |
| 117 base::FilePath name = current_path.BaseName(); | |
| 118 #if defined(OS_POSIX) | |
| 119 std::string name_str = name.value(); | |
| 120 #elif defined(OS_WIN) | |
| 121 // We created this file so it should only contain ASCII. | |
| 122 std::string name_str = base::UTF16ToASCII(name.value()); | |
| 123 #endif | |
| 124 | |
| 125 base::FilePath to_delete = GetTempCacheName(path, name_str); | |
| 126 if (to_delete.empty()) { | |
| 127 LOG(ERROR) << "Unable to get another cache folder"; | |
| 128 return false; | |
| 129 } | |
| 130 | |
| 131 if (!disk_cache::MoveCache(full_path, to_delete)) { | |
| 132 LOG(ERROR) << "Unable to move cache folder " << full_path.value() << " to " | |
| 133 << to_delete.value(); | |
| 134 return false; | |
| 135 } | |
| 136 | |
| 137 base::WorkerPool::PostTask( | |
| 138 FROM_HERE, base::Bind(&CleanupCallback, path, name_str), true); | |
| 139 return true; | |
| 140 } | |
| 141 | |
| 142 // Returns the preferred maximum number of bytes for the cache given the | |
| 143 // number of available bytes. | |
| 144 int PreferredCacheSize(int64 available) { | |
| 145 if (available < 0) | |
| 146 return kDefaultCacheSize; | |
| 147 | |
| 148 // Limit cache size to somewhat less than kint32max to avoid potential | |
| 149 // integer overflows in cache backend implementations. | |
| 150 DCHECK_LT(kDefaultCacheSize * 4, kint32max); | |
| 151 return static_cast<int32>(std::min( | |
| 152 PreferredCacheSizeInternal(available), | |
| 153 static_cast<int64>(kDefaultCacheSize * 4))); | |
| 154 } | |
| 155 | |
| 156 } // namespace disk_cache | |
| OLD | NEW |