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

Side by Side Diff: components/precache/core/precache_database.cc

Issue 2229983002: Send the list of used and unused resources for precache (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "components/precache/core/precache_database.h" 5 #include "components/precache/core/precache_database.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/metrics/histogram_macros.h" 10 #include "base/metrics/histogram_macros.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 db_.reset(new sql::Connection()); 51 db_.reset(new sql::Connection());
52 db_->set_histogram_tag("Precache"); 52 db_->set_histogram_tag("Precache");
53 53
54 if (!db_->Open(db_path)) { 54 if (!db_->Open(db_path)) {
55 // Don't initialize the URL table if unable to access 55 // Don't initialize the URL table if unable to access
56 // the database. 56 // the database.
57 return false; 57 return false;
58 } 58 }
59 59
60 if (!precache_url_table_.Init(db_.get()) || 60 if (!precache_url_table_.Init(db_.get()) ||
61 !precache_referrer_host_table_.Init(db_.get()) ||
61 !precache_session_table_.Init(db_.get())) { 62 !precache_session_table_.Init(db_.get())) {
62 // Raze and close the database connection to indicate that it's not usable, 63 // Raze and close the database connection to indicate that it's not usable,
63 // and so that the database will be created anew next time, in case it's 64 // and so that the database will be created anew next time, in case it's
64 // corrupted. 65 // corrupted.
65 db_->RazeAndClose(); 66 db_->RazeAndClose();
66 return false; 67 return false;
67 } 68 }
68 return true; 69 return true;
69 } 70 }
70 71
71 void PrecacheDatabase::DeleteExpiredPrecacheHistory( 72 void PrecacheDatabase::DeleteExpiredPrecacheHistory(
72 const base::Time& current_time) { 73 const base::Time& current_time) {
73 if (!IsDatabaseAccessible()) { 74 if (!IsDatabaseAccessible()) {
74 // Do nothing if unable to access the database. 75 // Do nothing if unable to access the database.
75 return; 76 return;
76 } 77 }
77 78
78 // Delete old precache history that has expired. 79 // Delete old precache history that has expired.
79 base::Time delete_end = current_time - base::TimeDelta::FromDays( 80 base::Time delete_end = current_time - base::TimeDelta::FromDays(
80 kPrecacheHistoryExpiryPeriodDays); 81 kPrecacheHistoryExpiryPeriodDays);
81 buffered_writes_.push_back( 82 buffered_writes_.push_back(
82 base::Bind(&PrecacheURLTable::DeleteAllPrecachedBefore, 83 base::Bind(&PrecacheURLTable::DeleteAllPrecachedBefore,
83 base::Unretained(&precache_url_table_), delete_end)); 84 base::Unretained(&precache_url_table_), delete_end));
85 buffered_writes_.push_back(
86 base::Bind(&PrecacheReferrerHostTable::DeleteAllEntriesBefore,
87 base::Unretained(&precache_referrer_host_table_), delete_end));
84 Flush(); 88 Flush();
85 } 89 }
86 90
87 void PrecacheDatabase::ClearHistory() { 91 void PrecacheDatabase::ClearHistory() {
88 if (!IsDatabaseAccessible()) { 92 if (!IsDatabaseAccessible()) {
89 // Do nothing if unable to access the database. 93 // Do nothing if unable to access the database.
90 return; 94 return;
91 } 95 }
92 96
93 buffered_writes_.push_back(base::Bind( 97 buffered_writes_.push_back(base::Bind(
94 &PrecacheURLTable::DeleteAll, base::Unretained(&precache_url_table_))); 98 &PrecacheURLTable::DeleteAll, base::Unretained(&precache_url_table_)));
99 buffered_writes_.push_back(
100 base::Bind(&PrecacheReferrerHostTable::DeleteAll,
101 base::Unretained(&precache_referrer_host_table_)));
95 Flush(); 102 Flush();
96 } 103 }
97 104
98 void PrecacheDatabase::SetLastPrecacheTimestamp(const base::Time& time) { 105 void PrecacheDatabase::SetLastPrecacheTimestamp(const base::Time& time) {
99 last_precache_timestamp_ = time; 106 last_precache_timestamp_ = time;
100 107
101 if (!IsDatabaseAccessible()) { 108 if (!IsDatabaseAccessible()) {
102 // Do nothing if unable to access the database. 109 // Do nothing if unable to access the database.
103 return; 110 return;
104 } 111 }
105 112
106 buffered_writes_.push_back( 113 buffered_writes_.push_back(
107 base::Bind(&PrecacheSessionTable::SetLastPrecacheTimestamp, 114 base::Bind(&PrecacheSessionTable::SetLastPrecacheTimestamp,
108 base::Unretained(&precache_session_table_), time)); 115 base::Unretained(&precache_session_table_), time));
109 MaybePostFlush(); 116 MaybePostFlush();
110 } 117 }
111 118
112 base::Time PrecacheDatabase::GetLastPrecacheTimestamp() { 119 base::Time PrecacheDatabase::GetLastPrecacheTimestamp() {
113 if (last_precache_timestamp_.is_null() && IsDatabaseAccessible()) { 120 if (last_precache_timestamp_.is_null() && IsDatabaseAccessible()) {
114 last_precache_timestamp_ = 121 last_precache_timestamp_ =
115 precache_session_table_.GetLastPrecacheTimestamp(); 122 precache_session_table_.GetLastPrecacheTimestamp();
116 } 123 }
117 return last_precache_timestamp_; 124 return last_precache_timestamp_;
118 } 125 }
119 126
120 void PrecacheDatabase::RecordURLPrefetch(const GURL& url, 127 PrecacheReferrerHostEntry PrecacheDatabase::GetReferrerHost(
121 const base::TimeDelta& latency, 128 const std::string& referrer_host) {
122 const base::Time& fetch_time, 129 DCHECK(thread_checker_.CalledOnValidThread());
123 const net::HttpResponseInfo& info, 130 return precache_referrer_host_table_.GetReferrerHost(referrer_host);
124 int64_t size) { 131 }
132
133 void PrecacheDatabase::GetURLListForReferrerHost(
134 int64_t referrer_host_id,
135 std::deque<GURL>& used_urls,
136 std::deque<GURL>& unused_urls) {
137 DCHECK_NE(PrecacheReferrerHostEntry::INVALID_ID, referrer_host_id);
138 precache_url_table_.GetURLListForReferrerHost(referrer_host_id, used_urls,
139 unused_urls);
140 }
141
142 void PrecacheDatabase::RecordURLPrefetchMetrics(
143 const net::HttpResponseInfo& info,
144 const base::TimeDelta& latency) {
145 DCHECK(thread_checker_.CalledOnValidThread());
146
125 UMA_HISTOGRAM_TIMES("Precache.Latency.Prefetch", latency); 147 UMA_HISTOGRAM_TIMES("Precache.Latency.Prefetch", latency);
126 148
127 if (!IsDatabaseAccessible()) {
128 // Don't track anything if unable to access the database.
129 return;
130 }
131
132 if (buffered_urls_.find(url.spec()) != buffered_urls_.end()) {
133 // If the URL for this fetch is in the write buffer, then flush the write
134 // buffer.
135 Flush();
136 }
137
138 DCHECK(info.headers) << "The headers are required to get the freshness."; 149 DCHECK(info.headers) << "The headers are required to get the freshness.";
139 if (info.headers) { 150 if (info.headers) {
140 UMA_HISTOGRAM_CUSTOM_COUNTS( 151 UMA_HISTOGRAM_CUSTOM_COUNTS(
141 "Precache.Freshness.Prefetch", 152 "Precache.Freshness.Prefetch",
142 info.headers->GetFreshnessLifetimes(info.response_time) 153 info.headers->GetFreshnessLifetimes(info.response_time)
143 .freshness.InSeconds(), 154 .freshness.InSeconds(),
144 base::TimeDelta::FromMinutes(5).InSeconds() /* min */, 155 base::TimeDelta::FromMinutes(5).InSeconds() /* min */,
145 base::TimeDelta::FromDays(356).InSeconds() /* max */, 156 base::TimeDelta::FromDays(356).InSeconds() /* max */,
146 100 /* bucket_count */); 157 100 /* bucket_count */);
147 } 158 }
159 }
148 160
149 if (info.was_cached && !precache_url_table_.HasURL(url)) { 161 void PrecacheDatabase::RecordURLPrefetch(const GURL& url,
150 // Since the precache came from the cache, and there's no entry in the URL 162 const std::string& referrer_host,
151 // table for the URL, this means that the resource was already in the cache 163 const base::Time& fetch_time,
152 // because of user browsing. Therefore, this precache won't be considered as 164 bool was_cached,
153 // precache-motivated since it had no significant effect (besides a possible 165 int64_t size) {
154 // revalidation and a change in the cache LRU priority). 166 DCHECK(thread_checker_.CalledOnValidThread());
167
168 if (!IsDatabaseAccessible()) {
169 // Don't track anything if unable to access the database.
155 return; 170 return;
156 } 171 }
157 172
158 if (!info.was_cached) { 173 if (buffered_urls_.find(url.spec()) != buffered_urls_.end()) {
174 // If the URL for this fetch is in the write buffer, then flush the write
175 // buffer.
176 Flush();
177 }
178
179 if (!was_cached) {
159 // The precache only counts as overhead if it was downloaded over the 180 // The precache only counts as overhead if it was downloaded over the
160 // network. 181 // network.
161 UMA_HISTOGRAM_COUNTS("Precache.DownloadedPrecacheMotivated", 182 UMA_HISTOGRAM_COUNTS("Precache.DownloadedPrecacheMotivated",
162 static_cast<base::HistogramBase::Sample>(size)); 183 static_cast<base::HistogramBase::Sample>(size));
163 } 184 }
164 185
165 // Use the URL table to keep track of URLs that are in the cache thanks to 186 // Use the URL table to keep track of URLs. URLs that are fetched via network
166 // precaching. If a row for the URL already exists, than update the timestamp 187 // or already in the cache due to prior precaching are recorded as
167 // to |fetch_time|. 188 // precache-motivated. URLs that came from the cache and not recorded as
168 buffered_writes_.push_back( 189 // precached previously, were already in the cache because of user browsing.
169 base::Bind(&PrecacheURLTable::AddURL, 190 // Therefore, this precache will not be considered as precache-motivated,
170 base::Unretained(&precache_url_table_), url, fetch_time)); 191 // since it had no significant effect (besides a possible revalidation and a
192 // change in the cache LRU priority). If a row for the URL already exists,
193 // then the timestamp is updated.
194 buffered_writes_.push_back(base::Bind(
195 &PrecacheDatabase::RecordURLPrefetchInternal, GetWeakPtr(), url,
196 referrer_host, !was_cached || precache_url_table_.IsURLPrecached(url),
197 fetch_time));
171 buffered_urls_.insert(url.spec()); 198 buffered_urls_.insert(url.spec());
172 MaybePostFlush(); 199 MaybePostFlush();
173 } 200 }
174 201
202 void PrecacheDatabase::RecordURLPrefetchInternal(
203 const GURL& url,
204 const std::string& referrer_host,
205 bool is_precached,
206 const base::Time& fetch_time) {
207 auto referrer_host_id =
208 precache_referrer_host_table_.GetReferrerHost(referrer_host).id;
209 if (referrer_host_id == PrecacheReferrerHostEntry::INVALID_ID) {
210 referrer_host_id = precache_referrer_host_table_.UpdateReferrerHost(
211 referrer_host, 0, fetch_time);
212 DCHECK_NE(referrer_host_id, PrecacheReferrerHostEntry::INVALID_ID);
213 }
214 precache_url_table_.AddURL(url, referrer_host_id, is_precached, fetch_time);
215 }
216
175 void PrecacheDatabase::RecordURLNonPrefetch(const GURL& url, 217 void PrecacheDatabase::RecordURLNonPrefetch(const GURL& url,
176 const base::TimeDelta& latency, 218 const base::TimeDelta& latency,
177 const base::Time& fetch_time, 219 const base::Time& fetch_time,
178 const net::HttpResponseInfo& info, 220 const net::HttpResponseInfo& info,
179 int64_t size, 221 int64_t size,
180 int host_rank, 222 int host_rank,
181 bool is_connection_cellular) { 223 bool is_connection_cellular) {
182 UMA_HISTOGRAM_TIMES("Precache.Latency.NonPrefetch", latency); 224 UMA_HISTOGRAM_TIMES("Precache.Latency.NonPrefetch", latency);
183 UMA_HISTOGRAM_ENUMERATION("Precache.CacheStatus.NonPrefetch", 225 UMA_HISTOGRAM_ENUMERATION("Precache.CacheStatus.NonPrefetch",
184 info.cache_entry_status, 226 info.cache_entry_status,
(...skipping 15 matching lines...) Expand all
200 } 242 }
201 243
202 RecordTimeSinceLastPrecache(fetch_time); 244 RecordTimeSinceLastPrecache(fetch_time);
203 245
204 if (buffered_urls_.find(url.spec()) != buffered_urls_.end()) { 246 if (buffered_urls_.find(url.spec()) != buffered_urls_.end()) {
205 // If the URL for this fetch is in the write buffer, then flush the write 247 // If the URL for this fetch is in the write buffer, then flush the write
206 // buffer. 248 // buffer.
207 Flush(); 249 Flush();
208 } 250 }
209 251
210 if (info.was_cached && !precache_url_table_.HasURL(url)) { 252 bool is_precached = precache_url_table_.IsURLPrecachedAndUnused(url);
253 if (info.was_cached && !is_precached) {
211 // Ignore cache hits that precache can't take credit for. 254 // Ignore cache hits that precache can't take credit for.
212 return; 255 return;
213 } 256 }
214 257
215 base::HistogramBase::Sample size_sample = 258 base::HistogramBase::Sample size_sample =
216 static_cast<base::HistogramBase::Sample>(size); 259 static_cast<base::HistogramBase::Sample>(size);
217 if (!info.was_cached) { 260 if (!info.was_cached) {
218 // The fetch was served over the network during user browsing, so count it 261 // The fetch was served over the network during user browsing, so count it
219 // as downloaded non-precache bytes. 262 // as downloaded non-precache bytes.
220 UMA_HISTOGRAM_COUNTS("Precache.DownloadedNonPrecache", size_sample); 263 UMA_HISTOGRAM_COUNTS("Precache.DownloadedNonPrecache", size_sample);
(...skipping 17 matching lines...) Expand all
238 UMA_HISTOGRAM_CUSTOM_COUNTS( 281 UMA_HISTOGRAM_CUSTOM_COUNTS(
239 "Precache.Saved.Freshness", 282 "Precache.Saved.Freshness",
240 info.headers->GetFreshnessLifetimes(info.response_time) 283 info.headers->GetFreshnessLifetimes(info.response_time)
241 .freshness.InSeconds(), 284 .freshness.InSeconds(),
242 base::TimeDelta::FromMinutes(5).InSeconds() /* min */, 285 base::TimeDelta::FromMinutes(5).InSeconds() /* min */,
243 base::TimeDelta::FromDays(356).InSeconds() /* max */, 286 base::TimeDelta::FromDays(356).InSeconds() /* max */,
244 100 /* bucket_count */); 287 100 /* bucket_count */);
245 } 288 }
246 } 289 }
247 290
248 // Since the resource has been fetched during user browsing, remove any record 291 if (is_precached) {
249 // of that URL having been precached from the URL table, if any exists. 292 // Since the resource has been fetched during user browsing, mark the URL as
250 // The current fetch would have put this resource in the cache regardless of 293 // used in the precache URL table, if any exists. The current fetch would
251 // whether or not it was previously precached, so delete any record of that 294 // have put this resource in the cache regardless of whether or not it was
252 // URL having been precached from the URL table. 295 // previously precached, so mark the URL as used.
296 buffered_writes_.push_back(
297 base::Bind(&PrecacheURLTable::SetPrecachedURLAsUsed,
298 base::Unretained(&precache_url_table_), url));
299 buffered_urls_.insert(url.spec());
300 MaybePostFlush();
301 }
302 }
303
304 void PrecacheDatabase::UpdatePrecacheReferrerHost(
305 const std::string& hostname,
306 int64_t manifest_id,
307 const base::Time& fetch_time) {
308 DCHECK(thread_checker_.CalledOnValidThread());
309
310 if (!IsDatabaseAccessible()) {
311 // Don't track anything if unable to access the database.
312 return;
313 }
314
253 buffered_writes_.push_back( 315 buffered_writes_.push_back(
254 base::Bind(&PrecacheURLTable::DeleteURL, 316 base::Bind(&PrecacheDatabase::UpdatePrecacheReferrerHostInternal,
255 base::Unretained(&precache_url_table_), url)); 317 GetWeakPtr(), hostname, manifest_id, fetch_time));
256 buffered_urls_.insert(url.spec());
257 MaybePostFlush(); 318 MaybePostFlush();
258 } 319 }
259 320
321 void PrecacheDatabase::UpdatePrecacheReferrerHostInternal(
322 const std::string& hostname,
323 int64_t manifest_id,
324 const base::Time& fetch_time) {
325 precache_referrer_host_table_.UpdateReferrerHost(hostname, manifest_id,
326 fetch_time);
327 }
328
260 void PrecacheDatabase::RecordTimeSinceLastPrecache( 329 void PrecacheDatabase::RecordTimeSinceLastPrecache(
261 const base::Time& fetch_time) { 330 const base::Time& fetch_time) {
262 const base::Time& last_precache_timestamp = GetLastPrecacheTimestamp(); 331 const base::Time& last_precache_timestamp = GetLastPrecacheTimestamp();
263 // It could still be null if the DB was not accessible. 332 // It could still be null if the DB was not accessible.
264 if (!last_precache_timestamp.is_null()) { 333 if (!last_precache_timestamp.is_null()) {
265 // This is the timespan (in seconds) between the last call to 334 // This is the timespan (in seconds) between the last call to
266 // PrecacheManager::StartPrecaching and the fetch time of a non-precache 335 // PrecacheManager::StartPrecaching and the fetch time of a non-precache
267 // URL. Please note that the session started by that call to 336 // URL. Please note that the session started by that call to
268 // PrecacheManager::StartPrecaching may not have precached this particular 337 // PrecacheManager::StartPrecaching may not have precached this particular
269 // URL or even any URL for that matter. 338 // URL or even any URL for that matter.
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 421
353 void PrecacheDatabase::DeleteUnfinishedWork() { 422 void PrecacheDatabase::DeleteUnfinishedWork() {
354 precache_session_table_.DeleteUnfinishedWork(); 423 precache_session_table_.DeleteUnfinishedWork();
355 } 424 }
356 425
357 base::WeakPtr<PrecacheDatabase> PrecacheDatabase::GetWeakPtr() { 426 base::WeakPtr<PrecacheDatabase> PrecacheDatabase::GetWeakPtr() {
358 return weak_factory_.GetWeakPtr(); 427 return weak_factory_.GetWeakPtr();
359 } 428 }
360 429
361 } // namespace precache 430 } // namespace precache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698