Revert 168224 - Update V8 to version 3.15.4.
[chromium-blink-merge.git] / chrome / browser / predictors / resource_prefetch_predictor_tables.cc
blobe4172503ddf79abcc3e4678565d03e52490baa80
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.
5 #include "chrome/browser/predictors/resource_prefetch_predictor_tables.h"
7 #include "base/logging.h"
8 #include "base/metrics/histogram.h"
9 #include "base/stringprintf.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "sql/statement.h"
13 using content::BrowserThread;
15 namespace {
17 const char kUrlResourceTableName[] = "resource_prefetch_predictor_url";
18 const char kUrlMetadataTableName[] = "resource_prefetch_predictor_url_metadata";
20 // The maximum length allowed for strings in the database.
21 const size_t kMaxURLLength = 2048;
23 std::string MaybeTrimUrl(const GURL& url, bool is_main_frame_url) {
24 std::string spec = url.spec();
25 if (spec.length() > kMaxURLLength) {
26 if (is_main_frame_url) {
27 UMA_HISTOGRAM_BOOLEAN("ResourcePrefetchPredictor.MainFrameUrlTooLong",
28 true);
29 } else {
30 UMA_HISTOGRAM_BOOLEAN("ResourcePrefetchPredictor.ResourceUrlTooLong",
31 true);
33 return spec.substr(0, kMaxURLLength);
35 return spec;
38 void BindUrlResourceRowToStatement(
39 const predictors::ResourcePrefetchPredictorTables::UrlResourceRow& row,
40 sql::Statement* statement) {
41 statement->BindString(0, MaybeTrimUrl(row.main_frame_url, true));
42 statement->BindString(1, MaybeTrimUrl(row.resource_url, false));
43 statement->BindInt(2, static_cast<int>(row.resource_type));
44 statement->BindInt(3, row.number_of_hits);
45 statement->BindInt(4, row.number_of_misses);
46 statement->BindInt(5, row.consecutive_misses);
47 statement->BindDouble(6, row.average_position);
50 bool StepAndInitializeUrlResourceRow(
51 sql::Statement* statement,
52 predictors::ResourcePrefetchPredictorTables::UrlResourceRow* row) {
53 if (!statement->Step())
54 return false;
56 row->main_frame_url = GURL(statement->ColumnString(0));
57 row->resource_url = GURL(statement->ColumnString(1));
58 row->resource_type = ResourceType::FromInt(statement->ColumnInt(2));
59 row->number_of_hits = statement->ColumnInt(3);
60 row->number_of_misses = statement->ColumnInt(4);
61 row->consecutive_misses = statement->ColumnInt(5);
62 row->average_position = statement->ColumnDouble(6);
63 return true;
66 } // namespace
68 namespace predictors {
70 ResourcePrefetchPredictorTables::UrlResourceRow::UrlResourceRow()
71 : resource_type(ResourceType::LAST_TYPE),
72 number_of_hits(0),
73 number_of_misses(0),
74 consecutive_misses(0),
75 average_position(0.0),
76 score(0.0) {
79 ResourcePrefetchPredictorTables::UrlResourceRow::UrlResourceRow(
80 const UrlResourceRow& other)
81 : main_frame_url(other.main_frame_url),
82 resource_url(other.resource_url),
83 resource_type(other.resource_type),
84 number_of_hits(other.number_of_hits),
85 number_of_misses(other.number_of_misses),
86 consecutive_misses(other.consecutive_misses),
87 average_position(other.average_position),
88 score(other.score) {
91 ResourcePrefetchPredictorTables::UrlResourceRow::UrlResourceRow(
92 const std::string& i_main_frame_url,
93 const std::string& i_resource_url,
94 ResourceType::Type i_resource_type,
95 int i_number_of_hits,
96 int i_number_of_misses,
97 int i_consecutive_misses,
98 double i_average_position)
99 : main_frame_url(i_main_frame_url),
100 resource_url(i_resource_url),
101 resource_type(i_resource_type),
102 number_of_hits(i_number_of_hits),
103 number_of_misses(i_number_of_misses),
104 consecutive_misses(i_consecutive_misses),
105 average_position(i_average_position) {
106 UpdateScore();
109 void ResourcePrefetchPredictorTables::UrlResourceRow::UpdateScore() {
110 // The score is calculated so that when the rows are sorted, the stylesheets
111 // and scripts appear first, sorted by position(ascending) and then the rest
112 // of the resources sorted by position(ascending).
113 static const int kMaxResourcesPerType = 100;
114 switch (resource_type) {
115 case ResourceType::STYLESHEET:
116 case ResourceType::SCRIPT:
117 score = (2 * kMaxResourcesPerType) - average_position;
118 break;
120 case ResourceType::IMAGE:
121 score = kMaxResourcesPerType - average_position;
122 break;
124 default:
125 score = kMaxResourcesPerType - average_position;
126 break;
130 bool ResourcePrefetchPredictorTables::UrlResourceRow::operator==(
131 const UrlResourceRow& rhs) const {
132 return main_frame_url == rhs.main_frame_url &&
133 resource_url == rhs.resource_url &&
134 resource_type == rhs.resource_type &&
135 number_of_hits == rhs.number_of_hits &&
136 number_of_misses == rhs.number_of_misses &&
137 consecutive_misses == rhs.consecutive_misses &&
138 average_position == rhs.average_position &&
139 score == rhs.score;
142 bool ResourcePrefetchPredictorTables::UrlResourceRowSorter::operator()(
143 const UrlResourceRow& x, const UrlResourceRow& y) const {
144 return x.score > y.score;
147 ResourcePrefetchPredictorTables::UrlData::UrlData(const GURL& i_main_frame_url)
148 : main_frame_url(i_main_frame_url) {
151 ResourcePrefetchPredictorTables::UrlData::UrlData(const UrlData& other)
152 : main_frame_url(other.main_frame_url),
153 last_visit(other.last_visit),
154 resources(other.resources) {
157 ResourcePrefetchPredictorTables::UrlData::~UrlData() {
160 bool ResourcePrefetchPredictorTables::UrlData::operator==(
161 const UrlData& rhs) const {
162 return main_frame_url == rhs.main_frame_url &&
163 resources == rhs.resources;
166 ResourcePrefetchPredictorTables::ResourcePrefetchPredictorTables()
167 : PredictorTableBase() {
170 ResourcePrefetchPredictorTables::~ResourcePrefetchPredictorTables() {
173 void ResourcePrefetchPredictorTables::GetAllUrlData(
174 std::vector<UrlData>* url_data_buffer) {
175 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
176 if (CantAccessDatabase())
177 return;
179 CHECK(url_data_buffer && url_data_buffer->empty());
181 // First read the resources table and organize it per main_frame_url.
182 sql::Statement resource_reader(DB()->GetCachedStatement(SQL_FROM_HERE,
183 base::StringPrintf("SELECT * FROM %s", kUrlResourceTableName).c_str()));
184 std::map<GURL, size_t> url_index;
185 UrlResourceRow url_row;
186 while (StepAndInitializeUrlResourceRow(&resource_reader, &url_row)) {
187 url_row.UpdateScore();
189 if (url_index.find(url_row.main_frame_url) == url_index.end()) {
190 url_index[url_row.main_frame_url] = url_data_buffer->size();
191 url_data_buffer->push_back(UrlData(url_row.main_frame_url));
193 url_data_buffer->at(url_index[url_row.main_frame_url]).resources.push_back(
194 url_row);
197 // Read the metadata and keep track of Urls that have metadata, but no
198 // resource entries, so they can be deleted.
199 std::vector<GURL> urls_to_delete;
201 sql::Statement metadata_reader(DB()->GetCachedStatement(SQL_FROM_HERE,
202 base::StringPrintf("SELECT * FROM %s", kUrlMetadataTableName).c_str()));
203 while (metadata_reader.Step()) {
204 GURL main_frame_url = GURL(metadata_reader.ColumnString(0));
205 if (url_index.find(main_frame_url) != url_index.end()) {
206 int64 last_visit = metadata_reader.ColumnInt64(1);
207 url_data_buffer->at(url_index[main_frame_url]).last_visit =
208 base::Time::FromInternalValue(last_visit);
209 } else {
210 urls_to_delete.push_back(main_frame_url);
214 // Delete rows in the UrlMetadataTable for which there are no resources.
215 if (!urls_to_delete.empty())
216 DeleteDataForUrls(urls_to_delete);
219 void ResourcePrefetchPredictorTables::UpdateDataForUrl(
220 const UrlData& url_data) {
221 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
222 if (CantAccessDatabase())
223 return;
225 // Sanitize the url.
226 const std::string main_frame_url = MaybeTrimUrl(url_data.main_frame_url,
227 true);
229 DB()->BeginTransaction();
231 // Delete the older data from both the tables.
232 sql::Statement resource_deleter(DB()->GetCachedStatement(
233 SQL_FROM_HERE,
234 base::StringPrintf("DELETE FROM %s WHERE main_page_url=?",
235 kUrlResourceTableName).c_str()));
236 resource_deleter.BindString(0, main_frame_url);
237 sql::Statement url_deleter(DB()->GetCachedStatement(
238 SQL_FROM_HERE,
239 base::StringPrintf("DELETE FROM %s WHERE main_page_url=?",
240 kUrlMetadataTableName).c_str()));
241 url_deleter.BindString(0, main_frame_url);
242 if (!resource_deleter.Run() || !url_deleter.Run()) {
243 DB()->RollbackTransaction();
244 return;
247 // Add the new data to the tables.
248 const UrlResourceRows& resources = url_data.resources;
249 for (UrlResourceRows::const_iterator it = resources.begin();
250 it != resources.end(); ++it) {
251 sql::Statement resource_inserter(
252 DB()->GetCachedStatement(
253 SQL_FROM_HERE,
254 base::StringPrintf(
255 "INSERT INTO %s "
256 "(main_page_url, resource_url, resource_type, number_of_hits, "
257 "number_of_misses, consecutive_misses, average_position) "
258 "VALUES (?,?,?,?,?,?,?)",
259 kUrlResourceTableName).c_str()));
260 BindUrlResourceRowToStatement(*it, &resource_inserter);
261 if (!resource_inserter.Run()) {
262 DB()->RollbackTransaction();
263 return;
267 sql::Statement metadata_inserter(DB()->GetCachedStatement(
268 SQL_FROM_HERE,
269 base::StringPrintf("INSERT INTO %s (main_page_url, last_visit_time) "
270 "VALUES (?,?)", kUrlMetadataTableName).c_str()));
271 metadata_inserter.BindString(0,main_frame_url);
272 metadata_inserter.BindInt64(1, url_data.last_visit.ToInternalValue());
273 if (!metadata_inserter.Run()) {
274 DB()->RollbackTransaction();
275 return;
278 DB()->CommitTransaction();
281 void ResourcePrefetchPredictorTables::DeleteDataForUrls(
282 const std::vector<GURL>& urls) {
283 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
284 if (CantAccessDatabase())
285 return;
287 for (std::vector<GURL>::const_iterator it = urls.begin(); it != urls.end();
288 ++it) {
289 sql::Statement resource_deleter(DB()->GetCachedStatement(
290 SQL_FROM_HERE,
291 base::StringPrintf("DELETE FROM %s WHERE main_page_url=?",
292 kUrlResourceTableName).c_str()));
293 resource_deleter.BindString(0, it->spec());
294 resource_deleter.Run();
296 sql::Statement url_deleter(DB()->GetCachedStatement(
297 SQL_FROM_HERE,
298 base::StringPrintf("DELETE FROM %s WHERE main_page_url=?",
299 kUrlMetadataTableName).c_str()));
300 url_deleter.BindString(0, it->spec());
301 url_deleter.Run();
305 void ResourcePrefetchPredictorTables::DeleteAllUrlData() {
306 if (CantAccessDatabase())
307 return;
309 sql::Statement resource_deleter(DB()->GetCachedStatement(
310 SQL_FROM_HERE,
311 base::StringPrintf("DELETE FROM %s", kUrlResourceTableName).c_str()));
312 resource_deleter.Run();
314 sql::Statement url_deleter(DB()->GetCachedStatement(
315 SQL_FROM_HERE,
316 base::StringPrintf("DELETE FROM %s", kUrlMetadataTableName).c_str()));
317 url_deleter.Run();
320 void ResourcePrefetchPredictorTables::CreateTableIfNonExistent() {
321 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
322 if (CantAccessDatabase())
323 return;
325 std::string url_resource_table_creation_statement = base::StringPrintf(
326 "CREATE TABLE %s ( "
327 "main_page_url TEXT, "
328 "resource_url TEXT, "
329 "resource_type INTEGER, "
330 "number_of_hits INTEGER, "
331 "number_of_misses INTEGER, "
332 "consecutive_misses INTEGER, "
333 "average_position DOUBLE, "
334 "PRIMARY KEY(main_page_url, resource_url))",
335 kUrlResourceTableName);
337 std::string url_metadata_table_creation_statement = base::StringPrintf(
338 "CREATE TABLE %s ( "
339 "main_page_url TEXT, "
340 "last_visit_time INTEGER, "
341 "PRIMARY KEY(main_page_url))",
342 kUrlMetadataTableName);
344 if ((!DB()->DoesTableExist(kUrlResourceTableName) &&
345 !DB()->Execute(url_resource_table_creation_statement.c_str())) ||
346 (!DB()->DoesTableExist(kUrlMetadataTableName) &&
347 !DB()->Execute(url_metadata_table_creation_statement.c_str()))) {
348 ResetDB();
352 void ResourcePrefetchPredictorTables::LogDatabaseStats() {
353 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
354 if (CantAccessDatabase())
355 return;
357 sql::Statement url_statement(DB()->GetUniqueStatement(
358 base::StringPrintf("SELECT count(*) FROM %s",
359 kUrlResourceTableName).c_str()));
360 if (url_statement.Step())
361 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.UrlTableRowCount",
362 url_statement.ColumnInt(0));
365 } // namespace predictors