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

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: Addressed nits Created 4 years, 3 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::vector<GURL>* used_urls,
136 std::vector<GURL>* unused_urls) {
137 DCHECK(thread_checker_.CalledOnValidThread());
138 DCHECK_NE(PrecacheReferrerHostEntry::kInvalidId, referrer_host_id);
139
140 // Flush any pending writes to the URL and referrer host tables.
141 Flush();
142
143 precache_url_table_.GetURLListForReferrerHost(referrer_host_id, used_urls,
144 unused_urls);
145 }
146
147 void PrecacheDatabase::RecordURLPrefetchMetrics(
148 const net::HttpResponseInfo& info,
149 const base::TimeDelta& latency) {
150 DCHECK(thread_checker_.CalledOnValidThread());
151
125 UMA_HISTOGRAM_TIMES("Precache.Latency.Prefetch", latency); 152 UMA_HISTOGRAM_TIMES("Precache.Latency.Prefetch", latency);
126 153
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."; 154 DCHECK(info.headers) << "The headers are required to get the freshness.";
139 if (info.headers) { 155 if (info.headers) {
140 UMA_HISTOGRAM_CUSTOM_COUNTS( 156 UMA_HISTOGRAM_CUSTOM_COUNTS(
141 "Precache.Freshness.Prefetch", 157 "Precache.Freshness.Prefetch",
142 info.headers->GetFreshnessLifetimes(info.response_time) 158 info.headers->GetFreshnessLifetimes(info.response_time)
143 .freshness.InSeconds(), 159 .freshness.InSeconds(),
144 base::TimeDelta::FromMinutes(5).InSeconds() /* min */, 160 base::TimeDelta::FromMinutes(5).InSeconds() /* min */,
145 base::TimeDelta::FromDays(356).InSeconds() /* max */, 161 base::TimeDelta::FromDays(356).InSeconds() /* max */,
146 100 /* bucket_count */); 162 100 /* bucket_count */);
147 } 163 }
164 }
148 165
149 if (info.was_cached && !precache_url_table_.HasURL(url)) { 166 void PrecacheDatabase::RecordURLPrefetch(const GURL& url,
150 // Since the precache came from the cache, and there's no entry in the URL 167 const std::string& referrer_host,
151 // table for the URL, this means that the resource was already in the cache 168 const base::Time& fetch_time,
152 // because of user browsing. Therefore, this precache won't be considered as 169 bool was_cached,
153 // precache-motivated since it had no significant effect (besides a possible 170 int64_t size) {
154 // revalidation and a change in the cache LRU priority). 171 DCHECK(thread_checker_.CalledOnValidThread());
172
173 if (!IsDatabaseAccessible()) {
174 // Don't track anything if unable to access the database.
155 return; 175 return;
156 } 176 }
157 177
158 if (!info.was_cached) { 178 if (buffered_urls_.find(url.spec()) != buffered_urls_.end()) {
179 // If the URL for this fetch is in the write buffer, then flush the write
180 // buffer.
181 Flush();
182 }
183
184 if (!was_cached) {
159 // The precache only counts as overhead if it was downloaded over the 185 // The precache only counts as overhead if it was downloaded over the
160 // network. 186 // network.
161 UMA_HISTOGRAM_COUNTS("Precache.DownloadedPrecacheMotivated", 187 UMA_HISTOGRAM_COUNTS("Precache.DownloadedPrecacheMotivated",
162 static_cast<base::HistogramBase::Sample>(size)); 188 static_cast<base::HistogramBase::Sample>(size));
163 } 189 }
164 190
165 // Use the URL table to keep track of URLs that are in the cache thanks to 191 // 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 192 // or already in the cache due to prior precaching are recorded as
167 // to |fetch_time|. 193 // precache-motivated. URLs that came from the cache and not recorded as
168 buffered_writes_.push_back( 194 // precached previously, were already in the cache because of user browsing.
169 base::Bind(&PrecacheURLTable::AddURL, 195 // Therefore, this precache will not be considered as precache-motivated,
170 base::Unretained(&precache_url_table_), url, fetch_time)); 196 // since it had no significant effect (besides a possible revalidation and a
197 // change in the cache LRU priority). If a row for the URL already exists,
198 // then the timestamp is updated.
199 buffered_writes_.push_back(base::Bind(
200 &PrecacheDatabase::RecordURLPrefetchInternal, GetWeakPtr(), url,
201 referrer_host, !was_cached || precache_url_table_.IsURLPrecached(url),
202 fetch_time));
171 buffered_urls_.insert(url.spec()); 203 buffered_urls_.insert(url.spec());
172 MaybePostFlush(); 204 MaybePostFlush();
173 } 205 }
174 206
207 void PrecacheDatabase::RecordURLPrefetchInternal(
208 const GURL& url,
209 const std::string& referrer_host,
210 bool is_precached,
211 const base::Time& fetch_time) {
212 auto referrer_host_id = precache_referrer_host_table_.UpdateReferrerHost(
213 referrer_host, 0, fetch_time);
214 DCHECK_NE(referrer_host_id, PrecacheReferrerHostEntry::kInvalidId);
215 precache_url_table_.AddURL(url, referrer_host_id, is_precached, fetch_time);
216 }
217
175 void PrecacheDatabase::RecordURLNonPrefetch(const GURL& url, 218 void PrecacheDatabase::RecordURLNonPrefetch(const GURL& url,
176 const base::TimeDelta& latency, 219 const base::TimeDelta& latency,
177 const base::Time& fetch_time, 220 const base::Time& fetch_time,
178 const net::HttpResponseInfo& info, 221 const net::HttpResponseInfo& info,
179 int64_t size, 222 int64_t size,
180 int host_rank, 223 int host_rank,
181 bool is_connection_cellular) { 224 bool is_connection_cellular) {
182 UMA_HISTOGRAM_TIMES("Precache.Latency.NonPrefetch", latency); 225 UMA_HISTOGRAM_TIMES("Precache.Latency.NonPrefetch", latency);
183 UMA_HISTOGRAM_ENUMERATION("Precache.CacheStatus.NonPrefetch", 226 UMA_HISTOGRAM_ENUMERATION("Precache.CacheStatus.NonPrefetch",
184 info.cache_entry_status, 227 info.cache_entry_status,
(...skipping 15 matching lines...) Expand all
200 } 243 }
201 244
202 RecordTimeSinceLastPrecache(fetch_time); 245 RecordTimeSinceLastPrecache(fetch_time);
203 246
204 if (buffered_urls_.find(url.spec()) != buffered_urls_.end()) { 247 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 248 // If the URL for this fetch is in the write buffer, then flush the write
206 // buffer. 249 // buffer.
207 Flush(); 250 Flush();
208 } 251 }
209 252
210 if (info.was_cached && !precache_url_table_.HasURL(url)) { 253 bool is_precached = precache_url_table_.IsURLPrecachedAndUnused(url);
254 if (info.was_cached && !is_precached) {
211 // Ignore cache hits that precache can't take credit for. 255 // Ignore cache hits that precache can't take credit for.
212 return; 256 return;
213 } 257 }
214 258
215 base::HistogramBase::Sample size_sample = 259 base::HistogramBase::Sample size_sample =
216 static_cast<base::HistogramBase::Sample>(size); 260 static_cast<base::HistogramBase::Sample>(size);
217 if (!info.was_cached) { 261 if (!info.was_cached) {
218 // The fetch was served over the network during user browsing, so count it 262 // The fetch was served over the network during user browsing, so count it
219 // as downloaded non-precache bytes. 263 // as downloaded non-precache bytes.
220 UMA_HISTOGRAM_COUNTS("Precache.DownloadedNonPrecache", size_sample); 264 UMA_HISTOGRAM_COUNTS("Precache.DownloadedNonPrecache", size_sample);
221 if (is_connection_cellular) { 265 if (is_connection_cellular) {
222 UMA_HISTOGRAM_COUNTS("Precache.DownloadedNonPrecache.Cellular", 266 UMA_HISTOGRAM_COUNTS("Precache.DownloadedNonPrecache.Cellular",
223 size_sample); 267 size_sample);
224 } 268 }
269 // Since the resource has been fetched during user browsing, mark the URL as
270 // used in the precache URL table, if any exists. The current fetch would
271 // have put this resource in the cache regardless of whether or not it was
272 // previously precached, so mark the URL as used.
273 buffered_writes_.push_back(
274 base::Bind(&PrecacheURLTable::SetURLAsNotPrecached,
275 base::Unretained(&precache_url_table_), url));
276 buffered_urls_.insert(url.spec());
277 MaybePostFlush();
225 } else { // info.was_cached. 278 } else { // info.was_cached.
226 // The fetch was served from the cache, and since there's an entry for this 279 // The fetch was served from the cache, and since there's an entry for this
227 // URL in the URL table, this means that the resource was served from the 280 // URL in the URL table, this means that the resource was served from the
228 // cache only because precaching put it there. Thus, precaching was helpful, 281 // cache only because precaching put it there. Thus, precaching was helpful,
229 // so count the fetch as saved bytes. 282 // so count the fetch as saved bytes.
230 UMA_HISTOGRAM_COUNTS("Precache.Saved", size_sample); 283 UMA_HISTOGRAM_COUNTS("Precache.Saved", size_sample);
231 if (is_connection_cellular) { 284 if (is_connection_cellular) {
232 UMA_HISTOGRAM_COUNTS("Precache.Saved.Cellular", size_sample); 285 UMA_HISTOGRAM_COUNTS("Precache.Saved.Cellular", size_sample);
233 } 286 }
234 287
235 DCHECK(info.headers) << "The headers are required to get the freshness."; 288 DCHECK(info.headers) << "The headers are required to get the freshness.";
236 if (info.headers) { 289 if (info.headers) {
237 // TODO(jamartin): Maybe report stale_while_validate as well. 290 // TODO(jamartin): Maybe report stale_while_validate as well.
238 UMA_HISTOGRAM_CUSTOM_COUNTS( 291 UMA_HISTOGRAM_CUSTOM_COUNTS(
239 "Precache.Saved.Freshness", 292 "Precache.Saved.Freshness",
240 info.headers->GetFreshnessLifetimes(info.response_time) 293 info.headers->GetFreshnessLifetimes(info.response_time)
241 .freshness.InSeconds(), 294 .freshness.InSeconds(),
242 base::TimeDelta::FromMinutes(5).InSeconds() /* min */, 295 base::TimeDelta::FromMinutes(5).InSeconds() /* min */,
243 base::TimeDelta::FromDays(356).InSeconds() /* max */, 296 base::TimeDelta::FromDays(356).InSeconds() /* max */,
244 100 /* bucket_count */); 297 100 /* bucket_count */);
245 } 298 }
299
300 buffered_writes_.push_back(
301 base::Bind(&PrecacheURLTable::SetPrecachedURLAsUsed,
302 base::Unretained(&precache_url_table_), url));
303 buffered_urls_.insert(url.spec());
304 MaybePostFlush();
305 }
306 }
307
308 void PrecacheDatabase::UpdatePrecacheReferrerHost(
309 const std::string& hostname,
310 int64_t manifest_id,
311 const base::Time& fetch_time) {
312 DCHECK(thread_checker_.CalledOnValidThread());
313
314 if (!IsDatabaseAccessible()) {
315 // Don't track anything if unable to access the database.
316 return;
246 } 317 }
247 318
248 // Since the resource has been fetched during user browsing, remove any record
249 // of that URL having been precached from the URL table, if any exists.
250 // The current fetch would have put this resource in the cache regardless of
251 // whether or not it was previously precached, so delete any record of that
252 // URL having been precached from the URL table.
253 buffered_writes_.push_back( 319 buffered_writes_.push_back(
254 base::Bind(&PrecacheURLTable::DeleteURL, 320 base::Bind(&PrecacheDatabase::UpdatePrecacheReferrerHostInternal,
255 base::Unretained(&precache_url_table_), url)); 321 GetWeakPtr(), hostname, manifest_id, fetch_time));
256 buffered_urls_.insert(url.spec());
257 MaybePostFlush(); 322 MaybePostFlush();
258 } 323 }
259 324
325 void PrecacheDatabase::UpdatePrecacheReferrerHostInternal(
326 const std::string& hostname,
327 int64_t manifest_id,
328 const base::Time& fetch_time) {
329 int64_t referrer_host_id = precache_referrer_host_table_.UpdateReferrerHost(
330 hostname, manifest_id, fetch_time);
331 if (referrer_host_id != PrecacheReferrerHostEntry::kInvalidId) {
332 precache_url_table_.ClearAllForReferrerHost(referrer_host_id);
333 }
334 }
335
260 void PrecacheDatabase::RecordTimeSinceLastPrecache( 336 void PrecacheDatabase::RecordTimeSinceLastPrecache(
261 const base::Time& fetch_time) { 337 const base::Time& fetch_time) {
262 const base::Time& last_precache_timestamp = GetLastPrecacheTimestamp(); 338 const base::Time& last_precache_timestamp = GetLastPrecacheTimestamp();
263 // It could still be null if the DB was not accessible. 339 // It could still be null if the DB was not accessible.
264 if (!last_precache_timestamp.is_null()) { 340 if (!last_precache_timestamp.is_null()) {
265 // This is the timespan (in seconds) between the last call to 341 // This is the timespan (in seconds) between the last call to
266 // PrecacheManager::StartPrecaching and the fetch time of a non-precache 342 // PrecacheManager::StartPrecaching and the fetch time of a non-precache
267 // URL. Please note that the session started by that call to 343 // URL. Please note that the session started by that call to
268 // PrecacheManager::StartPrecaching may not have precached this particular 344 // PrecacheManager::StartPrecaching may not have precached this particular
269 // URL or even any URL for that matter. 345 // URL or even any URL for that matter.
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 428
353 void PrecacheDatabase::DeleteUnfinishedWork() { 429 void PrecacheDatabase::DeleteUnfinishedWork() {
354 precache_session_table_.DeleteUnfinishedWork(); 430 precache_session_table_.DeleteUnfinishedWork();
355 } 431 }
356 432
357 base::WeakPtr<PrecacheDatabase> PrecacheDatabase::GetWeakPtr() { 433 base::WeakPtr<PrecacheDatabase> PrecacheDatabase::GetWeakPtr() {
358 return weak_factory_.GetWeakPtr(); 434 return weak_factory_.GetWeakPtr();
359 } 435 }
360 436
361 } // namespace precache 437 } // namespace precache
OLDNEW
« no previous file with comments | « components/precache/core/precache_database.h ('k') | components/precache/core/precache_database_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698