blob: 57cba5984c2d77a1a2f7257ca330e0ff6af6df4a [file] [log] [blame]
[email protected]398ad132013-04-02 15:11:011// 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
avid0181f32015-12-10 19:41:477#include <limits>
8
Sebastien Marchand6d0558fd2019-01-25 16:49:379#include "base/bind.h"
[email protected]76ed979ee2013-07-17 15:50:4510#include "base/files/file_enumerator.h"
thestigd8df0332014-09-04 06:33:2911#include "base/files/file_util.h"
[email protected]398ad132013-04-02 15:11:0112#include "base/location.h"
Matt Menkeb0f4c7c2018-07-06 19:25:3013#include "base/metrics/field_trial_params.h"
14#include "base/strings/string_number_conversions.h"
[email protected]be528af2013-06-11 07:39:4815#include "base/strings/string_util.h"
16#include "base/strings/stringprintf.h"
[email protected]74f778e2014-03-14 21:11:4617#include "base/strings/utf_string_conversions.h"
Gabriel Charette44db1422018-08-06 11:19:3318#include "base/task/post_task.h"
[email protected]398ad132013-04-02 15:11:0119#include "base/threading/thread_restrictions.h"
Fabrice de Gans-Riberi7de47372018-05-08 20:23:4720#include "build/build_config.h"
[email protected]398ad132013-04-02 15:11:0121
22namespace {
23
24const int kMaxOldFolders = 100;
25
26// Returns a fully qualified name from path and name, using a given name prefix
27// and index number. For instance, if the arguments are "/foo", "bar" and 5, it
28// will return "/foo/old_bar_005".
29base::FilePath GetPrefixedName(const base::FilePath& path,
30 const std::string& name,
31 int index) {
32 std::string tmp = base::StringPrintf("%s%s_%03d", "old_",
33 name.c_str(), index);
34 return path.AppendASCII(tmp);
35}
36
37// This is a simple callback to cleanup old caches.
38void CleanupCallback(const base::FilePath& path, const std::string& name) {
39 for (int i = 0; i < kMaxOldFolders; i++) {
40 base::FilePath to_delete = GetPrefixedName(path, name, i);
41 disk_cache::DeleteCache(to_delete, true);
42 }
43}
44
45// Returns a full path to rename the current cache, in order to delete it. path
46// is the current folder location, and name is the current folder name.
47base::FilePath GetTempCacheName(const base::FilePath& path,
48 const std::string& name) {
49 // We'll attempt to have up to kMaxOldFolders folders for deletion.
50 for (int i = 0; i < kMaxOldFolders; i++) {
51 base::FilePath to_delete = GetPrefixedName(path, name, i);
[email protected]7567484142013-07-11 17:36:0752 if (!base::PathExists(to_delete))
[email protected]398ad132013-04-02 15:11:0153 return to_delete;
54 }
55 return base::FilePath();
56}
57
avid0181f32015-12-10 19:41:4758int64_t PreferredCacheSizeInternal(int64_t available) {
[email protected]18b5b262013-11-19 18:41:3759 using disk_cache::kDefaultCacheSize;
60 // Return 80% of the available space if there is not enough space to use
61 // kDefaultCacheSize.
62 if (available < kDefaultCacheSize * 10 / 8)
63 return available * 8 / 10;
64
65 // Return kDefaultCacheSize if it uses 10% to 80% of the available space.
66 if (available < kDefaultCacheSize * 10)
67 return kDefaultCacheSize;
68
69 // Return 10% of the available space if the target size
70 // (2.5 * kDefaultCacheSize) is more than 10%.
avid0181f32015-12-10 19:41:4771 if (available < static_cast<int64_t>(kDefaultCacheSize) * 25)
[email protected]18b5b262013-11-19 18:41:3772 return available / 10;
73
74 // Return the target size (2.5 * kDefaultCacheSize) if it uses 10% to 1%
75 // of the available space.
avid0181f32015-12-10 19:41:4776 if (available < static_cast<int64_t>(kDefaultCacheSize) * 250)
[email protected]18b5b262013-11-19 18:41:3777 return kDefaultCacheSize * 5 / 2;
78
79 // Return 1% of the available space.
80 return available / 100;
81}
82
[email protected]398ad132013-04-02 15:11:0183} // namespace
84
85namespace disk_cache {
86
[email protected]18b5b262013-11-19 18:41:3787const int kDefaultCacheSize = 80 * 1024 * 1024;
88
Matt Menkeb0f4c7c2018-07-06 19:25:3089const base::Feature kChangeDiskCacheSizeExperiment{
90 "ChangeDiskCacheSize", base::FEATURE_DISABLED_BY_DEFAULT};
91
[email protected]76ed979ee2013-07-17 15:50:4592void DeleteCache(const base::FilePath& path, bool remove_folder) {
93 if (remove_folder) {
94 if (!base::DeleteFile(path, /* recursive */ true))
95 LOG(WARNING) << "Unable to delete cache folder.";
96 return;
97 }
98
99 base::FileEnumerator iter(
100 path,
101 /* recursive */ false,
102 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
103 for (base::FilePath file = iter.Next(); !file.value().empty();
104 file = iter.Next()) {
105 if (!base::DeleteFile(file, /* recursive */ true)) {
106 LOG(WARNING) << "Unable to delete cache.";
107 return;
108 }
109 }
110}
111
[email protected]398ad132013-04-02 15:11:01112// In order to process a potentially large number of files, we'll rename the
113// cache directory to old_ + original_name + number, (located on the same parent
114// directory), and use a worker thread to delete all the files on all the stale
115// cache directories. The whole process can still fail if we are not able to
116// rename the cache directory (for instance due to a sharing violation), and in
117// that case a cache for this profile (on the desired path) cannot be created.
118bool DelayedCacheCleanup(const base::FilePath& full_path) {
119 // GetTempCacheName() and MoveCache() use synchronous file
120 // operations.
121 base::ThreadRestrictions::ScopedAllowIO allow_io;
122
123 base::FilePath current_path = full_path.StripTrailingSeparators();
124
125 base::FilePath path = current_path.DirName();
126 base::FilePath name = current_path.BaseName();
Fabrice de Gans-Riberi7de47372018-05-08 20:23:47127#if defined(OS_WIN)
[email protected]398ad132013-04-02 15:11:01128 // We created this file so it should only contain ASCII.
[email protected]74f778e2014-03-14 21:11:46129 std::string name_str = base::UTF16ToASCII(name.value());
Fabrice de Gans-Riberi7de47372018-05-08 20:23:47130#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
131 std::string name_str = name.value();
[email protected]398ad132013-04-02 15:11:01132#endif
133
134 base::FilePath to_delete = GetTempCacheName(path, name_str);
135 if (to_delete.empty()) {
136 LOG(ERROR) << "Unable to get another cache folder";
137 return false;
138 }
139
140 if (!disk_cache::MoveCache(full_path, to_delete)) {
141 LOG(ERROR) << "Unable to move cache folder " << full_path.value() << " to "
142 << to_delete.value();
143 return false;
144 }
145
Sami Kyostila0b4314e2019-07-31 20:47:17146 base::PostTask(
147 FROM_HERE,
148 {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
149 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
150 base::BindOnce(&CleanupCallback, path, name_str));
[email protected]398ad132013-04-02 15:11:01151 return true;
152}
153
[email protected]18b5b262013-11-19 18:41:37154// Returns the preferred maximum number of bytes for the cache given the
155// number of available bytes.
avid0181f32015-12-10 19:41:47156int PreferredCacheSize(int64_t available) {
Matt Menkeb0f4c7c2018-07-06 19:25:30157 // Percent of cache size to use, relative to the default size. "100" means to
158 // use 100% of the default size.
159 int percent_relative_size;
160 std::map<std::string, std::string> params;
161 if (!base::GetFieldTrialParamsByFeature(
162 disk_cache::kChangeDiskCacheSizeExperiment, &params) ||
163 !base::StringToInt(params["percent_relative_size"],
164 &percent_relative_size) ||
165 percent_relative_size <= 0) {
166 percent_relative_size = 100;
167 }
168
169 // Cap scaling, as a safety check, to avoid overflow.
170 if (percent_relative_size > 200)
171 percent_relative_size = 200;
172
173 int64_t scaled_default_disk_cache_size =
174 static_cast<int64_t>(disk_cache::kDefaultCacheSize) *
175 percent_relative_size / 100;
[email protected]18b5b262013-11-19 18:41:37176 if (available < 0)
Matt Menkeb0f4c7c2018-07-06 19:25:30177 return static_cast<int32_t>(scaled_default_disk_cache_size);
178
179 int64_t preferred_cache_size = PreferredCacheSizeInternal(available);
180
181 // If the preferred cache size is less 20% of the available space, scale for
182 // the field trial, capping the scaled value at 20% of the available space.
183 if (preferred_cache_size < available / 5) {
184 preferred_cache_size = preferred_cache_size * percent_relative_size / 100;
185 if (preferred_cache_size > available / 5)
186 preferred_cache_size = available / 5;
187 }
[email protected]18b5b262013-11-19 18:41:37188
[email protected]18b5b262013-11-19 18:41:37189 // Limit cache size to somewhat less than kint32max to avoid potential
190 // integer overflows in cache backend implementations.
Matt Menkeb0f4c7c2018-07-06 19:25:30191 DCHECK_LT(scaled_default_disk_cache_size * 4,
192 std::numeric_limits<int32_t>::max());
avid0181f32015-12-10 19:41:47193 return static_cast<int32_t>(
Matt Menkeb0f4c7c2018-07-06 19:25:30194 std::min(preferred_cache_size,
195 static_cast<int64_t>(scaled_default_disk_cache_size * 4)));
[email protected]18b5b262013-11-19 18:41:37196}
197
[email protected]398ad132013-04-02 15:11:01198} // namespace disk_cache