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.0), | |
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() { | |
76 // The score is calculated so that when the rows are sorted, the stylesheets | |
77 // and scripts appear first, sorted by position(ascending) and then the rest | |
78 // of the resources sorted by position(ascending). | |
79 static const int kMaxResourcesPerType = 100; | |
80 switch (resource_type_) { | |
81 case ResourceType::STYLESHEET: | |
82 case ResourceType::SCRIPT: | |
83 score_ = (2 * kMaxResourcesPerType) - average_position_; | |
84 break; | |
85 | |
86 case ResourceType::IMAGE: | |
87 score_ = kMaxResourcesPerType - average_position_; | |
88 break; | |
89 | |
90 default: | |
91 score_ = kMaxResourcesPerType - average_position_; | |
92 break; | |
93 } | |
94 } | |
95 | |
96 bool ResourcePrefetchPredictorTables::UrlTableRowSorter::operator()( | |
97 const UrlTableRow& x, | |
98 const UrlTableRow& y) const { | |
99 return x.score_ > y.score_; | |
100 } | |
101 | |
102 ResourcePrefetchPredictorTables::ResourcePrefetchPredictorTables() | |
103 : PredictorTableBase() { | |
104 } | |
105 | |
106 ResourcePrefetchPredictorTables::~ResourcePrefetchPredictorTables() { | |
107 } | |
108 | |
109 void ResourcePrefetchPredictorTables::CreateTableIfNonExistent() { | |
110 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
111 if (CantAccessDatabase()) | |
112 return; | |
113 | |
114 std::string url_table_creation_statement = base::StringPrintf( | |
115 "CREATE TABLE %s ( " | |
116 "main_page_url TEXT, " | |
117 "resource_url TEXT, " | |
118 "resource_type INTEGER, " | |
119 "number_of_hits INTEGER, " | |
120 "number_of_misses INTEGER, " | |
121 "consecutive_misses INTEGER, " | |
122 "average_position DOUBLE, " | |
123 "PRIMARY KEY(main_page_url, resource_url))", | |
124 kResourcePredictorUrlTableName); | |
125 | |
126 if (!DB()->DoesTableExist(kResourcePredictorUrlTableName)) { | |
dominich
2012/05/30 15:35:01
nit:
if (!DB()->DoesTableExist(...) && !DB()->Exe
Shishir
2012/05/30 18:07:15
Done.
| |
127 if (!DB()->Execute(url_table_creation_statement.c_str())) { | |
128 ResetDB(); | |
129 return; | |
dominich
2012/05/30 15:35:01
nit: unnecessary return
Shishir
2012/05/30 18:07:15
Done.
| |
130 } | |
131 } | |
132 } | |
133 | |
134 void ResourcePrefetchPredictorTables::LogDatabaseStats() { | |
135 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
136 if (CantAccessDatabase()) | |
137 return; | |
138 | |
139 sql::Statement url_statement(DB()->GetUniqueStatement( | |
140 base::StringPrintf("SELECT count(*) FROM %s", | |
141 kResourcePredictorUrlTableName).c_str())); | |
142 if (url_statement.Step()) | |
143 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.UrlTableRowCount", | |
144 url_statement.ColumnInt(0)); | |
145 } | |
146 | |
147 void ResourcePrefetchPredictorTables::GetAllRows( | |
148 std::vector<UrlTableRow>* url_row_buffer) { | |
149 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
150 if (CantAccessDatabase()) | |
151 return; | |
152 | |
153 CHECK(url_row_buffer); | |
154 url_row_buffer->clear(); | |
dominich
2012/05/30 15:35:01
you could avoid the call to clear() and CHECK that
Shishir
2012/05/30 18:07:15
Done.
| |
155 sql::Statement url_statement(DB()->GetCachedStatement(SQL_FROM_HERE, | |
156 base::StringPrintf("SELECT * FROM %s", | |
157 kResourcePredictorUrlTableName).c_str())); | |
158 | |
159 UrlTableRow url_row; | |
160 while (StepAndInitializeUrlTableRow(&url_statement, &url_row)) { | |
161 url_row.UpdateScore(); | |
162 url_row_buffer->push_back(url_row); | |
163 } | |
164 } | |
165 | |
166 void ResourcePrefetchPredictorTables::UpdateRowsForUrl( | |
167 const GURL& main_page_url, | |
168 const std::vector<UrlTableRow>& row_buffer) { | |
169 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
170 if (CantAccessDatabase()) | |
171 return; | |
172 | |
173 DB()->BeginTransaction(); | |
174 | |
175 sql::Statement delete_statement(DB()->GetCachedStatement( | |
176 SQL_FROM_HERE, | |
177 base::StringPrintf("DELETE FROM %s WHERE main_page_url='%s'", | |
178 kResourcePredictorUrlTableName, | |
179 main_page_url.spec().c_str()).c_str())); | |
180 if (!delete_statement.Run()) { | |
181 DB()->RollbackTransaction(); | |
182 return; | |
183 } | |
184 | |
185 for (int i = 0; i < static_cast<int>(row_buffer.size()); ++i) { | |
dominich
2012/05/30 15:35:01
use iterator loop
Shishir
2012/05/30 18:07:15
Done.
| |
186 const UrlTableRow& row = row_buffer.at(i); | |
187 | |
188 sql::Statement add_statement( | |
189 DB()->GetCachedStatement( | |
190 SQL_FROM_HERE, | |
191 base::StringPrintf( | |
192 "INSERT INTO %s " | |
193 "(main_page_url, resource_url, resource_type, number_of_hits, " | |
194 "number_of_misses, consecutive_misses, average_position) " | |
195 "VALUES (?,?,?,?,?,?,?)", | |
196 kResourcePredictorUrlTableName).c_str())); | |
197 BindUrlTableRowToStatement(row, &add_statement); | |
198 if (!add_statement.Run()) { | |
199 DB()->RollbackTransaction(); | |
200 return; | |
201 } | |
202 } | |
203 | |
204 DB()->CommitTransaction(); | |
205 } | |
206 | |
207 void ResourcePrefetchPredictorTables::DeleteUrlRows( | |
208 const std::vector<GURL>& urls) { | |
209 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
210 if (CantAccessDatabase()) | |
211 return; | |
212 | |
213 // These do not need to be a transaction. | |
214 for (int i = 0; i < static_cast<int>(urls.size()); ++i) { | |
dominich
2012/05/30 15:35:01
iterator loop
Shishir
2012/05/30 18:07:15
Done.
| |
215 sql::Statement delete_statement(DB()->GetCachedStatement( | |
216 SQL_FROM_HERE, | |
217 base::StringPrintf("DELETE FROM %s WHERE main_page_url='%s'", | |
218 kResourcePredictorUrlTableName, | |
219 urls[i].spec().c_str()).c_str())); | |
220 } | |
221 } | |
222 | |
223 } // namespace predictors | |
OLD | NEW |