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

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

Issue 2586813004: Report downloaded resources at most once (Closed)
Patch Set: Fix race condition in PrecacheFetcherTest due to MaybePost Created 4 years 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_url_table.h" 5 #include "components/precache/core/precache_url_table.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "sql/connection.h" 10 #include "sql/connection.h"
(...skipping 21 matching lines...) Expand all
32 32
33 PrecacheURLTable::~PrecacheURLTable() {} 33 PrecacheURLTable::~PrecacheURLTable() {}
34 34
35 bool PrecacheURLTable::Init(sql::Connection* db) { 35 bool PrecacheURLTable::Init(sql::Connection* db) {
36 DCHECK(!db_); // Init must only be called once. 36 DCHECK(!db_); // Init must only be called once.
37 DCHECK(db); // The database connection must be non-NULL. 37 DCHECK(db); // The database connection must be non-NULL.
38 db_ = db; 38 db_ = db;
39 return CreateTableIfNonExistent(); 39 return CreateTableIfNonExistent();
40 } 40 }
41 41
42 bool PrecacheURLTable::BindStatementAndRun(const GURL& url,
43 int64_t referrer_host_id,
44 bool is_precached,
45 const base::Time& precache_time,
46 Statement* statement) {
47 statement->BindInt64(0, is_precached ? 1 : 0);
48 statement->BindInt64(1, precache_time.ToInternalValue());
49 statement->BindInt64(2, referrer_host_id);
50 statement->BindString(3, GetKey(url));
twifkak 2016/12/20 01:41:59 Make the order of the bindvars and the order of th
jamartin 2016/12/20 21:09:34 NA.
51 return statement->Run();
52 }
53
42 void PrecacheURLTable::AddURL(const GURL& url, 54 void PrecacheURLTable::AddURL(const GURL& url,
43 int64_t referrer_host_id, 55 int64_t referrer_host_id,
44 bool is_precached, 56 bool is_precached,
57 bool was_cached,
45 const base::Time& precache_time) { 58 const base::Time& precache_time) {
46 Statement statement( 59 Statement statement;
47 db_->GetCachedStatement(SQL_FROM_HERE, 60 if (is_precached && !was_cached) {
twifkak 2016/12/20 01:41:59 Note that "is_precached" here is a misnomer, since
jamartin 2016/12/20 21:09:34 Good catch. This is not applicable anymore but, e
48 "INSERT OR REPLACE INTO precache_urls (url, " 61 // We just precached from the network. Set is_download_reported = 0.
49 "referrer_host_id, was_used, is_precached, time) " 62 Statement statement(
50 "VALUES(?,?,0,?,?)")); 63 db_->GetCachedStatement(SQL_FROM_HERE,
51 64 "INSERT OR REPLACE INTO precache_urls "
52 statement.BindString(0, GetKey(url)); 65 "(was_used, is_precached, time, "
53 statement.BindInt64(1, referrer_host_id); 66 " is_download_reported, referrer_host_id, url) "
54 statement.BindInt64(2, is_precached ? 1 : 0); 67 "VALUES(0,?,?,0,?,?)"));
55 statement.BindInt64(3, precache_time.ToInternalValue()); 68 BindStatementAndRun(url, referrer_host_id, is_precached, precache_time,
56 statement.Run(); 69 &statement);
70 } else {
71 // Update the entry but do not modify is_download_reported.
72 // We need to do an INSERT possibly followed by an UPDATE because there is
73 // no INSERT OR UPDATE in sqlite.
74 Statement insert(db_->GetCachedStatement(
75 SQL_FROM_HERE,
76 "INSERT OR ABORT INTO precache_urls "
77 "(was_used, is_precached, time, referrer_host_id, url) "
78 "VALUES(0,?,?,?,?)"));
79 // If this FAILS during tests, it is because you need to set_error_callback
80 // in the SQL connection. The default behavior in DEBUG is crash whereas
81 // the default behavior live is the expected, just to return false.
82 if (!BindStatementAndRun(url, referrer_host_id, is_precached, precache_time,
twifkak 2016/12/20 01:42:00 I'd rather move this logic out of PrecacheURLTable
jamartin 2016/12/20 21:09:34 Done.
83 &insert)) {
84 Statement update(db_->GetCachedStatement(
85 SQL_FROM_HERE,
86 "UPDATE precache_urls SET "
87 "was_used=0, is_precached=?, time=?, referrer_host_id=?"
88 "WHERE url=?"));
89 BindStatementAndRun(url, referrer_host_id, is_precached, precache_time,
90 &update);
91 }
92 }
57 } 93 }
58 94
59 PrecacheURLInfo PrecacheURLTable::GetURLInfo(const GURL& url) { 95 PrecacheURLInfo PrecacheURLTable::GetURLInfo(const GURL& url) {
60 Statement statement(db_->GetCachedStatement( 96 Statement statement(db_->GetCachedStatement(
61 SQL_FROM_HERE, 97 SQL_FROM_HERE,
62 "SELECT is_precached, was_used FROM precache_urls WHERE url=?")); 98 "SELECT is_precached, was_used FROM precache_urls WHERE url=?"));
63 statement.BindString(0, GetKey(url)); 99 statement.BindString(0, GetKey(url));
64 100
65 if (statement.Step()) { 101 if (statement.Step()) {
66 return {/*present=*/true, /*is_precached=*/statement.ColumnBool(0), 102 return {/*present=*/true, /*is_precached=*/statement.ColumnBool(0),
(...skipping 19 matching lines...) Expand all
86 db_->GetCachedStatement(SQL_FROM_HERE, 122 db_->GetCachedStatement(SQL_FROM_HERE,
87 "UPDATE precache_urls SET is_precached=0 " 123 "UPDATE precache_urls SET is_precached=0 "
88 "WHERE url=? and is_precached=1")); 124 "WHERE url=? and is_precached=1"));
89 statement.BindString(0, GetKey(url)); 125 statement.BindString(0, GetKey(url));
90 statement.Run(); 126 statement.Run();
91 } 127 }
92 128
93 void PrecacheURLTable::GetURLListForReferrerHost( 129 void PrecacheURLTable::GetURLListForReferrerHost(
94 int64_t referrer_host_id, 130 int64_t referrer_host_id,
95 std::vector<GURL>* used_urls, 131 std::vector<GURL>* used_urls,
96 std::vector<GURL>* unused_urls) { 132 std::vector<GURL>* downloaded_urls) {
97 Statement statement(db_->GetCachedStatement( 133 Statement statement(
98 SQL_FROM_HERE, 134 db_->GetCachedStatement(SQL_FROM_HERE,
99 "SELECT url, was_used from precache_urls where referrer_host_id=?")); 135 "SELECT url, was_used, is_download_reported "
136 "from precache_urls where referrer_host_id=?"));
100 statement.BindInt64(0, referrer_host_id); 137 statement.BindInt64(0, referrer_host_id);
101 while (statement.Step()) { 138 while (statement.Step()) {
102 GURL url(statement.ColumnString(0)); 139 GURL url(statement.ColumnString(0));
103 if (statement.ColumnInt(1)) 140 if (statement.ColumnInt(1))
104 used_urls->push_back(url); 141 used_urls->push_back(url);
105 else 142 if (!statement.ColumnInt(2))
106 unused_urls->push_back(url); 143 downloaded_urls->push_back(url);
144 }
145 // Set is_download_reported for all the downloaded_urls.
146 if (!downloaded_urls->empty()) {
twifkak 2016/12/20 01:42:00 Likewise, consider moving this block into a separa
jamartin 2016/12/20 21:09:34 Done. I should have noticed this when I was testin
147 Statement update(db_->GetCachedStatement(
148 SQL_FROM_HERE,
149 "UPDATE precache_urls SET is_download_reported=1 "
150 "WHERE referrer_host_id=?"));
151 update.BindInt64(0, referrer_host_id);
152 update.Run();
107 } 153 }
108 } 154 }
109 155
110 void PrecacheURLTable::ClearAllForReferrerHost(int64_t referrer_host_id) { 156 void PrecacheURLTable::ClearAllForReferrerHost(int64_t referrer_host_id) {
111 // Delete the URLs that are not precached. 157 // Delete the URLs that are not precached.
112 Statement delete_statement( 158 Statement delete_statement(
113 db_->GetCachedStatement(SQL_FROM_HERE, 159 db_->GetCachedStatement(SQL_FROM_HERE,
114 "DELETE FROM precache_urls WHERE " 160 "DELETE FROM precache_urls WHERE "
115 "referrer_host_id=? AND is_precached=0")); 161 "referrer_host_id=? AND is_precached=0"));
116 delete_statement.BindInt64(0, referrer_host_id); 162 delete_statement.BindInt64(0, referrer_host_id);
(...skipping 29 matching lines...) Expand all
146 SQL_FROM_HERE, 192 SQL_FROM_HERE,
147 "SELECT url, time FROM precache_urls where is_precached=1")); 193 "SELECT url, time FROM precache_urls where is_precached=1"));
148 194
149 while (statement.Step()) { 195 while (statement.Step()) {
150 GURL url = GURL(statement.ColumnString(0)); 196 GURL url = GURL(statement.ColumnString(0));
151 (*map)[url] = base::Time::FromInternalValue(statement.ColumnInt64(1)); 197 (*map)[url] = base::Time::FromInternalValue(statement.ColumnInt64(1));
152 } 198 }
153 } 199 }
154 200
155 bool PrecacheURLTable::CreateTableIfNonExistent() { 201 bool PrecacheURLTable::CreateTableIfNonExistent() {
202 // TODO(jamartin): The PRIMARY KEY should be (url, referrer_host_id).
156 if (!db_->DoesTableExist("precache_urls")) { 203 if (!db_->DoesTableExist("precache_urls")) {
157 return db_->Execute( 204 return db_->Execute(
158 "CREATE TABLE precache_urls " 205 "CREATE TABLE precache_urls "
159 "(url TEXT PRIMARY KEY, referrer_host_id INTEGER, was_used INTEGER, " 206 "(url TEXT PRIMARY KEY, referrer_host_id INTEGER, was_used INTEGER, "
160 "is_precached INTEGER, " 207 "is_precached INTEGER, "
161 "time INTEGER)"); 208 "time INTEGER, is_download_reported INTEGER)");
162 } else { 209 } else {
163 // Migrate the table by creating the missing columns. 210 // Migrate the table by creating the missing columns.
164 if (!db_->DoesColumnExist("precache_urls", "was_used") && 211 if (!db_->DoesColumnExist("precache_urls", "was_used") &&
165 !db_->Execute("ALTER TABLE precache_urls ADD COLUMN was_used INTEGER")) 212 !db_->Execute("ALTER TABLE precache_urls "
213 "ADD COLUMN was_used INTEGER")) {
166 return false; 214 return false;
215 }
167 if (!db_->DoesColumnExist("precache_urls", "is_precached") && 216 if (!db_->DoesColumnExist("precache_urls", "is_precached") &&
168 !db_->Execute( 217 !db_->Execute("ALTER TABLE precache_urls ADD COLUMN is_precached "
169 "ALTER TABLE precache_urls ADD COLUMN is_precached " 218 "INTEGER default 1")) {
170 "INTEGER default 1"))
171 return false; 219 return false;
220 }
172 if (!db_->DoesColumnExist("precache_urls", "referrer_host_id") && 221 if (!db_->DoesColumnExist("precache_urls", "referrer_host_id") &&
173 !db_->Execute( 222 !db_->Execute(
174 "ALTER TABLE precache_urls ADD COLUMN referrer_host_id INTEGER")) 223 "ALTER TABLE precache_urls ADD COLUMN referrer_host_id INTEGER")) {
175 return false; 224 return false;
225 }
226 if (!db_->DoesColumnExist("precache_urls", "is_download_reported") &&
227 !db_->Execute("ALTER TABLE precache_urls "
228 "ADD COLUMN is_download_reported INTEGER")) {
229 // The FSM for is_download_reported has q_0 = 0 and delta of:
230 // Q Sigma (conditioned on host id) Q'
231 // 0 GetURLListForReferrerHost 1 // Reported.
232 // 1 AddUrl(is_precached && !was_cached) 0 // Downloaded from network.
233 return false;
234 }
176 } 235 }
177 return true; 236 return true;
178 } 237 }
179 238
180 } // namespace precache 239 } // namespace precache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698