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 "chrome/browser/predictors/resource_prefetch_predictor_tables.h" | |
6 | |
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" | |
12 | |
13 using content::BrowserThread; | |
14 | |
15 namespace { | |
16 | |
17 const char kResourcePredictorUrlTableName[] = "resource_prefetch_predictor_url"; | |
18 | |
19 // The maximum length allowed for strings in the database. | |
20 const size_t kMaxURLLength = 2048; | |
21 | |
22 void BindUrlTableRowToStatement( | |
23 const predictors::ResourcePrefetchPredictorTables::UrlTableRow& row, | |
24 sql::Statement* statement) { | |
25 statement->BindString(0, row.main_frame_url_.spec().substr(0, kMaxURLLength)); | |
26 statement->BindString(1, row.resource_url_.spec().substr(0, kMaxURLLength)); | |
27 statement->BindInt(2, static_cast<int>(row.resource_type_)); | |
28 statement->BindInt(3, row.number_of_hits_); | |
29 statement->BindInt(4, row.number_of_misses_); | |
30 statement->BindInt(5, row.consecutive_misses_); | |
31 statement->BindDouble(6, row.average_position_); | |
32 } | |
33 | |
34 bool StepAndInitializeUrlTableRow( | |
35 sql::Statement* statement, | |
36 predictors::ResourcePrefetchPredictorTables::UrlTableRow* row) { | |
37 if (!statement->Step()) | |
38 return false; | |
39 | |
40 row->main_frame_url_ = GURL(statement->ColumnString(0)); | |
41 row->resource_url_ = GURL(statement->ColumnString(1)); | |
42 row->resource_type_ = ResourceType::FromInt(statement->ColumnInt(2)); | |
43 row->number_of_hits_ = statement->ColumnInt(3); | |
44 row->number_of_misses_ = statement->ColumnInt(4); | |
45 row->consecutive_misses_ = statement->ColumnInt(5); | |
46 row->average_position_ = statement->ColumnDouble(6); | |
47 return true; | |
48 } | |
49 | |
50 } // namespace | |
51 | |
52 namespace predictors { | |
53 | |
54 ResourcePrefetchPredictorTables::UrlTableRow::UrlTableRow() | |
55 : resource_type_(ResourceType::LAST_TYPE), | |
56 number_of_hits_(0), | |
57 number_of_misses_(0), | |
58 consecutive_misses_(0), | |
59 average_position_(0), | |
dominich
2012/05/21 16:16:53
warning: initializing a double with an int.
Shishir
2012/05/23 01:46:46
Done.
| |
60 score_(0.0) { | |
61 } | |
62 | |
63 ResourcePrefetchPredictorTables::UrlTableRow::UrlTableRow( | |
64 const UrlTableRow& other) | |
65 : main_frame_url_(other.main_frame_url_), | |
66 resource_url_(other.resource_url_), | |
67 resource_type_(other.resource_type_), | |
68 number_of_hits_(other.number_of_hits_), | |
69 number_of_misses_(other.number_of_misses_), | |
70 consecutive_misses_(other.consecutive_misses_), | |
71 average_position_(other.average_position_), | |
72 score_(other.score_) { | |
73 } | |
74 | |
75 void ResourcePrefetchPredictorTables::UrlTableRow::UpdateScore() { | |
dominich
2012/05/21 16:16:53
Comment explaining the heuristic here. Also, might
Shishir
2012/05/23 01:46:46
Added comment. We might have additional field tria
| |
76 static const int kMaxResourcesPerType = 100; | |
77 switch (resource_type_) { | |
78 case ResourceType::STYLESHEET: | |
79 case ResourceType::SCRIPT: | |
80 score_ = (2 * kMaxResourcesPerType) - average_position_; | |
81 break; | |
82 | |
83 case ResourceType::IMAGE: | |
84 score_ = kMaxResourcesPerType - average_position_; | |
85 break; | |
86 | |
87 default: | |
dominich
2012/05/21 16:16:53
What other resource types should be handled? Maybe
Shishir
2012/05/23 01:46:46
Sometimes we do not know the type of resource, eg
| |
88 score_ = kMaxResourcesPerType - average_position_; | |
89 break; | |
90 } | |
91 } | |
92 | |
93 bool ResourcePrefetchPredictorTables::UrlTableRowSorter::operator()( | |
94 const UrlTableRow& x, | |
95 const UrlTableRow& y) const { | |
96 return x.score_ > y.score_; | |
97 } | |
98 | |
99 ResourcePrefetchPredictorTables::ResourcePrefetchPredictorTables() | |
100 : PredictorTableBase() { | |
101 } | |
102 | |
103 ResourcePrefetchPredictorTables::~ResourcePrefetchPredictorTables() { | |
104 } | |
105 | |
106 void ResourcePrefetchPredictorTables::CreateTableIfNonExistent() { | |
107 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
108 if (CantAccessDatabase()) | |
109 return; | |
110 | |
111 std::string url_table_creation_statement = base::StringPrintf( | |
112 "CREATE TABLE %s ( " | |
113 "main_page_url TEXT, " | |
114 "resource_url TEXT, " | |
115 "resource_type INTEGER, " | |
116 "number_of_hits INTEGER, " | |
117 "number_of_misses INTEGER, " | |
118 "consecutive_misses INTEGER, " | |
119 "average_position DOUBLE, " | |
120 "PRIMARY KEY(main_page_url, resource_url))", | |
121 kResourcePredictorUrlTableName); | |
122 | |
123 if (!DB()->DoesTableExist(kResourcePredictorUrlTableName)) | |
dominich
2012/05/21 16:16:53
add braces as the inner if has them.
Shishir
2012/05/23 01:46:46
Done.
| |
124 if (!DB()->Execute(url_table_creation_statement.c_str())) { | |
125 ResetDB(); | |
126 return; | |
127 } | |
128 } | |
129 | |
130 void ResourcePrefetchPredictorTables::LogDatabaseStats() { | |
dominich
2012/05/21 16:16:53
Consider tracking the raw file size.
Shishir
2012/05/23 01:46:46
That happens in the PredictorDatabaseInternal.
| |
131 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
132 if (CantAccessDatabase()) | |
133 return; | |
134 | |
135 sql::Statement url_statement(DB()->GetUniqueStatement( | |
136 base::StringPrintf("SELECT count(*) FROM %s", | |
137 kResourcePredictorUrlTableName).c_str())); | |
138 if (url_statement.Step()) | |
139 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.UrlTableRowCount", | |
140 url_statement.ColumnInt(0)); | |
141 } | |
142 | |
143 void ResourcePrefetchPredictorTables::GetAllRows( | |
144 std::vector<UrlTableRow>* url_row_buffer) { | |
145 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
146 if (CantAccessDatabase()) | |
147 return; | |
148 | |
149 CHECK(url_row_buffer); | |
150 url_row_buffer->clear(); | |
151 sql::Statement url_statement(DB()->GetCachedStatement(SQL_FROM_HERE, | |
152 base::StringPrintf("SELECT * FROM %s", | |
153 kResourcePredictorUrlTableName).c_str())); | |
154 | |
155 UrlTableRow url_row; | |
156 while (StepAndInitializeUrlTableRow(&url_statement, &url_row)) { | |
157 url_row.UpdateScore(); | |
dominich
2012/05/21 16:16:53
why don't you store the score?
Shishir
2012/05/23 01:46:46
Not storing it right now because we want to run ex
| |
158 url_row_buffer->push_back(url_row); | |
159 } | |
160 } | |
161 | |
162 void ResourcePrefetchPredictorTables::UpdateRowsForUrl( | |
163 const GURL& main_page_url, | |
164 const std::vector<UrlTableRow>& row_buffer) { | |
165 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
166 if (CantAccessDatabase()) | |
167 return; | |
168 | |
169 DB()->BeginTransaction(); | |
170 | |
171 sql::Statement delete_statement(DB()->GetUniqueStatement( | |
dominich
2012/05/21 16:16:53
would it be more optimal to SELECT and then UPDATE
Shishir
2012/05/23 01:46:46
May not be, since we will end up updating all the
| |
172 base::StringPrintf("DELETE FROM %s WHERE main_page_url='%s'", | |
173 kResourcePredictorUrlTableName, | |
174 main_page_url.spec().c_str()).c_str())); | |
175 if (!delete_statement.Run()) { | |
176 DB()->RollbackTransaction(); | |
177 return; | |
178 } | |
179 | |
180 for (int i = 0; i < static_cast<int>(row_buffer.size()); ++i) { | |
181 const UrlTableRow& row = row_buffer.at(i); | |
182 | |
183 sql::Statement add_statement( | |
184 DB()->GetCachedStatement( | |
185 SQL_FROM_HERE, | |
186 base::StringPrintf( | |
187 "INSERT INTO %s " | |
188 "(main_page_url, resource_url, resource_type, number_of_hits, " | |
189 "number_of_misses, consecutive_misses, average_position) " | |
190 "VALUES (?,?,?,?,?,?,?)", | |
191 kResourcePredictorUrlTableName).c_str())); | |
192 BindUrlTableRowToStatement(row, &add_statement); | |
193 if (!add_statement.Run()) { | |
194 DB()->RollbackTransaction(); | |
195 return; | |
196 } | |
197 } | |
198 | |
199 DB()->CommitTransaction(); | |
200 } | |
201 | |
202 void ResourcePrefetchPredictorTables::DeleteUrlRows( | |
203 const std::vector<GURL>& urls) { | |
204 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
205 if (CantAccessDatabase()) | |
206 return; | |
207 | |
208 // These do not need to be a transaction. | |
209 for (int i = 0; i < static_cast<int>(urls.size()); ++i) { | |
210 sql::Statement delete_statement(DB()->GetCachedStatement( | |
211 SQL_FROM_HERE, | |
212 base::StringPrintf("DELETE FROM %s WHERE main_page_url='%s'", | |
213 kResourcePredictorUrlTableName, | |
214 urls[i].spec().c_str()).c_str())); | |
215 } | |
216 } | |
217 | |
218 } // namespace predictors | |
OLD | NEW |